LoginSignup
1
2

More than 1 year has passed since last update.

Xcode設定自動化スクリプト

Last updated at Posted at 2017-10-16

PBXProjectEditor.cs

PBXProjectEditor.cs
#if UNITY_IOS
/**
 * @file     PBXProjectEditor.cs
 * @brief    PBXプロジェクトの編集を行う。
 * @date     $Date$
 * @version  $Rev$
 * @author   $Author$
 */
using UnityEditor;
using UnityEditor.iOS.Xcode;
using UnityEditor.iOS.Xcode.Extensions;
using System;
using System.IO;
using System.Collections.Generic;

namespace yyama2.Editor.XCProjEdit
{

    /// <summary>
    /// PBXプロジェクトのプロパティを設定する。
    /// 
    /// 
    /// 設定は下記の様に定義してください。
    /// 
    /// ■file操作(追加・削除・移動) ※PBXParamFile.FileParam参照
    /// new List() {
    ///     new PBXParamFile.FileParam( 
    ///         type, 
    ///         fromDir, 
    ///         fromFile, 
    ///         toDir, 
    ///         toFile, 
    ///         compileFlag // 省略可
    ///     ),
    /// }
    /// 
    /// ■Framework ※PBXParamFramework参照
    /// new Dictionary<string, int>() {
    ///     { "value.framework", 1 },
    /// } 
    /// 
    /// ■Property設定 ※PBXParamProperty.PropertyParams参照
    /// new Dictionary<string, List<PBXParamProperty.PropertyParams>>() { 
    ///     "property", 
    ///     new List<PBXParamProperty.PropertyParams>() {
    ///         new PBXParamProperty.PropertyParams( 
    ///             configType:"config_type",          // configType
    ///             addValue:new string[]{ "YES" },  // AddValue
    ///             nremoveType:ew string[]{ "NO" },   // RemoveValue
    ///             forceOverride:false                   // 上書きフラグ
    ///         ), 
    ///     }
    /// },
    /// </summary>
    public static class PBXProjectEditor
    {

        /// <summary> Unityデフォルトのプロジェクト名(基本変更しなくていい)</summary>
        public const string NATIVE_TARGET_NAME = "Unity-iPhone";
        /// <summary> XcodeProjectの拡張子</summary>
        public const string XCODE_PROJ_FILE_EXTENSION = ".xcodeproj";
        /// <summary> XcodeProjectファイル</summary>
        public const string XCODE_PROJ_FILE = NATIVE_TARGET_NAME + XCODE_PROJ_FILE_EXTENSION;
        /// <summary> PBXプロジェクトファイル</summary>
        public const string PBX_PROJ_FILE = "project.pbxproj";

        /// <summary> project.pbxprojのパスを取得する</summary>
        /// <param name="path"> project.pbxprojのあるフォルダパス</param>
        /// <returns> project.pbxprojのファイルパス</returns>
        public static string GetDefaultPBXProjectPath(string path)
        {
            return Path.Combine(Path.Combine(path, XCODE_PROJ_FILE), PBX_PROJ_FILE);
        }

        /// <summary>
        /// PBXプロジェクトの編集
        /// </summary>
        /// <param name="pbxProjPath">Pbx proj path.</param>
        /// <param name="pbxParams">Pbx parameters.</param>
        /// <param name="callClass">この関数を呼び出しているクラスタイプ.ログ出力に飲み使用します.typeof( クラス )</param>
        public static void PBXProjectEdit(string pbxProjPath, List<PBXParam> pbxParams, Type callClass = null, bool isMain = true)
        {
            string className = "";

            if (callClass != null)
            {
                className += callClass.Name;
            }
            UnityEngine.Debug.Log("PBXProjectEditor:" + className);
            string log = "======================= PBXProjectValue =======================\n";
            UnityEngine.Debug.Log("pbxProjPath=>" + pbxProjPath);
            PBXProject pbxProj = new PBXProject();
            pbxProj.ReadFromFile(pbxProjPath);

            foreach (PBXParam param in pbxParams)
            {
                param.Edit(ref pbxProj);
            }

            pbxProj.WriteToFile(pbxProjPath);

            log += className + "\n";
            foreach (PBXParam param in pbxParams)
            {
                log += param.GetParamLog();
            }

            log += "\n======================= PBXProjectValue =======================";
            UnityEngine.Debug.Log(log);
        }

    }

