├── Assets ├── Resources │ ├── BillingMode.json │ └── BillingMode.json.meta ├── testframework │ ├── localizationForiOS │ │ ├── ko.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── InfoPlist.strings.meta │ │ ├── ja.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── InfoPlist.strings.meta │ │ ├── zh-Hans.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── InfoPlist.strings.meta │ │ ├── zh-Hant.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── InfoPlist.strings.meta │ │ ├── en.lproj │ │ │ ├── InfoPlist.strings │ │ │ └── InfoPlist.strings.meta │ │ ├── en.lproj.meta │ │ ├── ja.lproj.meta │ │ ├── ko.lproj.meta │ │ ├── zh-Hans.lproj.meta │ │ └── zh-Hant.lproj.meta │ └── localizationForiOS.meta ├── Editor.meta ├── Scenes.meta ├── Scenes │ ├── SampleScene.unity.meta │ └── SampleScene.unity ├── NativeLocale.meta ├── Resources.meta ├── testframework.meta └── Editor │ ├── Xcode.meta │ ├── Xcode │ ├── PBX.meta │ ├── JsonParser.cs.meta │ ├── PBX │ │ ├── Lexer.cs.meta │ │ ├── Objects.cs.meta │ │ ├── Parser.cs.meta │ │ ├── Utils.cs.meta │ │ ├── Elements.cs.meta │ │ ├── Sections.cs.meta │ │ ├── Serializer.cs.meta │ │ ├── Elements.cs │ │ ├── Sections.cs │ │ ├── Parser.cs │ │ ├── Lexer.cs │ │ ├── Serializer.cs │ │ └── Utils.cs │ ├── PBXPath.cs.meta │ ├── PBXProject.cs.meta │ ├── PlistParser.cs.meta │ ├── AssetCatalog.cs.meta │ ├── PBXProjectData.cs.meta │ ├── PBXCapabilityType.cs.meta │ ├── PBXProjectExtensions.cs.meta │ ├── ProjectCapabilityManager.cs.meta │ ├── PBXPath.cs │ ├── PBXCapabilityType.cs │ ├── JsonParser.cs │ ├── PlistParser.cs │ ├── PBXProjectExtensions.cs │ └── ProjectCapabilityManager.cs │ ├── LocalizeName.cs.meta │ ├── PostProcess.cs.meta │ ├── PostProcess.cs │ └── LocalizeName.cs ├── ProjectSettings ├── ProjectVersion.txt ├── ClusterInputManager.asset ├── NetworkManager.asset ├── XRSettings.asset ├── VersionControlSettings.asset ├── TimeManager.asset ├── EditorBuildSettings.asset ├── VFXManager.asset ├── AudioManager.asset ├── TagManager.asset ├── EditorSettings.asset ├── PresetManager.asset ├── UnityConnectSettings.asset ├── PackageManagerSettings.asset ├── DynamicsManager.asset ├── Physics2DSettings.asset ├── NavMeshAreas.asset ├── GraphicsSettings.asset ├── QualitySettings.asset ├── InputManager.asset └── ProjectSettings.asset ├── .idea └── .idea.UnityiOSLocalization │ └── .idea │ ├── encodings.xml │ ├── vcs.xml │ ├── indexLayout.xml │ └── .gitignore ├── README.md ├── .gitignore └── Packages ├── manifest.json └── packages-lock.json /Assets/Resources/BillingMode.json: -------------------------------------------------------------------------------- 1 | {"androidStore":"GooglePlay"} -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/ko.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | "CFBundleDisplayName" = "숲속농장"; 2 | 3 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/ja.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | "CFBundleDisplayName" = "マイリトルファーム"; 2 | 3 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/zh-Hans.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | "CFBundleDisplayName" = "快乐农场"; 2 | 3 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/zh-Hant.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | "CFBundleDisplayName" = "快樂農場"; 2 | 3 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | "CFBundleDisplayName" = "Happy Ranch"; 2 | 3 | -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2020.3.15f2 2 | m_EditorVersionWithRevision: 2020.3.15f2 (6cf78cb77498) 3 | -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /Assets/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d1995b76918c543638277358608da8b3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 84c01cd07fe3246a8a64fb1dac523399 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Scenes/SampleScene.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8dcefbff236db468ea094005da029440 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Assets/NativeLocale.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 770e3cb26c0e841bd9e1a2435f8770ba 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 69926427253e341ff95da65f923e035f 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Resources/BillingMode.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3058f497f2ad644e899b2935b4c44845 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /.idea/.idea.UnityiOSLocalization/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Assets/testframework.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1a7ef88d569d0490584770789d8d8ab4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /ProjectSettings/XRSettings.asset: -------------------------------------------------------------------------------- 1 | { 2 | "m_SettingKeys": [ 3 | "VR Device Disabled", 4 | "VR Device User Alert" 5 | ], 6 | "m_SettingValues": [ 7 | "False", 8 | "False" 9 | ] 10 | } -------------------------------------------------------------------------------- /.idea/.idea.UnityiOSLocalization/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4ddbc2e96d7e843b1a69cd158f916b07 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 670d932844d474051b5ad5960f043d7c 3 | folderAsset: yes 4 | timeCreated: 1535613234 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7625017be5ff149a6b0f20ee645ce11e 3 | folderAsset: yes 4 | timeCreated: 1496741689 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /ProjectSettings/VersionControlSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!890905787 &1 4 | VersionControlSettings: 5 | m_ObjectHideFlags: 0 6 | m_Mode: Visible Meta Files 7 | m_CollabEditorSettings: 8 | inProgressEnabled: 1 9 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/en.lproj/InfoPlist.strings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ab1681df1e38c46e3aff627f7a524e0f 3 | timeCreated: 1535100536 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/ja.lproj/InfoPlist.strings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 81e29d34a607f4de4af35be759402d05 3 | timeCreated: 1535100536 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/ko.lproj/InfoPlist.strings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c854fdf2e801941e3891cbf5eb81fa5c 3 | timeCreated: 1535100536 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.1 8 | m_TimeScale: 1 9 | Maximum Particle Timestep: 0.03 10 | -------------------------------------------------------------------------------- /.idea/.idea.UnityiOSLocalization/.idea/indexLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/zh-Hans.lproj/InfoPlist.strings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6bf01c3fb24924bca822641e520fee19 3 | timeCreated: 1535100536 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/zh-Hant.lproj/InfoPlist.strings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: acb6c30553f25469297dd903e332d689 3 | timeCreated: 1535100536 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/en.lproj.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d16819a599a6a414da6041632b0b304b 3 | folderAsset: yes 4 | timeCreated: 1535100536 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/ja.lproj.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7f56c6844430b44479a48c9a5ce3aa75 3 | folderAsset: yes 4 | timeCreated: 1535100536 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/ko.lproj.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5daa403c129724ebea32621f4ea7989d 3 | folderAsset: yes 4 | timeCreated: 1535100536 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/zh-Hans.lproj.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ed75300803a644304adb37d6b89ba0d1 3 | folderAsset: yes 4 | timeCreated: 1535100536 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/testframework/localizationForiOS/zh-Hant.lproj.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7630b4e7b9c204e69b5725a0d8f781a4 3 | folderAsset: yes 4 | timeCreated: 1535100536 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Editor/LocalizeName.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f71f959e449a34e318f18ef8ff951f39 3 | timeCreated: 1535600010 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/PostProcess.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 99cef3a16ce8b4417a1e8bf36010cd64 3 | timeCreated: 1535626135 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: 8 | - enabled: 1 9 | path: Assets/Scenes/SampleScene.unity 10 | guid: 8dcefbff236db468ea094005da029440 11 | m_configObjects: {} 12 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/JsonParser.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 052ac8a8c9ae3466f94f7b3b6c5b61af 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Lexer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9766f6c4eb5ef42f99c0d5f86e34ba84 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Objects.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 67cf10cf994604c719f706525399f867 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Parser.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5ce5a244bc4e04a668ab097db4456665 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Utils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8eafbccf2ded14760af588ffcb1ca0f5 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBXPath.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 57be5de7dcd844631b3e835186497c25 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBXProject.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5923416dbf32e48428afbeee2b4eb48e 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PlistParser.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c2ed9743fe9634c808ea1dc01c20e01e 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /ProjectSettings/VFXManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!937362698 &1 4 | VFXManager: 5 | m_ObjectHideFlags: 0 6 | m_IndirectShader: {fileID: 0} 7 | m_CopyBufferShader: {fileID: 0} 8 | m_SortShader: {fileID: 0} 9 | m_RenderPipeSettingsPath: 10 | m_FixedTimeStep: 0.016666668 11 | m_MaxDeltaTime: 0.05 12 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/AssetCatalog.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 46dd33873affe4e5caf86cb784bd831a 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Elements.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 83cffec4be0e045258109e9714cdaa5f 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Sections.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 60639b138b83f4ce9b2448c38a6ba285 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Serializer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: afe8316bf614347729fac3466d7c77f2 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBXProjectData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 54c86bc46b87645c78e5b211a0eeada5 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBXCapabilityType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 71f2dd6273cda4741b9b3bac41a9b765 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBXProjectExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b84f17869f54f4d7a952c9f63e5744d6 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/ProjectCapabilityManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2bfeebf480ee141979c8981b78c0a488 3 | timeCreated: 1496741691 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /.idea/.idea.UnityiOSLocalization/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Rider ignored files 5 | /contentModel.xml 6 | /modules.xml 7 | /.idea.UnityiOSLocalization.iml 8 | /projectSettingsUpdater.xml 9 | # Datasource local storage ignored files 10 | /dataSources/ 11 | /dataSources.local.xml 12 | # Editor-based HTTP Client requests 13 | /httpRequests/ 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UnityiOSLocalization sample project 2 | 3 | sample project for iOS localizable works with onPostProcessBuild API and Unity XcodeAPI 4 | 5 | 6 | 7 | Refs 8 | - https://github.com/zeyangl/UnityAppNameLocalizationForIOS 9 | - https://bitbucket.org/Unity-Technologies/xcodeapi/src/stable/ 10 | - https://docs.unity3d.com/kr/2017.4/ScriptReference/Build.IPostprocessBuild.OnPostprocessBuild.html 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | Doppler Factor: 1 9 | Default Speaker Mode: 2 10 | m_SampleRate: 0 11 | m_DSPBufferSize: 1024 12 | m_VirtualVoiceCount: 512 13 | m_RealVoiceCount: 32 14 | m_SpatializerPlugin: 15 | m_AmbisonicDecoderPlugin: 16 | m_DisableAudio: 0 17 | m_VirtualizeEffects: 1 18 | -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - PostProcessing 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_LineEndingsForNewScripts: 2 10 | m_DefaultBehaviorMode: 0 11 | m_PrefabRegularEnvironment: {fileID: 0} 12 | m_PrefabUIEnvironment: {fileID: 0} 13 | m_SpritePackerMode: 0 14 | m_SpritePackerPaddingPower: 1 15 | m_EtcTextureCompressorBehavior: 1 16 | m_EtcTextureFastCompressor: 1 17 | m_EtcTextureNormalCompressor: 2 18 | m_EtcTextureBestCompressor: 4 19 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef 20 | m_ProjectGenerationRootNamespace: 21 | m_CollabEditorSettings: 22 | inProgressEnabled: 1 23 | m_EnableTextureStreamingInPlayMode: 1 24 | -------------------------------------------------------------------------------- /ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | m_DefaultList: 7 | - type: 8 | m_NativeTypeID: 108 9 | m_ManagedTypePPtr: {fileID: 0} 10 | m_ManagedTypeFallback: 11 | defaultPresets: 12 | - m_Preset: {fileID: 2655988077585873504, guid: c1cf8506f04ef2c4a88b64b6c4202eea, 13 | type: 2} 14 | - type: 15 | m_NativeTypeID: 1020 16 | m_ManagedTypePPtr: {fileID: 0} 17 | m_ManagedTypeFallback: 18 | defaultPresets: 19 | - m_Preset: {fileID: 2655988077585873504, guid: 0cd792cc87e492d43b4e95b205fc5cc6, 20 | type: 2} 21 | - type: 22 | m_NativeTypeID: 1006 23 | m_ManagedTypePPtr: {fileID: 0} 24 | m_ManagedTypeFallback: 25 | defaultPresets: 26 | - m_Preset: {fileID: 2655988077585873504, guid: 7a99f8aa944efe94cb9bd74562b7d5f9, 27 | type: 2} 28 | -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 1 7 | m_Enabled: 0 8 | m_TestMode: 0 9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events 10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events 11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com 12 | m_DashboardUrl: https://dashboard.unity3d.com 13 | m_TestInitMode: 0 14 | CrashReportingSettings: 15 | m_EventUrl: https://perf-events.cloud.unity3d.com 16 | m_Enabled: 0 17 | m_LogBufferSize: 10 18 | m_CaptureEditorExceptions: 1 19 | UnityPurchasingSettings: 20 | m_Enabled: 0 21 | m_TestMode: 0 22 | UnityAnalyticsSettings: 23 | m_Enabled: 0 24 | m_TestMode: 0 25 | m_InitializeOnStartup: 1 26 | UnityAdsSettings: 27 | m_Enabled: 0 28 | m_InitializeOnStartup: 1 29 | m_TestMode: 0 30 | m_IosGameId: 31 | m_AndroidGameId: 32 | m_GameIds: {} 33 | m_GameId: 34 | PerformanceReportingSettings: 35 | m_Enabled: 0 36 | -------------------------------------------------------------------------------- /ProjectSettings/PackageManagerSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &1 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 61 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} 13 | m_Name: 14 | m_EditorClassIdentifier: 15 | m_EnablePreviewPackages: 0 16 | m_EnablePackageDependencies: 0 17 | m_AdvancedSettingsExpanded: 1 18 | m_ScopedRegistriesSettingsExpanded: 1 19 | oneTimeWarningShown: 0 20 | m_Registries: 21 | - m_Id: main 22 | m_Name: 23 | m_Url: https://packages.unity.com 24 | m_Scopes: [] 25 | m_IsDefault: 1 26 | m_Capabilities: 7 27 | m_UserSelectedRegistryName: 28 | m_UserAddingNewScopedRegistry: 0 29 | m_RegistryInfoDraft: 30 | m_ErrorMessage: 31 | m_Original: 32 | m_Id: 33 | m_Name: 34 | m_Url: 35 | m_Scopes: [] 36 | m_IsDefault: 0 37 | m_Capabilities: 0 38 | m_Modified: 0 39 | m_Name: 40 | m_Url: 41 | m_Scopes: 42 | - 43 | m_SelectedScopeIndex: 0 44 | -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 8 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_DefaultSolverIterations: 6 13 | m_DefaultSolverVelocityIterations: 1 14 | m_QueriesHitBackfaces: 0 15 | m_QueriesHitTriggers: 1 16 | m_EnableAdaptiveForce: 0 17 | m_ClothInterCollisionDistance: 0 18 | m_ClothInterCollisionStiffness: 0 19 | m_ContactsGeneration: 1 20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21 | m_AutoSimulation: 1 22 | m_AutoSyncTransforms: 0 23 | m_ReuseCollisionCallbacks: 1 24 | m_ClothInterCollisionSettingsToggle: 0 25 | m_ContactPairsMode: 0 26 | m_BroadphaseType: 0 27 | m_WorldBounds: 28 | m_Center: {x: 0, y: 0, z: 0} 29 | m_Extent: {x: 250, y: 250, z: 250} 30 | m_WorldSubdivisions: 8 31 | -------------------------------------------------------------------------------- /Assets/Editor/PostProcess.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using UnityEditor.Callbacks; 6 | using Strings; 7 | using System.IO; 8 | using UnityEditor.iOS.Xcode; 9 | 10 | namespace Strings 11 | { 12 | public class PostProcess : MonoBehaviour 13 | { 14 | private const string ADMOB_SETTING = "GADIsAdManagerApp"; 15 | 16 | [PostProcessBuildAttribute(199999)] 17 | public static void OnPostProcessBuild(BuildTarget target, string path) 18 | { 19 | if (target == BuildTarget.iOS) 20 | { 21 | OnIOSBuild(target, path); 22 | } 23 | } 24 | 25 | private static void OnIOSBuild(BuildTarget target, string path) 26 | { 27 | LocalizeName.AddLocalizedStringsIOS(path, Path.Combine(Application.dataPath, "testframework/localizationForiOS")); 28 | 29 | string infoPlistPath = path + "/Info.plist"; 30 | 31 | PlistDocument plistDoc = new PlistDocument(); 32 | plistDoc.ReadFromFile(infoPlistPath); 33 | if (plistDoc.root != null) { 34 | plistDoc.root.SetBoolean(ADMOB_SETTING, true); 35 | plistDoc.WriteToFile(infoPlistPath); 36 | } 37 | else { 38 | Debug.LogError("ERROR: Can't open " + infoPlistPath); 39 | } 40 | } 41 | } 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore 4 | # 5 | /[Ll]ibrary/* 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Uu]ser[Ss]ettings/ 12 | 13 | 14 | # MemoryCaptures can get excessive in size. 15 | # They also could contain extremely sensitive data 16 | /[Mm]emoryCaptures/ 17 | 18 | # Recordings can get excessive in size 19 | /[Rr]ecordings/ 20 | 21 | # Uncomment this line if you wish to ignore the asset store tools plugin 22 | # /[Aa]ssets/AssetStoreTools* 23 | 24 | # Autogenerated Jetbrains Rider plugin 25 | /[Aa]ssets/Plugins/Editor/JetBrains* 26 | 27 | # Visual Studio cache directory 28 | .vs/ 29 | 30 | # Gradle cache directory 31 | .gradle/ 32 | 33 | # Autogenerated VS/MD/Consulo solution and project files 34 | ExportedObj/ 35 | .consulo/ 36 | *.csproj 37 | *.unityproj 38 | *.sln 39 | *.suo 40 | *.tmp 41 | *.user 42 | *.userprefs 43 | *.pidb 44 | *.booproj 45 | *.svd 46 | *.pdb 47 | *.mdb 48 | *.opendb 49 | *.VC.db 50 | 51 | # Unity3D generated meta files 52 | *.pidb.meta 53 | *.pdb.meta 54 | *.mdb.meta 55 | 56 | # Unity3D generated file on crash reports 57 | sysinfo.txt 58 | 59 | # Builds 60 | *.apk 61 | *.aab 62 | *.unitypackage 63 | *.app 64 | 65 | # Crashlytics generated file 66 | crashlytics-build.properties 67 | 68 | # Packed Addressables 69 | /[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* 70 | 71 | # Temporary auto-generated Android Assets 72 | /[Aa]ssets/[Ss]treamingAssets/aa.meta 73 | /[Aa]ssets/[Ss]treamingAssets/aa/* -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 4 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_BaumgarteScale: 0.2 17 | m_BaumgarteTimeOfImpactScale: 0.75 18 | m_TimeToSleep: 0.5 19 | m_LinearSleepTolerance: 0.01 20 | m_AngularSleepTolerance: 2 21 | m_DefaultContactOffset: 0.01 22 | m_AutoSimulation: 1 23 | m_QueriesHitTriggers: 1 24 | m_QueriesStartInColliders: 1 25 | m_ChangeStopsCallbacks: 0 26 | m_CallbacksOnDisable: 1 27 | m_ReuseCollisionCallbacks: 1 28 | m_AutoSyncTransforms: 0 29 | m_AlwaysShowColliders: 0 30 | m_ShowColliderSleep: 1 31 | m_ShowColliderContacts: 0 32 | m_ShowColliderAABB: 0 33 | m_ContactArrowScale: 0.2 34 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 35 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 36 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 37 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} 38 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 39 | -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshProjectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | m_LastAgentTypeID: -887442657 73 | m_Settings: 74 | - serializedVersion: 2 75 | agentTypeID: 0 76 | agentRadius: 0.5 77 | agentHeight: 2 78 | agentSlope: 45 79 | agentClimb: 0.75 80 | ledgeDropHeight: 0 81 | maxJumpAcrossDistance: 0 82 | minRegionArea: 2 83 | manualCellSize: 0 84 | cellSize: 0.16666667 85 | manualTileSize: 0 86 | tileSize: 256 87 | accuratePlacement: 0 88 | debug: 89 | m_Flags: 0 90 | m_SettingNames: 91 | - Humanoid 92 | -------------------------------------------------------------------------------- /Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.2d.sprite": "1.0.0", 4 | "com.unity.2d.tilemap": "1.0.0", 5 | "com.unity.ads": "3.7.1", 6 | "com.unity.analytics": "3.5.3", 7 | "com.unity.collab-proxy": "1.7.1", 8 | "com.unity.ide.rider": "2.0.7", 9 | "com.unity.ide.visualstudio": "2.0.9", 10 | "com.unity.ide.vscode": "1.2.3", 11 | "com.unity.purchasing": "3.2.2", 12 | "com.unity.test-framework": "1.1.27", 13 | "com.unity.textmeshpro": "3.0.6", 14 | "com.unity.timeline": "1.4.8", 15 | "com.unity.ugui": "1.0.0", 16 | "com.unity.xr.legacyinputhelpers": "2.1.7", 17 | "com.unity.modules.ai": "1.0.0", 18 | "com.unity.modules.androidjni": "1.0.0", 19 | "com.unity.modules.animation": "1.0.0", 20 | "com.unity.modules.assetbundle": "1.0.0", 21 | "com.unity.modules.audio": "1.0.0", 22 | "com.unity.modules.cloth": "1.0.0", 23 | "com.unity.modules.director": "1.0.0", 24 | "com.unity.modules.imageconversion": "1.0.0", 25 | "com.unity.modules.imgui": "1.0.0", 26 | "com.unity.modules.jsonserialize": "1.0.0", 27 | "com.unity.modules.particlesystem": "1.0.0", 28 | "com.unity.modules.physics": "1.0.0", 29 | "com.unity.modules.physics2d": "1.0.0", 30 | "com.unity.modules.screencapture": "1.0.0", 31 | "com.unity.modules.terrain": "1.0.0", 32 | "com.unity.modules.terrainphysics": "1.0.0", 33 | "com.unity.modules.tilemap": "1.0.0", 34 | "com.unity.modules.ui": "1.0.0", 35 | "com.unity.modules.uielements": "1.0.0", 36 | "com.unity.modules.umbra": "1.0.0", 37 | "com.unity.modules.unityanalytics": "1.0.0", 38 | "com.unity.modules.unitywebrequest": "1.0.0", 39 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 40 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 41 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 42 | "com.unity.modules.unitywebrequestwww": "1.0.0", 43 | "com.unity.modules.vehicles": "1.0.0", 44 | "com.unity.modules.video": "1.0.0", 45 | "com.unity.modules.vr": "1.0.0", 46 | "com.unity.modules.wind": "1.0.0", 47 | "com.unity.modules.xr": "1.0.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 12 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 38 | - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} 39 | - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} 40 | - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} 41 | m_PreloadedShaders: [] 42 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 43 | type: 0} 44 | m_CustomRenderPipeline: {fileID: 0} 45 | m_TransparencySortMode: 0 46 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 47 | m_DefaultRenderingPath: 1 48 | m_DefaultMobileRenderingPath: 1 49 | m_TierSettings: [] 50 | m_LightmapStripping: 0 51 | m_FogStripping: 0 52 | m_InstancingStripping: 0 53 | m_LightmapKeepPlain: 1 54 | m_LightmapKeepDirCombined: 1 55 | m_LightmapKeepDynamicPlain: 1 56 | m_LightmapKeepDynamicDirCombined: 1 57 | m_LightmapKeepShadowMask: 1 58 | m_LightmapKeepSubtractive: 1 59 | m_FogKeepLinear: 1 60 | m_FogKeepExp: 1 61 | m_FogKeepExp2: 1 62 | m_AlbedoSwatchInfos: [] 63 | m_LightsUseLinearIntensity: 0 64 | m_LightsUseColorTemperature: 0 65 | m_LogWhenShaderIsCompiled: 0 66 | -------------------------------------------------------------------------------- /Assets/Editor/LocalizeName.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using System.IO; 6 | using Strings.iOS.Xcode; 7 | 8 | namespace Strings 9 | { 10 | public class LocalizeName 11 | { 12 | public static void AddLocalizedStringsIOS(string projectPath, string localizedDirectoryPath) 13 | { 14 | DirectoryInfo dir = new DirectoryInfo(localizedDirectoryPath); 15 | if (!dir.Exists) 16 | return; 17 | 18 | List locales = new List(); 19 | var localeDirs = dir.GetDirectories("*.lproj", SearchOption.TopDirectoryOnly); 20 | 21 | foreach (var sub in localeDirs) 22 | locales.Add(Path.GetFileNameWithoutExtension(sub.Name)); 23 | 24 | AddLocalizedStringsIOS(projectPath, localizedDirectoryPath, locales); 25 | } 26 | 27 | public static void AddLocalizedStringsIOS(string projectPath, string localizedDirectoryPath, List validLocales) 28 | { 29 | string projPath = projectPath + "/Unity-iPhone.xcodeproj/project.pbxproj"; 30 | PBXProject proj = new PBXProject(); 31 | proj.ReadFromFile(projPath); 32 | proj.ClearVariantGroupEntries("InfoPlist.strings"); 33 | foreach (var locale in validLocales) 34 | { 35 | string src = Path.Combine(localizedDirectoryPath, locale + ".lproj"); 36 | DirectoryCopy(src, Path.Combine(projectPath, locale + ".lproj")); 37 | 38 | string fileRelatvePath = string.Format("{0}.lproj/InfoPlist.strings", locale); 39 | proj.AddLocalization("InfoPlist.strings", locale, fileRelatvePath); 40 | } 41 | 42 | proj.WriteToFile(projPath); 43 | } 44 | 45 | 46 | private static void DirectoryCopy(string sourceDirName, string destDirName) 47 | { 48 | DirectoryInfo dir = new DirectoryInfo(sourceDirName); 49 | 50 | if (!dir.Exists) 51 | return; 52 | 53 | if (!Directory.Exists(destDirName)) 54 | { 55 | Directory.CreateDirectory(destDirName); 56 | } 57 | 58 | FileInfo[] files = dir.GetFiles(); 59 | 60 | foreach (FileInfo file in files) 61 | { 62 | if (file.FullName.EndsWith(".meta")) 63 | continue; 64 | 65 | string temppath = Path.Combine(destDirName, file.Name); 66 | file.CopyTo(temppath, false); 67 | } 68 | 69 | DirectoryInfo[] dirs = dir.GetDirectories(); 70 | foreach (DirectoryInfo subdir in dirs) 71 | { 72 | string temppath = Path.Combine(destDirName, subdir.Name); 73 | DirectoryCopy(subdir.FullName, temppath); 74 | } 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Elements.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections; 3 | using System; 4 | 5 | 6 | namespace Strings.iOS.Xcode.PBX 7 | { 8 | 9 | class PBXElement 10 | { 11 | protected PBXElement() {} 12 | 13 | // convenience methods 14 | public string AsString() { return ((PBXElementString)this).value; } 15 | public PBXElementArray AsArray() { return (PBXElementArray)this; } 16 | public PBXElementDict AsDict() { return (PBXElementDict)this; } 17 | 18 | public PBXElement this[string key] 19 | { 20 | get { return AsDict()[key]; } 21 | set { AsDict()[key] = value; } 22 | } 23 | } 24 | 25 | class PBXElementString : PBXElement 26 | { 27 | public PBXElementString(string v) { value = v; } 28 | 29 | public string value; 30 | } 31 | 32 | class PBXElementDict : PBXElement 33 | { 34 | public PBXElementDict() : base() {} 35 | 36 | private Dictionary m_PrivateValue = new Dictionary(); 37 | public IDictionary values { get { return m_PrivateValue; }} 38 | 39 | new public PBXElement this[string key] 40 | { 41 | get { 42 | if (values.ContainsKey(key)) 43 | return values[key]; 44 | return null; 45 | } 46 | set { this.values[key] = value; } 47 | } 48 | 49 | public bool Contains(string key) 50 | { 51 | return values.ContainsKey(key); 52 | } 53 | 54 | public void Remove(string key) 55 | { 56 | values.Remove(key); 57 | } 58 | 59 | public void SetString(string key, string val) 60 | { 61 | values[key] = new PBXElementString(val); 62 | } 63 | 64 | public PBXElementArray CreateArray(string key) 65 | { 66 | var v = new PBXElementArray(); 67 | values[key] = v; 68 | return v; 69 | } 70 | 71 | public PBXElementDict CreateDict(string key) 72 | { 73 | var v = new PBXElementDict(); 74 | values[key] = v; 75 | return v; 76 | } 77 | } 78 | 79 | class PBXElementArray : PBXElement 80 | { 81 | public PBXElementArray() : base() {} 82 | public List values = new List(); 83 | 84 | // convenience methods 85 | public void AddString(string val) 86 | { 87 | values.Add(new PBXElementString(val)); 88 | } 89 | 90 | public PBXElementArray AddArray() 91 | { 92 | var v = new PBXElementArray(); 93 | values.Add(v); 94 | return v; 95 | } 96 | 97 | public PBXElementDict AddDict() 98 | { 99 | var v = new PBXElementDict(); 100 | values.Add(v); 101 | return v; 102 | } 103 | } 104 | 105 | } // namespace UnityEditor.iOS.Xcode 106 | 107 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBXPath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | using System.IO; 6 | 7 | namespace Strings.iOS.Xcode 8 | { 9 | internal class PBXPath 10 | { 11 | /// Replaces '\' with '/'. We need to apply this function to all paths that come from the user 12 | /// of the API because we store paths to pbxproj and on windows we may get path with '\' slashes 13 | /// instead of '/' slashes 14 | public static string FixSlashes(string path) 15 | { 16 | if (path == null) 17 | return null; 18 | return path.Replace('\\', '/'); 19 | } 20 | 21 | public static void Combine(string path1, PBXSourceTree tree1, string path2, PBXSourceTree tree2, 22 | out string resPath, out PBXSourceTree resTree) 23 | { 24 | if (tree2 == PBXSourceTree.Group) 25 | { 26 | resPath = Combine(path1, path2); 27 | resTree = tree1; 28 | return; 29 | } 30 | 31 | resPath = path2; 32 | resTree = tree2; 33 | } 34 | 35 | // Combines two paths 36 | public static string Combine(string path1, string path2) 37 | { 38 | if (path2.StartsWith("/")) 39 | return path2; 40 | if (path1.EndsWith("/")) 41 | return path1 + path2; 42 | if (path1 == "") 43 | return path2; 44 | if (path2 == "") 45 | return path1; 46 | return path1 + "/" + path2; 47 | } 48 | 49 | public static string GetDirectory(string path) 50 | { 51 | path = path.TrimEnd('/'); 52 | int pos = path.LastIndexOf('/'); 53 | if (pos == -1) 54 | return ""; 55 | else 56 | return path.Substring(0, pos); 57 | } 58 | 59 | public static string GetCurrentDirectory() 60 | { 61 | if (Environment.OSVersion.Platform != PlatformID.MacOSX && 62 | Environment.OSVersion.Platform != PlatformID.Unix) 63 | { 64 | throw new Exception("PBX project compatible current directory can only obtained on OSX"); 65 | } 66 | 67 | string path = Directory.GetCurrentDirectory(); 68 | path = FixSlashes(path); 69 | if (!IsPathRooted(path)) 70 | return "/" + path; 71 | return path; 72 | } 73 | 74 | public static string GetFilename(string path) 75 | { 76 | int pos = path.LastIndexOf('/'); 77 | if (pos == -1) 78 | return path; 79 | else 80 | return path.Substring(pos + 1); 81 | } 82 | 83 | public static bool IsPathRooted(string path) 84 | { 85 | if (path == null || path.Length == 0) 86 | return false; 87 | return path[0] == '/'; 88 | } 89 | 90 | public static string GetFullPath(string path) 91 | { 92 | if (IsPathRooted(path)) 93 | return path; 94 | else 95 | return Combine(GetCurrentDirectory(), path); 96 | } 97 | 98 | public static string[] Split(string path) 99 | { 100 | if (string.IsNullOrEmpty(path)) 101 | return new string[]{}; 102 | return path.Split(new[]{'/'}, StringSplitOptions.RemoveEmptyEntries); 103 | } 104 | } 105 | 106 | } // UnityEditor.iOS.Xcode 107 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Sections.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using System.IO; 7 | 8 | // Basr classes for section handling 9 | 10 | namespace Strings.iOS.Xcode.PBX 11 | { 12 | 13 | // common base 14 | internal abstract class SectionBase 15 | { 16 | public abstract void AddObject(string key, PBXElementDict value); 17 | public abstract void WriteSection(StringBuilder sb, GUIDToCommentMap comments); 18 | } 19 | 20 | // known section: contains objects that we care about 21 | internal class KnownSectionBase : SectionBase where T : PBXObjectData, new() 22 | { 23 | private Dictionary m_Entries = new Dictionary(); 24 | 25 | private string m_Name; 26 | 27 | public KnownSectionBase(string sectionName) 28 | { 29 | m_Name = sectionName; 30 | } 31 | 32 | public IEnumerable> GetEntries() 33 | { 34 | return m_Entries; 35 | } 36 | 37 | public IEnumerable GetGuids() 38 | { 39 | return m_Entries.Keys; 40 | } 41 | 42 | public IEnumerable GetObjects() 43 | { 44 | return m_Entries.Values; 45 | } 46 | 47 | public override void AddObject(string key, PBXElementDict value) 48 | { 49 | T obj = new T(); 50 | obj.guid = key; 51 | obj.SetPropertiesWhenSerializing(value); 52 | obj.UpdateVars(); 53 | m_Entries[obj.guid] = obj; 54 | } 55 | 56 | public override void WriteSection(StringBuilder sb, GUIDToCommentMap comments) 57 | { 58 | if (m_Entries.Count == 0) 59 | return; // do not write empty sections 60 | 61 | sb.AppendFormat("\n\n/* Begin {0} section */", m_Name); 62 | var keys = new List(m_Entries.Keys); 63 | keys.Sort(StringComparer.Ordinal); 64 | foreach (string key in keys) 65 | { 66 | T obj = m_Entries[key]; 67 | obj.UpdateProps(); 68 | sb.Append("\n\t\t"); 69 | comments.WriteStringBuilder(sb, obj.guid); 70 | sb.Append(" = "); 71 | Serializer.WriteDict(sb, obj.GetPropertiesWhenSerializing(), 2, 72 | obj.shouldCompact, obj.checker, comments); 73 | sb.Append(";"); 74 | } 75 | sb.AppendFormat("\n/* End {0} section */", m_Name); 76 | } 77 | 78 | // returns null if not found 79 | public T this[string guid] 80 | { 81 | get { 82 | if (m_Entries.ContainsKey(guid)) 83 | return m_Entries[guid]; 84 | return null; 85 | } 86 | } 87 | 88 | public bool HasEntry(string guid) 89 | { 90 | return m_Entries.ContainsKey(guid); 91 | } 92 | 93 | public void AddEntry(T obj) 94 | { 95 | m_Entries[obj.guid] = obj; 96 | } 97 | 98 | public void RemoveEntry(string guid) 99 | { 100 | if (m_Entries.ContainsKey(guid)) 101 | m_Entries.Remove(guid); 102 | } 103 | } 104 | 105 | // we assume there is only one PBXProject entry 106 | internal class PBXProjectSection : KnownSectionBase 107 | { 108 | public PBXProjectSection() : base("PBXProject") 109 | { 110 | } 111 | 112 | public PBXProjectObjectData project 113 | { 114 | get { 115 | foreach (var kv in GetEntries()) 116 | return kv.Value; 117 | return null; 118 | } 119 | } 120 | } 121 | 122 | } // UnityEditor.iOS.Xcode 123 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Parser.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.RegularExpressions; 3 | using System.IO; 4 | using System.Linq; 5 | using System; 6 | 7 | 8 | namespace Strings.iOS.Xcode.PBX 9 | { 10 | 11 | class ValueAST {} 12 | 13 | // IdentifierAST := \ 14 | class IdentifierAST : ValueAST 15 | { 16 | public int value = 0; // token id 17 | } 18 | 19 | // TreeAST := '{' KeyValuePairList '}' 20 | // KeyValuePairList := KeyValuePair ',' KeyValuePairList 21 | // KeyValuePair ',' 22 | // (empty) 23 | class TreeAST : ValueAST 24 | { 25 | public List values = new List(); 26 | } 27 | 28 | // ListAST := '(' ValueList ')' 29 | // ValueList := ValueAST ',' ValueList 30 | // ValueAST ',' 31 | // (empty) 32 | class ArrayAST : ValueAST 33 | { 34 | public List values = new List(); 35 | } 36 | 37 | // KeyValueAST := IdentifierAST '=' ValueAST ';' 38 | // ValueAST := IdentifierAST | TreeAST | ListAST 39 | class KeyValueAST 40 | { 41 | public IdentifierAST key = null; 42 | public ValueAST value = null; // either IdentifierAST, TreeAST or ListAST 43 | } 44 | 45 | class Parser 46 | { 47 | TokenList tokens; 48 | int currPos; 49 | 50 | public Parser(TokenList tokens) 51 | { 52 | this.tokens = tokens; 53 | currPos = SkipComments(0); 54 | } 55 | 56 | int SkipComments(int pos) 57 | { 58 | while (pos < tokens.Count && tokens[pos].type == TokenType.Comment) 59 | { 60 | pos++; 61 | } 62 | return pos; 63 | } 64 | 65 | // returns new position 66 | int IncInternal(int pos) 67 | { 68 | if (pos >= tokens.Count) 69 | return pos; 70 | pos++; 71 | 72 | return SkipComments(pos); 73 | } 74 | 75 | // Increments current pointer if not past the end, returns previous pos 76 | int Inc() 77 | { 78 | int prev = currPos; 79 | currPos = IncInternal(currPos); 80 | return prev; 81 | } 82 | 83 | // Returns the token type of the current token 84 | TokenType Tok() 85 | { 86 | if (currPos >= tokens.Count) 87 | return TokenType.EOF; 88 | return tokens[currPos].type; 89 | } 90 | 91 | void SkipIf(TokenType type) 92 | { 93 | if (Tok() == type) 94 | Inc(); 95 | } 96 | 97 | string GetErrorMsg() 98 | { 99 | return "Invalid PBX project (parsing line " + tokens[currPos].line + ")"; 100 | } 101 | 102 | public IdentifierAST ParseIdentifier() 103 | { 104 | if (Tok() != TokenType.String && Tok() != TokenType.QuotedString) 105 | throw new Exception(GetErrorMsg()); 106 | var ast = new IdentifierAST(); 107 | ast.value = Inc(); 108 | return ast; 109 | } 110 | 111 | public TreeAST ParseTree() 112 | { 113 | if (Tok() != TokenType.LBrace) 114 | throw new Exception(GetErrorMsg()); 115 | Inc(); 116 | 117 | var ast = new TreeAST(); 118 | while (Tok() != TokenType.RBrace && Tok() != TokenType.EOF) 119 | { 120 | ast.values.Add(ParseKeyValue()); 121 | } 122 | SkipIf(TokenType.RBrace); 123 | return ast; 124 | } 125 | 126 | public ArrayAST ParseList() 127 | { 128 | if (Tok() != TokenType.LParen) 129 | throw new Exception(GetErrorMsg()); 130 | Inc(); 131 | 132 | var ast = new ArrayAST(); 133 | while (Tok() != TokenType.RParen && Tok() != TokenType.EOF) 134 | { 135 | ast.values.Add(ParseValue()); 136 | SkipIf(TokenType.Comma); 137 | } 138 | SkipIf(TokenType.RParen); 139 | return ast; 140 | } 141 | 142 | // throws on error 143 | public KeyValueAST ParseKeyValue() 144 | { 145 | var ast = new KeyValueAST(); 146 | ast.key = ParseIdentifier(); 147 | 148 | if (Tok() != TokenType.Eq) 149 | throw new Exception(GetErrorMsg()); 150 | Inc(); // skip '=' 151 | 152 | ast.value = ParseValue(); 153 | SkipIf(TokenType.Semicolon); 154 | 155 | return ast; 156 | } 157 | 158 | // throws on error 159 | public ValueAST ParseValue() 160 | { 161 | if (Tok() == TokenType.String || Tok() == TokenType.QuotedString) 162 | return ParseIdentifier(); 163 | else if (Tok() == TokenType.LBrace) 164 | return ParseTree(); 165 | else if (Tok() == TokenType.LParen) 166 | return ParseList(); 167 | throw new Exception(GetErrorMsg()); 168 | } 169 | } 170 | 171 | } // namespace UnityEditor.iOS.Xcode -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 4 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Very Low 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 3 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | shadowmaskMode: 0 21 | blendWeights: 1 22 | textureQuality: 1 23 | anisotropicTextures: 0 24 | antiAliasing: 0 25 | softParticles: 0 26 | softVegetation: 0 27 | realtimeReflectionProbes: 0 28 | billboardsFaceCameraPosition: 0 29 | vSyncCount: 0 30 | lodBias: 0.3 31 | maximumLODLevel: 0 32 | particleRaycastBudget: 4 33 | asyncUploadTimeSlice: 2 34 | asyncUploadBufferSize: 16 35 | resolutionScalingFixedDPIFactor: 1 36 | excludedTargetPlatforms: [] 37 | - serializedVersion: 2 38 | name: Low 39 | pixelLightCount: 0 40 | shadows: 0 41 | shadowResolution: 0 42 | shadowProjection: 1 43 | shadowCascades: 1 44 | shadowDistance: 20 45 | shadowNearPlaneOffset: 3 46 | shadowCascade2Split: 0.33333334 47 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 48 | shadowmaskMode: 0 49 | blendWeights: 2 50 | textureQuality: 0 51 | anisotropicTextures: 0 52 | antiAliasing: 0 53 | softParticles: 0 54 | softVegetation: 0 55 | realtimeReflectionProbes: 0 56 | billboardsFaceCameraPosition: 0 57 | vSyncCount: 0 58 | lodBias: 0.4 59 | maximumLODLevel: 0 60 | particleRaycastBudget: 16 61 | asyncUploadTimeSlice: 2 62 | asyncUploadBufferSize: 16 63 | resolutionScalingFixedDPIFactor: 1 64 | excludedTargetPlatforms: [] 65 | - serializedVersion: 2 66 | name: Medium 67 | pixelLightCount: 1 68 | shadows: 1 69 | shadowResolution: 0 70 | shadowProjection: 1 71 | shadowCascades: 1 72 | shadowDistance: 20 73 | shadowNearPlaneOffset: 3 74 | shadowCascade2Split: 0.33333334 75 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 76 | shadowmaskMode: 0 77 | blendWeights: 2 78 | textureQuality: 0 79 | anisotropicTextures: 1 80 | antiAliasing: 0 81 | softParticles: 0 82 | softVegetation: 0 83 | realtimeReflectionProbes: 0 84 | billboardsFaceCameraPosition: 0 85 | vSyncCount: 1 86 | lodBias: 0.7 87 | maximumLODLevel: 0 88 | particleRaycastBudget: 64 89 | asyncUploadTimeSlice: 2 90 | asyncUploadBufferSize: 16 91 | resolutionScalingFixedDPIFactor: 1 92 | excludedTargetPlatforms: [] 93 | - serializedVersion: 2 94 | name: High 95 | pixelLightCount: 2 96 | shadows: 2 97 | shadowResolution: 1 98 | shadowProjection: 1 99 | shadowCascades: 2 100 | shadowDistance: 40 101 | shadowNearPlaneOffset: 3 102 | shadowCascade2Split: 0.33333334 103 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 104 | shadowmaskMode: 1 105 | blendWeights: 2 106 | textureQuality: 0 107 | anisotropicTextures: 1 108 | antiAliasing: 2 109 | softParticles: 0 110 | softVegetation: 1 111 | realtimeReflectionProbes: 1 112 | billboardsFaceCameraPosition: 1 113 | vSyncCount: 1 114 | lodBias: 1 115 | maximumLODLevel: 0 116 | particleRaycastBudget: 256 117 | asyncUploadTimeSlice: 2 118 | asyncUploadBufferSize: 16 119 | resolutionScalingFixedDPIFactor: 1 120 | excludedTargetPlatforms: [] 121 | - serializedVersion: 2 122 | name: Very High 123 | pixelLightCount: 3 124 | shadows: 2 125 | shadowResolution: 2 126 | shadowProjection: 1 127 | shadowCascades: 2 128 | shadowDistance: 40 129 | shadowNearPlaneOffset: 3 130 | shadowCascade2Split: 0.33333334 131 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 132 | shadowmaskMode: 1 133 | blendWeights: 4 134 | textureQuality: 0 135 | anisotropicTextures: 1 136 | antiAliasing: 4 137 | softParticles: 1 138 | softVegetation: 1 139 | realtimeReflectionProbes: 1 140 | billboardsFaceCameraPosition: 1 141 | vSyncCount: 1 142 | lodBias: 1.5 143 | maximumLODLevel: 0 144 | particleRaycastBudget: 1024 145 | asyncUploadTimeSlice: 2 146 | asyncUploadBufferSize: 16 147 | resolutionScalingFixedDPIFactor: 1 148 | excludedTargetPlatforms: [] 149 | - serializedVersion: 2 150 | name: Ultra 151 | pixelLightCount: 4 152 | shadows: 2 153 | shadowResolution: 2 154 | shadowProjection: 1 155 | shadowCascades: 4 156 | shadowDistance: 150 157 | shadowNearPlaneOffset: 3 158 | shadowCascade2Split: 0.33333334 159 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 160 | shadowmaskMode: 1 161 | blendWeights: 4 162 | textureQuality: 0 163 | anisotropicTextures: 1 164 | antiAliasing: 4 165 | softParticles: 1 166 | softVegetation: 1 167 | realtimeReflectionProbes: 1 168 | billboardsFaceCameraPosition: 1 169 | vSyncCount: 1 170 | lodBias: 2 171 | maximumLODLevel: 0 172 | particleRaycastBudget: 4096 173 | asyncUploadTimeSlice: 2 174 | asyncUploadBufferSize: 16 175 | resolutionScalingFixedDPIFactor: 1 176 | excludedTargetPlatforms: [] 177 | m_PerPlatformDefaultQuality: 178 | Android: 2 179 | Nintendo 3DS: 5 180 | Nintendo Switch: 5 181 | PS4: 5 182 | PSP2: 2 183 | Standalone: 5 184 | Tizen: 2 185 | WebGL: 3 186 | WiiU: 5 187 | Windows Store Apps: 5 188 | XboxOne: 5 189 | iPhone: 2 190 | tvOS: 2 191 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBXCapabilityType.cs: -------------------------------------------------------------------------------- 1 | namespace Strings.iOS.Xcode 2 | { 3 | /// 4 | /// List of all the capabilities available. 5 | /// 6 | public sealed class PBXCapabilityType 7 | { 8 | public static readonly PBXCapabilityType ApplePay = new PBXCapabilityType ("com.apple.ApplePay", true); 9 | public static readonly PBXCapabilityType AppGroups = new PBXCapabilityType ("com.apple.ApplicationGroups.iOS", true); 10 | public static readonly PBXCapabilityType AssociatedDomains = new PBXCapabilityType ("com.apple.SafariKeychain", true); 11 | public static readonly PBXCapabilityType BackgroundModes = new PBXCapabilityType ("com.apple.BackgroundModes", false); 12 | public static readonly PBXCapabilityType DataProtection = new PBXCapabilityType ("com.apple.DataProtection", true); 13 | public static readonly PBXCapabilityType GameCenter = new PBXCapabilityType ("com.apple.GameCenter", false, "GameKit.framework"); 14 | public static readonly PBXCapabilityType HealthKit = new PBXCapabilityType ("com.apple.HealthKit", true, "HealthKit.framework"); 15 | public static readonly PBXCapabilityType HomeKit = new PBXCapabilityType ("com.apple.HomeKit", true, "HomeKit.framework"); 16 | public static readonly PBXCapabilityType iCloud = new PBXCapabilityType("com.apple.iCloud", true, "CloudKit.framework", true); 17 | public static readonly PBXCapabilityType InAppPurchase = new PBXCapabilityType ("com.apple.InAppPurchase", false); 18 | public static readonly PBXCapabilityType InterAppAudio = new PBXCapabilityType ("com.apple.InterAppAudio", true, "AudioToolbox.framework"); 19 | public static readonly PBXCapabilityType KeychainSharing = new PBXCapabilityType ("com.apple.KeychainSharing", true); 20 | public static readonly PBXCapabilityType Maps = new PBXCapabilityType("com.apple.Maps.iOS", false, "MapKit.framework"); 21 | public static readonly PBXCapabilityType PersonalVPN = new PBXCapabilityType("com.apple.VPNLite", true, "NetworkExtension.framework"); 22 | public static readonly PBXCapabilityType PushNotifications = new PBXCapabilityType ("com.apple.Push", true); 23 | public static readonly PBXCapabilityType Siri = new PBXCapabilityType ("com.apple.Siri", true); 24 | public static readonly PBXCapabilityType Wallet = new PBXCapabilityType ("com.apple.Wallet", true, "PassKit.framework"); 25 | public static readonly PBXCapabilityType WirelessAccessoryConfiguration = new PBXCapabilityType("com.apple.WAC", true, "ExternalAccessory.framework"); 26 | 27 | private readonly string m_ID; 28 | private readonly bool m_RequiresEntitlements; 29 | private readonly string m_Framework; 30 | private readonly bool m_OptionalFramework; 31 | 32 | public bool optionalFramework 33 | { 34 | get { return m_OptionalFramework; } 35 | } 36 | 37 | public string framework 38 | { 39 | get { return m_Framework; } 40 | } 41 | 42 | public string id 43 | { 44 | get { return m_ID; } 45 | } 46 | 47 | public bool requiresEntitlements 48 | { 49 | get { return m_RequiresEntitlements; } 50 | } 51 | 52 | public struct TargetCapabilityPair 53 | { 54 | public string targetGuid; 55 | public PBXCapabilityType capability; 56 | 57 | public TargetCapabilityPair(string guid, PBXCapabilityType type) 58 | { 59 | targetGuid = guid; 60 | capability = type; 61 | } 62 | } 63 | 64 | /// 65 | /// This private object represents what a capability changes in the PBXProject file 66 | /// 67 | /// The string used in the PBXProject file to identify the capability and mark it as enabled. 68 | /// This capability requires an entitlements file therefore we need to add this entitlements file to the code signing entitlement. 69 | /// Specify which framework need to be added to the project for this capability, if "" no framework are added. 70 | /// Some capability (right now only iCloud) adds a framework, not all the time but just when some option are checked 71 | /// this parameter indicates if one of them is checked. 72 | private PBXCapabilityType(string _id, bool _requiresEntitlements, string _framework = "", bool _optionalFramework = false) 73 | { 74 | m_ID = _id; 75 | m_RequiresEntitlements = _requiresEntitlements; 76 | m_Framework = _framework; 77 | m_OptionalFramework = _optionalFramework; 78 | } 79 | 80 | public static PBXCapabilityType StringToPBXCapabilityType(string cap) 81 | { 82 | switch (cap) 83 | { 84 | case "com.apple.ApplePay": 85 | return ApplePay; 86 | case "com.apple.ApplicationGroups.iOS": 87 | return AppGroups; 88 | case "com.apple.SafariKeychain": 89 | return AssociatedDomains; 90 | case "com.apple.BackgroundModes": 91 | return BackgroundModes; 92 | case "com.apple.DataProtection": 93 | return DataProtection; 94 | case "com.apple.GameCenter": 95 | return GameCenter; 96 | case "com.apple.HealthKit": 97 | return HealthKit; 98 | case "com.apple.HomeKit": 99 | return HomeKit; 100 | case "com.apple.iCloud": 101 | return iCloud; 102 | case "com.apple.InAppPurchase": 103 | return InAppPurchase; 104 | case "com.apple.InterAppAudio": 105 | return InterAppAudio; 106 | case "com.apple.KeychainSharing": 107 | return KeychainSharing; 108 | case "com.apple.Maps.iOS": 109 | return Maps; 110 | case "com.apple.VPNLite": 111 | return PersonalVPN; 112 | case "com.apple.Push": 113 | return PushNotifications; 114 | case "com.apple.Siri": 115 | return Siri; 116 | case "com.apple.Wallet": 117 | return Wallet; 118 | case "WAC": 119 | return WirelessAccessoryConfiguration; 120 | default: 121 | return null; 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!13 &1 4 | InputManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Axes: 8 | - serializedVersion: 3 9 | m_Name: Horizontal 10 | descriptiveName: 11 | descriptiveNegativeName: 12 | negativeButton: left 13 | positiveButton: right 14 | altNegativeButton: a 15 | altPositiveButton: d 16 | gravity: 3 17 | dead: 0.001 18 | sensitivity: 3 19 | snap: 1 20 | invert: 0 21 | type: 0 22 | axis: 0 23 | joyNum: 0 24 | - serializedVersion: 3 25 | m_Name: Vertical 26 | descriptiveName: 27 | descriptiveNegativeName: 28 | negativeButton: down 29 | positiveButton: up 30 | altNegativeButton: s 31 | altPositiveButton: w 32 | gravity: 3 33 | dead: 0.001 34 | sensitivity: 3 35 | snap: 1 36 | invert: 0 37 | type: 0 38 | axis: 0 39 | joyNum: 0 40 | - serializedVersion: 3 41 | m_Name: Fire1 42 | descriptiveName: 43 | descriptiveNegativeName: 44 | negativeButton: 45 | positiveButton: left ctrl 46 | altNegativeButton: 47 | altPositiveButton: mouse 0 48 | gravity: 1000 49 | dead: 0.001 50 | sensitivity: 1000 51 | snap: 0 52 | invert: 0 53 | type: 0 54 | axis: 0 55 | joyNum: 0 56 | - serializedVersion: 3 57 | m_Name: Fire2 58 | descriptiveName: 59 | descriptiveNegativeName: 60 | negativeButton: 61 | positiveButton: left alt 62 | altNegativeButton: 63 | altPositiveButton: mouse 1 64 | gravity: 1000 65 | dead: 0.001 66 | sensitivity: 1000 67 | snap: 0 68 | invert: 0 69 | type: 0 70 | axis: 0 71 | joyNum: 0 72 | - serializedVersion: 3 73 | m_Name: Fire3 74 | descriptiveName: 75 | descriptiveNegativeName: 76 | negativeButton: 77 | positiveButton: left shift 78 | altNegativeButton: 79 | altPositiveButton: mouse 2 80 | gravity: 1000 81 | dead: 0.001 82 | sensitivity: 1000 83 | snap: 0 84 | invert: 0 85 | type: 0 86 | axis: 0 87 | joyNum: 0 88 | - serializedVersion: 3 89 | m_Name: Jump 90 | descriptiveName: 91 | descriptiveNegativeName: 92 | negativeButton: 93 | positiveButton: space 94 | altNegativeButton: 95 | altPositiveButton: 96 | gravity: 1000 97 | dead: 0.001 98 | sensitivity: 1000 99 | snap: 0 100 | invert: 0 101 | type: 0 102 | axis: 0 103 | joyNum: 0 104 | - serializedVersion: 3 105 | m_Name: Mouse X 106 | descriptiveName: 107 | descriptiveNegativeName: 108 | negativeButton: 109 | positiveButton: 110 | altNegativeButton: 111 | altPositiveButton: 112 | gravity: 0 113 | dead: 0 114 | sensitivity: 0.1 115 | snap: 0 116 | invert: 0 117 | type: 1 118 | axis: 0 119 | joyNum: 0 120 | - serializedVersion: 3 121 | m_Name: Mouse Y 122 | descriptiveName: 123 | descriptiveNegativeName: 124 | negativeButton: 125 | positiveButton: 126 | altNegativeButton: 127 | altPositiveButton: 128 | gravity: 0 129 | dead: 0 130 | sensitivity: 0.1 131 | snap: 0 132 | invert: 0 133 | type: 1 134 | axis: 1 135 | joyNum: 0 136 | - serializedVersion: 3 137 | m_Name: Mouse ScrollWheel 138 | descriptiveName: 139 | descriptiveNegativeName: 140 | negativeButton: 141 | positiveButton: 142 | altNegativeButton: 143 | altPositiveButton: 144 | gravity: 0 145 | dead: 0 146 | sensitivity: 0.1 147 | snap: 0 148 | invert: 0 149 | type: 1 150 | axis: 2 151 | joyNum: 0 152 | - serializedVersion: 3 153 | m_Name: Horizontal 154 | descriptiveName: 155 | descriptiveNegativeName: 156 | negativeButton: 157 | positiveButton: 158 | altNegativeButton: 159 | altPositiveButton: 160 | gravity: 0 161 | dead: 0.19 162 | sensitivity: 1 163 | snap: 0 164 | invert: 0 165 | type: 2 166 | axis: 0 167 | joyNum: 0 168 | - serializedVersion: 3 169 | m_Name: Vertical 170 | descriptiveName: 171 | descriptiveNegativeName: 172 | negativeButton: 173 | positiveButton: 174 | altNegativeButton: 175 | altPositiveButton: 176 | gravity: 0 177 | dead: 0.19 178 | sensitivity: 1 179 | snap: 0 180 | invert: 1 181 | type: 2 182 | axis: 1 183 | joyNum: 0 184 | - serializedVersion: 3 185 | m_Name: Fire1 186 | descriptiveName: 187 | descriptiveNegativeName: 188 | negativeButton: 189 | positiveButton: joystick button 0 190 | altNegativeButton: 191 | altPositiveButton: 192 | gravity: 1000 193 | dead: 0.001 194 | sensitivity: 1000 195 | snap: 0 196 | invert: 0 197 | type: 0 198 | axis: 0 199 | joyNum: 0 200 | - serializedVersion: 3 201 | m_Name: Fire2 202 | descriptiveName: 203 | descriptiveNegativeName: 204 | negativeButton: 205 | positiveButton: joystick button 1 206 | altNegativeButton: 207 | altPositiveButton: 208 | gravity: 1000 209 | dead: 0.001 210 | sensitivity: 1000 211 | snap: 0 212 | invert: 0 213 | type: 0 214 | axis: 0 215 | joyNum: 0 216 | - serializedVersion: 3 217 | m_Name: Fire3 218 | descriptiveName: 219 | descriptiveNegativeName: 220 | negativeButton: 221 | positiveButton: joystick button 2 222 | altNegativeButton: 223 | altPositiveButton: 224 | gravity: 1000 225 | dead: 0.001 226 | sensitivity: 1000 227 | snap: 0 228 | invert: 0 229 | type: 0 230 | axis: 0 231 | joyNum: 0 232 | - serializedVersion: 3 233 | m_Name: Jump 234 | descriptiveName: 235 | descriptiveNegativeName: 236 | negativeButton: 237 | positiveButton: joystick button 3 238 | altNegativeButton: 239 | altPositiveButton: 240 | gravity: 1000 241 | dead: 0.001 242 | sensitivity: 1000 243 | snap: 0 244 | invert: 0 245 | type: 0 246 | axis: 0 247 | joyNum: 0 248 | - serializedVersion: 3 249 | m_Name: Submit 250 | descriptiveName: 251 | descriptiveNegativeName: 252 | negativeButton: 253 | positiveButton: return 254 | altNegativeButton: 255 | altPositiveButton: joystick button 0 256 | gravity: 1000 257 | dead: 0.001 258 | sensitivity: 1000 259 | snap: 0 260 | invert: 0 261 | type: 0 262 | axis: 0 263 | joyNum: 0 264 | - serializedVersion: 3 265 | m_Name: Submit 266 | descriptiveName: 267 | descriptiveNegativeName: 268 | negativeButton: 269 | positiveButton: enter 270 | altNegativeButton: 271 | altPositiveButton: space 272 | gravity: 1000 273 | dead: 0.001 274 | sensitivity: 1000 275 | snap: 0 276 | invert: 0 277 | type: 0 278 | axis: 0 279 | joyNum: 0 280 | - serializedVersion: 3 281 | m_Name: Cancel 282 | descriptiveName: 283 | descriptiveNegativeName: 284 | negativeButton: 285 | positiveButton: escape 286 | altNegativeButton: 287 | altPositiveButton: joystick button 1 288 | gravity: 1000 289 | dead: 0.001 290 | sensitivity: 1000 291 | snap: 0 292 | invert: 0 293 | type: 0 294 | axis: 0 295 | joyNum: 0 296 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Lexer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.RegularExpressions; 3 | using System.IO; 4 | using System.Linq; 5 | using System; 6 | 7 | 8 | namespace Strings.iOS.Xcode.PBX 9 | { 10 | enum TokenType 11 | { 12 | EOF, 13 | Invalid, 14 | String, 15 | QuotedString, 16 | Comment, 17 | 18 | Semicolon, // ; 19 | Comma, // , 20 | Eq, // = 21 | LParen, // ( 22 | RParen, // ) 23 | LBrace, // { 24 | RBrace, // } 25 | } 26 | 27 | class Token 28 | { 29 | public TokenType type; 30 | 31 | // the line of the input stream the token starts in (0-based) 32 | public int line; 33 | 34 | // start and past-the-end positions of the token in the input stream 35 | public int begin, end; 36 | } 37 | 38 | class TokenList : List 39 | { 40 | } 41 | 42 | class Lexer 43 | { 44 | string text; 45 | int pos; 46 | int length; 47 | int line; 48 | 49 | public static TokenList Tokenize(string text) 50 | { 51 | var lexer = new Lexer(); 52 | lexer.SetText(text); 53 | return lexer.ScanAll(); 54 | } 55 | 56 | public void SetText(string text) 57 | { 58 | this.text = text + " "; // to prevent out-of-bounds access during look ahead 59 | pos = 0; 60 | length = text.Length; 61 | line = 0; 62 | } 63 | 64 | public TokenList ScanAll() 65 | { 66 | var tokens = new TokenList(); 67 | 68 | while (true) 69 | { 70 | var tok = new Token(); 71 | ScanOne(tok); 72 | tokens.Add(tok); 73 | if (tok.type == TokenType.EOF) 74 | break; 75 | } 76 | return tokens; 77 | } 78 | 79 | void UpdateNewlineStats(char ch) 80 | { 81 | if (ch == '\n') 82 | line++; 83 | } 84 | 85 | // tokens list is modified in the case when we add BrokenLine token and need to remove already 86 | // added tokens for the current line 87 | void ScanOne(Token tok) 88 | { 89 | while (true) 90 | { 91 | while (pos < length && Char.IsWhiteSpace(text[pos])) 92 | { 93 | UpdateNewlineStats(text[pos]); 94 | pos++; 95 | } 96 | 97 | if (pos >= length) 98 | { 99 | tok.type = TokenType.EOF; 100 | break; 101 | } 102 | 103 | char ch = text[pos]; 104 | char ch2 = text[pos+1]; 105 | 106 | if (ch == '\"') 107 | ScanQuotedString(tok); 108 | else if (ch == '/' && ch2 == '*') 109 | ScanMultilineComment(tok); 110 | else if (ch == '/' && ch2 == '/') 111 | ScanComment(tok); 112 | else if (IsOperator(ch)) 113 | ScanOperator(tok); 114 | else 115 | ScanString(tok); // be more robust and accept whatever is left 116 | return; 117 | } 118 | } 119 | 120 | void ScanString(Token tok) 121 | { 122 | tok.type = TokenType.String; 123 | tok.begin = pos; 124 | while (pos < length) 125 | { 126 | char ch = text[pos]; 127 | char ch2 = text[pos+1]; 128 | 129 | if (Char.IsWhiteSpace(ch)) 130 | break; 131 | else if (ch == '\"') 132 | break; 133 | else if (ch == '/' && ch2 == '*') 134 | break; 135 | else if (ch == '/' && ch2 == '/') 136 | break; 137 | else if (IsOperator(ch)) 138 | break; 139 | pos++; 140 | } 141 | tok.end = pos; 142 | tok.line = line; 143 | } 144 | 145 | void ScanQuotedString(Token tok) 146 | { 147 | tok.type = TokenType.QuotedString; 148 | tok.begin = pos; 149 | pos++; 150 | 151 | while (pos < length) 152 | { 153 | // ignore escaped quotes 154 | if (text[pos] == '\\' && text[pos+1] == '\"') 155 | { 156 | pos += 2; 157 | continue; 158 | } 159 | 160 | // note that we close unclosed quotes 161 | if (text[pos] == '\"') 162 | break; 163 | 164 | UpdateNewlineStats(text[pos]); 165 | pos++; 166 | } 167 | pos++; 168 | tok.end = pos; 169 | tok.line = line; 170 | } 171 | 172 | void ScanMultilineComment(Token tok) 173 | { 174 | tok.type = TokenType.Comment; 175 | tok.begin = pos; 176 | pos += 2; 177 | 178 | while (pos < length) 179 | { 180 | if (text[pos] == '*' && text[pos+1] == '/') 181 | break; 182 | 183 | // we support multiline comments 184 | UpdateNewlineStats(text[pos]); 185 | pos++; 186 | } 187 | pos += 2; 188 | tok.end = pos; 189 | tok.line = line; 190 | } 191 | 192 | void ScanComment(Token tok) 193 | { 194 | tok.type = TokenType.Comment; 195 | tok.begin = pos; 196 | pos += 2; 197 | 198 | while (pos < length) 199 | { 200 | if (text[pos] == '\n') 201 | break; 202 | pos++; 203 | } 204 | UpdateNewlineStats(text[pos]); 205 | pos++; 206 | tok.end = pos; 207 | tok.line = line; 208 | } 209 | 210 | bool IsOperator(char ch) 211 | { 212 | if (ch == ';' || ch == ',' || ch == '=' || ch == '(' || ch == ')' || ch == '{' || ch == '}') 213 | return true; 214 | return false; 215 | } 216 | 217 | void ScanOperator(Token tok) 218 | { 219 | switch (text[pos]) 220 | { 221 | case ';': ScanOperatorSpecific(tok, TokenType.Semicolon); return; 222 | case ',': ScanOperatorSpecific(tok, TokenType.Comma); return; 223 | case '=': ScanOperatorSpecific(tok, TokenType.Eq); return; 224 | case '(': ScanOperatorSpecific(tok, TokenType.LParen); return; 225 | case ')': ScanOperatorSpecific(tok, TokenType.RParen); return; 226 | case '{': ScanOperatorSpecific(tok, TokenType.LBrace); return; 227 | case '}': ScanOperatorSpecific(tok, TokenType.RBrace); return; 228 | default: return; 229 | } 230 | } 231 | 232 | void ScanOperatorSpecific(Token tok, TokenType type) 233 | { 234 | tok.type = type; 235 | tok.begin = pos; 236 | pos++; 237 | tok.end = pos; 238 | tok.line = line; 239 | } 240 | } 241 | 242 | 243 | } // namespace UnityEditor.iOS.Xcode -------------------------------------------------------------------------------- /Assets/Scenes/SampleScene.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 170076734} 41 | m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!157 &3 44 | LightmapSettings: 45 | m_ObjectHideFlags: 0 46 | serializedVersion: 11 47 | m_GIWorkflowMode: 0 48 | m_GISettings: 49 | serializedVersion: 2 50 | m_BounceScale: 1 51 | m_IndirectOutputScale: 1 52 | m_AlbedoBoost: 1 53 | m_TemporalCoherenceThreshold: 1 54 | m_EnvironmentLightingMode: 0 55 | m_EnableBakedLightmaps: 1 56 | m_EnableRealtimeLightmaps: 0 57 | m_LightmapEditorSettings: 58 | serializedVersion: 10 59 | m_Resolution: 2 60 | m_BakeResolution: 10 61 | m_AtlasSize: 512 62 | m_AO: 0 63 | m_AOMaxDistance: 1 64 | m_CompAOExponent: 1 65 | m_CompAOExponentDirect: 0 66 | m_Padding: 2 67 | m_LightmapParameters: {fileID: 0} 68 | m_LightmapsBakeMode: 1 69 | m_TextureCompression: 1 70 | m_FinalGather: 0 71 | m_FinalGatherFiltering: 1 72 | m_FinalGatherRayCount: 256 73 | m_ReflectionCompression: 2 74 | m_MixedBakeMode: 2 75 | m_BakeBackend: 1 76 | m_PVRSampling: 1 77 | m_PVRDirectSampleCount: 32 78 | m_PVRSampleCount: 256 79 | m_PVRBounces: 2 80 | m_PVRFilterTypeDirect: 0 81 | m_PVRFilterTypeIndirect: 0 82 | m_PVRFilterTypeAO: 0 83 | m_PVRFilteringMode: 1 84 | m_PVRCulling: 1 85 | m_PVRFilteringGaussRadiusDirect: 1 86 | m_PVRFilteringGaussRadiusIndirect: 5 87 | m_PVRFilteringGaussRadiusAO: 2 88 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 89 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 90 | m_PVRFilteringAtrousPositionSigmaAO: 1 91 | m_ShowResolutionOverlay: 1 92 | m_LightingDataAsset: {fileID: 0} 93 | m_UseShadowmask: 1 94 | --- !u!196 &4 95 | NavMeshSettings: 96 | serializedVersion: 2 97 | m_ObjectHideFlags: 0 98 | m_BuildSettings: 99 | serializedVersion: 2 100 | agentTypeID: 0 101 | agentRadius: 0.5 102 | agentHeight: 2 103 | agentSlope: 45 104 | agentClimb: 0.4 105 | ledgeDropHeight: 0 106 | maxJumpAcrossDistance: 0 107 | minRegionArea: 2 108 | manualCellSize: 0 109 | cellSize: 0.16666667 110 | manualTileSize: 0 111 | tileSize: 256 112 | accuratePlacement: 0 113 | debug: 114 | m_Flags: 0 115 | m_NavMeshData: {fileID: 0} 116 | --- !u!1 &170076733 117 | GameObject: 118 | m_ObjectHideFlags: 0 119 | m_CorrespondingSourceObject: {fileID: 0} 120 | m_PrefabInternal: {fileID: 0} 121 | serializedVersion: 6 122 | m_Component: 123 | - component: {fileID: 170076735} 124 | - component: {fileID: 170076734} 125 | m_Layer: 0 126 | m_Name: Directional Light 127 | m_TagString: Untagged 128 | m_Icon: {fileID: 0} 129 | m_NavMeshLayer: 0 130 | m_StaticEditorFlags: 0 131 | m_IsActive: 1 132 | --- !u!108 &170076734 133 | Light: 134 | m_ObjectHideFlags: 0 135 | m_CorrespondingSourceObject: {fileID: 0} 136 | m_PrefabInternal: {fileID: 0} 137 | m_GameObject: {fileID: 170076733} 138 | m_Enabled: 1 139 | serializedVersion: 8 140 | m_Type: 1 141 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 142 | m_Intensity: 1 143 | m_Range: 10 144 | m_SpotAngle: 30 145 | m_CookieSize: 10 146 | m_Shadows: 147 | m_Type: 2 148 | m_Resolution: -1 149 | m_CustomResolution: -1 150 | m_Strength: 1 151 | m_Bias: 0.05 152 | m_NormalBias: 0.4 153 | m_NearPlane: 0.2 154 | m_Cookie: {fileID: 0} 155 | m_DrawHalo: 0 156 | m_Flare: {fileID: 0} 157 | m_RenderMode: 0 158 | m_CullingMask: 159 | serializedVersion: 2 160 | m_Bits: 4294967295 161 | m_Lightmapping: 1 162 | m_LightShadowCasterMode: 0 163 | m_AreaSize: {x: 1, y: 1} 164 | m_BounceIntensity: 1 165 | m_ColorTemperature: 6570 166 | m_UseColorTemperature: 0 167 | m_ShadowRadius: 0 168 | m_ShadowAngle: 0 169 | --- !u!4 &170076735 170 | Transform: 171 | m_ObjectHideFlags: 0 172 | m_CorrespondingSourceObject: {fileID: 0} 173 | m_PrefabInternal: {fileID: 0} 174 | m_GameObject: {fileID: 170076733} 175 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} 176 | m_LocalPosition: {x: 0, y: 3, z: 0} 177 | m_LocalScale: {x: 1, y: 1, z: 1} 178 | m_Children: [] 179 | m_Father: {fileID: 0} 180 | m_RootOrder: 1 181 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} 182 | --- !u!1 &534669902 183 | GameObject: 184 | m_ObjectHideFlags: 0 185 | m_CorrespondingSourceObject: {fileID: 0} 186 | m_PrefabInternal: {fileID: 0} 187 | serializedVersion: 6 188 | m_Component: 189 | - component: {fileID: 534669905} 190 | - component: {fileID: 534669904} 191 | - component: {fileID: 534669903} 192 | m_Layer: 0 193 | m_Name: Main Camera 194 | m_TagString: MainCamera 195 | m_Icon: {fileID: 0} 196 | m_NavMeshLayer: 0 197 | m_StaticEditorFlags: 0 198 | m_IsActive: 1 199 | --- !u!81 &534669903 200 | AudioListener: 201 | m_ObjectHideFlags: 0 202 | m_CorrespondingSourceObject: {fileID: 0} 203 | m_PrefabInternal: {fileID: 0} 204 | m_GameObject: {fileID: 534669902} 205 | m_Enabled: 1 206 | --- !u!20 &534669904 207 | Camera: 208 | m_ObjectHideFlags: 0 209 | m_CorrespondingSourceObject: {fileID: 0} 210 | m_PrefabInternal: {fileID: 0} 211 | m_GameObject: {fileID: 534669902} 212 | m_Enabled: 1 213 | serializedVersion: 2 214 | m_ClearFlags: 1 215 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 216 | m_projectionMatrixMode: 1 217 | m_SensorSize: {x: 36, y: 24} 218 | m_LensShift: {x: 0, y: 0} 219 | m_GateFitMode: 2 220 | m_FocalLength: 50 221 | m_NormalizedViewPortRect: 222 | serializedVersion: 2 223 | x: 0 224 | y: 0 225 | width: 1 226 | height: 1 227 | near clip plane: 0.3 228 | far clip plane: 1000 229 | field of view: 60 230 | orthographic: 0 231 | orthographic size: 5 232 | m_Depth: -1 233 | m_CullingMask: 234 | serializedVersion: 2 235 | m_Bits: 4294967295 236 | m_RenderingPath: -1 237 | m_TargetTexture: {fileID: 0} 238 | m_TargetDisplay: 0 239 | m_TargetEye: 3 240 | m_HDR: 1 241 | m_AllowMSAA: 1 242 | m_AllowDynamicResolution: 0 243 | m_ForceIntoRT: 0 244 | m_OcclusionCulling: 1 245 | m_StereoConvergence: 10 246 | m_StereoSeparation: 0.022 247 | --- !u!4 &534669905 248 | Transform: 249 | m_ObjectHideFlags: 0 250 | m_CorrespondingSourceObject: {fileID: 0} 251 | m_PrefabInternal: {fileID: 0} 252 | m_GameObject: {fileID: 534669902} 253 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 254 | m_LocalPosition: {x: 0, y: 1, z: -10} 255 | m_LocalScale: {x: 1, y: 1, z: 1} 256 | m_Children: [] 257 | m_Father: {fileID: 0} 258 | m_RootOrder: 0 259 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 260 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/JsonParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using System.Linq; 6 | 7 | namespace Strings.iOS.Xcode 8 | { 9 | internal class JsonElement 10 | { 11 | protected JsonElement() {} 12 | 13 | // convenience methods 14 | public string AsString() { return ((JsonElementString)this).value; } 15 | public int AsInteger() { return ((JsonElementInteger)this).value; } 16 | public bool AsBoolean() { return ((JsonElementBoolean)this).value; } 17 | public JsonElementArray AsArray() { return (JsonElementArray)this; } 18 | public JsonElementDict AsDict() { return (JsonElementDict)this; } 19 | 20 | public JsonElement this[string key] 21 | { 22 | get { return AsDict()[key]; } 23 | set { AsDict()[key] = value; } 24 | } 25 | } 26 | 27 | internal class JsonElementString : JsonElement 28 | { 29 | public JsonElementString(string v) { value = v; } 30 | 31 | public string value; 32 | } 33 | 34 | internal class JsonElementInteger : JsonElement 35 | { 36 | public JsonElementInteger(int v) { value = v; } 37 | 38 | public int value; 39 | } 40 | 41 | internal class JsonElementBoolean : JsonElement 42 | { 43 | public JsonElementBoolean(bool v) { value = v; } 44 | 45 | public bool value; 46 | } 47 | 48 | internal class JsonElementDict : JsonElement 49 | { 50 | public JsonElementDict() : base() {} 51 | 52 | private SortedDictionary m_PrivateValue = new SortedDictionary(); 53 | public IDictionary values { get { return m_PrivateValue; }} 54 | 55 | new public JsonElement this[string key] 56 | { 57 | get { 58 | if (values.ContainsKey(key)) 59 | return values[key]; 60 | return null; 61 | } 62 | set { this.values[key] = value; } 63 | } 64 | 65 | public bool Contains(string key) 66 | { 67 | return values.ContainsKey(key); 68 | } 69 | 70 | public void Remove(string key) 71 | { 72 | values.Remove(key); 73 | } 74 | 75 | // convenience methods 76 | public void SetInteger(string key, int val) 77 | { 78 | values[key] = new JsonElementInteger(val); 79 | } 80 | 81 | public void SetString(string key, string val) 82 | { 83 | values[key] = new JsonElementString(val); 84 | } 85 | 86 | public void SetBoolean(string key, bool val) 87 | { 88 | values[key] = new JsonElementBoolean(val); 89 | } 90 | 91 | public JsonElementArray CreateArray(string key) 92 | { 93 | var v = new JsonElementArray(); 94 | values[key] = v; 95 | return v; 96 | } 97 | 98 | public JsonElementDict CreateDict(string key) 99 | { 100 | var v = new JsonElementDict(); 101 | values[key] = v; 102 | return v; 103 | } 104 | } 105 | 106 | internal class JsonElementArray : JsonElement 107 | { 108 | public JsonElementArray() : base() {} 109 | public List values = new List(); 110 | 111 | // convenience methods 112 | public void AddString(string val) 113 | { 114 | values.Add(new JsonElementString(val)); 115 | } 116 | 117 | public void AddInteger(int val) 118 | { 119 | values.Add(new JsonElementInteger(val)); 120 | } 121 | 122 | public void AddBoolean(bool val) 123 | { 124 | values.Add(new JsonElementBoolean(val)); 125 | } 126 | 127 | public JsonElementArray AddArray() 128 | { 129 | var v = new JsonElementArray(); 130 | values.Add(v); 131 | return v; 132 | } 133 | 134 | public JsonElementDict AddDict() 135 | { 136 | var v = new JsonElementDict(); 137 | values.Add(v); 138 | return v; 139 | } 140 | } 141 | 142 | internal class JsonDocument 143 | { 144 | public JsonElementDict root; 145 | public string indentString = " "; 146 | 147 | public JsonDocument() 148 | { 149 | root = new JsonElementDict(); 150 | } 151 | 152 | void AppendIndent(StringBuilder sb, int indent) 153 | { 154 | for (int i = 0; i < indent; ++i) 155 | sb.Append(indentString); 156 | } 157 | 158 | void WriteString(StringBuilder sb, string str) 159 | { 160 | // TODO: escape 161 | sb.Append('"'); 162 | sb.Append(str); 163 | sb.Append('"'); 164 | } 165 | 166 | void WriteBoolean(StringBuilder sb, bool value) 167 | { 168 | sb.Append(value ? "true" : "false"); 169 | } 170 | 171 | void WriteInteger(StringBuilder sb, int value) 172 | { 173 | sb.Append(value.ToString()); 174 | } 175 | 176 | void WriteDictKeyValue(StringBuilder sb, string key, JsonElement value, int indent) 177 | { 178 | sb.Append("\n"); 179 | AppendIndent(sb, indent); 180 | WriteString(sb, key); 181 | sb.Append(" : "); 182 | if (value is JsonElementString) 183 | WriteString(sb, value.AsString()); 184 | else if (value is JsonElementInteger) 185 | WriteInteger(sb, value.AsInteger()); 186 | else if (value is JsonElementBoolean) 187 | WriteBoolean(sb, value.AsBoolean()); 188 | else if (value is JsonElementDict) 189 | WriteDict(sb, value.AsDict(), indent); 190 | else if (value is JsonElementArray) 191 | WriteArray(sb, value.AsArray(), indent); 192 | } 193 | 194 | void WriteDict(StringBuilder sb, JsonElementDict el, int indent) 195 | { 196 | sb.Append("{"); 197 | bool hasElement = false; 198 | foreach (var key in el.values.Keys) 199 | { 200 | if (hasElement) 201 | sb.Append(","); // trailing commas not supported 202 | WriteDictKeyValue(sb, key, el[key], indent+1); 203 | hasElement = true; 204 | } 205 | sb.Append("\n"); 206 | AppendIndent(sb, indent); 207 | sb.Append("}"); 208 | } 209 | 210 | void WriteArray(StringBuilder sb, JsonElementArray el, int indent) 211 | { 212 | sb.Append("["); 213 | bool hasElement = false; 214 | foreach (var value in el.values) 215 | { 216 | if (hasElement) 217 | sb.Append(","); // trailing commas not supported 218 | sb.Append("\n"); 219 | AppendIndent(sb, indent+1); 220 | 221 | if (value is JsonElementString) 222 | WriteString(sb, value.AsString()); 223 | else if (value is JsonElementInteger) 224 | WriteInteger(sb, value.AsInteger()); 225 | else if (value is JsonElementBoolean) 226 | WriteBoolean(sb, value.AsBoolean()); 227 | else if (value is JsonElementDict) 228 | WriteDict(sb, value.AsDict(), indent+1); 229 | else if (value is JsonElementArray) 230 | WriteArray(sb, value.AsArray(), indent+1); 231 | hasElement = true; 232 | } 233 | sb.Append("\n"); 234 | AppendIndent(sb, indent); 235 | sb.Append("]"); 236 | } 237 | 238 | public void WriteToFile(string path) 239 | { 240 | File.WriteAllText(path, WriteToString()); 241 | } 242 | 243 | public void WriteToStream(TextWriter tw) 244 | { 245 | tw.Write(WriteToString()); 246 | } 247 | 248 | public string WriteToString() 249 | { 250 | var sb = new StringBuilder(); 251 | WriteDict(sb, root, 0); 252 | return sb.ToString(); 253 | } 254 | } 255 | 256 | 257 | } // namespace UnityEditor.iOS.Xcode -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Serializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | using System.IO; 6 | using System.Linq; 7 | 8 | namespace Strings.iOS.Xcode.PBX 9 | { 10 | class PropertyCommentChecker 11 | { 12 | private int m_Level; 13 | private bool m_All; 14 | private List> m_Props; 15 | 16 | /* The argument is an array of matcher strings each of which determine 17 | whether a property with a certain path needs to be decorated with a 18 | comment. 19 | 20 | A path is a number of path elements concatenated by '/'. The last path 21 | element is either: 22 | the key if we're referring to a dict key 23 | the value if we're referring to a value in an array 24 | the value if we're referring to a value in a dict 25 | All other path elements are either: 26 | the key if the container is dict 27 | '*' if the container is array 28 | 29 | Path matcher has the same structure as a path, except that any of the 30 | elements may be '*'. Matcher matches a path if both have the same number 31 | of elements and for each pair matcher element is the same as path element 32 | or is '*'. 33 | 34 | a/b/c matches a/b/c but not a/b nor a/b/c/d 35 | a/* /c matches a/d/c but not a/b nor a/b/c/d 36 | * /* /* matches any path from three elements 37 | */ 38 | protected PropertyCommentChecker(int level, List> props) 39 | { 40 | m_Level = level; 41 | m_All = false; 42 | m_Props = props; 43 | } 44 | 45 | public PropertyCommentChecker() 46 | { 47 | m_Level = 0; 48 | m_All = false; 49 | m_Props = new List>(); 50 | } 51 | 52 | public PropertyCommentChecker(IEnumerable props) 53 | { 54 | m_Level = 0; 55 | m_All = false; 56 | m_Props = new List>(); 57 | foreach (var prop in props) 58 | { 59 | m_Props.Add(new List(prop.Split('/'))); 60 | } 61 | } 62 | 63 | bool CheckContained(string prop) 64 | { 65 | if (m_All) 66 | return true; 67 | foreach (var list in m_Props) 68 | { 69 | if (list.Count == m_Level+1) 70 | { 71 | if (list[m_Level] == prop) 72 | return true; 73 | if (list[m_Level] == "*") 74 | { 75 | m_All = true; // short-circuit all at this level 76 | return true; 77 | } 78 | } 79 | } 80 | return false; 81 | } 82 | 83 | public bool CheckStringValueInArray(string value) { return CheckContained(value); } 84 | public bool CheckKeyInDict(string key) { return CheckContained(key); } 85 | 86 | public bool CheckStringValueInDict(string key, string value) 87 | { 88 | foreach (var list in m_Props) 89 | { 90 | if (list.Count == m_Level + 2) 91 | { 92 | if ((list[m_Level] == "*" || list[m_Level] == key) && 93 | list[m_Level+1] == "*" || list[m_Level+1] == value) 94 | return true; 95 | } 96 | } 97 | return false; 98 | } 99 | 100 | public PropertyCommentChecker NextLevel(string prop) 101 | { 102 | var newList = new List>(); 103 | foreach (var list in m_Props) 104 | { 105 | if (list.Count <= m_Level+1) 106 | continue; 107 | if (list[m_Level] == "*" || list[m_Level] == prop) 108 | newList.Add(list); 109 | } 110 | return new PropertyCommentChecker(m_Level + 1, newList); 111 | } 112 | } 113 | 114 | class Serializer 115 | { 116 | public static PBXElementDict ParseTreeAST(TreeAST ast, TokenList tokens, string text) 117 | { 118 | var el = new PBXElementDict(); 119 | foreach (var kv in ast.values) 120 | { 121 | PBXElementString key = ParseIdentifierAST(kv.key, tokens, text); 122 | PBXElement value = ParseValueAST(kv.value, tokens, text); 123 | el[key.value] = value; 124 | } 125 | return el; 126 | } 127 | 128 | public static PBXElementArray ParseArrayAST(ArrayAST ast, TokenList tokens, string text) 129 | { 130 | var el = new PBXElementArray(); 131 | foreach (var v in ast.values) 132 | { 133 | el.values.Add(ParseValueAST(v, tokens, text)); 134 | } 135 | return el; 136 | } 137 | 138 | public static PBXElement ParseValueAST(ValueAST ast, TokenList tokens, string text) 139 | { 140 | if (ast is TreeAST) 141 | return ParseTreeAST((TreeAST)ast, tokens, text); 142 | if (ast is ArrayAST) 143 | return ParseArrayAST((ArrayAST)ast, tokens, text); 144 | if (ast is IdentifierAST) 145 | return ParseIdentifierAST((IdentifierAST)ast, tokens, text); 146 | return null; 147 | } 148 | 149 | public static PBXElementString ParseIdentifierAST(IdentifierAST ast, TokenList tokens, string text) 150 | { 151 | Token tok = tokens[ast.value]; 152 | string value; 153 | switch (tok.type) 154 | { 155 | case TokenType.String: 156 | value = text.Substring(tok.begin, tok.end - tok.begin); 157 | return new PBXElementString(value); 158 | case TokenType.QuotedString: 159 | value = text.Substring(tok.begin, tok.end - tok.begin); 160 | value = PBXStream.UnquoteString(value); 161 | return new PBXElementString(value); 162 | default: 163 | throw new Exception("Internal parser error"); 164 | } 165 | } 166 | 167 | static string k_Indent = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; 168 | 169 | static string GetIndent(int indent) 170 | { 171 | return k_Indent.Substring(0, indent); 172 | } 173 | 174 | static void WriteStringImpl(StringBuilder sb, string s, bool comment, GUIDToCommentMap comments) 175 | { 176 | if (comment) 177 | comments.WriteStringBuilder(sb, s); 178 | else 179 | sb.Append(PBXStream.QuoteStringIfNeeded(s)); 180 | } 181 | 182 | public static void WriteDictKeyValue(StringBuilder sb, string key, PBXElement value, int indent, bool compact, 183 | PropertyCommentChecker checker, GUIDToCommentMap comments) 184 | { 185 | if (!compact) 186 | { 187 | sb.Append("\n"); 188 | sb.Append(GetIndent(indent)); 189 | } 190 | WriteStringImpl(sb, key, checker.CheckKeyInDict(key), comments); 191 | sb.Append(" = "); 192 | 193 | if (value is PBXElementString) 194 | WriteStringImpl(sb, value.AsString(), checker.CheckStringValueInDict(key, value.AsString()), comments); 195 | else if (value is PBXElementDict) 196 | WriteDict(sb, value.AsDict(), indent, compact, checker.NextLevel(key), comments); 197 | else if (value is PBXElementArray) 198 | WriteArray(sb, value.AsArray(), indent, compact, checker.NextLevel(key), comments); 199 | sb.Append(";"); 200 | if (compact) 201 | sb.Append(" "); 202 | } 203 | 204 | public static void WriteDict(StringBuilder sb, PBXElementDict el, int indent, bool compact, 205 | PropertyCommentChecker checker, GUIDToCommentMap comments) 206 | { 207 | sb.Append("{"); 208 | 209 | if (el.Contains("isa")) 210 | WriteDictKeyValue(sb, "isa", el["isa"], indent+1, compact, checker, comments); 211 | var keys = new List(el.values.Keys); 212 | keys.Sort(StringComparer.Ordinal); 213 | foreach (var key in keys) 214 | { 215 | if (key != "isa") 216 | WriteDictKeyValue(sb, key, el[key], indent+1, compact, checker, comments); 217 | } 218 | if (!compact) 219 | { 220 | sb.Append("\n"); 221 | sb.Append(GetIndent(indent)); 222 | } 223 | sb.Append("}"); 224 | } 225 | 226 | public static void WriteArray(StringBuilder sb, PBXElementArray el, int indent, bool compact, 227 | PropertyCommentChecker checker, GUIDToCommentMap comments) 228 | { 229 | sb.Append("("); 230 | foreach (var value in el.values) 231 | { 232 | if (!compact) 233 | { 234 | sb.Append("\n"); 235 | sb.Append(GetIndent(indent+1)); 236 | } 237 | 238 | if (value is PBXElementString) 239 | WriteStringImpl(sb, value.AsString(), checker.CheckStringValueInArray(value.AsString()), comments); 240 | else if (value is PBXElementDict) 241 | WriteDict(sb, value.AsDict(), indent+1, compact, checker.NextLevel("*"), comments); 242 | else if (value is PBXElementArray) 243 | WriteArray(sb, value.AsArray(), indent+1, compact, checker.NextLevel("*"), comments); 244 | sb.Append(","); 245 | if (compact) 246 | sb.Append(" "); 247 | } 248 | 249 | if (!compact) 250 | { 251 | sb.Append("\n"); 252 | sb.Append(GetIndent(indent)); 253 | } 254 | sb.Append(")"); 255 | } 256 | } 257 | 258 | } // namespace UnityEditor.iOS.Xcode 259 | 260 | -------------------------------------------------------------------------------- /Packages/packages-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.2d.sprite": { 4 | "version": "1.0.0", 5 | "depth": 0, 6 | "source": "builtin", 7 | "dependencies": {} 8 | }, 9 | "com.unity.2d.tilemap": { 10 | "version": "1.0.0", 11 | "depth": 0, 12 | "source": "builtin", 13 | "dependencies": {} 14 | }, 15 | "com.unity.ads": { 16 | "version": "3.7.1", 17 | "depth": 0, 18 | "source": "registry", 19 | "dependencies": { 20 | "com.unity.ugui": "1.0.0" 21 | }, 22 | "url": "https://packages.unity.com" 23 | }, 24 | "com.unity.analytics": { 25 | "version": "3.5.3", 26 | "depth": 0, 27 | "source": "registry", 28 | "dependencies": { 29 | "com.unity.ugui": "1.0.0" 30 | }, 31 | "url": "https://packages.unity.com" 32 | }, 33 | "com.unity.collab-proxy": { 34 | "version": "1.7.1", 35 | "depth": 0, 36 | "source": "registry", 37 | "dependencies": { 38 | "com.unity.nuget.newtonsoft-json": "2.0.0" 39 | }, 40 | "url": "https://packages.unity.com" 41 | }, 42 | "com.unity.ext.nunit": { 43 | "version": "1.0.6", 44 | "depth": 1, 45 | "source": "registry", 46 | "dependencies": {}, 47 | "url": "https://packages.unity.com" 48 | }, 49 | "com.unity.ide.rider": { 50 | "version": "2.0.7", 51 | "depth": 0, 52 | "source": "registry", 53 | "dependencies": { 54 | "com.unity.test-framework": "1.1.1" 55 | }, 56 | "url": "https://packages.unity.com" 57 | }, 58 | "com.unity.ide.visualstudio": { 59 | "version": "2.0.9", 60 | "depth": 0, 61 | "source": "registry", 62 | "dependencies": { 63 | "com.unity.test-framework": "1.1.9" 64 | }, 65 | "url": "https://packages.unity.com" 66 | }, 67 | "com.unity.ide.vscode": { 68 | "version": "1.2.3", 69 | "depth": 0, 70 | "source": "registry", 71 | "dependencies": {}, 72 | "url": "https://packages.unity.com" 73 | }, 74 | "com.unity.nuget.newtonsoft-json": { 75 | "version": "2.0.0", 76 | "depth": 1, 77 | "source": "registry", 78 | "dependencies": {}, 79 | "url": "https://packages.unity.com" 80 | }, 81 | "com.unity.purchasing": { 82 | "version": "3.2.2", 83 | "depth": 0, 84 | "source": "registry", 85 | "dependencies": { 86 | "com.unity.ugui": "1.0.0", 87 | "com.unity.modules.unityanalytics": "1.0.0", 88 | "com.unity.modules.unitywebrequest": "1.0.0", 89 | "com.unity.modules.jsonserialize": "1.0.0", 90 | "com.unity.modules.androidjni": "1.0.0" 91 | }, 92 | "url": "https://packages.unity.com" 93 | }, 94 | "com.unity.test-framework": { 95 | "version": "1.1.27", 96 | "depth": 0, 97 | "source": "registry", 98 | "dependencies": { 99 | "com.unity.ext.nunit": "1.0.6", 100 | "com.unity.modules.imgui": "1.0.0", 101 | "com.unity.modules.jsonserialize": "1.0.0" 102 | }, 103 | "url": "https://packages.unity.com" 104 | }, 105 | "com.unity.textmeshpro": { 106 | "version": "3.0.6", 107 | "depth": 0, 108 | "source": "registry", 109 | "dependencies": { 110 | "com.unity.ugui": "1.0.0" 111 | }, 112 | "url": "https://packages.unity.com" 113 | }, 114 | "com.unity.timeline": { 115 | "version": "1.4.8", 116 | "depth": 0, 117 | "source": "registry", 118 | "dependencies": { 119 | "com.unity.modules.director": "1.0.0", 120 | "com.unity.modules.animation": "1.0.0", 121 | "com.unity.modules.audio": "1.0.0", 122 | "com.unity.modules.particlesystem": "1.0.0" 123 | }, 124 | "url": "https://packages.unity.com" 125 | }, 126 | "com.unity.ugui": { 127 | "version": "1.0.0", 128 | "depth": 0, 129 | "source": "builtin", 130 | "dependencies": { 131 | "com.unity.modules.ui": "1.0.0", 132 | "com.unity.modules.imgui": "1.0.0" 133 | } 134 | }, 135 | "com.unity.xr.legacyinputhelpers": { 136 | "version": "2.1.7", 137 | "depth": 0, 138 | "source": "registry", 139 | "dependencies": { 140 | "com.unity.modules.vr": "1.0.0", 141 | "com.unity.modules.xr": "1.0.0" 142 | }, 143 | "url": "https://packages.unity.com" 144 | }, 145 | "com.unity.modules.ai": { 146 | "version": "1.0.0", 147 | "depth": 0, 148 | "source": "builtin", 149 | "dependencies": {} 150 | }, 151 | "com.unity.modules.androidjni": { 152 | "version": "1.0.0", 153 | "depth": 0, 154 | "source": "builtin", 155 | "dependencies": {} 156 | }, 157 | "com.unity.modules.animation": { 158 | "version": "1.0.0", 159 | "depth": 0, 160 | "source": "builtin", 161 | "dependencies": {} 162 | }, 163 | "com.unity.modules.assetbundle": { 164 | "version": "1.0.0", 165 | "depth": 0, 166 | "source": "builtin", 167 | "dependencies": {} 168 | }, 169 | "com.unity.modules.audio": { 170 | "version": "1.0.0", 171 | "depth": 0, 172 | "source": "builtin", 173 | "dependencies": {} 174 | }, 175 | "com.unity.modules.cloth": { 176 | "version": "1.0.0", 177 | "depth": 0, 178 | "source": "builtin", 179 | "dependencies": { 180 | "com.unity.modules.physics": "1.0.0" 181 | } 182 | }, 183 | "com.unity.modules.director": { 184 | "version": "1.0.0", 185 | "depth": 0, 186 | "source": "builtin", 187 | "dependencies": { 188 | "com.unity.modules.audio": "1.0.0", 189 | "com.unity.modules.animation": "1.0.0" 190 | } 191 | }, 192 | "com.unity.modules.imageconversion": { 193 | "version": "1.0.0", 194 | "depth": 0, 195 | "source": "builtin", 196 | "dependencies": {} 197 | }, 198 | "com.unity.modules.imgui": { 199 | "version": "1.0.0", 200 | "depth": 0, 201 | "source": "builtin", 202 | "dependencies": {} 203 | }, 204 | "com.unity.modules.jsonserialize": { 205 | "version": "1.0.0", 206 | "depth": 0, 207 | "source": "builtin", 208 | "dependencies": {} 209 | }, 210 | "com.unity.modules.particlesystem": { 211 | "version": "1.0.0", 212 | "depth": 0, 213 | "source": "builtin", 214 | "dependencies": {} 215 | }, 216 | "com.unity.modules.physics": { 217 | "version": "1.0.0", 218 | "depth": 0, 219 | "source": "builtin", 220 | "dependencies": {} 221 | }, 222 | "com.unity.modules.physics2d": { 223 | "version": "1.0.0", 224 | "depth": 0, 225 | "source": "builtin", 226 | "dependencies": {} 227 | }, 228 | "com.unity.modules.screencapture": { 229 | "version": "1.0.0", 230 | "depth": 0, 231 | "source": "builtin", 232 | "dependencies": { 233 | "com.unity.modules.imageconversion": "1.0.0" 234 | } 235 | }, 236 | "com.unity.modules.subsystems": { 237 | "version": "1.0.0", 238 | "depth": 1, 239 | "source": "builtin", 240 | "dependencies": { 241 | "com.unity.modules.jsonserialize": "1.0.0" 242 | } 243 | }, 244 | "com.unity.modules.terrain": { 245 | "version": "1.0.0", 246 | "depth": 0, 247 | "source": "builtin", 248 | "dependencies": {} 249 | }, 250 | "com.unity.modules.terrainphysics": { 251 | "version": "1.0.0", 252 | "depth": 0, 253 | "source": "builtin", 254 | "dependencies": { 255 | "com.unity.modules.physics": "1.0.0", 256 | "com.unity.modules.terrain": "1.0.0" 257 | } 258 | }, 259 | "com.unity.modules.tilemap": { 260 | "version": "1.0.0", 261 | "depth": 0, 262 | "source": "builtin", 263 | "dependencies": { 264 | "com.unity.modules.physics2d": "1.0.0" 265 | } 266 | }, 267 | "com.unity.modules.ui": { 268 | "version": "1.0.0", 269 | "depth": 0, 270 | "source": "builtin", 271 | "dependencies": {} 272 | }, 273 | "com.unity.modules.uielements": { 274 | "version": "1.0.0", 275 | "depth": 0, 276 | "source": "builtin", 277 | "dependencies": { 278 | "com.unity.modules.ui": "1.0.0", 279 | "com.unity.modules.imgui": "1.0.0", 280 | "com.unity.modules.jsonserialize": "1.0.0", 281 | "com.unity.modules.uielementsnative": "1.0.0" 282 | } 283 | }, 284 | "com.unity.modules.uielementsnative": { 285 | "version": "1.0.0", 286 | "depth": 1, 287 | "source": "builtin", 288 | "dependencies": { 289 | "com.unity.modules.ui": "1.0.0", 290 | "com.unity.modules.imgui": "1.0.0", 291 | "com.unity.modules.jsonserialize": "1.0.0" 292 | } 293 | }, 294 | "com.unity.modules.umbra": { 295 | "version": "1.0.0", 296 | "depth": 0, 297 | "source": "builtin", 298 | "dependencies": {} 299 | }, 300 | "com.unity.modules.unityanalytics": { 301 | "version": "1.0.0", 302 | "depth": 0, 303 | "source": "builtin", 304 | "dependencies": { 305 | "com.unity.modules.unitywebrequest": "1.0.0", 306 | "com.unity.modules.jsonserialize": "1.0.0" 307 | } 308 | }, 309 | "com.unity.modules.unitywebrequest": { 310 | "version": "1.0.0", 311 | "depth": 0, 312 | "source": "builtin", 313 | "dependencies": {} 314 | }, 315 | "com.unity.modules.unitywebrequestassetbundle": { 316 | "version": "1.0.0", 317 | "depth": 0, 318 | "source": "builtin", 319 | "dependencies": { 320 | "com.unity.modules.assetbundle": "1.0.0", 321 | "com.unity.modules.unitywebrequest": "1.0.0" 322 | } 323 | }, 324 | "com.unity.modules.unitywebrequestaudio": { 325 | "version": "1.0.0", 326 | "depth": 0, 327 | "source": "builtin", 328 | "dependencies": { 329 | "com.unity.modules.unitywebrequest": "1.0.0", 330 | "com.unity.modules.audio": "1.0.0" 331 | } 332 | }, 333 | "com.unity.modules.unitywebrequesttexture": { 334 | "version": "1.0.0", 335 | "depth": 0, 336 | "source": "builtin", 337 | "dependencies": { 338 | "com.unity.modules.unitywebrequest": "1.0.0", 339 | "com.unity.modules.imageconversion": "1.0.0" 340 | } 341 | }, 342 | "com.unity.modules.unitywebrequestwww": { 343 | "version": "1.0.0", 344 | "depth": 0, 345 | "source": "builtin", 346 | "dependencies": { 347 | "com.unity.modules.unitywebrequest": "1.0.0", 348 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 349 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 350 | "com.unity.modules.audio": "1.0.0", 351 | "com.unity.modules.assetbundle": "1.0.0", 352 | "com.unity.modules.imageconversion": "1.0.0" 353 | } 354 | }, 355 | "com.unity.modules.vehicles": { 356 | "version": "1.0.0", 357 | "depth": 0, 358 | "source": "builtin", 359 | "dependencies": { 360 | "com.unity.modules.physics": "1.0.0" 361 | } 362 | }, 363 | "com.unity.modules.video": { 364 | "version": "1.0.0", 365 | "depth": 0, 366 | "source": "builtin", 367 | "dependencies": { 368 | "com.unity.modules.audio": "1.0.0", 369 | "com.unity.modules.ui": "1.0.0", 370 | "com.unity.modules.unitywebrequest": "1.0.0" 371 | } 372 | }, 373 | "com.unity.modules.vr": { 374 | "version": "1.0.0", 375 | "depth": 0, 376 | "source": "builtin", 377 | "dependencies": { 378 | "com.unity.modules.jsonserialize": "1.0.0", 379 | "com.unity.modules.physics": "1.0.0", 380 | "com.unity.modules.xr": "1.0.0" 381 | } 382 | }, 383 | "com.unity.modules.wind": { 384 | "version": "1.0.0", 385 | "depth": 0, 386 | "source": "builtin", 387 | "dependencies": {} 388 | }, 389 | "com.unity.modules.xr": { 390 | "version": "1.0.0", 391 | "depth": 0, 392 | "source": "builtin", 393 | "dependencies": { 394 | "com.unity.modules.physics": "1.0.0", 395 | "com.unity.modules.jsonserialize": "1.0.0", 396 | "com.unity.modules.subsystems": "1.0.0" 397 | } 398 | } 399 | } 400 | } 401 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBX/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | using System.IO; 6 | 7 | namespace Strings.iOS.Xcode.PBX 8 | { 9 | internal class GUIDToCommentMap 10 | { 11 | private Dictionary m_Dict = new Dictionary(); 12 | 13 | public string this[string guid] 14 | { 15 | get { 16 | if (m_Dict.ContainsKey(guid)) 17 | return m_Dict[guid]; 18 | return null; 19 | } 20 | } 21 | 22 | public void Add(string guid, string comment) 23 | { 24 | if (m_Dict.ContainsKey(guid)) 25 | return; 26 | m_Dict.Add(guid, comment); 27 | } 28 | 29 | public void Remove(string guid) 30 | { 31 | m_Dict.Remove(guid); 32 | } 33 | 34 | public string Write(string guid) 35 | { 36 | string comment = this[guid]; 37 | if (comment == null) 38 | return guid; 39 | return String.Format("{0} /* {1} */", guid, comment); 40 | } 41 | 42 | public void WriteStringBuilder(StringBuilder sb, string guid) 43 | { 44 | string comment = this[guid]; 45 | if (comment == null) 46 | sb.Append(guid); 47 | else 48 | { 49 | // {0} /* {1} */ 50 | sb.Append(guid).Append(" /* ").Append(comment).Append(" */"); 51 | } 52 | } 53 | } 54 | 55 | internal class PBXGUID 56 | { 57 | internal delegate string GuidGenerator(); 58 | 59 | // We allow changing Guid generator to make testing of PBXProject possible 60 | private static GuidGenerator guidGenerator = DefaultGuidGenerator; 61 | 62 | internal static string DefaultGuidGenerator() 63 | { 64 | return Guid.NewGuid().ToString("N").Substring(8).ToUpper(); 65 | } 66 | 67 | internal static void SetGuidGenerator(GuidGenerator generator) 68 | { 69 | guidGenerator = generator; 70 | } 71 | 72 | // Generates a GUID. 73 | public static string Generate() 74 | { 75 | return guidGenerator(); 76 | } 77 | } 78 | 79 | internal class PBXRegex 80 | { 81 | public static string GuidRegexString = "[A-Fa-f0-9]{24}"; 82 | } 83 | 84 | internal class PBXStream 85 | { 86 | static bool DontNeedQuotes(string src) 87 | { 88 | // using a regex instead of explicit matching slows down common cases by 40% 89 | if (src.Length == 0) 90 | return false; 91 | 92 | bool hasSlash = false; 93 | for (int i = 0; i < src.Length; ++i) 94 | { 95 | char c = src[i]; 96 | if (Char.IsLetterOrDigit(c) || c == '.' || c == '*' || c == '_') 97 | continue; 98 | if (c == '/') 99 | { 100 | hasSlash = true; 101 | continue; 102 | } 103 | return false; 104 | } 105 | if (hasSlash) 106 | { 107 | if (src.Contains("//") || src.Contains("/*") || src.Contains("*/")) 108 | return false; 109 | } 110 | return true; 111 | } 112 | 113 | // Quotes the given string if it contains special characters. Note: if the string already 114 | // contains quotes, then they are escaped and the entire string quoted again 115 | public static string QuoteStringIfNeeded(string src) 116 | { 117 | if (DontNeedQuotes(src)) 118 | return src; 119 | return "\"" + src.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") + "\""; 120 | } 121 | 122 | // If the given string is quoted, removes the quotes and unescapes any quotes within the string 123 | public static string UnquoteString(string src) 124 | { 125 | if (!src.StartsWith("\"") || !src.EndsWith("\"")) 126 | return src; 127 | return src.Substring(1, src.Length - 2).Replace("\\\\", "\u569f").Replace("\\\"", "\"") 128 | .Replace("\\n", "\n").Replace("\u569f", "\\"); // U+569f is a rarely used Chinese character 129 | } 130 | } 131 | 132 | internal enum PBXFileType 133 | { 134 | NotBuildable, 135 | Framework, 136 | Source, 137 | Resource, 138 | CopyFile 139 | } 140 | 141 | internal class FileTypeUtils 142 | { 143 | internal class FileTypeDesc 144 | { 145 | public FileTypeDesc(string typeName, PBXFileType type) 146 | { 147 | this.name = typeName; 148 | this.type = type; 149 | this.isExplicit = false; 150 | } 151 | 152 | public FileTypeDesc(string typeName, PBXFileType type, bool isExplicit) 153 | { 154 | this.name = typeName; 155 | this.type = type; 156 | this.isExplicit = isExplicit; 157 | } 158 | 159 | public string name; 160 | public PBXFileType type; 161 | public bool isExplicit; 162 | } 163 | 164 | private static readonly Dictionary types = 165 | new Dictionary 166 | { 167 | { "a", new FileTypeDesc("archive.ar", PBXFileType.Framework) }, 168 | { "app", new FileTypeDesc("wrapper.application", PBXFileType.NotBuildable, true) }, 169 | { "appex", new FileTypeDesc("wrapper.app-extension", PBXFileType.CopyFile) }, 170 | { "bin", new FileTypeDesc("archive.macbinary", PBXFileType.Resource) }, 171 | { "s", new FileTypeDesc("sourcecode.asm", PBXFileType.Source) }, 172 | { "c", new FileTypeDesc("sourcecode.c.c", PBXFileType.Source) }, 173 | { "cc", new FileTypeDesc("sourcecode.cpp.cpp", PBXFileType.Source) }, 174 | { "cpp", new FileTypeDesc("sourcecode.cpp.cpp", PBXFileType.Source) }, 175 | { "swift", new FileTypeDesc("sourcecode.swift", PBXFileType.Source) }, 176 | { "dll", new FileTypeDesc("file", PBXFileType.NotBuildable) }, 177 | { "framework", new FileTypeDesc("wrapper.framework", PBXFileType.Framework) }, 178 | { "h", new FileTypeDesc("sourcecode.c.h", PBXFileType.NotBuildable) }, 179 | { "pch", new FileTypeDesc("sourcecode.c.h", PBXFileType.NotBuildable) }, 180 | { "icns", new FileTypeDesc("image.icns", PBXFileType.Resource) }, 181 | { "xcassets", new FileTypeDesc("folder.assetcatalog", PBXFileType.Resource) }, 182 | { "inc", new FileTypeDesc("sourcecode.inc", PBXFileType.NotBuildable) }, 183 | { "m", new FileTypeDesc("sourcecode.c.objc", PBXFileType.Source) }, 184 | { "mm", new FileTypeDesc("sourcecode.cpp.objcpp", PBXFileType.Source ) }, 185 | { "nib", new FileTypeDesc("wrapper.nib", PBXFileType.Resource) }, 186 | { "plist", new FileTypeDesc("text.plist.xml", PBXFileType.Resource) }, 187 | { "png", new FileTypeDesc("image.png", PBXFileType.Resource) }, 188 | { "rtf", new FileTypeDesc("text.rtf", PBXFileType.Resource) }, 189 | { "tiff", new FileTypeDesc("image.tiff", PBXFileType.Resource) }, 190 | { "txt", new FileTypeDesc("text", PBXFileType.Resource) }, 191 | { "json", new FileTypeDesc("text.json", PBXFileType.Resource) }, 192 | { "xcodeproj", new FileTypeDesc("wrapper.pb-project", PBXFileType.NotBuildable) }, 193 | { "xib", new FileTypeDesc("file.xib", PBXFileType.Resource) }, 194 | { "strings", new FileTypeDesc("text.plist.strings", PBXFileType.Resource) }, 195 | { "storyboard",new FileTypeDesc("file.storyboard", PBXFileType.Resource) }, 196 | { "bundle", new FileTypeDesc("wrapper.plug-in", PBXFileType.Resource) }, 197 | { "dylib", new FileTypeDesc("compiled.mach-o.dylib", PBXFileType.Framework) }, 198 | { "tbd", new FileTypeDesc("sourcecode.text-based-dylib-definition", PBXFileType.Framework) } 199 | }; 200 | 201 | public static string TrimExtension(string ext) 202 | { 203 | return ext.TrimStart('.'); 204 | } 205 | 206 | public static bool IsKnownExtension(string ext) 207 | { 208 | ext = TrimExtension(ext); 209 | return types.ContainsKey(ext); 210 | } 211 | 212 | internal static bool IsFileTypeExplicit(string ext) 213 | { 214 | ext = TrimExtension(ext); 215 | if (types.ContainsKey(ext)) 216 | return types[ext].isExplicit; 217 | return false; 218 | } 219 | 220 | public static PBXFileType GetFileType(string ext, bool isFolderRef) 221 | { 222 | ext = TrimExtension(ext); 223 | if (isFolderRef) 224 | return PBXFileType.Resource; 225 | if (!types.ContainsKey(ext)) 226 | return PBXFileType.Resource; 227 | return types[ext].type; 228 | } 229 | 230 | public static string GetTypeName(string ext) 231 | { 232 | ext = TrimExtension(ext); 233 | if (types.ContainsKey(ext)) 234 | return types[ext].name; 235 | // Xcode actually checks the file contents to determine the file type. 236 | // Text files have "text" type and all other files have "file" type. 237 | // Since we can't reasonably determine whether the file in question is 238 | // a text file, we just take the safe route and return "file" type. 239 | return "file"; 240 | } 241 | 242 | public static bool IsBuildableFile(string ext) 243 | { 244 | ext = TrimExtension(ext); 245 | if (!types.ContainsKey(ext)) 246 | return true; 247 | if (types[ext].type != PBXFileType.NotBuildable) 248 | return true; 249 | return false; 250 | } 251 | 252 | public static bool IsBuildable(string ext, bool isFolderReference) 253 | { 254 | ext = TrimExtension(ext); 255 | if (isFolderReference) 256 | return true; 257 | return IsBuildableFile(ext); 258 | } 259 | 260 | private static readonly Dictionary sourceTree = new Dictionary 261 | { 262 | { PBXSourceTree.Absolute, "" }, 263 | { PBXSourceTree.Group, "" }, 264 | { PBXSourceTree.Build, "BUILT_PRODUCTS_DIR" }, 265 | { PBXSourceTree.Developer, "DEVELOPER_DIR" }, 266 | { PBXSourceTree.Sdk, "SDKROOT" }, 267 | { PBXSourceTree.Source, "SOURCE_ROOT" }, 268 | }; 269 | 270 | private static readonly Dictionary stringToSourceTreeMap = new Dictionary 271 | { 272 | { "", PBXSourceTree.Absolute }, 273 | { "", PBXSourceTree.Group }, 274 | { "BUILT_PRODUCTS_DIR", PBXSourceTree.Build }, 275 | { "DEVELOPER_DIR", PBXSourceTree.Developer }, 276 | { "SDKROOT", PBXSourceTree.Sdk }, 277 | { "SOURCE_ROOT", PBXSourceTree.Source }, 278 | }; 279 | 280 | internal static string SourceTreeDesc(PBXSourceTree tree) 281 | { 282 | return sourceTree[tree]; 283 | } 284 | 285 | // returns PBXSourceTree.Source on error 286 | internal static PBXSourceTree ParseSourceTree(string tree) 287 | { 288 | if (stringToSourceTreeMap.ContainsKey(tree)) 289 | return stringToSourceTreeMap[tree]; 290 | return PBXSourceTree.Source; 291 | } 292 | 293 | internal static List AllAbsoluteSourceTrees() 294 | { 295 | return new List{PBXSourceTree.Absolute, PBXSourceTree.Build, 296 | PBXSourceTree.Developer, PBXSourceTree.Sdk, PBXSourceTree.Source}; 297 | } 298 | } 299 | 300 | } // UnityEditor.iOS.Xcode 301 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PlistParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Xml; 6 | using System.Xml.Linq; 7 | using System.Xml.XPath; 8 | 9 | namespace Strings.iOS.Xcode 10 | { 11 | 12 | public class PlistElement 13 | { 14 | protected PlistElement() {} 15 | 16 | // convenience methods 17 | public string AsString() { return ((PlistElementString)this).value; } 18 | public int AsInteger() { return ((PlistElementInteger)this).value; } 19 | public bool AsBoolean() { return ((PlistElementBoolean)this).value; } 20 | public PlistElementArray AsArray() { return (PlistElementArray)this; } 21 | public PlistElementDict AsDict() { return (PlistElementDict)this; } 22 | 23 | public PlistElement this[string key] 24 | { 25 | get { return AsDict()[key]; } 26 | set { AsDict()[key] = value; } 27 | } 28 | } 29 | 30 | public class PlistElementString : PlistElement 31 | { 32 | public PlistElementString(string v) { value = v; } 33 | 34 | public string value; 35 | } 36 | 37 | public class PlistElementInteger : PlistElement 38 | { 39 | public PlistElementInteger(int v) { value = v; } 40 | 41 | public int value; 42 | } 43 | 44 | public class PlistElementBoolean : PlistElement 45 | { 46 | public PlistElementBoolean(bool v) { value = v; } 47 | 48 | public bool value; 49 | } 50 | 51 | public class PlistElementDict : PlistElement 52 | { 53 | public PlistElementDict() : base() {} 54 | 55 | private SortedDictionary m_PrivateValue = new SortedDictionary(); 56 | public IDictionary values { get { return m_PrivateValue; }} 57 | 58 | new public PlistElement this[string key] 59 | { 60 | get { 61 | if (values.ContainsKey(key)) 62 | return values[key]; 63 | return null; 64 | } 65 | set { this.values[key] = value; } 66 | } 67 | 68 | 69 | // convenience methods 70 | public void SetInteger(string key, int val) 71 | { 72 | values[key] = new PlistElementInteger(val); 73 | } 74 | 75 | public void SetString(string key, string val) 76 | { 77 | values[key] = new PlistElementString(val); 78 | } 79 | 80 | public void SetBoolean(string key, bool val) 81 | { 82 | values[key] = new PlistElementBoolean(val); 83 | } 84 | 85 | public PlistElementArray CreateArray(string key) 86 | { 87 | var v = new PlistElementArray(); 88 | values[key] = v; 89 | return v; 90 | } 91 | 92 | public PlistElementDict CreateDict(string key) 93 | { 94 | var v = new PlistElementDict(); 95 | values[key] = v; 96 | return v; 97 | } 98 | } 99 | 100 | public class PlistElementArray : PlistElement 101 | { 102 | public PlistElementArray() : base() {} 103 | public List values = new List(); 104 | 105 | // convenience methods 106 | public void AddString(string val) 107 | { 108 | values.Add(new PlistElementString(val)); 109 | } 110 | 111 | public void AddInteger(int val) 112 | { 113 | values.Add(new PlistElementInteger(val)); 114 | } 115 | 116 | public void AddBoolean(bool val) 117 | { 118 | values.Add(new PlistElementBoolean(val)); 119 | } 120 | 121 | public PlistElementArray AddArray() 122 | { 123 | var v = new PlistElementArray(); 124 | values.Add(v); 125 | return v; 126 | } 127 | 128 | public PlistElementDict AddDict() 129 | { 130 | var v = new PlistElementDict(); 131 | values.Add(v); 132 | return v; 133 | } 134 | } 135 | 136 | public class PlistDocument 137 | { 138 | public PlistElementDict root; 139 | public string version; 140 | 141 | public PlistDocument() 142 | { 143 | root = new PlistElementDict(); 144 | version = "1.0"; 145 | } 146 | 147 | // Parses a string that contains a XML file. No validation is done. 148 | internal static XDocument ParseXmlNoDtd(string text) 149 | { 150 | XmlReaderSettings settings = new XmlReaderSettings(); 151 | settings.ProhibitDtd = false; 152 | settings.XmlResolver = null; // prevent DTD download 153 | 154 | XmlReader xmlReader = XmlReader.Create(new StringReader(text), settings); 155 | return XDocument.Load(xmlReader); 156 | } 157 | 158 | // LINQ serializes XML DTD declaration with an explicit empty 'internal subset' 159 | // (a pair of square brackets at the end of Doctype declaration). 160 | // Even though this is valid XML, XCode does not like it, hence this workaround. 161 | internal static string CleanDtdToString(XDocument doc) 162 | { 163 | // LINQ does not support changing the DTD of existing XDocument instances, 164 | // so we create a dummy document for printing of the Doctype declaration. 165 | // A single dummy element is added to force LINQ not to omit the declaration. 166 | // Also, utf-8 encoding is forced since this is the encoding we use when writing to file in UpdateInfoPlist. 167 | if (doc.DocumentType != null) 168 | { 169 | XDocument tmpDoc = 170 | new XDocument(new XDeclaration("1.0", "utf-8", null), 171 | new XDocumentType(doc.DocumentType.Name, doc.DocumentType.PublicId, doc.DocumentType.SystemId, null), 172 | new XElement(doc.Root.Name)); 173 | return "" + tmpDoc.Declaration + "\n" + tmpDoc.DocumentType + "\n" + doc.Root; 174 | } 175 | else 176 | { 177 | XDocument tmpDoc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement(doc.Root.Name)); 178 | return "" + tmpDoc.Declaration + Environment.NewLine + doc.Root; 179 | } 180 | } 181 | 182 | private static string GetText(XElement xml) 183 | { 184 | return String.Join("", xml.Nodes().OfType().Select(x => x.Value).ToArray()); 185 | } 186 | 187 | private static PlistElement ReadElement(XElement xml) 188 | { 189 | switch (xml.Name.LocalName) 190 | { 191 | case "dict": 192 | { 193 | List children = xml.Elements().ToList(); 194 | var el = new PlistElementDict(); 195 | 196 | if (children.Count % 2 == 1) 197 | throw new Exception("Malformed plist file"); 198 | 199 | for (int i = 0; i < children.Count - 1; i++) 200 | { 201 | if (children[i].Name != "key") 202 | throw new Exception("Malformed plist file"); 203 | string key = GetText(children[i]).Trim(); 204 | var newChild = ReadElement(children[i+1]); 205 | if (newChild != null) 206 | { 207 | i++; 208 | el[key] = newChild; 209 | } 210 | } 211 | return el; 212 | } 213 | case "array": 214 | { 215 | List children = xml.Elements().ToList(); 216 | var el = new PlistElementArray(); 217 | 218 | foreach (var childXml in children) 219 | { 220 | var newChild = ReadElement(childXml); 221 | if (newChild != null) 222 | el.values.Add(newChild); 223 | } 224 | return el; 225 | } 226 | case "string": 227 | return new PlistElementString(GetText(xml)); 228 | case "integer": 229 | { 230 | int r; 231 | if (int.TryParse(GetText(xml), out r)) 232 | return new PlistElementInteger(r); 233 | return null; 234 | } 235 | case "true": 236 | return new PlistElementBoolean(true); 237 | case "false": 238 | return new PlistElementBoolean(false); 239 | default: 240 | return null; 241 | } 242 | } 243 | 244 | public void Create() 245 | { 246 | const string doc = "" + 247 | "" + 248 | "" + 249 | "" + 250 | "" + 251 | ""; 252 | ReadFromString(doc); 253 | } 254 | 255 | public void ReadFromFile(string path) 256 | { 257 | ReadFromString(File.ReadAllText(path)); 258 | } 259 | 260 | public void ReadFromStream(TextReader tr) 261 | { 262 | ReadFromString(tr.ReadToEnd()); 263 | } 264 | 265 | public void ReadFromString(string text) 266 | { 267 | XDocument doc = ParseXmlNoDtd(text); 268 | version = (string) doc.Root.Attribute("version"); 269 | XElement xml = doc.XPathSelectElement("plist/dict"); 270 | 271 | var dict = ReadElement(xml); 272 | if (dict == null) 273 | throw new Exception("Error parsing plist file"); 274 | root = dict as PlistElementDict; 275 | if (root == null) 276 | throw new Exception("Malformed plist file"); 277 | } 278 | 279 | private static XElement WriteElement(PlistElement el) 280 | { 281 | if (el is PlistElementBoolean) 282 | { 283 | var realEl = el as PlistElementBoolean; 284 | return new XElement(realEl.value ? "true" : "false"); 285 | } 286 | if (el is PlistElementInteger) 287 | { 288 | var realEl = el as PlistElementInteger; 289 | return new XElement("integer", realEl.value.ToString()); 290 | } 291 | if (el is PlistElementString) 292 | { 293 | var realEl = el as PlistElementString; 294 | return new XElement("string", realEl.value); 295 | } 296 | if (el is PlistElementDict) 297 | { 298 | var realEl = el as PlistElementDict; 299 | var dictXml = new XElement("dict"); 300 | foreach (var kv in realEl.values) 301 | { 302 | var keyXml = new XElement("key", kv.Key); 303 | var valueXml = WriteElement(kv.Value); 304 | if (valueXml != null) 305 | { 306 | dictXml.Add(keyXml); 307 | dictXml.Add(valueXml); 308 | } 309 | } 310 | return dictXml; 311 | } 312 | if (el is PlistElementArray) 313 | { 314 | var realEl = el as PlistElementArray; 315 | var arrayXml = new XElement("array"); 316 | foreach (var v in realEl.values) 317 | { 318 | var elXml = WriteElement(v); 319 | if (elXml != null) 320 | arrayXml.Add(elXml); 321 | } 322 | return arrayXml; 323 | } 324 | return null; 325 | } 326 | 327 | public void WriteToFile(string path) 328 | { 329 | System.Text.Encoding utf8WithoutBom = new System.Text.UTF8Encoding(false); 330 | File.WriteAllText(path, WriteToString(), utf8WithoutBom); 331 | } 332 | 333 | public void WriteToStream(TextWriter tw) 334 | { 335 | tw.Write(WriteToString()); 336 | } 337 | 338 | public string WriteToString() 339 | { 340 | var el = WriteElement(root); 341 | var rootEl = new XElement("plist"); 342 | rootEl.Add(new XAttribute("version", version)); 343 | rootEl.Add(el); 344 | 345 | var doc = new XDocument(); 346 | doc.Add(rootEl); 347 | return CleanDtdToString(doc).Replace("\r\n", "\n"); 348 | } 349 | } 350 | 351 | } // namespace UnityEditor.iOS.XCode 352 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/PBXProjectExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | using System.Text.RegularExpressions; 4 | using System.IO; 5 | using System; 6 | using Strings.iOS.Xcode.PBX; 7 | 8 | namespace Strings.iOS.Xcode.Extensions 9 | { 10 | /* This class implements a number of static methods for performing common tasks 11 | on xcode projects. 12 | TODO: Make sure enough stuff is exposed so that it's possible to perform the tasks 13 | without using internal APIs 14 | */ 15 | public static class PBXProjectExtensions 16 | { 17 | // Create a wrapper class so that collection initializers work and we can have a 18 | // compact notation. Note that we can't use Dictionary because the keys may be duplicate 19 | internal class FlagList : List> 20 | { 21 | public void Add(string flag, string value) 22 | { 23 | Add(new KeyValuePair(flag, value)); 24 | } 25 | } 26 | 27 | internal static FlagList appExtensionReleaseBuildFlags = new FlagList 28 | { 29 | // { "INFOPLIST_FILE", }, 30 | { "LD_RUNPATH_SEARCH_PATHS", "$(inherited)" }, 31 | { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks" }, 32 | { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/../../Frameworks" }, 33 | // { "PRODUCT_BUNDLE_IDENTIFIER", "" }, 34 | { "PRODUCT_NAME", "$(TARGET_NAME)" }, 35 | { "SKIP_INSTALL", "YES" }, 36 | }; 37 | 38 | internal static FlagList appExtensionDebugBuildFlags = new FlagList 39 | { 40 | // { "INFOPLIST_FILE", }, 41 | { "LD_RUNPATH_SEARCH_PATHS", "$(inherited)" }, 42 | { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks" }, 43 | { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/../../Frameworks" }, 44 | // { "PRODUCT_BUNDLE_IDENTIFIER", "" }, 45 | { "PRODUCT_NAME", "$(TARGET_NAME)" }, 46 | { "SKIP_INSTALL", "YES" }, 47 | }; 48 | 49 | internal static FlagList watchExtensionReleaseBuildFlags = new FlagList 50 | { 51 | { "ASSETCATALOG_COMPILER_COMPLICATION_NAME", "Complication" }, 52 | { "CLANG_ANALYZER_NONNULL", "YES" }, 53 | { "CLANG_WARN_DOCUMENTATION_COMMENTS", "YES" }, 54 | { "CLANG_WARN_INFINITE_RECURSION", "YES" }, 55 | { "CLANG_WARN_SUSPICIOUS_MOVE", "YES" }, 56 | { "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym" }, 57 | { "GCC_NO_COMMON_BLOCKS", "YES" }, 58 | //{ "INFOPLIST_FILE", "" }, 59 | { "LD_RUNPATH_SEARCH_PATHS", "$(inherited)" }, 60 | { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks" }, 61 | { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/../../Frameworks" }, 62 | // { "PRODUCT_BUNDLE_IDENTIFIER", "" }, 63 | { "PRODUCT_NAME", "${TARGET_NAME}" }, 64 | { "SDKROOT", "watchos" }, 65 | { "SKIP_INSTALL", "YES" }, 66 | { "TARGETED_DEVICE_FAMILY", "4" }, 67 | { "WATCHOS_DEPLOYMENT_TARGET", "3.1" }, 68 | // the following are needed to override project settings in Unity Xcode project 69 | { "ARCHS", "$(ARCHS_STANDARD)" }, 70 | { "SUPPORTED_PLATFORMS", "watchos" }, 71 | { "SUPPORTED_PLATFORMS", "watchsimulator" }, 72 | }; 73 | 74 | internal static FlagList watchExtensionDebugBuildFlags = new FlagList 75 | { 76 | { "ASSETCATALOG_COMPILER_COMPLICATION_NAME", "Complication" }, 77 | { "CLANG_ANALYZER_NONNULL", "YES" }, 78 | { "CLANG_WARN_DOCUMENTATION_COMMENTS", "YES" }, 79 | { "CLANG_WARN_INFINITE_RECURSION", "YES" }, 80 | { "CLANG_WARN_SUSPICIOUS_MOVE", "YES" }, 81 | { "DEBUG_INFORMATION_FORMAT", "dwarf" }, 82 | { "ENABLE_TESTABILITY", "YES" }, 83 | { "GCC_NO_COMMON_BLOCKS", "YES" }, 84 | // { "INFOPLIST_FILE", "" }, 85 | { "LD_RUNPATH_SEARCH_PATHS", "$(inherited)" }, 86 | { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks" }, 87 | { "LD_RUNPATH_SEARCH_PATHS", "@executable_path/../../Frameworks" }, 88 | // { "PRODUCT_BUNDLE_IDENTIFIER", "" }, 89 | { "PRODUCT_NAME", "${TARGET_NAME}" }, 90 | { "SDKROOT", "watchos" }, 91 | { "SKIP_INSTALL", "YES" }, 92 | { "TARGETED_DEVICE_FAMILY", "4" }, 93 | { "WATCHOS_DEPLOYMENT_TARGET", "3.1" }, 94 | // the following are needed to override project settings in Unity Xcode project 95 | { "ARCHS", "$(ARCHS_STANDARD)" }, 96 | { "SUPPORTED_PLATFORMS", "watchos" }, 97 | { "SUPPORTED_PLATFORMS", "watchsimulator" }, 98 | }; 99 | 100 | internal static FlagList watchAppReleaseBuildFlags = new FlagList 101 | { 102 | { "ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon" }, 103 | { "CLANG_ANALYZER_NONNULL", "YES" }, 104 | { "CLANG_WARN_DOCUMENTATION_COMMENTS", "YES" }, 105 | { "CLANG_WARN_INFINITE_RECURSION", "YES" }, 106 | { "CLANG_WARN_SUSPICIOUS_MOVE", "YES" }, 107 | { "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym" }, 108 | { "GCC_NO_COMMON_BLOCKS", "YES" }, 109 | //{ "IBSC_MODULE", "the extension target name with ' ' replaced with '_'" }, 110 | //{ "INFOPLIST_FILE", "" }, 111 | //{ "PRODUCT_BUNDLE_IDENTIFIER", "" }, 112 | { "PRODUCT_NAME", "$(TARGET_NAME)" }, 113 | { "SDKROOT", "watchos" }, 114 | { "SKIP_INSTALL", "YES" }, 115 | { "TARGETED_DEVICE_FAMILY", "4" }, 116 | { "WATCHOS_DEPLOYMENT_TARGET", "3.1" }, 117 | // the following are needed to override project settings in Unity Xcode project 118 | { "ARCHS", "$(ARCHS_STANDARD)" }, 119 | { "SUPPORTED_PLATFORMS", "watchos" }, 120 | { "SUPPORTED_PLATFORMS", "watchsimulator" }, 121 | }; 122 | 123 | internal static FlagList watchAppDebugBuildFlags = new FlagList 124 | { 125 | { "ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon" }, 126 | { "CLANG_ANALYZER_NONNULL", "YES" }, 127 | { "CLANG_WARN_DOCUMENTATION_COMMENTS", "YES" }, 128 | { "CLANG_WARN_INFINITE_RECURSION", "YES" }, 129 | { "CLANG_WARN_SUSPICIOUS_MOVE", "YES" }, 130 | { "DEBUG_INFORMATION_FORMAT", "dwarf" }, 131 | { "ENABLE_TESTABILITY", "YES" }, 132 | { "GCC_NO_COMMON_BLOCKS", "YES" }, 133 | //{ "IBSC_MODULE", "the extension target name with ' ' replaced with '_'" }, 134 | //{ "INFOPLIST_FILE", "" }, 135 | //{ "PRODUCT_BUNDLE_IDENTIFIER", "" }, 136 | { "PRODUCT_NAME", "$(TARGET_NAME)" }, 137 | { "SDKROOT", "watchos" }, 138 | { "SKIP_INSTALL", "YES" }, 139 | { "TARGETED_DEVICE_FAMILY", "4" }, 140 | { "WATCHOS_DEPLOYMENT_TARGET", "3.1" }, 141 | // the following are needed to override project settings in Unity Xcode project 142 | { "ARCHS", "$(ARCHS_STANDARD)" }, 143 | { "SUPPORTED_PLATFORMS", "watchos" }, 144 | { "SUPPORTED_PLATFORMS", "watchsimulator" }, 145 | }; 146 | 147 | static void SetBuildFlagsFromDict(this PBXProject proj, string configGuid, IEnumerable> data) 148 | { 149 | foreach (var kv in data) 150 | proj.AddBuildPropertyForConfig(configGuid, kv.Key, kv.Value); 151 | } 152 | 153 | internal static void SetDefaultAppExtensionReleaseBuildFlags(this PBXProject proj, string configGuid) 154 | { 155 | SetBuildFlagsFromDict(proj, configGuid, appExtensionReleaseBuildFlags); 156 | } 157 | 158 | internal static void SetDefaultAppExtensionDebugBuildFlags(this PBXProject proj, string configGuid) 159 | { 160 | SetBuildFlagsFromDict(proj, configGuid, appExtensionDebugBuildFlags); 161 | } 162 | 163 | internal static void SetDefaultWatchExtensionReleaseBuildFlags(this PBXProject proj, string configGuid) 164 | { 165 | SetBuildFlagsFromDict(proj, configGuid, watchExtensionReleaseBuildFlags); 166 | } 167 | 168 | internal static void SetDefaultWatchExtensionDebugBuildFlags(this PBXProject proj, string configGuid) 169 | { 170 | SetBuildFlagsFromDict(proj, configGuid, watchExtensionDebugBuildFlags); 171 | } 172 | 173 | internal static void SetDefaultWatchAppReleaseBuildFlags(this PBXProject proj, string configGuid) 174 | { 175 | SetBuildFlagsFromDict(proj, configGuid, watchAppReleaseBuildFlags); 176 | } 177 | 178 | internal static void SetDefaultWatchAppDebugBuildFlags(this PBXProject proj, string configGuid) 179 | { 180 | SetBuildFlagsFromDict(proj, configGuid, watchAppDebugBuildFlags); 181 | } 182 | 183 | /// 184 | /// Creates an app extension. 185 | /// 186 | /// The GUID of the new target. 187 | /// A project passed as this argument. 188 | /// The GUID of the main target to link the app to. 189 | /// The name of the app extension. 190 | /// The bundle ID of the app extension. The bundle ID must be 191 | /// prefixed with the parent app bundle ID. 192 | /// Path to the app extension Info.plist document. 193 | public static string AddAppExtension(this PBXProject proj, string mainTargetGuid, 194 | string name, string bundleId, string infoPlistPath) 195 | { 196 | string ext = ".appex"; 197 | var newTargetGuid = proj.AddTarget(name, ext, "com.apple.product-type.app-extension"); 198 | 199 | foreach (var configName in proj.BuildConfigNames()) 200 | { 201 | var configGuid = proj.BuildConfigByName(newTargetGuid, configName); 202 | if (configName.Contains("Debug")) 203 | SetDefaultAppExtensionDebugBuildFlags(proj, configGuid); 204 | else 205 | SetDefaultAppExtensionReleaseBuildFlags(proj, configGuid); 206 | proj.SetBuildPropertyForConfig(configGuid, "INFOPLIST_FILE", infoPlistPath); 207 | proj.SetBuildPropertyForConfig(configGuid, "PRODUCT_BUNDLE_IDENTIFIER", bundleId); 208 | } 209 | 210 | proj.AddSourcesBuildPhase(newTargetGuid); 211 | proj.AddResourcesBuildPhase(newTargetGuid); 212 | proj.AddFrameworksBuildPhase(newTargetGuid); 213 | string copyFilesPhaseGuid = proj.AddCopyFilesBuildPhase(mainTargetGuid, "Embed App Extensions", "", "13"); 214 | proj.AddFileToBuildSection(mainTargetGuid, copyFilesPhaseGuid, proj.GetTargetProductFileRef(newTargetGuid)); 215 | 216 | proj.AddTargetDependency(mainTargetGuid, newTargetGuid); 217 | 218 | return newTargetGuid; 219 | } 220 | 221 | /// 222 | /// Creates a watch application. 223 | /// 224 | /// The GUID of the new target. 225 | /// A project passed as this argument. 226 | /// The GUID of the main target to link the watch app to. 227 | /// The GUID of watch extension as returned by [[AddWatchExtension()]]. 228 | /// The name of the watch app. It must the same as the name of the watch extension. 229 | /// The bundle ID of the watch app. 230 | /// Path to the watch app Info.plist document. 231 | public static string AddWatchApp(this PBXProject proj, string mainTargetGuid, string watchExtensionTargetGuid, 232 | string name, string bundleId, string infoPlistPath) 233 | { 234 | var newTargetGuid = proj.AddTarget(name, ".app", "com.apple.product-type.application.watchapp2"); 235 | 236 | var isbcModuleName = proj.nativeTargets[watchExtensionTargetGuid].name.Replace(" ", "_"); 237 | 238 | foreach (var configName in proj.BuildConfigNames()) 239 | { 240 | var configGuid = proj.BuildConfigByName(newTargetGuid, configName); 241 | if (configName.Contains("Debug")) 242 | SetDefaultWatchAppDebugBuildFlags(proj, configGuid); 243 | else 244 | SetDefaultWatchAppReleaseBuildFlags(proj, configGuid); 245 | proj.SetBuildPropertyForConfig(configGuid, "PRODUCT_BUNDLE_IDENTIFIER", bundleId); 246 | proj.SetBuildPropertyForConfig(configGuid, "INFOPLIST_FILE", infoPlistPath); 247 | proj.SetBuildPropertyForConfig(configGuid, "IBSC_MODULE", isbcModuleName); 248 | } 249 | 250 | proj.AddResourcesBuildPhase(newTargetGuid); 251 | string copyFilesGuid = proj.AddCopyFilesBuildPhase(newTargetGuid, "Embed App Extensions", "", "13"); 252 | proj.AddFileToBuildSection(newTargetGuid, copyFilesGuid, proj.GetTargetProductFileRef(watchExtensionTargetGuid)); 253 | 254 | string copyWatchFilesGuid = proj.AddCopyFilesBuildPhase(mainTargetGuid, "Embed Watch Content", "$(CONTENTS_FOLDER_PATH)/Watch", "16"); 255 | proj.AddFileToBuildSection(mainTargetGuid, copyWatchFilesGuid, proj.GetTargetProductFileRef(newTargetGuid)); 256 | 257 | proj.AddTargetDependency(newTargetGuid, watchExtensionTargetGuid); 258 | proj.AddTargetDependency(mainTargetGuid, newTargetGuid); 259 | 260 | return newTargetGuid; 261 | } 262 | 263 | /// 264 | /// Creates a watch extension. 265 | /// 266 | /// The GUID of the new target. 267 | /// A project passed as this argument. 268 | /// The GUID of the main target to link the watch extension to. 269 | /// The name of the watch extension. 270 | /// The bundle ID of the watch extension. The bundle ID must be 271 | /// prefixed with the parent watch app bundle ID. 272 | /// Path to the watch extension Info.plist document. 273 | public static string AddWatchExtension(this PBXProject proj, string mainTarget, 274 | string name, string bundleId, string infoPlistPath) 275 | { 276 | var newTargetGuid = proj.AddTarget(name, ".appex", "com.apple.product-type.watchkit2-extension"); 277 | 278 | foreach (var configName in proj.BuildConfigNames()) 279 | { 280 | var configGuid = proj.BuildConfigByName(newTargetGuid, configName); 281 | if (configName.Contains("Debug")) 282 | SetDefaultWatchExtensionDebugBuildFlags(proj, configGuid); 283 | else 284 | SetDefaultWatchExtensionReleaseBuildFlags(proj, configGuid); 285 | proj.SetBuildPropertyForConfig(configGuid, "PRODUCT_BUNDLE_IDENTIFIER", bundleId); 286 | proj.SetBuildPropertyForConfig(configGuid, "INFOPLIST_FILE", infoPlistPath); 287 | } 288 | 289 | proj.AddSourcesBuildPhase(newTargetGuid); 290 | proj.AddResourcesBuildPhase(newTargetGuid); 291 | proj.AddFrameworksBuildPhase(newTargetGuid); 292 | 293 | return newTargetGuid; 294 | } 295 | } 296 | } // namespace UnityEditor.iOS.Xcode 297 | -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!129 &1 4 | PlayerSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 18 7 | productGUID: f671b82672e4a4d1a83f8dbd70d548c6 8 | AndroidProfiler: 0 9 | AndroidFilterTouchesWhenObscured: 0 10 | AndroidEnableSustainedPerformanceMode: 0 11 | defaultScreenOrientation: 4 12 | targetDevice: 2 13 | useOnDemandResources: 0 14 | accelerometerFrequency: 60 15 | companyName: DefaultCompany 16 | productName: OnPostProcessBuild 17 | defaultCursor: {fileID: 0} 18 | cursorHotspot: {x: 0, y: 0} 19 | m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} 20 | m_ShowUnitySplashScreen: 1 21 | m_ShowUnitySplashLogo: 1 22 | m_SplashScreenOverlayOpacity: 1 23 | m_SplashScreenAnimation: 1 24 | m_SplashScreenLogoStyle: 1 25 | m_SplashScreenDrawMode: 0 26 | m_SplashScreenBackgroundAnimationZoom: 1 27 | m_SplashScreenLogoAnimationZoom: 1 28 | m_SplashScreenBackgroundLandscapeAspect: 1 29 | m_SplashScreenBackgroundPortraitAspect: 1 30 | m_SplashScreenBackgroundLandscapeUvs: 31 | serializedVersion: 2 32 | x: 0 33 | y: 0 34 | width: 1 35 | height: 1 36 | m_SplashScreenBackgroundPortraitUvs: 37 | serializedVersion: 2 38 | x: 0 39 | y: 0 40 | width: 1 41 | height: 1 42 | m_SplashScreenLogos: [] 43 | m_VirtualRealitySplashScreen: {fileID: 0} 44 | m_HolographicTrackingLossScreen: {fileID: 0} 45 | defaultScreenWidth: 1024 46 | defaultScreenHeight: 768 47 | defaultScreenWidthWeb: 960 48 | defaultScreenHeightWeb: 600 49 | m_StereoRenderingPath: 0 50 | m_ActiveColorSpace: 0 51 | m_MTRendering: 1 52 | m_StackTraceTypes: 010000000100000001000000010000000100000001000000 53 | iosShowActivityIndicatorOnLoading: -1 54 | androidShowActivityIndicatorOnLoading: -1 55 | displayResolutionDialog: 1 56 | iosUseCustomAppBackgroundBehavior: 0 57 | iosAllowHTTPDownload: 1 58 | allowedAutorotateToPortrait: 1 59 | allowedAutorotateToPortraitUpsideDown: 1 60 | allowedAutorotateToLandscapeRight: 1 61 | allowedAutorotateToLandscapeLeft: 1 62 | useOSAutorotation: 1 63 | use32BitDisplayBuffer: 1 64 | preserveFramebufferAlpha: 0 65 | disableDepthAndStencilBuffers: 0 66 | androidStartInFullscreen: 1 67 | androidRenderOutsideSafeArea: 0 68 | androidBlitType: 0 69 | defaultIsNativeResolution: 1 70 | macRetinaSupport: 1 71 | runInBackground: 1 72 | captureSingleScreen: 0 73 | muteOtherAudioSources: 0 74 | Prepare IOS For Recording: 0 75 | Force IOS Speakers When Recording: 0 76 | deferSystemGesturesMode: 0 77 | hideHomeButton: 0 78 | submitAnalytics: 1 79 | usePlayerLog: 1 80 | bakeCollisionMeshes: 0 81 | forceSingleInstance: 0 82 | resizableWindow: 0 83 | useMacAppStoreValidation: 0 84 | macAppStoreCategory: public.app-category.games 85 | gpuSkinning: 1 86 | graphicsJobs: 0 87 | xboxPIXTextureCapture: 0 88 | xboxEnableAvatar: 0 89 | xboxEnableKinect: 0 90 | xboxEnableKinectAutoTracking: 0 91 | xboxEnableFitness: 0 92 | visibleInBackground: 1 93 | allowFullscreenSwitch: 1 94 | graphicsJobMode: 0 95 | fullscreenMode: 1 96 | xboxSpeechDB: 0 97 | xboxEnableHeadOrientation: 0 98 | xboxEnableGuest: 0 99 | xboxEnablePIXSampling: 0 100 | metalFramebufferOnly: 0 101 | xboxOneResolution: 0 102 | xboxOneSResolution: 0 103 | xboxOneXResolution: 3 104 | xboxOneMonoLoggingLevel: 0 105 | xboxOneLoggingLevel: 1 106 | xboxOneDisableEsram: 0 107 | xboxOnePresentImmediateThreshold: 0 108 | switchQueueCommandMemory: 0 109 | switchQueueControlMemory: 16384 110 | switchQueueComputeMemory: 262144 111 | switchNVNShaderPoolsGranularity: 33554432 112 | switchNVNDefaultPoolsGranularity: 16777216 113 | switchNVNOtherPoolsGranularity: 16777216 114 | vulkanEnableSetSRGBWrite: 0 115 | m_SupportedAspectRatios: 116 | 4:3: 1 117 | 5:4: 1 118 | 16:10: 1 119 | 16:9: 1 120 | Others: 1 121 | bundleVersion: 0.1 122 | preloadedAssets: [] 123 | metroInputSource: 0 124 | wsaTransparentSwapchain: 0 125 | m_HolographicPauseOnTrackingLoss: 1 126 | xboxOneDisableKinectGpuReservation: 1 127 | xboxOneEnable7thCore: 1 128 | isWsaHolographicRemotingEnabled: 0 129 | vrSettings: 130 | cardboard: 131 | depthFormat: 0 132 | enableTransitionView: 0 133 | daydream: 134 | depthFormat: 0 135 | useSustainedPerformanceMode: 0 136 | enableVideoLayer: 0 137 | useProtectedVideoMemory: 0 138 | minimumSupportedHeadTracking: 0 139 | maximumSupportedHeadTracking: 1 140 | hololens: 141 | depthFormat: 1 142 | depthBufferSharingEnabled: 1 143 | oculus: 144 | sharedDepthBuffer: 1 145 | dashSupport: 1 146 | lowOverheadMode: 0 147 | protectedContext: 0 148 | v2Signing: 0 149 | enable360StereoCapture: 0 150 | protectGraphicsMemory: 0 151 | enableFrameTimingStats: 0 152 | useHDRDisplay: 0 153 | m_ColorGamuts: 00000000 154 | targetPixelDensity: 30 155 | resolutionScalingMode: 0 156 | androidSupportedAspectRatio: 1 157 | androidMaxAspectRatio: 2.1 158 | applicationIdentifier: {} 159 | buildNumber: {} 160 | AndroidBundleVersionCode: 1 161 | AndroidMinSdkVersion: 16 162 | AndroidTargetSdkVersion: 0 163 | AndroidPreferredInstallLocation: 1 164 | aotOptions: 165 | stripEngineCode: 1 166 | iPhoneStrippingLevel: 0 167 | iPhoneScriptCallOptimization: 0 168 | ForceInternetPermission: 0 169 | ForceSDCardPermission: 0 170 | CreateWallpaper: 0 171 | APKExpansionFiles: 0 172 | keepLoadedShadersAlive: 0 173 | StripUnusedMeshComponents: 1 174 | VertexChannelCompressionMask: 4054 175 | iPhoneSdkVersion: 988 176 | iOSTargetOSVersionString: 9.0 177 | tvOSSdkVersion: 0 178 | tvOSRequireExtendedGameController: 0 179 | tvOSTargetOSVersionString: 9.0 180 | uIPrerenderedIcon: 0 181 | uIRequiresPersistentWiFi: 0 182 | uIRequiresFullScreen: 1 183 | uIStatusBarHidden: 1 184 | uIExitOnSuspend: 0 185 | uIStatusBarStyle: 0 186 | iPhoneSplashScreen: {fileID: 0} 187 | iPhoneHighResSplashScreen: {fileID: 0} 188 | iPhoneTallHighResSplashScreen: {fileID: 0} 189 | iPhone47inSplashScreen: {fileID: 0} 190 | iPhone55inPortraitSplashScreen: {fileID: 0} 191 | iPhone55inLandscapeSplashScreen: {fileID: 0} 192 | iPhone58inPortraitSplashScreen: {fileID: 0} 193 | iPhone58inLandscapeSplashScreen: {fileID: 0} 194 | iPadPortraitSplashScreen: {fileID: 0} 195 | iPadHighResPortraitSplashScreen: {fileID: 0} 196 | iPadLandscapeSplashScreen: {fileID: 0} 197 | iPadHighResLandscapeSplashScreen: {fileID: 0} 198 | appleTVSplashScreen: {fileID: 0} 199 | appleTVSplashScreen2x: {fileID: 0} 200 | tvOSSmallIconLayers: [] 201 | tvOSSmallIconLayers2x: [] 202 | tvOSLargeIconLayers: [] 203 | tvOSLargeIconLayers2x: [] 204 | tvOSTopShelfImageLayers: [] 205 | tvOSTopShelfImageLayers2x: [] 206 | tvOSTopShelfImageWideLayers: [] 207 | tvOSTopShelfImageWideLayers2x: [] 208 | iOSLaunchScreenType: 0 209 | iOSLaunchScreenPortrait: {fileID: 0} 210 | iOSLaunchScreenLandscape: {fileID: 0} 211 | iOSLaunchScreenBackgroundColor: 212 | serializedVersion: 2 213 | rgba: 0 214 | iOSLaunchScreenFillPct: 100 215 | iOSLaunchScreenSize: 100 216 | iOSLaunchScreenCustomXibPath: 217 | iOSLaunchScreeniPadType: 0 218 | iOSLaunchScreeniPadImage: {fileID: 0} 219 | iOSLaunchScreeniPadBackgroundColor: 220 | serializedVersion: 2 221 | rgba: 0 222 | iOSLaunchScreeniPadFillPct: 100 223 | iOSLaunchScreeniPadSize: 100 224 | iOSLaunchScreeniPadCustomXibPath: 225 | iOSUseLaunchScreenStoryboard: 0 226 | iOSLaunchScreenCustomStoryboardPath: 227 | iOSDeviceRequirements: [] 228 | iOSURLSchemes: [] 229 | iOSBackgroundModes: 0 230 | iOSMetalForceHardShadows: 0 231 | metalEditorSupport: 1 232 | metalAPIValidation: 1 233 | iOSRenderExtraFrameOnPause: 0 234 | appleDeveloperTeamID: 235 | iOSManualSigningProvisioningProfileID: 236 | tvOSManualSigningProvisioningProfileID: 237 | iOSManualSigningProvisioningProfileType: 0 238 | tvOSManualSigningProvisioningProfileType: 0 239 | appleEnableAutomaticSigning: 0 240 | iOSRequireARKit: 0 241 | iOSAutomaticallyDetectAndAddCapabilities: 1 242 | appleEnableProMotion: 0 243 | clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea 244 | templatePackageId: com.unity.template.3d@1.3.0 245 | templateDefaultScene: Assets/Scenes/SampleScene.unity 246 | AndroidTargetArchitectures: 5 247 | AndroidSplashScreenScale: 0 248 | androidSplashScreen: {fileID: 0} 249 | AndroidKeystoreName: 250 | AndroidKeyaliasName: 251 | AndroidBuildApkPerCpuArchitecture: 0 252 | AndroidTVCompatibility: 1 253 | AndroidIsGame: 1 254 | AndroidEnableTango: 0 255 | androidEnableBanner: 1 256 | androidUseLowAccuracyLocation: 0 257 | m_AndroidBanners: 258 | - width: 320 259 | height: 180 260 | banner: {fileID: 0} 261 | androidGamepadSupportLevel: 0 262 | resolutionDialogBanner: {fileID: 0} 263 | m_BuildTargetIcons: [] 264 | m_BuildTargetPlatformIcons: [] 265 | m_BuildTargetBatching: 266 | - m_BuildTarget: Standalone 267 | m_StaticBatching: 1 268 | m_DynamicBatching: 0 269 | - m_BuildTarget: tvOS 270 | m_StaticBatching: 1 271 | m_DynamicBatching: 0 272 | - m_BuildTarget: Android 273 | m_StaticBatching: 1 274 | m_DynamicBatching: 0 275 | - m_BuildTarget: iPhone 276 | m_StaticBatching: 1 277 | m_DynamicBatching: 0 278 | - m_BuildTarget: WebGL 279 | m_StaticBatching: 0 280 | m_DynamicBatching: 0 281 | m_BuildTargetGraphicsAPIs: 282 | - m_BuildTarget: AndroidPlayer 283 | m_APIs: 0b00000008000000 284 | m_Automatic: 1 285 | - m_BuildTarget: iOSSupport 286 | m_APIs: 10000000 287 | m_Automatic: 1 288 | - m_BuildTarget: AppleTVSupport 289 | m_APIs: 10000000 290 | m_Automatic: 0 291 | - m_BuildTarget: WebGLSupport 292 | m_APIs: 0b000000 293 | m_Automatic: 1 294 | m_BuildTargetVRSettings: 295 | - m_BuildTarget: Standalone 296 | m_Enabled: 0 297 | m_Devices: 298 | - Oculus 299 | - OpenVR 300 | m_BuildTargetEnableVuforiaSettings: [] 301 | openGLRequireES31: 0 302 | openGLRequireES31AEP: 0 303 | m_TemplateCustomTags: {} 304 | mobileMTRendering: 305 | Android: 1 306 | iPhone: 1 307 | tvOS: 1 308 | m_BuildTargetGroupLightmapEncodingQuality: [] 309 | m_BuildTargetGroupLightmapSettings: [] 310 | playModeTestRunnerEnabled: 0 311 | runPlayModeTestAsEditModeTest: 0 312 | actionOnDotNetUnhandledException: 1 313 | enableInternalProfiler: 0 314 | logObjCUncaughtExceptions: 1 315 | enableCrashReportAPI: 0 316 | cameraUsageDescription: 317 | locationUsageDescription: 318 | microphoneUsageDescription: 319 | switchNetLibKey: 320 | switchSocketMemoryPoolSize: 6144 321 | switchSocketAllocatorPoolSize: 128 322 | switchSocketConcurrencyLimit: 14 323 | switchScreenResolutionBehavior: 2 324 | switchUseCPUProfiler: 0 325 | switchApplicationID: 0x01004b9000490000 326 | switchNSODependencies: 327 | switchTitleNames_0: 328 | switchTitleNames_1: 329 | switchTitleNames_2: 330 | switchTitleNames_3: 331 | switchTitleNames_4: 332 | switchTitleNames_5: 333 | switchTitleNames_6: 334 | switchTitleNames_7: 335 | switchTitleNames_8: 336 | switchTitleNames_9: 337 | switchTitleNames_10: 338 | switchTitleNames_11: 339 | switchTitleNames_12: 340 | switchTitleNames_13: 341 | switchTitleNames_14: 342 | switchPublisherNames_0: 343 | switchPublisherNames_1: 344 | switchPublisherNames_2: 345 | switchPublisherNames_3: 346 | switchPublisherNames_4: 347 | switchPublisherNames_5: 348 | switchPublisherNames_6: 349 | switchPublisherNames_7: 350 | switchPublisherNames_8: 351 | switchPublisherNames_9: 352 | switchPublisherNames_10: 353 | switchPublisherNames_11: 354 | switchPublisherNames_12: 355 | switchPublisherNames_13: 356 | switchPublisherNames_14: 357 | switchIcons_0: {fileID: 0} 358 | switchIcons_1: {fileID: 0} 359 | switchIcons_2: {fileID: 0} 360 | switchIcons_3: {fileID: 0} 361 | switchIcons_4: {fileID: 0} 362 | switchIcons_5: {fileID: 0} 363 | switchIcons_6: {fileID: 0} 364 | switchIcons_7: {fileID: 0} 365 | switchIcons_8: {fileID: 0} 366 | switchIcons_9: {fileID: 0} 367 | switchIcons_10: {fileID: 0} 368 | switchIcons_11: {fileID: 0} 369 | switchIcons_12: {fileID: 0} 370 | switchIcons_13: {fileID: 0} 371 | switchIcons_14: {fileID: 0} 372 | switchSmallIcons_0: {fileID: 0} 373 | switchSmallIcons_1: {fileID: 0} 374 | switchSmallIcons_2: {fileID: 0} 375 | switchSmallIcons_3: {fileID: 0} 376 | switchSmallIcons_4: {fileID: 0} 377 | switchSmallIcons_5: {fileID: 0} 378 | switchSmallIcons_6: {fileID: 0} 379 | switchSmallIcons_7: {fileID: 0} 380 | switchSmallIcons_8: {fileID: 0} 381 | switchSmallIcons_9: {fileID: 0} 382 | switchSmallIcons_10: {fileID: 0} 383 | switchSmallIcons_11: {fileID: 0} 384 | switchSmallIcons_12: {fileID: 0} 385 | switchSmallIcons_13: {fileID: 0} 386 | switchSmallIcons_14: {fileID: 0} 387 | switchManualHTML: 388 | switchAccessibleURLs: 389 | switchLegalInformation: 390 | switchMainThreadStackSize: 1048576 391 | switchPresenceGroupId: 392 | switchLogoHandling: 0 393 | switchReleaseVersion: 0 394 | switchDisplayVersion: 1.0.0 395 | switchStartupUserAccount: 0 396 | switchTouchScreenUsage: 0 397 | switchSupportedLanguagesMask: 0 398 | switchLogoType: 0 399 | switchApplicationErrorCodeCategory: 400 | switchUserAccountSaveDataSize: 0 401 | switchUserAccountSaveDataJournalSize: 0 402 | switchApplicationAttribute: 0 403 | switchCardSpecSize: -1 404 | switchCardSpecClock: -1 405 | switchRatingsMask: 0 406 | switchRatingsInt_0: 0 407 | switchRatingsInt_1: 0 408 | switchRatingsInt_2: 0 409 | switchRatingsInt_3: 0 410 | switchRatingsInt_4: 0 411 | switchRatingsInt_5: 0 412 | switchRatingsInt_6: 0 413 | switchRatingsInt_7: 0 414 | switchRatingsInt_8: 0 415 | switchRatingsInt_9: 0 416 | switchRatingsInt_10: 0 417 | switchRatingsInt_11: 0 418 | switchLocalCommunicationIds_0: 419 | switchLocalCommunicationIds_1: 420 | switchLocalCommunicationIds_2: 421 | switchLocalCommunicationIds_3: 422 | switchLocalCommunicationIds_4: 423 | switchLocalCommunicationIds_5: 424 | switchLocalCommunicationIds_6: 425 | switchLocalCommunicationIds_7: 426 | switchParentalControl: 0 427 | switchAllowsScreenshot: 1 428 | switchAllowsVideoCapturing: 1 429 | switchAllowsRuntimeAddOnContentInstall: 0 430 | switchDataLossConfirmation: 0 431 | switchUserAccountLockEnabled: 0 432 | switchSystemResourceMemory: 16777216 433 | switchSupportedNpadStyles: 3 434 | switchNativeFsCacheSize: 32 435 | switchIsHoldTypeHorizontal: 0 436 | switchSupportedNpadCount: 8 437 | switchSocketConfigEnabled: 0 438 | switchTcpInitialSendBufferSize: 32 439 | switchTcpInitialReceiveBufferSize: 64 440 | switchTcpAutoSendBufferSizeMax: 256 441 | switchTcpAutoReceiveBufferSizeMax: 256 442 | switchUdpSendBufferSize: 9 443 | switchUdpReceiveBufferSize: 42 444 | switchSocketBufferEfficiency: 4 445 | switchSocketInitializeEnabled: 1 446 | switchNetworkInterfaceManagerInitializeEnabled: 1 447 | switchPlayerConnectionEnabled: 1 448 | ps4NPAgeRating: 12 449 | ps4NPTitleSecret: 450 | ps4NPTrophyPackPath: 451 | ps4ParentalLevel: 11 452 | ps4ContentID: ED1633-NPXX51362_00-0000000000000000 453 | ps4Category: 0 454 | ps4MasterVersion: 01.00 455 | ps4AppVersion: 01.00 456 | ps4AppType: 0 457 | ps4ParamSfxPath: 458 | ps4VideoOutPixelFormat: 0 459 | ps4VideoOutInitialWidth: 1920 460 | ps4VideoOutBaseModeInitialWidth: 1920 461 | ps4VideoOutReprojectionRate: 60 462 | ps4PronunciationXMLPath: 463 | ps4PronunciationSIGPath: 464 | ps4BackgroundImagePath: 465 | ps4StartupImagePath: 466 | ps4StartupImagesFolder: 467 | ps4IconImagesFolder: 468 | ps4SaveDataImagePath: 469 | ps4SdkOverride: 470 | ps4BGMPath: 471 | ps4ShareFilePath: 472 | ps4ShareOverlayImagePath: 473 | ps4PrivacyGuardImagePath: 474 | ps4NPtitleDatPath: 475 | ps4RemotePlayKeyAssignment: -1 476 | ps4RemotePlayKeyMappingDir: 477 | ps4PlayTogetherPlayerCount: 0 478 | ps4EnterButtonAssignment: 1 479 | ps4ApplicationParam1: 0 480 | ps4ApplicationParam2: 0 481 | ps4ApplicationParam3: 0 482 | ps4ApplicationParam4: 0 483 | ps4DownloadDataSize: 0 484 | ps4GarlicHeapSize: 2048 485 | ps4ProGarlicHeapSize: 2560 486 | ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ 487 | ps4pnSessions: 1 488 | ps4pnPresence: 1 489 | ps4pnFriends: 1 490 | ps4pnGameCustomData: 1 491 | playerPrefsSupport: 0 492 | enableApplicationExit: 0 493 | resetTempFolder: 1 494 | restrictedAudioUsageRights: 0 495 | ps4UseResolutionFallback: 0 496 | ps4ReprojectionSupport: 0 497 | ps4UseAudio3dBackend: 0 498 | ps4SocialScreenEnabled: 0 499 | ps4ScriptOptimizationLevel: 0 500 | ps4Audio3dVirtualSpeakerCount: 14 501 | ps4attribCpuUsage: 0 502 | ps4PatchPkgPath: 503 | ps4PatchLatestPkgPath: 504 | ps4PatchChangeinfoPath: 505 | ps4PatchDayOne: 0 506 | ps4attribUserManagement: 0 507 | ps4attribMoveSupport: 0 508 | ps4attrib3DSupport: 0 509 | ps4attribShareSupport: 0 510 | ps4attribExclusiveVR: 0 511 | ps4disableAutoHideSplash: 0 512 | ps4videoRecordingFeaturesUsed: 0 513 | ps4contentSearchFeaturesUsed: 0 514 | ps4attribEyeToEyeDistanceSettingVR: 0 515 | ps4IncludedModules: [] 516 | monoEnv: 517 | splashScreenBackgroundSourceLandscape: {fileID: 0} 518 | splashScreenBackgroundSourcePortrait: {fileID: 0} 519 | spritePackerPolicy: 520 | webGLMemorySize: 256 521 | webGLExceptionSupport: 1 522 | webGLNameFilesAsHashes: 0 523 | webGLDataCaching: 1 524 | webGLDebugSymbols: 0 525 | webGLEmscriptenArgs: 526 | webGLModulesDirectory: 527 | webGLTemplate: APPLICATION:Default 528 | webGLAnalyzeBuildSize: 0 529 | webGLUseEmbeddedResources: 0 530 | webGLCompressionFormat: 1 531 | webGLLinkerTarget: 1 532 | webGLThreadsSupport: 0 533 | scriptingDefineSymbols: {} 534 | platformArchitecture: {} 535 | scriptingBackend: {} 536 | il2cppCompilerConfiguration: {} 537 | managedStrippingLevel: {} 538 | incrementalIl2cppBuild: {} 539 | allowUnsafeCode: 0 540 | additionalIl2CppArgs: 541 | scriptingRuntimeVersion: 1 542 | apiCompatibilityLevelPerPlatform: {} 543 | m_RenderingPath: 1 544 | m_MobileRenderingPath: 1 545 | metroPackageName: Template_3D 546 | metroPackageVersion: 547 | metroCertificatePath: 548 | metroCertificatePassword: 549 | metroCertificateSubject: 550 | metroCertificateIssuer: 551 | metroCertificateNotAfter: 0000000000000000 552 | metroApplicationDescription: Template_3D 553 | wsaImages: {} 554 | metroTileShortName: 555 | metroTileShowName: 0 556 | metroMediumTileShowName: 0 557 | metroLargeTileShowName: 0 558 | metroWideTileShowName: 0 559 | metroSupportStreamingInstall: 0 560 | metroLastRequiredScene: 0 561 | metroDefaultTileSize: 1 562 | metroTileForegroundText: 2 563 | metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} 564 | metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, 565 | a: 1} 566 | metroSplashScreenUseBackgroundColor: 0 567 | platformCapabilities: {} 568 | metroTargetDeviceFamilies: {} 569 | metroFTAName: 570 | metroFTAFileTypes: [] 571 | metroProtocolName: 572 | metroCompilationOverrides: 1 573 | XboxOneProductId: 574 | XboxOneUpdateKey: 575 | XboxOneSandboxId: 576 | XboxOneContentId: 577 | XboxOneTitleId: 578 | XboxOneSCId: 579 | XboxOneGameOsOverridePath: 580 | XboxOnePackagingOverridePath: 581 | XboxOneAppManifestOverridePath: 582 | XboxOneVersion: 1.0.0.0 583 | XboxOnePackageEncryption: 0 584 | XboxOnePackageUpdateGranularity: 2 585 | XboxOneDescription: 586 | XboxOneLanguage: 587 | - enus 588 | XboxOneCapability: [] 589 | XboxOneGameRating: {} 590 | XboxOneIsContentPackage: 0 591 | XboxOneEnableGPUVariability: 1 592 | XboxOneSockets: {} 593 | XboxOneSplashScreen: {fileID: 0} 594 | XboxOneAllowedProductIds: [] 595 | XboxOnePersistentLocalStorageSize: 0 596 | XboxOneXTitleMemory: 8 597 | xboxOneScriptCompiler: 1 598 | XboxOneOverrideIdentityName: 599 | vrEditorSettings: 600 | daydream: 601 | daydreamIconForeground: {fileID: 0} 602 | daydreamIconBackground: {fileID: 0} 603 | cloudServicesEnabled: 604 | UNet: 1 605 | luminIcon: 606 | m_Name: 607 | m_ModelFolderPath: 608 | m_PortalFolderPath: 609 | luminCert: 610 | m_CertPath: 611 | m_PrivateKeyPath: 612 | luminIsChannelApp: 0 613 | luminVersion: 614 | m_VersionCode: 1 615 | m_VersionName: 616 | facebookSdkVersion: 7.9.4 617 | facebookAppId: 618 | facebookCookies: 1 619 | facebookLogging: 1 620 | facebookStatus: 1 621 | facebookXfbml: 0 622 | facebookFrictionlessRequests: 1 623 | apiCompatibilityLevel: 6 624 | cloudProjectId: 625 | framebufferDepthMemorylessMode: 0 626 | projectName: 627 | organizationId: 628 | cloudEnabled: 0 629 | enableNativePlatformBackendsForNewInputSystem: 0 630 | disableOldInputManagerSupport: 0 631 | legacyClampBlendShapeWeights: 0 632 | -------------------------------------------------------------------------------- /Assets/Editor/Xcode/ProjectCapabilityManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace Strings.iOS.Xcode 5 | { 6 | // This class is here to help you add capabilities to your Xcode project. 7 | // Because capabilities modify the PBXProject, the entitlements file and/or the Info.plist and not consistently, 8 | // it can be tedious. 9 | // Therefore this class open the PBXProject that is always modify by capabilities and open Entitlement and info.plist only when needed. 10 | // For optimisation reasons, we write the file only in the close method. 11 | // If you don't call it the file will not be written. 12 | public class ProjectCapabilityManager 13 | { 14 | private readonly string m_BuildPath; 15 | private readonly string m_TargetGuid; 16 | private readonly string m_PBXProjectPath; 17 | private readonly string m_EntitlementFilePath; 18 | private PlistDocument m_Entitlements; 19 | private PlistDocument m_InfoPlist; 20 | protected internal PBXProject project; 21 | 22 | // Create the manager with the required parameter to open files and set the properties in the write place. 23 | public ProjectCapabilityManager(string pbxProjectPath, string entitlementFilePath, string targetName) 24 | { 25 | m_BuildPath = Directory.GetParent(Path.GetDirectoryName(pbxProjectPath)).FullName; 26 | 27 | m_EntitlementFilePath = entitlementFilePath; 28 | m_PBXProjectPath = pbxProjectPath; 29 | project = new PBXProject(); 30 | project.ReadFromString(File.ReadAllText(m_PBXProjectPath)); 31 | m_TargetGuid = project.TargetGuidByName(targetName); 32 | } 33 | 34 | // Write the actual file to the disk. 35 | // If you don't call this method nothing will change. 36 | public void WriteToFile() 37 | { 38 | File.WriteAllText(m_PBXProjectPath, project.WriteToString()); 39 | if (m_Entitlements != null) 40 | m_Entitlements.WriteToFile(PBXPath.Combine(m_BuildPath, m_EntitlementFilePath)); 41 | if (m_InfoPlist != null) 42 | m_InfoPlist.WriteToFile(PBXPath.Combine(m_BuildPath, "Info.plist")); 43 | } 44 | 45 | // Add the iCloud capability with the desired options. 46 | public void AddiCloud(bool keyValueStorage, bool iCloudDocument, string[] customContainers) 47 | { 48 | var ent = GetOrCreateEntitlementDoc(); 49 | var val = (ent.root[ICloudEntitlements.ContainerIdValue] = new PlistElementArray()) as PlistElementArray; 50 | if (iCloudDocument) 51 | { 52 | val.values.Add(new PlistElementString(ICloudEntitlements.ContainerIdValue)); 53 | var ser = (ent.root[ICloudEntitlements.ServicesKey] = new PlistElementArray()) as PlistElementArray; 54 | ser.values.Add(new PlistElementString(ICloudEntitlements.ServicesKitValue)); 55 | ser.values.Add(new PlistElementString(ICloudEntitlements.ServicesDocValue)); 56 | var ubiquity = (ent.root[ICloudEntitlements.UbiquityContainerIdKey] = new PlistElementArray()) as PlistElementArray; 57 | ubiquity.values.Add(new PlistElementString(ICloudEntitlements.UbiquityContainerIdValue)); 58 | for (var i = 0; i < customContainers.Length; i++) 59 | { 60 | ser.values.Add(new PlistElementString(customContainers[i])); 61 | } 62 | } 63 | 64 | if (keyValueStorage) 65 | { 66 | ent.root[ICloudEntitlements.KeyValueStoreKey] = new PlistElementString(ICloudEntitlements.KeyValueStoreValue); 67 | } 68 | 69 | project.AddCapability(m_TargetGuid, PBXCapabilityType.iCloud, m_EntitlementFilePath, iCloudDocument); 70 | } 71 | 72 | // Add Push (or remote) Notifications capability to your project 73 | public void AddPushNotifications(bool development) 74 | { 75 | GetOrCreateEntitlementDoc().root[PushNotificationEntitlements.Key] = new PlistElementString(development ? PushNotificationEntitlements.DevelopmentValue : PushNotificationEntitlements.ProductionValue); 76 | project.AddCapability(m_TargetGuid, PBXCapabilityType.PushNotifications, m_EntitlementFilePath); 77 | } 78 | 79 | // Add GameCenter capability to the project. 80 | public void AddGameCenter() 81 | { 82 | var arr = (GetOrCreateInfoDoc().root[GameCenterInfo.Key] ?? (GetOrCreateInfoDoc().root[GameCenterInfo.Key] = new PlistElementArray())) as PlistElementArray; 83 | arr.values.Add(new PlistElementString(GameCenterInfo.Value)); 84 | project.AddCapability(m_TargetGuid, PBXCapabilityType.GameCenter); 85 | } 86 | 87 | // Add Wallet capability to the project. 88 | public void AddWallet(string[] passSubset) 89 | { 90 | var arr = (GetOrCreateEntitlementDoc().root[WalletEntitlements.Key] = new PlistElementArray()) as PlistElementArray; 91 | if ((passSubset == null || passSubset.Length == 0) && arr != null) 92 | { 93 | arr.values.Add(new PlistElementString(WalletEntitlements.BaseValue + WalletEntitlements.BaseValue)); 94 | } 95 | else 96 | { 97 | for (var i = 0; i < passSubset.Length; i++) 98 | { 99 | if (arr != null) 100 | arr.values.Add(new PlistElementString(WalletEntitlements.BaseValue + passSubset[i])); 101 | } 102 | } 103 | 104 | project.AddCapability(m_TargetGuid, PBXCapabilityType.Wallet, m_EntitlementFilePath); 105 | } 106 | 107 | // Add Siri capability to the project. 108 | public void AddSiri() 109 | { 110 | GetOrCreateEntitlementDoc().root[SiriEntitlements.Key] = new PlistElementBoolean(true); 111 | 112 | project.AddCapability(m_TargetGuid, PBXCapabilityType.Siri, m_EntitlementFilePath); 113 | } 114 | 115 | // Add Apple Pay capability to the project. 116 | public void AddApplePay(string[] merchants) 117 | { 118 | var arr = (GetOrCreateEntitlementDoc().root[ApplePayEntitlements.Key] = new PlistElementArray()) as PlistElementArray; 119 | for (var i = 0; i < merchants.Length; i++) 120 | { 121 | arr.values.Add(new PlistElementString(merchants[i])); 122 | } 123 | 124 | project.AddCapability(m_TargetGuid, PBXCapabilityType.ApplePay, m_EntitlementFilePath); 125 | } 126 | 127 | // Add In App Purchase capability to the project. 128 | public void AddInAppPurchase() 129 | { 130 | project.AddCapability(m_TargetGuid, PBXCapabilityType.InAppPurchase); 131 | } 132 | 133 | // Add Maps capability to the project. 134 | public void AddMaps(MapsOptions options) 135 | { 136 | var bundleArr = (GetOrCreateInfoDoc().root[MapsInfo.BundleKey] ?? (GetOrCreateInfoDoc().root[MapsInfo.BundleKey] = new PlistElementArray())) as PlistElementArray; 137 | bundleArr.values.Add(new PlistElementDict()); 138 | PlistElementDict bundleDic = GetOrCreateUniqueDictElementInArray(bundleArr); 139 | bundleDic[MapsInfo.BundleNameKey] = new PlistElementString(MapsInfo.BundleNameValue); 140 | var bundleTypeArr = (bundleDic[MapsInfo.BundleTypeKey] ?? (bundleDic[MapsInfo.BundleTypeKey] = new PlistElementArray())) as PlistElementArray; 141 | GetOrCreateStringElementInArray(bundleTypeArr, MapsInfo.BundleTypeValue); 142 | 143 | var optionArr = (GetOrCreateInfoDoc().root[MapsInfo.ModeKey] ?? 144 | (GetOrCreateInfoDoc().root[MapsInfo.ModeKey] = new PlistElementArray())) as PlistElementArray; 145 | if ((options & MapsOptions.Airplane) == MapsOptions.Airplane) 146 | { 147 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModePlaneValue); 148 | } 149 | if ((options & MapsOptions.Bike) == MapsOptions.Bike) 150 | { 151 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeBikeValue); 152 | } 153 | if ((options & MapsOptions.Bus) == MapsOptions.Bus) 154 | { 155 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeBusValue); 156 | } 157 | if ((options & MapsOptions.Car) == MapsOptions.Car) 158 | { 159 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeCarValue); 160 | } 161 | if ((options & MapsOptions.Ferry) == MapsOptions.Ferry) 162 | { 163 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeFerryValue); 164 | } 165 | if ((options & MapsOptions.Other) == MapsOptions.Other) 166 | { 167 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeOtherValue); 168 | } 169 | if ((options & MapsOptions.Pedestrian) == MapsOptions.Pedestrian) 170 | { 171 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModePedestrianValue); 172 | } 173 | if ((options & MapsOptions.RideSharing) == MapsOptions.RideSharing) 174 | { 175 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeRideShareValue); 176 | } 177 | if ((options & MapsOptions.StreetCar) == MapsOptions.StreetCar) 178 | { 179 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeStreetCarValue); 180 | } 181 | if ((options & MapsOptions.Subway) == MapsOptions.Subway) 182 | { 183 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeSubwayValue); 184 | } 185 | if ((options & MapsOptions.Taxi) == MapsOptions.Taxi) 186 | { 187 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeTaxiValue); 188 | } 189 | if ((options & MapsOptions.Train) == MapsOptions.Train) 190 | { 191 | GetOrCreateStringElementInArray(optionArr, MapsInfo.ModeTrainValue); 192 | } 193 | 194 | project.AddCapability(m_TargetGuid, PBXCapabilityType.Maps); 195 | } 196 | 197 | // Add Personal VPN capability to the project. 198 | public void AddPersonalVPN() 199 | { 200 | var arr = (GetOrCreateEntitlementDoc().root[VPNEntitlements.Key] = new PlistElementArray()) as PlistElementArray; 201 | arr.values.Add(new PlistElementString(VPNEntitlements.Value)); 202 | 203 | project.AddCapability(m_TargetGuid, PBXCapabilityType.PersonalVPN, m_EntitlementFilePath); 204 | } 205 | 206 | // Add Background capability to the project with the options wanted. 207 | public void AddBackgroundModes(BackgroundModesOptions options) 208 | { 209 | var optionArr = (GetOrCreateInfoDoc().root[BackgroundInfo.Key] ?? 210 | (GetOrCreateInfoDoc().root[BackgroundInfo.Key] = new PlistElementArray())) as PlistElementArray; 211 | 212 | if ((options & BackgroundModesOptions.ActsAsABluetoothLEAccessory) == BackgroundModesOptions.ActsAsABluetoothLEAccessory) 213 | { 214 | GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeActsBluetoothValue); 215 | } 216 | if ((options & BackgroundModesOptions.AudioAirplayPiP) == BackgroundModesOptions.AudioAirplayPiP) 217 | { 218 | GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeAudioValue); 219 | } 220 | if ((options & BackgroundModesOptions.BackgroundFetch) == BackgroundModesOptions.BackgroundFetch) 221 | { 222 | GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeFetchValue); 223 | } 224 | if ((options & BackgroundModesOptions.ExternalAccessoryCommunication) == BackgroundModesOptions.ExternalAccessoryCommunication) 225 | { 226 | GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeExtAccessoryValue); 227 | } 228 | if ((options & BackgroundModesOptions.LocationUpdates) == BackgroundModesOptions.LocationUpdates) 229 | { 230 | GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeLocationValue); 231 | } 232 | if ((options & BackgroundModesOptions.NewsstandDownloads) == BackgroundModesOptions.NewsstandDownloads) 233 | { 234 | GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeNewsstandValue); 235 | } 236 | if ((options & BackgroundModesOptions.RemoteNotifications) == BackgroundModesOptions.RemoteNotifications) 237 | { 238 | GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModePushValue); 239 | } 240 | if ((options & BackgroundModesOptions.VoiceOverIP) == BackgroundModesOptions.VoiceOverIP) 241 | { 242 | GetOrCreateStringElementInArray(optionArr, BackgroundInfo.ModeVOIPValue); 243 | } 244 | project.AddCapability(m_TargetGuid, PBXCapabilityType.BackgroundModes); 245 | } 246 | 247 | // Add Keychain Sharing capability to the project with a list of groups. 248 | public void AddKeychainSharing(string[] accessGroups) 249 | { 250 | var arr = (GetOrCreateEntitlementDoc().root[KeyChainEntitlements.Key] = new PlistElementArray()) as PlistElementArray; 251 | if (accessGroups != null) 252 | { 253 | for (var i = 0; i < accessGroups.Length; i++) 254 | { 255 | arr.values.Add(new PlistElementString(accessGroups[i])); 256 | } 257 | } 258 | else 259 | { 260 | arr.values.Add(new PlistElementString(KeyChainEntitlements.DefaultValue)); 261 | } 262 | 263 | project.AddCapability(m_TargetGuid, PBXCapabilityType.KeychainSharing, m_EntitlementFilePath); 264 | } 265 | 266 | // Add Inter App Audio capability to the project. 267 | public void AddInterAppAudio() 268 | { 269 | GetOrCreateEntitlementDoc().root[AudioEntitlements.Key] = new PlistElementBoolean(true); 270 | project.AddCapability(m_TargetGuid, PBXCapabilityType.InterAppAudio, m_EntitlementFilePath); 271 | } 272 | 273 | // Add Associated Domains capability to the project. 274 | public void AddAssociatedDomains(string[] domains) 275 | { 276 | var arr = (GetOrCreateEntitlementDoc().root[AssociatedDomainsEntitlements.Key] = new PlistElementArray()) as PlistElementArray; 277 | for (var i = 0; i < domains.Length; i++) 278 | { 279 | arr.values.Add(new PlistElementString(domains[i])); 280 | } 281 | 282 | project.AddCapability(m_TargetGuid, PBXCapabilityType.AssociatedDomains, m_EntitlementFilePath); 283 | } 284 | 285 | // Add App Groups capability to the project. 286 | public void AddAppGroups(string[] groups) 287 | { 288 | var arr = (GetOrCreateEntitlementDoc().root[AppGroupsEntitlements.Key] = new PlistElementArray()) as PlistElementArray; 289 | for (var i = 0; i < groups.Length; i++) 290 | { 291 | arr.values.Add(new PlistElementString(groups[i])); 292 | } 293 | 294 | project.AddCapability(m_TargetGuid, PBXCapabilityType.AppGroups, m_EntitlementFilePath); 295 | } 296 | 297 | // Add HomeKit capability to the project. 298 | public void AddHomeKit() 299 | { 300 | GetOrCreateEntitlementDoc().root[HomeKitEntitlements.Key] = new PlistElementBoolean(true); 301 | project.AddCapability(m_TargetGuid, PBXCapabilityType.HomeKit, m_EntitlementFilePath); 302 | } 303 | 304 | // Add Data Protection capability to the project. 305 | public void AddDataProtection() 306 | { 307 | GetOrCreateEntitlementDoc().root[DataProtectionEntitlements.Key] = new PlistElementString(DataProtectionEntitlements.Value); 308 | project.AddCapability(m_TargetGuid, PBXCapabilityType.DataProtection, m_EntitlementFilePath); 309 | } 310 | 311 | // Add HealthKit capability to the project. 312 | public void AddHealthKit() 313 | { 314 | var capabilityArr = (GetOrCreateInfoDoc().root[HealthInfo.Key] ?? 315 | (GetOrCreateInfoDoc().root[HealthInfo.Key] = new PlistElementArray())) as PlistElementArray; 316 | GetOrCreateStringElementInArray(capabilityArr, HealthInfo.Value); 317 | GetOrCreateEntitlementDoc().root[HealthKitEntitlements.Key] = new PlistElementBoolean(true); 318 | project.AddCapability(m_TargetGuid, PBXCapabilityType.HealthKit, m_EntitlementFilePath); 319 | } 320 | 321 | // Add Wireless Accessory Configuration capability to the project. 322 | public void AddWirelessAccessoryConfiguration() 323 | { 324 | GetOrCreateEntitlementDoc().root[WirelessAccessoryConfigurationEntitlements.Key] = new PlistElementBoolean(true); 325 | project.AddCapability(m_TargetGuid, PBXCapabilityType.WirelessAccessoryConfiguration, m_EntitlementFilePath); 326 | } 327 | 328 | private PlistDocument GetOrCreateEntitlementDoc() 329 | { 330 | if (m_Entitlements == null) 331 | { 332 | m_Entitlements = new PlistDocument(); 333 | string[] entitlementsFiles = Directory.GetFiles(m_BuildPath, m_EntitlementFilePath); 334 | if (entitlementsFiles.Length > 0) 335 | { 336 | m_Entitlements.ReadFromFile(entitlementsFiles[0]); 337 | } 338 | else 339 | { 340 | m_Entitlements.Create(); 341 | } 342 | } 343 | 344 | return m_Entitlements; 345 | } 346 | 347 | private PlistDocument GetOrCreateInfoDoc() 348 | { 349 | if (m_InfoPlist == null) 350 | { 351 | m_InfoPlist = new PlistDocument(); 352 | string[] infoFiles = Directory.GetFiles(m_BuildPath + "/", "Info.plist"); 353 | if (infoFiles.Length > 0) 354 | { 355 | m_InfoPlist.ReadFromFile(infoFiles[0]); 356 | } 357 | else 358 | { 359 | m_InfoPlist.Create(); 360 | } 361 | } 362 | 363 | return m_InfoPlist; 364 | } 365 | 366 | private PlistElementString GetOrCreateStringElementInArray(PlistElementArray root, string value) 367 | { 368 | PlistElementString r = null; 369 | var c = root.values.Count; 370 | var exist = false; 371 | for (var i = 0; i < c; i++) 372 | { 373 | if (root.values[i] is PlistElementString && (root.values[i] as PlistElementString).value == value) 374 | { 375 | r = root.values[i] as PlistElementString; 376 | exist = true; 377 | } 378 | } 379 | if (!exist) 380 | { 381 | r = new PlistElementString(value); 382 | root.values.Add(r); 383 | } 384 | return r; 385 | } 386 | 387 | private PlistElementDict GetOrCreateUniqueDictElementInArray(PlistElementArray root) 388 | { 389 | PlistElementDict r; 390 | if (root.values.Count == 0) 391 | { 392 | r = root.values[0] as PlistElementDict; 393 | } 394 | else 395 | { 396 | r = new PlistElementDict(); 397 | root.values.Add(r); 398 | } 399 | return r; 400 | } 401 | } 402 | 403 | // The list of options available for Background Mode. 404 | [Flags] 405 | [Serializable] 406 | public enum BackgroundModesOptions 407 | { 408 | None = 0, 409 | AudioAirplayPiP = 1<<0, 410 | LocationUpdates = 1<<1, 411 | VoiceOverIP = 1<<2, 412 | NewsstandDownloads = 1<<3, 413 | ExternalAccessoryCommunication = 1<<4, 414 | UsesBluetoothLEAccessory = 1<<5, 415 | ActsAsABluetoothLEAccessory = 1<<6, 416 | BackgroundFetch = 1<<7, 417 | RemoteNotifications = 1<<8 418 | } 419 | 420 | // The list of options available for Maps. 421 | [Serializable] 422 | [Flags] 423 | public enum MapsOptions 424 | { 425 | None = 0, 426 | Airplane = 1<<0, 427 | Bike = 1<<1, 428 | Bus = 1<<2, 429 | Car = 1<<3, 430 | Ferry = 1<<4, 431 | Pedestrian = 1<<5, 432 | RideSharing = 1<<6, 433 | StreetCar = 1<<7, 434 | Subway = 1<<8, 435 | Taxi = 1<<9, 436 | Train = 1<<10, 437 | Other = 1<<11 438 | } 439 | 440 | /* Follows the large quantity of string used as key and value all over the place in the info.plist or entitlements file. */ 441 | internal class GameCenterInfo 442 | { 443 | internal static readonly string Key = "UIRequiredDeviceCapabilities"; 444 | internal static readonly string Value = "gamekit"; 445 | } 446 | 447 | internal class MapsInfo 448 | { 449 | internal static readonly string BundleKey = "CFBundleDocumentTypes"; 450 | internal static readonly string BundleNameKey = "CFBundleTypeName"; 451 | internal static readonly string BundleNameValue = "MKDirectionsRequest"; 452 | internal static readonly string BundleTypeKey = "LSItemContentTypes"; 453 | internal static readonly string BundleTypeValue = "com.apple.maps.directionsrequest"; 454 | internal static readonly string ModeKey = "MKDirectionsApplicationSupportedModes"; 455 | internal static readonly string ModePlaneValue = "MKDirectionsModePlane"; 456 | internal static readonly string ModeBikeValue = "MKDirectionsModeBike"; 457 | internal static readonly string ModeBusValue = "MKDirectionsModeBus"; 458 | internal static readonly string ModeCarValue = "MKDirectionsModeCar"; 459 | internal static readonly string ModeFerryValue = "MKDirectionsModeFerry"; 460 | internal static readonly string ModeOtherValue = "MKDirectionsModeOther"; 461 | internal static readonly string ModePedestrianValue = "MKDirectionsModePedestrian"; 462 | internal static readonly string ModeRideShareValue = "MKDirectionsModeRideShare"; 463 | internal static readonly string ModeStreetCarValue = "MKDirectionsModeStreetCar"; 464 | internal static readonly string ModeSubwayValue = "MKDirectionsModeSubway"; 465 | internal static readonly string ModeTaxiValue = "MKDirectionsModeTaxi"; 466 | internal static readonly string ModeTrainValue = "MKDirectionsModeTrain"; 467 | } 468 | 469 | internal class BackgroundInfo 470 | { 471 | internal static readonly string Key = "UIBackgroundModes"; 472 | internal static readonly string ModeAudioValue = "audio"; 473 | internal static readonly string ModeBluetoothValue = "bluetooth-central"; 474 | internal static readonly string ModeActsBluetoothValue = "bluetooth-peripheral"; 475 | internal static readonly string ModeExtAccessoryValue = "external-accessory"; 476 | internal static readonly string ModeFetchValue = "fetch"; 477 | internal static readonly string ModeLocationValue = "location"; 478 | internal static readonly string ModeNewsstandValue = "newsstand-content"; 479 | internal static readonly string ModePushValue = "remote-notification"; 480 | internal static readonly string ModeVOIPValue = "voip"; 481 | } 482 | 483 | internal class HealthInfo 484 | { 485 | internal static readonly string Key = "UIRequiredDeviceCapabilities"; 486 | internal static readonly string Value = "healthkit"; 487 | } 488 | 489 | internal class ICloudEntitlements 490 | { 491 | internal static readonly string ContainerIdKey = "com.apple.developer.icloud-container-identifiers"; 492 | internal static readonly string UbiquityContainerIdKey = "com.apple.developer.ubiquity-container-identifiers"; 493 | internal static readonly string ContainerIdValue = "iCloud.$(CFBundleIdentifier)"; 494 | internal static readonly string UbiquityContainerIdValue = "iCloud.$(CFBundleIdentifier)"; 495 | internal static readonly string ServicesKey = "com.apple.developer.icloud-services"; 496 | internal static readonly string ServicesDocValue = "CloudDocuments"; 497 | internal static readonly string ServicesKitValue = "CloudKit"; 498 | internal static readonly string KeyValueStoreKey = "com.apple.developer.ubiquity-kvstore-identifier"; 499 | internal static readonly string KeyValueStoreValue = "$(TeamIdentifierPrefix)$(CFBundleIdentifier)"; 500 | } 501 | 502 | internal class PushNotificationEntitlements 503 | { 504 | internal static readonly string Key = "aps-environment"; 505 | internal static readonly string DevelopmentValue = "development"; 506 | internal static readonly string ProductionValue = "production"; 507 | } 508 | 509 | internal class WalletEntitlements 510 | { 511 | internal static readonly string Key = "com.apple.developer.pass-type-identifiers"; 512 | internal static readonly string BaseValue = "$(TeamIdentifierPrefix)"; 513 | internal static readonly string DefaultValue = "*"; 514 | } 515 | 516 | internal class SiriEntitlements 517 | { 518 | internal static readonly string Key = "com.apple.developer.siri"; 519 | } 520 | 521 | internal class ApplePayEntitlements 522 | { 523 | internal static readonly string Key = "com.apple.developer.in-app-payments"; 524 | } 525 | 526 | internal class VPNEntitlements 527 | { 528 | internal static readonly string Key = "com.apple.developer.networking.vpn.api"; 529 | internal static readonly string Value = "allow-vpn"; 530 | } 531 | 532 | internal class KeyChainEntitlements 533 | { 534 | internal static readonly string Key = "keychain-access-groups"; 535 | internal static readonly string DefaultValue = "$(AppIdentifierPrefix)$(CFBundleIdentifier)"; 536 | } 537 | 538 | internal class AudioEntitlements 539 | { 540 | internal static readonly string Key = "inter-app-audio"; 541 | } 542 | 543 | internal class AssociatedDomainsEntitlements 544 | { 545 | // value is an array of string of domains 546 | internal static readonly string Key = "com.apple.developer.associated-domains"; 547 | } 548 | 549 | internal class AppGroupsEntitlements 550 | { 551 | // value is an array of string of groups 552 | internal static readonly string Key = "com.apple.security.application-groups"; 553 | } 554 | 555 | internal class HomeKitEntitlements 556 | { 557 | // value is bool true. 558 | internal static readonly string Key = "com.apple.developer.homekit"; 559 | } 560 | 561 | internal class DataProtectionEntitlements 562 | { 563 | internal static readonly string Key = "com.apple.developer.default-data-protection"; 564 | internal static readonly string Value = "NSFileProtectionComplete"; 565 | } 566 | 567 | internal class HealthKitEntitlements 568 | { 569 | // value is bool true. 570 | internal static readonly string Key = "com.apple.developer.healthkit"; 571 | } 572 | 573 | internal class WirelessAccessoryConfigurationEntitlements 574 | { 575 | // value is bool true. 576 | internal static readonly string Key = "com.apple.external-accessory.wireless-configuration"; 577 | } 578 | } 579 | --------------------------------------------------------------------------------