    /// <summary>
    /// 設定項目のクラス。 
    /// </summary>
    public abstract class PBXParam
    {
        public enum ProjectType
        {
            Main = 1 << 0,
            Framework = 1 << 1,
        }
        /// <summary>
        /// 設定されているパラメータのログ。
        /// </summary>
        /// <returns>The parameter log.</returns>
        public abstract string GetParamLog();
        /// <summary>
        /// 設定の編集を行う
        /// </summary>
        /// <param name="pbxProj">Pbx projct.</param>
        public abstract void Edit(ref PBXProject pbxProj);

        /// <summary>
        /// プロジェクト名のリスト(基本的には、Unity-iPhoneのみ)
        /// </summary>
        private ProjectType m_projectType;


        /// <summary>
        /// プロジェクトのguidを取得する。
        /// </summary>
        /// <returns>The project guids.</returns>
        /// <param name="pbxProj">Pbx project.</param>
        protected IEnumerable<string> GetProjectGuids(PBXProject pbxProj)
        {
            var guids = new List<string>();
            if ((m_projectType & ProjectType.Main) == ProjectType.Main)
            {
                guids.Add(pbxProj.GetUnityMainTargetGuid());
            }
            if ((m_projectType & ProjectType.Framework) == ProjectType.Framework)
            {
                guids.Add(pbxProj.GetUnityFrameworkTargetGuid());
            }
            return guids;
        }

        /// <summary>
        /// コンストラクタ。継承先のクラスで必ず呼び出すこと( GetProjectGuids()で使用します。 )
        /// </summary>
        /// <param name="projectType">Project types.</param>
        public PBXParam(ProjectType projectType)
        {
            m_projectType = projectType;
        }
    }

    /// <summary>
    /// プロジェクトに設定されているファイルを追加するクラス。
    /// </summary>
    public class PBXParamFile : PBXParam
    {

        /// <summary> 編集を行うかどうか</summary>
        private readonly List<FileParam> m_params;

        /// <summary> Xcodeプロジェクトのディレクトリ</summary>
        private readonly string m_xcodePath;

        /// <summary>
        /// どのようなファイル操作を行うか。
        /// </summary>
        public enum FileEditType
        {
            /// <summary> ファイルの追加 </summary>
            ADD,
            /// <summary> ファイルのリネーム(移動)</summary>
            MOVE,
            /// <summary> ファイルの削除(物理削除は行わない)</summary>
            REMOVE,
        }

        /// <summary>
        /// 変更設定。
        /// </summary>
        public class FileParam
        {

            /// <summary> edit type.</summary>
            public FileEditType Type { get; private set; }
            /// <summary> form directory path.</summary>
            public string FromDirPath { get; private set; }
            /// <summary> from file name.</summary>
            public string FromFileName { get; private set; }
            /// <summary> to directory path.</summary>
            public string ToDirPath { get; private set; }
            /// <summary> to file name.</summary>
            public string ToFileName { get; private set; }
            /// <summary> to file name.</summary>
            public string CompileFlags { get; private set; }
            public bool CodeSignOnCopy { get; private set; }
            public bool RemoveHeadersOnCopy { get; private set; }


            /// <summary>
            /// <para>指定するタイプによって引数の使い分けを行う。</para>
            /// <para></para>
            /// <para>ADD</para>
            /// <para>(Unityから自動で転送されないファイルをXcodeに転送してプロジェクトに追加する)</para>
            /// <para>_fromDir : Unity上(Assetsを除く)</para>
            /// <para>fromFile : Unity上のファイル名</para>
            /// <para>___toDir : Xcode上のディレクトリ</para>
            /// <para>__toFile : Xcode上のファイル名</para>
            /// <para></para>
            /// <para>MOVE</para>
            /// <para>(Xcode上からファイルを移動(リネーム)する)</para>
            /// <para>_fromDir : Xcode上で移動前のディレクトリ</para>
            /// <para>fromFile : Xcode上で移動前のファイル名</para>
            /// <para>___toDir : Xcode上で移動後のディレクトリ</para>
            /// <para>__toFile : Xcode上で移動後のファイル名</para>
            /// <para></para>
            /// <para>REMOVE</para>
            /// <para>(Xcode上からファイルを削除する)</para>
            /// <para>_fromDir : Xcode上のディレクトリ</para>
            /// <para>fromFile : Xcode上のファイル名</para>
            /// <para>___toDir : -</para>
            /// <para>__toFile : -</para>
            /// </summary>
            /// <param name="type">Type.</param>
            /// <param name="fromDir">From dir.</param>
            /// <param name="fromFile">From file.</param>
            /// <param name="toDir">To dir.</param>
            /// <param name="toFile">To file.</param>
            /// <param name="compileFlags">Compile Flags.</param>
            public FileParam(FileEditType type, string fromDir, string fromFile, string toDir = null, string toFile = null, string compileFlags = null, bool codeSignOnCopy = false, bool removeHeadersOnCopy = false)
            {
                if (type != FileEditType.REMOVE)
                {
                    var param = "";
                    var isNull = false;
                    if (toDir == null)
                    {
                        param += "toDir";
                        isNull = true;
                    }
                    if (toFile == null)
                    {
                        if (isNull)
                        {
                            param += ", ";
                        }
                        param += "toFile";
                    }
                    if (isNull)
                    {
                        throw new System.ArgumentNullException(param, "If type is not REMOVE, you must set toXXX parameter!");
                    }
                }
                if (toFile == null)
                {
                    toFile = fromFile;
                }
                if (toDir == null)
                {
                    toDir = fromDir;
                }
                this.Type = type;
                this.FromDirPath = fromDir;
                this.FromFileName = fromFile;
                this.ToDirPath = toDir;
                this.ToFileName = toFile;
                this.CompileFlags = compileFlags;
                this.CodeSignOnCopy = codeSignOnCopy;
                this.RemoveHeadersOnCopy = removeHeadersOnCopy;
            }

            /// <summary>
            /// ログを作成.
            /// </summary>
            public string CreateLog()
            {
                var log = "[File:";

                switch (Type)
                {
                    case FileEditType.ADD:
                        log += "Add]" + "\n\tUnity file: " + CombinePath(FromDirPath, FromFileName) + "\n\tXcode file: " + CombinePath(ToDirPath, ToFileName + "\n\tCompile flags: " + CompileFlags);
                        break;
                    case FileEditType.MOVE:
                        log += "Move]" + "\n\tXC before file: " + CombinePath(FromDirPath, FromFileName) + "\n\tXC  after file: " + CombinePath(ToDirPath, ToFileName + "\n\tCompile flags: " + CompileFlags);
                        break;
                    case FileEditType.REMOVE:
                        log += "Delete]" + "\n\tDelete file: " + CombinePath(FromDirPath, FromFileName);
                        break;
                }
                return log;
            }
        }

        /// <summary>
        /// 設定されているパラメータのログ。
        /// </summary>
        /// <returns>The parameter log.</returns>
        public override string GetParamLog()
        {
            var log = "";

            foreach (FileParam param in m_params)
            {
                log += param.CreateLog() + "\n";
            }
            return log;
        }

        /// <summary>
        /// 設定の編集を行う
        /// </summary>
        /// <param name="pbxProj">Pbx projct.</param>
        public override void Edit(ref PBXProject pbxProj)
        {
            foreach (FileParam param in m_params)
            {
                switch (param.Type)
                {
                    case FileEditType.ADD:
                        {
                            // ファイルを追加する
                            AddFile(ref pbxProj, param);
                            break;
                        }
                    case FileEditType.MOVE:
                        {
                            // ファイルのリネームや移動
                            MoveFile(ref pbxProj, param);
                            break;
                        }
                    case FileEditType.REMOVE:
                        {
                            // ファイルの削除
                            RemoveFile(ref pbxProj, param);
                            break;
                        }
                }
            }
        }

        /// <summary>
        /// Unity上にはあるが、プロジェクトに追加されていないファイルをXcodeプロジェクトに追加する。
        /// </summary>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="param">Parameter.</param>
        private void AddFile(ref PBXProject pbxProj, FileParam param)
        {
            // UnityのファイルをXcodeにコピーする
            var unityPath = CombinePath(UnityEngine.Application.dataPath, param.FromDirPath, param.FromFileName);
            var xcodePath = CombinePath(m_xcodePath, param.ToDirPath, param.ToFileName);
            CopyFile(unityPath, xcodePath);
            var addPath = CombinePath(param.ToDirPath, param.ToFileName);
            AddFileProc(ref pbxProj, addPath, param);
        }

        /// <summary>
        /// Xcodeにファイルを追加する
        /// </summary>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="addPath">Add path.</param>
        /// <param name="compileFlag">Compile flag.</param>
        private void AddFileProc(ref PBXProject pbxProj, string addPath, FileParam param)// string compileFlag)
        {
            // ファイル参照をプロジェクトに追加
            var fileGuid = pbxProj.AddFile(addPath, addPath);

            // プロジェクトの設定(BuildPhase)に追加
            foreach (var guid in GetProjectGuids(pbxProj))
            {
                if (param.CodeSignOnCopy) PBXProjectExtensions.AddFileToEmbedFrameworks(pbxProj, guid, fileGuid);
                pbxProj.AddFileToBuildWithFlags(guid, fileGuid, param.CompileFlags);
            }
        }

        /// <summary>
        /// Xcodeのファイルを移動(リネーム)する
        /// </summary>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="param">Parameter.</param>
        private void MoveFile(ref PBXProject pbxProj, FileParam param)
        {
            var beforePath = CombinePath(param.FromDirPath, param.FromFileName);
            var afterPath = CombinePath(param.ToDirPath, param.ToFileName);
            // 既存のファイルを削除
            RemoveFileProc(ref pbxProj, beforePath);

            // 既存のファイルのリネーム
            MoveFile(CombinePath(m_xcodePath, beforePath), CombinePath(m_xcodePath, afterPath));

            // リネーム後ファイルの追加
            AddFileProc(ref pbxProj, afterPath, param);
        }

        /// <summary>
        /// Xcodeに追加されているファイルの削除(物理削除は行わない)
        /// </summary>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="param">Parameter.</param>
        private void RemoveFile(ref PBXProject pbxProj, FileParam param)
        {
            var removePath = CombinePath(param.FromDirPath, param.FromFileName);
            RemoveFileProc(ref pbxProj, removePath);
        }

        /// <summary>
        /// Xcodeに追加されているファイルの削除(物理削除は行わない)
        /// </summary>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="removePath">Remove path.</param>
        private void RemoveFileProc(ref PBXProject pbxProj, string removePath)
        {
            if (!pbxProj.ContainsFileByProjectPath(removePath)) return;

            var fileGuid = pbxProj.FindFileGuidByProjectPath(removePath);
            foreach (var guid in GetProjectGuids(pbxProj))
            {
                pbxProj.RemoveFileFromBuild(guid, fileGuid);
            }
            pbxProj.RemoveFile(fileGuid);
        }

        /// <summary>
        /// ファイルの親ディレクトリを作成する。
        /// </summary>
        /// <param name="filePath">File path.</param>
        public static void CreateParentDirectory(string filePath)
        {
            var files = filePath.Split("/"[0]);

            string path = null;
            for (int i = 0; i < files.Length - 1; ++i)
            {
                path = path == null ? files[i] : path + "/" + files[i];
                if (string.IsNullOrEmpty(path)) continue;
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
            }
        }
        /// <summary>
        /// ファイルをコピーする.
        /// </summary>
        /// <param name="fromFile">From file.</param>
        /// <param name="toFile">To file.</param>
        public static void CopyFile(string fromFile, string toFile)
        {
            CreateParentDirectory(toFile);
            FileUtil.CopyFileOrDirectory(fromFile, toFile);
        }

        /// <summary>
        /// ファイルを移動(リネーム)する。
        /// </summary>
        /// <param name="fromFile">From file.</param>
        /// <param name="toFile">To file.</param>
        public static void MoveFile(string fromFile, string toFile)
        {
            CreateParentDirectory(toFile);
            FileUtil.MoveFileOrDirectory(fromFile, toFile);
        }

        /// <summary>
        /// パスの結合
        /// </summary>
        /// <returns>The path.</returns>
        /// <param name="fileAndDir">File and dir.</param>
        public static string CombinePath(params string[] fileAndDir)
        {
            string root = fileAndDir[0];
            for (int i = 1; i < fileAndDir.Length; ++i)
            {
                root = Path.Combine(root, fileAndDir[i]);
            }
            return root;
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="parameters">Parameters.</param>
        /// <param name="xcodePath">Xcode path.</param>
        /// <param name="projectNames">Project names.</param>
        public PBXParamFile(List<FileParam> parameters, string xcodePath, ProjectType projectType = ProjectType.Main) : base(projectType)
        {
            m_params = parameters;
            m_xcodePath = xcodePath;
        }
    }

    /// <summary>
    /// Framework変更
    /// </summary>
    public class PBXParamFramework : PBXParam
    {

        /// <summary>
        /// Framework設定
        /// </summary>
        private readonly Dictionary<string, int> m_framemworks;

        /// <summary>
        /// ログ用の文字列作成
        /// </summary>
        /// <returns>The parameter log.</returns>
        public override string GetParamLog()
        {
            string log = "";
            foreach (KeyValuePair<string, int> framework in m_framemworks)
            {
                log += "[Framework] " + framework.Key + ": " +
                (
                    (framework.Value == -1) ? "Delete!!" :
                    (
                        (framework.Value == 1) ? "Optional" : "Required"
                    )
                ) + "\n";
            }
            return log;
        }

        /// <summary>
        /// 設定の編集を行う
        /// </summary>
        /// <param name="pbxProj">Pbx projct.</param>
        public override void Edit(ref PBXProject pbxProj)
        {
            IEnumerable<string> guids = GetProjectGuids(pbxProj);
            foreach (string guid in guids)
            {
                foreach (KeyValuePair<string, int> framemwork in m_framemworks)
                {
                    if (framemwork.Value == -1)
                        pbxProj.RemoveFrameworkFromProject(guid, framemwork.Key);
                    else
                        pbxProj.AddFrameworkToProject(guid, framemwork.Key, framemwork.Value == 1);
                }
            }
        }

        /// <summary>
        /// コンストラクタ
        /// 
        /// new Dictionary<string, int>() {
        ///     { "value1", 0 }, // Required
        ///     { "value2", 1 }, // Optional
        ///     { "value3", -1 },// 削除
        /// } 
        /// </summary>
        /// <param name="framemworks">Framemworks.</param>
        /// <param name="projectNames">Project names.</param>
        public PBXParamFramework(Dictionary<string, int> framemworks, ProjectType projectType = ProjectType.Main) : base(projectType)
        {
            this.m_framemworks = framemworks;
        }
    }

    /// <summary>
    /// プロパティ変更
    /// </summary>
    public class PBXParamProperty : PBXParam
    {

        /// <summary>
        /// プロパティ設定
        /// </summary>
        private readonly Dictionary<string, List<PropertyParams>> m_params;

        /// <summary>
        /// プロパティ設定項目
        /// </summary>
        public class PropertyParams
        {

            /// <summary> 設定を行うタイプ(Debug/Releaseなど) </summary>
            public string ConfigType { get; private set; }
            /// <summary> 追加する値</summary>
            public string[] AddValues { get; private set; }
            /// <summary> 削除する値</summary>
            public string[] RemoveValues { get; private set; }
            /// <summary> 既存の項目をむしして上書きするかどうか。</summary>
            public bool ForceOverride { get; private set; }

            /// <summary>
            /// コンストラクタ
            /// </summary>
            /// <param name="configType">設定を行うコンフィグのタイプ.nullの場合はすべての設定に反映されます.</param>
            /// <param name="addValue">追加する値の配列.</param>
            /// <param name="removeValue">削除する値の配列.</param>
            /// <param name="forceOverride">強制的に上書きを行うかどうか.</param>
            public PropertyParams(string[] addValue, string[] removeValue = null, string configType = null, bool forceOverride = false)
            {
                this.ConfigType = configType;
                this.AddValues = addValue;
                this.RemoveValues = removeValue;
                this.ForceOverride = forceOverride;
            }
            /// <summary>
            /// 単一の値を全オプションに反映する用の簡易コンストラクタ
            /// </summary>
            /// <param name="addValue">追加する値</param>
            /// <returns></returns>
            public PropertyParams(string addValue) : this(new string[] { addValue }) { }


            /// <summary>
            /// ログの作成
            /// </summary>
            /// <returns>The log.</returns>
            public string CraeteLog()
            {
                var add = "[";
                for (int i = 0; AddValues != null && i < AddValues.Length; ++i)
                {
                    add += AddValues[i];
                    if (AddValues.Length - 1 != i)
                    {
                        add += ",";
                    }
                }
                add += "]";

                var remove = "[";
                for (int i = 0; RemoveValues != null && i < RemoveValues.Length; ++i)
                {
                    remove += RemoveValues[i];
                    if (RemoveValues.Length - 1 != i)
                    {
                        remove += ",";
                    }
                }
                remove += "]";

                return "\n\tConfig Type: " + ConfigType + "\n\tadd values: " + add + "\n\tremove values: " + remove;
            }
        }

        /// <summary>
        /// コンフィグ設定のguidを取得
        /// </summary>
        /// <returns>The config guids.</returns>
        /// <param name="pbxProj">Pbx proj.</param>
        /// <param name="configName">Config name.</param>
        private IEnumerable<string> GetConfigGuids(PBXProject pbxProj, string configName)
        {
            IEnumerable<string> projects = GetProjectGuids(pbxProj);
            List<string> guids = new List<string>();
            foreach (string guid in projects)
            {
                guids.Add(pbxProj.BuildConfigByName(guid, configName));
            }
            return guids;
        }

        /// <summary>
        /// ログの作成
        /// </summary>
        /// <returns>The parameter log.</returns>
        public override string GetParamLog()
        {
            var log = "";
            foreach (KeyValuePair<string, List<PropertyParams>> kv in m_params)
            {
                foreach (PropertyParams param in kv.Value)
                {
                    log += "[Property] " + kv.Key + ":" + param.CraeteLog() + "\n";
                }
            }
            return log;
        }

        /// <summary>
        /// 設定の編集を行う
        /// </summary>
        /// <param name="pbxProj">Pbx projct.</param>
        public override void Edit(ref PBXProject pbxProj)
        {
            foreach (KeyValuePair<string, List<PropertyParams>> param in m_params)
            {
                var key = param.Key;
                foreach (PropertyParams propertyItem in param.Value)
                {
                    IEnumerable<string> guids = propertyItem.ConfigType == null ? GetProjectGuids(pbxProj) : GetConfigGuids(pbxProj, propertyItem.ConfigType);
                    // 既存設定を無視して上書き
                    if (propertyItem.ForceOverride)
                    {
                        int i = 0;
                        if (propertyItem.ConfigType == null)
                        {
                            foreach (string addValue in propertyItem.AddValues)
                            {
                                if (i == 0)
                                    pbxProj.SetBuildProperty(guids, key, addValue);
                                else
                                    pbxProj.AddBuildProperty(guids, key, addValue);
                            }
                            ++i;
                        }
                        else
                        {
                            guids = GetConfigGuids(pbxProj, propertyItem.ConfigType);
                            foreach (string addValue in propertyItem.AddValues)
                            {
                                if (i == 0)
                                    pbxProj.SetBuildPropertyForConfig(guids, key, addValue);
                                else
                                    pbxProj.AddBuildPropertyForConfig(guids, key, addValue);
                            }
                            ++i;
                        }
                    }
                    else
                    {
                        if (propertyItem.ConfigType == null)
                        {
                            pbxProj.UpdateBuildProperty(guids, key, propertyItem.AddValues, propertyItem.RemoveValues);
                        }
                        else
                        {
                            /* 
                                 * UpdateBuildPropertyForConfig( IEnumerator<string>, stirng, string[], string[] )
                                 * は内部的に、UpdateBuildProperty( string, string, string[], string[] )をコールしており、
                                 * UpdateBuildPropertyForConfig( string, string, string[], string[] )と挙動が異なるので、foreachでguidはループで指定する
                                 */
                            foreach (string guid in guids)
                            {
                                pbxProj.UpdateBuildPropertyForConfig(guid, key, propertyItem.AddValues, propertyItem.RemoveValues);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="parameters">Parameters.</param>
        /// <param name="projectNames">Project names.</param>
        public PBXParamProperty(Dictionary<string, List<PropertyParams>> parameters, ProjectType projectType = ProjectType.Main) : base(projectType)
        {
            this.m_params = parameters;
        }
        /// <summary>
        /// コンストラクタ string のみで簡易設定用
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="projectType"></param>
        /// <returns></returns>
        public PBXParamProperty(Dictionary<string, string> parameters, ProjectType projectType = ProjectType.Main) : base(projectType)
        {
            m_params = new Dictionary<string, List<PropertyParams>>();
            foreach (var param in parameters)
            {
                m_params[param.Key] = new List<PropertyParams> { new PropertyParams(param.Value) };
            }
        }
    }
}
#endif

PlistEditor.cs

PlistEditor.cs
#if UNITY_IOS
/**
 * @file     PlistEditor.cs
 * @brief    plistの編集を行うクラス。
 * @date     $Date$
 * @version  $Rev$
 * @author   $Author$
 */
using UnityEditor.iOS.Xcode;
using System;
using System.IO;
using System.Collections.Generic;

namespace yyama2.Editor.XCProjEdit {

	/// <summary>
	/// plistの値を変更する。
	/// 
	/// 
	/// 値の設定は、下記のように定義してください。
	/// ※キーは任意の文字列です。
	/// 
	/// int 系のデータ
	/// { "int", 1 },
	/// boolean系の値
	/// { "bool", true },
	/// 文字列
	/// { "string", "string value" },
	/// 配列
	/// { "list", new List<object>() { 1, 2, 3 } },
	/// Dict
	/// { "dict", new Dictionary<string, object>() {
	/// 		{ "value1", "string value" },
	/// 		{ "value2", 1 },
	/// 		{ "value3", true },
	/// 	} 
	/// },
	/// </summary>
	public class PlistEditor {

		/// <summary> Info.plistのパスを取得する</summary>
		/// <param name="path"> Info.plistのあるフォルダパス</param>
		/// <returns> Info.plistのファイルパス</returns>
		public static string GetInfoPlistPath( string path )
		{
			return Path.Combine( path, "Info.plist" );
		}

		/// <summary>
		/// plistを編集する。
		/// </summary>
		/// <param name="plistPath"> plistファイルパス</param>
		/// <param name="values">追加する値.</param>
		/// <param name="callClass">この関数を呼び出しているクラス.</param>
		public static void EditPlist( string plistPath, Dictionary<string, object> values, Type callClass )
		{
			string className = "";

			if( callClass != null )
			{
				className += callClass.Name;
			}
			UnityEngine.Debug.Log( "PlistEditor:" + className );
			string log = "======================= PlistValue =======================\n";
			UnityEngine.Debug.Log( "plistPath=>" + plistPath );
			PlistDocument plist = new PlistDocument();
			plist.ReadFromFile( plistPath );

			foreach( KeyValuePair<string, object> value in values )
			{
				setValue( value.Key, value.Value, ref plist.root );
			}

			// Documentsフォルダを共有可能にする
			plist.WriteToFile( plistPath );

			log += className + "\n";
			log += plistPath +"\n{";
			foreach( var value in values )
			{
				CreateLog( value.Key, value.Value, 0, ref log );
			}
			log += "\n}\n" + "======================= PlistValue =======================";
			UnityEngine.Debug.Log( log );
		}

		/// <summary>
		/// 値をセットする
		/// </summary>
		/// <param name="key"> キー.</param>
		/// <param name="value"> 値.</param>
		/// <param name="dict"> Dictオブジェクト.</param>
		private static void setValue( string key, object value, ref PlistElementDict dict )
		{
			bool validValue = true;
			Type type = value.GetType();

			// int .
			if( type == typeof(int) )
			{
				dict.SetInteger( key, (int)value );
			}
			// bool .
			else if( type == typeof(bool) )
			{
				dict.SetBoolean( key, (bool)value );
			}
			// string .
			else if( type == typeof(string) )
			{
				dict.SetString( key, (string)value );
			}
			// list
			else if( type == typeof(List<object>) )
			{
				PlistElementArray subArray;

				if( !tryGetValue<PlistElementArray>( key, dict, out subArray ) )
				{
					subArray = dict.CreateArray( key );
				}

				List<object> list = (List<object>)value;
				foreach( object val in list )
				{
					addValue( val, ref subArray );
				}
			}
			// dictionary
			else if( type == typeof(Dictionary<string, object>) )
			{
				PlistElementDict subDict;

				if( !tryGetValue<PlistElementDict>( key, dict, out subDict ) )
				{
					subDict = dict.CreateDict( key );
				}

				Dictionary<string, object> dictionary = (Dictionary<string, object>)value;
				foreach( var dictItem in dictionary )
				{
					setValue( dictItem.Key, dictItem.Value, ref subDict );
				}
			}
			else validValue = false;

			// invalid parameter
			if( !validValue )
			{
				UnityEngine.Debug.LogError( "Plist Editor.  Invalid Parameter => " + key );
			}
		}

		/// <summary>
		/// リストに値をセットする
		/// </summary>
		/// <param name="value">値.</param>
		/// <param name="array">Arrayオブジェクト.</param>
		private static void addValue( object value, ref PlistElementArray array )
		{
			Type type = value.GetType();

			// int .
			if( type == typeof(int) )
			{
				array.AddInteger( (int)value );
			}
			// bool .
			else if( type == typeof(bool) )
			{
				array.AddBoolean( (bool)value );
			}
			// string .
			else if( type == typeof(string) )
			{
				array.AddString( (string)value );
			}
			// list
			else if( type == typeof(List<object>) )
			{
				PlistElementArray subArray = array.AddArray();
				List<object> list = (List<object>)value;
				foreach( object val in list )
				{
					addValue( val, ref subArray );
				}
			}
			// dictionary
			else if( type == typeof(Dictionary<string, object>) )
			{
				PlistElementDict subDict = array.AddDict();
				Dictionary<string, object> dictionary = (Dictionary<string, object>)value;
				foreach( var dictItem in dictionary )
				{
					setValue( dictItem.Key, dictItem.Value, ref subDict );
				}
			}
			else
			{
				UnityEngine.Debug.LogError( "Add List Error!!" );
			}
		}

		/// <summary>
		/// dictオブジェクトから値を抽出する
		/// </summary>
		/// <returns><c>true</c>, if success to get, <c>false</c> otherwise.</returns>
		/// <param name="key">Key.</param>
		/// <param name="dict">Dictオブジェクト.</param>
		/// <param name="val">Value.</param>
		/// <typeparam name="T">The 1st type parameter.</typeparam>
		private static bool tryGetValue<T>( string key, PlistElementDict dict, out T val ) where T : PlistElement
		{
			IDictionary<string, PlistElement> dictValue = dict.values;
			PlistElement el;
			val = null;
			if( dictValue.TryGetValue( key, out el ) )
			{
				val = el as T;
			}
			return val != null;
		}

		/// <summary>
		/// ログ様の文字列作成 .
		/// </summary>
		/// <param name="key">Key.</param>
		/// <param name="value">Value.</param>
		/// <param name="indent">Indent.</param>
		/// <param name="log">Log.</param>
		private static void CreateLog( string key, object value, int indent, ref string log )
		{
			++indent;
			string indentTabs = "";
			for( int i = 0; i < indent; ++i )
			{
				indentTabs += "\t";
			}
			log += "\n" + indentTabs + key + ":";
			Type type = value.GetType();
			// int .
			if( type == typeof(int) )
			{
				log += value;
			}
			// bool .
			else if( type == typeof(bool) )
			{
				log += value;
			}
			// string .
			else if( type == typeof(string) )
			{
				log += "\"" + value + "\"";
			}
			// list
			else if( type == typeof(List<object>) )
			{
				log += "[";
				List<object> list = (List<object>)value;
				for( int i = 0; i < list.Count; ++i )
				{
					CreateLog( "["+ i +"]", list[i], indent, ref log);
				}
				log += "\n" + indentTabs + "]";
			}
			// dictionary
			else if( type == typeof(Dictionary<string, object>) )
			{
				Dictionary<string, object> dictionary = (Dictionary<string, object>)value;
				log += "{";			
				foreach( var dictItem in dictionary )
				{
					CreateLog( dictItem.Key, dictItem.Value, indent, ref log );
				}

				log += "\n" + indentTabs + "}";
			}
			log += ",";
		}
	}
}
#endif
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2