public void Run(string nodeId, string labelToNext, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            var usedCache = new List <string>();

            var outputDict = new Dictionary <string, List <InternalAssetData> >();


            // caution if import setting file is exists already or not.
            var samplingDirectoryPath = FileController.PathCombine(AssetBundleGraphSettings.MODIFIER_SAMPLING_PLACE, nodeId);

            var sampleAssetPath = string.Empty;

            ValidateModifierSample(samplingDirectoryPath,
                                   (string noSampleFolder) => {
                Debug.LogWarning("modifierSetting:" + noSampleFolder);
            },
                                   (string noSampleFile) => {
                throw new Exception("modifierSetting error:" + noSampleFile);
            },
                                   (string samplePath) => {
                Debug.Log("using modifier setting:" + samplePath);
                sampleAssetPath = samplePath;
            },
                                   (string tooManysample) => {
                throw new Exception("modifierSetting error:" + tooManysample);
            }
                                   );

            if (groupedSources.Keys.Count == 0)
            {
                return;
            }

            var the1stGroupKey = groupedSources.Keys.ToList()[0];


            // shrink group to 1 group.
            if (1 < groupedSources.Keys.Count)
            {
                Debug.LogWarning("modifierSetting shrinking group to \"" + the1stGroupKey + "\" forcely.");
            }

            var inputSources = new List <InternalAssetData>();

            foreach (var groupKey in groupedSources.Keys)
            {
                inputSources.AddRange(groupedSources[groupKey]);
            }

            var importSetOveredAssetsAndUpdatedFlagDict = new Dictionary <InternalAssetData, bool>();

            /*
             *      check file & setting.
             *      if need, apply modifierSetting to file.
             */
            {
                var samplingAssetImporter = AssetImporter.GetAtPath(sampleAssetPath);
                var effector = new InternalSamplingImportEffector(samplingAssetImporter);
                {
                    foreach (var inputSource in inputSources)
                    {
                        var importer = AssetImporter.GetAtPath(inputSource.importedPath);

                        /*
                         *      compare type of import setting effector.
                         */
                        var importerTypeStr = importer.GetType().ToString();

                        if (importerTypeStr != samplingAssetImporter.GetType().ToString())
                        {
                            // mismatched target will be ignored. but already imported.
                            importSetOveredAssetsAndUpdatedFlagDict[inputSource] = false;
                            continue;
                        }
                        importSetOveredAssetsAndUpdatedFlagDict[inputSource] = false;

                        /*
                         *      kind of importer is matched.
                         *      check setting then apply setting or no changed.
                         */
                        switch (importerTypeStr)
                        {
                        case "UnityEditor.AssetImporter": {                                // materials and others... assets which are generated in Unity.
                            var assetType = inputSource.assetType.ToString();
                            switch (assetType)
                            {
                            case "UnityEngine.Material": {
                                // 判別はできるんだけど、このあとどうしたもんか。ロードしなきゃいけない + loadしてもなんかグローバルなプロパティだけ比較とかそういうのかなあ、、

                                // var materialInstance = AssetDatabase.LoadAssetAtPath(inputSource.importedPath, inputSource.assetType) as Material;// 型を指定してロードしないといけないので、ここのコードのようにswitchに落としたほうが良さそう。
                                // var s = materialInstance.globalIlluminationFlags;// グローバルなプロパティ、リフレクションで列挙できそうではあるけど、、、

                                break;
                            }

                            default: {
                                Debug.LogError("unsupported type. assetType:" + assetType);
                                break;
                            }
                            }

                            /*
                             *      試しにserializeして云々してみる
                             */
                            var assetInstance    = AssetDatabase.LoadAssetAtPath(inputSource.importedPath, inputSource.assetType) as Material;                                 // ここの型が露出しちゃうのやばい
                            var serializedObject = new UnityEditor.SerializedObject(assetInstance);

                            var itr = serializedObject.GetIterator();
                            itr.NextVisible(true);
                            // Debug.LogError("0 itr:" + itr.propertyPath + " displayName:" + itr.displayName + " name:" + itr.name + " type:" + itr.type);

                            // while (itr.NextVisible(true)) {
                            //  Debug.LogError("~ itr:" + itr.propertyPath + " displayName:" + itr.displayName + " name:" + itr.name + " type:" + itr.type);
                            // }

                            /*
                             *      このへんのログはこんな感じになる。
                             *
                             * 0 itr:m_Shader displayName:Shader name:m_Shader type:PPtr<Shader>
                             * ~ itr:m_ShaderKeywords displayName:Shader Keywords name:m_ShaderKeywords type:string
                             * ~ itr:m_LightmapFlags displayName:Lightmap Flags name:m_LightmapFlags type:uint
                             * ~ itr:m_CustomRenderQueue displayName:Custom Render Queue name:m_CustomRenderQueue type:int
                             * ~ itr:stringTagMap displayName:String Tag Map name:stringTagMap type:map
                             * ~ itr:stringTagMap.Array.size displayName:Size name:size type:ArraySize
                             * ~ itr:m_SavedProperties displayName:Saved Properties name:m_SavedProperties type:UnityPropertySheet
                             * ~ itr:m_SavedProperties.m_TexEnvs displayName:Tex Envs name:m_TexEnvs type:map
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.size displayName:Size name:size type:ArraySize
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0] displayName:Element 0 name:data type:pair
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0].second displayName:Second name:second type:UnityTexEnv
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0].second.m_Texture displayName:Texture name:m_Texture type:PPtr<Texture>
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0].second.m_Scale displayName:Scale name:m_Scale type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0].second.m_Scale.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0].second.m_Scale.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0].second.m_Offset displayName:Offset name:m_Offset type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0].second.m_Offset.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[0].second.m_Offset.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1] displayName:Element 1 name:data type:pair
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1].second displayName:Second name:second type:UnityTexEnv
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1].second.m_Texture displayName:Texture name:m_Texture type:PPtr<Texture>
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1].second.m_Scale displayName:Scale name:m_Scale type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1].second.m_Scale.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1].second.m_Scale.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1].second.m_Offset displayName:Offset name:m_Offset type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1].second.m_Offset.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[1].second.m_Offset.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2] displayName:Element 2 name:data type:pair
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2].second displayName:Second name:second type:UnityTexEnv
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2].second.m_Texture displayName:Texture name:m_Texture type:PPtr<Texture>
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2].second.m_Scale displayName:Scale name:m_Scale type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2].second.m_Scale.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2].second.m_Scale.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2].second.m_Offset displayName:Offset name:m_Offset type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2].second.m_Offset.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[2].second.m_Offset.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3] displayName:Element 3 name:data type:pair
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3].second displayName:Second name:second type:UnityTexEnv
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3].second.m_Texture displayName:Texture name:m_Texture type:PPtr<Texture>
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3].second.m_Scale displayName:Scale name:m_Scale type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3].second.m_Scale.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3].second.m_Scale.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3].second.m_Offset displayName:Offset name:m_Offset type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3].second.m_Offset.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[3].second.m_Offset.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4] displayName:Element 4 name:data type:pair
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4].second displayName:Second name:second type:UnityTexEnv
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4].second.m_Texture displayName:Texture name:m_Texture type:PPtr<Texture>
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4].second.m_Scale displayName:Scale name:m_Scale type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4].second.m_Scale.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4].second.m_Scale.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4].second.m_Offset displayName:Offset name:m_Offset type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4].second.m_Offset.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[4].second.m_Offset.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5] displayName:Element 5 name:data type:pair
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5].second displayName:Second name:second type:UnityTexEnv
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5].second.m_Texture displayName:Texture name:m_Texture type:PPtr<Texture>
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5].second.m_Scale displayName:Scale name:m_Scale type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5].second.m_Scale.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5].second.m_Scale.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5].second.m_Offset displayName:Offset name:m_Offset type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5].second.m_Offset.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[5].second.m_Offset.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6] displayName:Element 6 name:data type:pair
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6].second displayName:Second name:second type:UnityTexEnv
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6].second.m_Texture displayName:Texture name:m_Texture type:PPtr<Texture>
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6].second.m_Scale displayName:Scale name:m_Scale type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6].second.m_Scale.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6].second.m_Scale.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6].second.m_Offset displayName:Offset name:m_Offset type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6].second.m_Offset.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[6].second.m_Offset.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7] displayName:Element 7 name:data type:pair
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7].second displayName:Second name:second type:UnityTexEnv
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7].second.m_Texture displayName:Texture name:m_Texture type:PPtr<Texture>
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7].second.m_Scale displayName:Scale name:m_Scale type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7].second.m_Scale.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7].second.m_Scale.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7].second.m_Offset displayName:Offset name:m_Offset type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7].second.m_Offset.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[7].second.m_Offset.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8] displayName:Element 8 name:data type:pair
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8].second displayName:Second name:second type:UnityTexEnv
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8].second.m_Texture displayName:Texture name:m_Texture type:PPtr<Texture>
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8].second.m_Scale displayName:Scale name:m_Scale type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8].second.m_Scale.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8].second.m_Scale.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8].second.m_Offset displayName:Offset name:m_Offset type:Vector2
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8].second.m_Offset.x displayName:X name:x type:float
                             * ~ itr:m_SavedProperties.m_TexEnvs.Array.data[8].second.m_Offset.y displayName:Y name:y type:float
                             * ~ itr:m_SavedProperties.m_Floats displayName:Floats name:m_Floats type:map
                             * ~ itr:m_SavedProperties.m_Floats.Array.size displayName:Size name:size type:ArraySize
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[0] displayName:Element 0 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[0].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[0].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[0].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[1] displayName:Element 1 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[1].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[1].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[1].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[2] displayName:Element 2 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[2].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[2].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[2].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[3] displayName:Element 3 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[3].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[3].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[3].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[4] displayName:Element 4 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[4].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[4].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[4].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[5] displayName:Element 5 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[5].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[5].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[5].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[6] displayName:Element 6 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[6].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[6].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[6].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[7] displayName:Element 7 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[7].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[7].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[7].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[8] displayName:Element 8 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[8].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[8].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[8].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[9] displayName:Element 9 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[9].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[9].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[9].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[10] displayName:Element 10 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[10].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[10].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[10].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[11] displayName:Element 11 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[11].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[11].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Floats.Array.data[11].second displayName:Second name:second type:float
                             * ~ itr:m_SavedProperties.m_Colors displayName:Colors name:m_Colors type:map
                             * ~ itr:m_SavedProperties.m_Colors.Array.size displayName:Size name:size type:ArraySize
                             * ~ itr:m_SavedProperties.m_Colors.Array.data[0] displayName:Element 0 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Colors.Array.data[0].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Colors.Array.data[0].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Colors.Array.data[0].second displayName:Second name:second type:Color
                             * ~ itr:m_SavedProperties.m_Colors.Array.data[1] displayName:Element 1 name:data type:pair
                             * ~ itr:m_SavedProperties.m_Colors.Array.data[1].first displayName:First name:first type:FastPropertyName
                             * ~ itr:m_SavedProperties.m_Colors.Array.data[1].first.name displayName:Name name:name type:string
                             * ~ itr:m_SavedProperties.m_Colors.Array.data[1].second displayName:Second name:second type:Color
                             *
                             */



                            // もしサンプルとの差があれば、この素材には変更があったものとして、関連するPrefabの作成時にprefabのキャッシュを消すとかする。
                            // if (!same) {
                            //  effector.ForceOnPreprocessTexture(texImporter);
                            //  importSetOveredAssetsAndUpdatedFlagDict[inputSource] = true;
                            // }

                            // とりあえず決め打ちで、変化があったものとしてみなす。デバッグ中。
                            Debug.LogError("modifierは、現状「通過した素材の設定が変更されてるかどうか把握できない」ので、常に新規扱いになっている。そのため、このファイルと、このファイルを使ったpredab生成が常に新作になり、キャッシュが効かないようになっている。");
                            importSetOveredAssetsAndUpdatedFlagDict[inputSource] = true;
                            break;
                        }

                        default: {
                            throw new Exception("unhandled modifier type:" + importerTypeStr);
                        }
                        }
                    }
                }
            }


            /*
             *      inputSetting sequence is over.
             */

            var outputSources = new List <InternalAssetData>();


            foreach (var inputAsset in inputSources)
            {
                var updated = importSetOveredAssetsAndUpdatedFlagDict[inputAsset];
                if (!updated)
                {
                    // already set completed.
                    var newInternalAssetData = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                        inputAsset.importedPath,
                        AssetDatabase.AssetPathToGUID(inputAsset.importedPath),
                        AssetBundleGraphInternalFunctions.GetAssetType(inputAsset.importedPath),
                        false,                        // not changed.
                        false
                        );
                    outputSources.Add(newInternalAssetData);
                }
                else
                {
                    // updated asset.
                    var newInternalAssetData = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                        inputAsset.importedPath,
                        AssetDatabase.AssetPathToGUID(inputAsset.importedPath),
                        AssetBundleGraphInternalFunctions.GetAssetType(inputAsset.importedPath),
                        true,                        // changed.
                        false
                        );
                    outputSources.Add(newInternalAssetData);
                }
            }

            outputDict[the1stGroupKey] = outputSources;

            Output(nodeId, labelToNext, outputDict, usedCache);
        }
        public void Setup(string nodeId, string labelToNext, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            var outputDict = new Dictionary <string, List <InternalAssetData> >();

            var first = true;

            if (groupedSources.Keys.Count == 0)
            {
                return;
            }

            // shrink group to 1 group.
            if (1 < groupedSources.Keys.Count)
            {
                Debug.LogWarning("modifierSetting shrinking group to \"" + groupedSources.Keys.ToList()[0] + "\" forcely.");
            }

            var inputSources = new List <InternalAssetData>();

            foreach (var groupKey in groupedSources.Keys)
            {
                inputSources.AddRange(groupedSources[groupKey]);
            }

            var assumedImportedAssetDatas = new List <InternalAssetData>();


            var samplingDirectoryPath = FileController.PathCombine(AssetBundleGraphSettings.MODIFIER_SAMPLING_PLACE, nodeId);

            ValidateModifierSample(samplingDirectoryPath,
                                   (string noSampleFolder) => {
                // do nothing. keep importing new asset for sampling.
            },
                                   (string noSampleFile) => {
                // do nothing. keep importing new asset for sampling.
            },
                                   (string samplePath) => {
                first = false;
            },
                                   (string tooManysample) => {
                first = false;
            }
                                   );

            var alreadyImported = new List <string>();
            var ignoredResource = new List <string>();

            foreach (var inputSource in inputSources)
            {
                if (string.IsNullOrEmpty(inputSource.absoluteSourcePath))
                {
                    if (!string.IsNullOrEmpty(inputSource.importedPath))
                    {
                        alreadyImported.Add(inputSource.importedPath);
                        continue;
                    }

                    ignoredResource.Add(inputSource.fileNameAndExtension);
                    continue;
                }

                var assumedType = TypeBinder.AssumeTypeOfAsset(inputSource.importedPath);

                var newData = InternalAssetData.InternalAssetDataByImporter(
                    inputSource.traceId,
                    inputSource.absoluteSourcePath,
                    inputSource.sourceBasePath,
                    inputSource.fileNameAndExtension,
                    inputSource.pathUnderSourceBase,
                    inputSource.importedPath,
                    null,
                    assumedType
                    );
                assumedImportedAssetDatas.Add(newData);

                if (first)
                {
                    if (!Directory.Exists(samplingDirectoryPath))
                    {
                        Directory.CreateDirectory(samplingDirectoryPath);
                    }

                    var absoluteFilePath = inputSource.absoluteSourcePath;
                    var targetFilePath   = FileController.PathCombine(samplingDirectoryPath, inputSource.fileNameAndExtension);

                    EditorUtility.DisplayProgressBar("AssetBundleGraph Modifier generating ModifierSetting...", targetFilePath, 0);
                    FileController.CopyFileFromGlobalToLocal(absoluteFilePath, targetFilePath);
                    first = false;
                    AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
                    EditorUtility.ClearProgressBar();
                }


                if (alreadyImported.Any())
                {
                    Debug.LogError("modifierSetting:" + string.Join(", ", alreadyImported.ToArray()) + " are already imported.");
                }
                if (ignoredResource.Any())
                {
                    Debug.LogError("modifierSetting:" + string.Join(", ", ignoredResource.ToArray()) + " are ignored.");
                }

                outputDict[groupedSources.Keys.ToList()[0]] = assumedImportedAssetDatas;
            }

            Output(nodeId, labelToNext, outputDict, new List <string>());
        }
Exemple #3
0
        public void Run(string nodeName, string nodeId, string connectionIdToNextNode, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            if (groupedSources.Keys.Count == 0)
            {
                return;
            }

            // Modifier merges multiple incoming groups into one.
            if (1 < groupedSources.Keys.Count)
            {
                Debug.LogWarning(nodeName + " Modifier merges incoming group into \"" + groupedSources.Keys.ToList()[0]);
            }

            var groupMergeKey = groupedSources.Keys.ToList()[0];

            // merge all assets into single list.
            var inputSources = new List <InternalAssetData>();

            foreach (var groupKey in groupedSources.Keys)
            {
                inputSources.AddRange(groupedSources[groupKey]);
            }

            if (!inputSources.Any())
            {
                return;
            }

            // load type from 1st asset of flow.
            var modifierType = TypeBinder.AssumeTypeOfAsset(inputSources[0].importedPath).ToString();

            // modifierType is fixed. check support.
            if (!TypeBinder.SupportedModifierOperatorDefinition.ContainsKey(modifierType))
            {
                throw new NodeException("current incoming Asset Type:" + modifierType + " is unsupported.", nodeId);
            }


            // validate saved data.
            ValidateModifiyOperationData(
                nodeId,
                currentPlatformStr,
                () => {
                throw new NodeException("No ModifierOperatorData found. please Setup first.", nodeId);
            },
                () => {
                /*do nothing.*/
            }
                );

            var outputSources = new List <InternalAssetData>();

            var modifierOperatorDataPathForTargetPlatform = FileController.PathCombine(AssetBundleGraphSettings.MODIFIER_OPERATOR_DATAS_PLACE, nodeId, ModifierOperatiorDataName(currentPlatformStr));

            // if runtime platform specified modifierOperatorData is nof found,
            // use default platform modifierOperatorData.
            if (!File.Exists(modifierOperatorDataPathForTargetPlatform))
            {
                modifierOperatorDataPathForTargetPlatform = FileController.PathCombine(AssetBundleGraphSettings.MODIFIER_OPERATOR_DATAS_PLACE, nodeId, ModifierOperatiorDataName(AssetBundleGraphSettings.PLATFORM_DEFAULT_NAME));
            }

            var loadedModifierOperatorData = string.Empty;

            using (var sr = new StreamReader(modifierOperatorDataPathForTargetPlatform)) {
                loadedModifierOperatorData = sr.ReadToEnd();
            }

            /*
             *      read saved modifierOperator type for detect data type.
             */
            var deserializedDataObject = JsonUtility.FromJson <ModifierOperators.OperatorBase>(loadedModifierOperatorData);
            var dataTypeString         = deserializedDataObject.dataType;

            // sadly, if loaded assetType is no longer supported or not.
            if (!TypeBinder.SupportedModifierOperatorDefinition.ContainsKey(dataTypeString))
            {
                throw new NodeException("unsupported ModifierOperator Type:" + modifierType, nodeId);
            }

            var modifyOperatorType = TypeBinder.SupportedModifierOperatorDefinition[dataTypeString];

            /*
             *      make generic method for genearte desired typed ModifierOperator instance.
             */
            var modifyOperatorInstance = typeof(IntegratedGUIModifier)
                                         .GetMethod("FromJson")
                                         .MakeGenericMethod(modifyOperatorType)// set desired generic type here.
                                         .Invoke(this, new object[] { loadedModifierOperatorData }) as ModifierOperators.OperatorBase;

            var isChanged = false;

            foreach (var inputSource in inputSources)
            {
                var modifyTargetAssetPath = inputSource.importedPath;

                var modifyOperationTargetAsset = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(modifyTargetAssetPath);

                if (!modifyOperatorInstance.IsChanged(modifyOperationTargetAsset))
                {
                    var notChangedData = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                        inputSource.importedPath,
                        AssetDatabase.AssetPathToGUID(inputSource.importedPath),
                        AssetBundleGraphInternalFunctions.GetAssetType(inputSource.importedPath),
                        false,                        // marked as not changed.
                        false
                        );
                    outputSources.Add(notChangedData);
                    continue;
                }

                isChanged = true;
                modifyOperatorInstance.Modify(modifyOperationTargetAsset);

                var newData = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                    inputSource.importedPath,
                    AssetDatabase.AssetPathToGUID(inputSource.importedPath),
                    AssetBundleGraphInternalFunctions.GetAssetType(inputSource.importedPath),
                    true,                    // marked as changed.
                    false
                    );

                outputSources.Add(newData);
            }

            if (isChanged)
            {
                // apply asset setting changes to AssetDatabase.
                AssetDatabase.Refresh();
            }

            var outputDict = new Dictionary <string, List <InternalAssetData> >();

            outputDict[groupMergeKey] = outputSources;

            Output(nodeId, connectionIdToNextNode, outputDict, new List <string>());
        }
Exemple #4
0
        public void Setup(string nodeName, string nodeId, string connectionIdToNextNode, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            if (groupedSources.Keys.Count == 0)
            {
                return;
            }

            // Modifier merges multiple incoming groups into one.
            if (1 < groupedSources.Keys.Count)
            {
                Debug.LogWarning(nodeName + " Modifier merges incoming group into \"" + groupedSources.Keys.ToList()[0]);
            }

            var groupMergeKey = groupedSources.Keys.ToList()[0];

            // merge all assets into single list.
            var inputSources = new List <InternalAssetData>();

            foreach (var groupKey in groupedSources.Keys)
            {
                inputSources.AddRange(groupedSources[groupKey]);
            }

            if (!inputSources.Any())
            {
                return;
            }

            // initialize as object.
            var modifierType = string.Empty;

            var first = true;

            foreach (var inputSource in inputSources)
            {
                var modifyTargetAssetPath = inputSource.importedPath;
                var assumedType           = TypeBinder.AssumeTypeOfAsset(modifyTargetAssetPath);

                if (assumedType == null || assumedType == typeof(object))
                {
                    continue;
                }

                if (first)
                {
                    first        = false;
                    modifierType = assumedType.ToString();
                    continue;
                }

                if (modifierType != assumedType.ToString())
                {
                    throw new NodeException("multiple Asset Type detected. consider reduce Asset Type number to only 1 by Filter. detected Asset Types is:" + modifierType + " , and " + assumedType.ToString(), nodeId);
                }
            }

            // modifierType is fixed. check support.
            if (!TypeBinder.SupportedModifierOperatorDefinition.ContainsKey(modifierType))
            {
                throw new NodeException("current incoming Asset Type:" + modifierType + " is unsupported.", nodeId);
            }

            // generate modifierOperatorData if data is not exist yet.
            {
                var modifierOperatorDataFolderPath = AssetBundleGraphSettings.MODIFIER_OPERATOR_DATAS_PLACE;
                if (!Directory.Exists(modifierOperatorDataFolderPath))
                {
                    Directory.CreateDirectory(modifierOperatorDataFolderPath);
                }

                var opDataFolderPath = FileController.PathCombine(modifierOperatorDataFolderPath, nodeId);
                if (!Directory.Exists(opDataFolderPath))
                {
                    Directory.CreateDirectory(opDataFolderPath);
                }

                // ready default platform path.
                var modifierOperatorDataPathForDefaultPlatform = FileController.PathCombine(opDataFolderPath, ModifierOperatiorDataName(AssetBundleGraphSettings.PLATFORM_DEFAULT_NAME));

                /*
                 *      create default platform ModifierOperatorData if not exist.
                 *      default ModifierOperatorData is the target platform for every platform by default.
                 */
                if (!File.Exists(modifierOperatorDataPathForDefaultPlatform))
                {
                    var operatorType = TypeBinder.SupportedModifierOperatorDefinition[modifierType];

                    var operatorInstance = Activator.CreateInstance(operatorType) as ModifierOperators.OperatorBase;

                    var defaultRenderTextureOp = operatorInstance.DefaultSetting();

                    /*
                     *      generated json data is typed as supported ModifierOperation type.
                     */
                    var jsonData   = JsonUtility.ToJson(defaultRenderTextureOp);
                    var prettified = AssetBundleGraph.PrettifyJson(jsonData);
                    using (var sw = new StreamWriter(modifierOperatorDataPathForDefaultPlatform)) {
                        sw.WriteLine(prettified);
                    }
                }
            }


            // validate saved data.
            ValidateModifiyOperationData(
                nodeId,
                currentPlatformStr,
                () => {
                throw new NodeException("No ModifierOperatorData found. please Setup first.", nodeId);
            },
                () => {
                /*do nothing.*/
            }
                );

            var outputSources = new List <InternalAssetData>();

            /*
             *      all assets types are same and do nothing to assets in setup.
             */
            foreach (var inputSource in inputSources)
            {
                var modifyTargetAssetPath = inputSource.importedPath;

                var newData = InternalAssetData.InternalAssetDataByImporterOrModifier(
                    inputSource.traceId,
                    inputSource.absoluteSourcePath,
                    inputSource.sourceBasePath,
                    inputSource.fileNameAndExtension,
                    inputSource.pathUnderSourceBase,
                    inputSource.importedPath,
                    null,
                    inputSource.assetType
                    );

                outputSources.Add(newData);
            }

            var outputDict = new Dictionary <string, List <InternalAssetData> >();

            outputDict[groupMergeKey] = outputSources;

            Output(nodeId, connectionIdToNextNode, outputDict, new List <string>());
        }
        public string BundlizeAssets(string nodeName, string groupkey, List <InternalAssetData> sources, string recommendedBundleOutputDir, bool isRun)
        {
            var invalids = new List <string>();

            foreach (var source in sources)
            {
                if (string.IsNullOrEmpty(source.importedPath))
                {
                    invalids.Add(source.pathUnderSourceBase);
                }
            }
            if (invalids.Any())
            {
                throw new AssetBundleGraphBuildException(nodeName + ": Invalid files to bundle. Following files need to be imported before bundlize: " + string.Join(", ", invalids.ToArray()));
            }

            var bundleName = bundleNameTemplate;

            /*
             *      if contains KEYWORD_WILDCARD, use group identifier to bundlize name.
             */
            if (bundleNameTemplate.Contains(AssetBundleGraphSettings.KEYWORD_WILDCARD))
            {
                var templateHead = bundleNameTemplate.Split(AssetBundleGraphSettings.KEYWORD_WILDCARD)[0];
                var templateTail = bundleNameTemplate.Split(AssetBundleGraphSettings.KEYWORD_WILDCARD)[1];

                bundleName = (templateHead + groupkey + templateTail + "." + GraphStackController.Platform_Dot_Package()).ToLower();
            }

            var bundlePath = FileController.PathCombine(recommendedBundleOutputDir, bundleName);

            for (var i = 0; i < sources.Count; i++)
            {
                var source = sources[i];

                // if already bundled in this running, avoid changing that name.
                if (source.isBundled)
                {
                    continue;
                }

                if (isRun)
                {
                    if (GraphStackController.IsMetaFile(source.importedPath))
                    {
                        continue;
                    }
                    var assetImporter = AssetImporter.GetAtPath(source.importedPath);
                    if (assetImporter == null)
                    {
                        continue;
                    }
                    assetImporter.assetBundleName = bundleName;
                }

                // set as this resource is already bundled.
                sources[i] = InternalAssetData.InternalAssetDataBundledByBundlizer(sources[i]);
            }

            return(bundlePath);
        }
        private void Export(string nodeId, string labelToNext, Dictionary <string, List <InternalAssetData> > groupedSources, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output, bool isRun)
        {
            var outputDict = new Dictionary <string, List <InternalAssetData> >();

            outputDict["0"] = new List <InternalAssetData>();

            var failedExports = new List <string>();

            foreach (var groupKey in groupedSources.Keys)
            {
                var exportedAssets = new List <InternalAssetData>();
                var inputSources   = groupedSources[groupKey];

                foreach (var source in inputSources)
                {
                    if (isRun)
                    {
                        if (!Directory.Exists(exportFilePath))
                        {
                            Directory.CreateDirectory(exportFilePath);
                        }
                    }

                    var destinationSourcePath = source.importedPath;

                    // in bundleBulider, use platform-package folder for export destination.
                    if (destinationSourcePath.StartsWith(AssetBundleGraphSettings.BUNDLEBUILDER_CACHE_PLACE))
                    {
                        var depth = AssetBundleGraphSettings.BUNDLEBUILDER_CACHE_PLACE.Split(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR).Length + 1;

                        var splitted     = destinationSourcePath.Split(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR);
                        var reducedArray = new string[splitted.Length - depth];

                        Array.Copy(splitted, depth, reducedArray, 0, reducedArray.Length);
                        var fromDepthToEnd = string.Join(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString(), reducedArray);

                        destinationSourcePath = fromDepthToEnd;
                    }

                    var destination = FileController.PathCombine(exportFilePath, destinationSourcePath);

                    var parentDir = Directory.GetParent(destination).ToString();

                    if (isRun)
                    {
                        if (!Directory.Exists(parentDir))
                        {
                            Directory.CreateDirectory(parentDir);
                        }
                        if (File.Exists(destination))
                        {
                            File.Delete(destination);
                        }
                        if (string.IsNullOrEmpty(source.importedPath))
                        {
                            failedExports.Add(source.absoluteSourcePath);
                            continue;
                        }
                        File.Copy(source.importedPath, destination);
                    }

                    var exportedAsset = InternalAssetData.InternalAssetDataGeneratedByExporter(destination);
                    exportedAssets.Add(exportedAsset);
                }
                outputDict["0"].AddRange(exportedAssets);
            }

            if (failedExports.Any())
            {
                Debug.LogError("exporter: " + string.Join(", ", failedExports.ToArray()) + " is not imported yet, should import before export.");
            }

            Output(nodeId, labelToNext, outputDict, new List <string>());
        }
        public void Run(string nodeId, string labelToNext, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            var usedCache = new List <string>();

            var invalids = new List <string>();

            foreach (var sources in groupedSources.Values)
            {
                foreach (var source in sources)
                {
                    if (string.IsNullOrEmpty(source.importedPath))
                    {
                        invalids.Add(source.pathUnderSourceBase);
                    }
                }
            }

            if (invalids.Any())
            {
                throw new Exception("prefabricator:" + string.Join(", ", invalids.ToArray()) + " are not imported yet, should import before prefabricate.");
            }

            var recommendedPrefabOutputDirectoryPath = FileController.PathCombine(AssetBundleGraphSettings.PREFABRICATOR_CACHE_PLACE, nodeId, GraphStackController.Current_Platform_Package_Folder());

            var outputDict        = new Dictionary <string, List <InternalAssetData> >();
            var cachedOrGenerated = new List <string>();

            foreach (var groupKey in groupedSources.Keys)
            {
                var inputSources = groupedSources[groupKey];

                var recommendedPrefabPath = FileController.PathCombine(recommendedPrefabOutputDirectoryPath, groupKey);
                if (!recommendedPrefabPath.EndsWith(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString()))
                {
                    recommendedPrefabPath = recommendedPrefabPath + AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString();
                }

                /*
                 *      ready input resource info for execute. not contains cache in this node.
                 */
                var assets = new List <AssetInfo>();
                foreach (var assetData in inputSources)
                {
                    var assetName = assetData.fileNameAndExtension;
                    var assetType = assetData.assetType;
                    var assetPath = assetData.importedPath;
                    var assetId   = assetData.assetId;
                    assets.Add(new AssetInfo(assetName, assetType, assetPath, assetId));
                }

                // collect generated prefab path.
                var generated     = new List <string>();
                var outputSources = new List <InternalAssetData>();


                /*
                 *      Prefabricate(GameObject baseObject, string prefabName, bool forceGenerate) method.
                 */
                Func <GameObject, string, bool, string> Prefabricate = (GameObject baseObject, string prefabName, bool forceGenerate) => {
                    var newPrefabOutputPath = Path.Combine(recommendedPrefabPath, prefabName);

                    if (forceGenerate || !GraphStackController.IsCachedForEachSource(inputSources, alreadyCached, newPrefabOutputPath))
                    {
                        // not cached, create new.
                        UnityEngine.Object prefabFile = PrefabUtility.CreateEmptyPrefab(newPrefabOutputPath);

                        // export prefab data.
                        PrefabUtility.ReplacePrefab(baseObject, prefabFile);

                        // save prefab.
                        AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
                        AssetDatabase.SaveAssets();
                        generated.Add(newPrefabOutputPath);
                        cachedOrGenerated.Add(newPrefabOutputPath);
                        Debug.Log("AssetBundleGraph prefab:" + newPrefabOutputPath + " is newly generated.");
                    }
                    else
                    {
                        // cached.
                        usedCache.Add(newPrefabOutputPath);
                        cachedOrGenerated.Add(newPrefabOutputPath);
                        Debug.Log("AssetBundleGraph prefab:" + newPrefabOutputPath + " is already cached. if want to regenerate forcely, set Prefabricate(baseObject, prefabName, true) <- forcely regenerate prefab.");
                    }

                    // set used.
                    PrefabricateIsUsed();

                    return(newPrefabOutputPath);
                };

                if (!Directory.Exists(recommendedPrefabPath))
                {
                    // create recommended directory.
                    Directory.CreateDirectory(recommendedPrefabPath);
                }

                /*
                 *      execute inheritee's input method.
                 */
                try {
                    Run(groupKey, assets, recommendedPrefabPath, Prefabricate);
                } catch (Exception e) {
                    Debug.LogError("Prefabricator:" + this + " error:" + e);
                }

                if (!isUsed)
                {
                    Debug.LogWarning("should use 'Prefabricate' method for create prefab in Prefabricator for cache.");
                }


                /*
                 *      ready assets-output-data from this node to next output.
                 *      it contains "cached" or "generated as prefab" or "else" assets.
                 *      output all assets.
                 */
                var currentAssetsInThisNode = FileController.FilePathsInFolder(recommendedPrefabPath);
                foreach (var generatedCandidateAssetPath in currentAssetsInThisNode)
                {
                    /*
                     *      candidate is new, regenerated prefab.
                     */
                    if (generated.Contains(generatedCandidateAssetPath))
                    {
                        var newAsset = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                            generatedCandidateAssetPath,
                            AssetDatabase.AssetPathToGUID(generatedCandidateAssetPath),
                            AssetBundleGraphInternalFunctions.GetAssetType(generatedCandidateAssetPath),
                            true,
                            false
                            );
                        outputSources.Add(newAsset);
                        continue;
                    }

                    /*
                     *      candidate is not new prefab.
                     */
                    var cachedPrefabAsset = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                        generatedCandidateAssetPath,
                        AssetDatabase.AssetPathToGUID(generatedCandidateAssetPath),
                        AssetBundleGraphInternalFunctions.GetAssetType(generatedCandidateAssetPath),
                        false,
                        false
                        );
                    outputSources.Add(cachedPrefabAsset);
                }


                /*
                 *      add current resources to next node's resources.
                 */
                outputSources.AddRange(inputSources);

                outputDict[groupKey] = outputSources;
            }

            // delete unused cached prefabs.
            var unusedCachePaths = alreadyCached.Except(cachedOrGenerated).Where(path => !GraphStackController.IsMetaFile(path)).ToList();

            foreach (var unusedCachePath in unusedCachePaths)
            {
                // unbundlize unused prefabricated cached asset.
                var assetImporter = AssetImporter.GetAtPath(unusedCachePath);
                assetImporter.assetBundleName = string.Empty;

                FileController.DeleteFileThenDeleteFolderIfEmpty(unusedCachePath);
            }


            Output(nodeId, labelToNext, outputDict, usedCache);
        }
        public void Setup(string nodeId, string labelToNext, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            var invalids = new List <string>();

            foreach (var sources in groupedSources.Values)
            {
                foreach (var source in sources)
                {
                    if (string.IsNullOrEmpty(source.importedPath))
                    {
                        invalids.Add(source.pathUnderSourceBase);
                    }
                }
            }

            if (invalids.Any())
            {
                throw new Exception("prefabricator:" + string.Join(", ", invalids.ToArray()) + " are not imported yet, should import before prefabricate.");
            }

            var recommendedPrefabOutputDirectoryPath = FileController.PathCombine(AssetBundleGraphSettings.PREFABRICATOR_CACHE_PLACE, nodeId, GraphStackController.Current_Platform_Package_Folder());

            var outputDict = new Dictionary <string, List <InternalAssetData> >();

            foreach (var groupKey in groupedSources.Keys)
            {
                var inputSources = groupedSources[groupKey];

                var recommendedPrefabPath = FileController.PathCombine(recommendedPrefabOutputDirectoryPath, groupKey);
                if (!recommendedPrefabPath.EndsWith(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString()))
                {
                    recommendedPrefabPath = recommendedPrefabPath + AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString();
                }

                /*
                 *      ready input resource info for execute. not contains cache in this node.
                 */
                var assets = new List <AssetInfo>();
                foreach (var assetData in inputSources)
                {
                    var assetName = assetData.fileNameAndExtension;
                    var assetType = assetData.assetType;
                    var assetPath = assetData.importedPath;
                    var assetId   = assetData.assetId;
                    assets.Add(new AssetInfo(assetName, assetType, assetPath, assetId));
                }

                // collect generated prefab path.
                var generated = new List <string>();

                /*
                 *      Prefabricate(string prefabName) method.
                 */
                Func <string, string> Prefabricate = (string prefabName) => {
                    var newPrefabOutputPath = Path.Combine(recommendedPrefabPath, prefabName);
                    generated.Add(newPrefabOutputPath);
                    // set used.
                    PrefabricateIsUsed();

                    return(newPrefabOutputPath);
                };

                /*
                 *      execute inheritee's input method.
                 */
                try {
                    Estimate(groupKey, assets, recommendedPrefabPath, Prefabricate);
                } catch (Exception e) {
                    Debug.LogError("Prefabricator:" + this + " error:" + e);
                }

                if (!isUsed)
                {
                    Debug.LogWarning("should use 'Prefabricate' method for create prefab in Prefabricator for cache.");
                }

                foreach (var generatedPrefabPath in generated)
                {
                    var newAsset = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                        generatedPrefabPath,
                        string.Empty,                // dummy data
                        typeof(string),              // dummy data
                        true,                        // absolutely new in setup.
                        false
                        );

                    if (!outputDict.ContainsKey(groupKey))
                    {
                        outputDict[groupKey] = new List <InternalAssetData>();
                    }
                    outputDict[groupKey].Add(newAsset);
                }
                outputDict[groupKey].AddRange(inputSources);
            }

            Output(nodeId, labelToNext, outputDict, new List <string>());
        }
        public void Setup(string nodeName, string nodeId, string connectionIdToNextNode, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            var invalids = new List <string>();

            foreach (var sources in groupedSources.Values)
            {
                foreach (var source in sources)
                {
                    if (string.IsNullOrEmpty(source.importedPath))
                    {
                        invalids.Add(source.pathUnderSourceBase);
                    }
                }
            }

            if (invalids.Any())
            {
                throw new NodeException(string.Join(", ", invalids.ToArray()) + " are not imported yet. These assets need to be imported before prefabricated.", nodeId);
            }

            var recommendedPrefabOutputDirectoryPath = FileController.PathCombine(AssetBundleGraphSettings.PREFABRICATOR_CACHE_PLACE, nodeId, GraphStackController.GetCurrentPlatformPackageFolder());
            var outputDict = new Dictionary <string, List <InternalAssetData> >();

            foreach (var groupKey in groupedSources.Keys)
            {
                var inputSources = groupedSources[groupKey];

                var recommendedPrefabPath = FileController.PathCombine(recommendedPrefabOutputDirectoryPath, groupKey);
                if (!recommendedPrefabPath.EndsWith(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString()))
                {
                    recommendedPrefabPath = recommendedPrefabPath + AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString();
                }

                /*
                 *      ready input resource info for execute. not contains cache in this node.
                 */
                var assets = new List <AssetInfo>();
                foreach (var assetData in inputSources)
                {
                    var assetName = assetData.fileNameAndExtension;
                    var assetType = assetData.assetType;
                    var assetPath = assetData.importedPath;
                    var assetId   = assetData.assetId;
                    assets.Add(new AssetInfo(assetName, assetType, assetPath, assetId));
                }

                // collect generated prefab path.
                var generated = new List <string>();

                /*
                 *      Prefabricate(string prefabName) method.
                 */
                Func <string, string> Prefabricate = (string prefabName) => {
                    var newPrefabOutputPath = Path.Combine(recommendedPrefabPath, prefabName);
                    generated.Add(newPrefabOutputPath);
                    isPrefabricateFunctionCalled = true;

                    return(newPrefabOutputPath);
                };

                ValidateCanCreatePrefab(nodeName, nodeId, groupKey, assets, recommendedPrefabPath, Prefabricate);

                if (!isPrefabricateFunctionCalled)
                {
                    Debug.LogWarning(nodeName + ": Prefabricate delegate was not called. Prefab might not be created properly.");
                }

                foreach (var generatedPrefabPath in generated)
                {
                    var newAsset = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                        generatedPrefabPath,
                        string.Empty,                // dummy data
                        typeof(string),              // dummy data
                        true,                        // absolutely new in setup.
                        false
                        );

                    if (!outputDict.ContainsKey(groupKey))
                    {
                        outputDict[groupKey] = new List <InternalAssetData>();
                    }
                    outputDict[groupKey].Add(newAsset);
                }
                outputDict[groupKey].AddRange(inputSources);
            }

            Output(nodeId, connectionIdToNextNode, outputDict, new List <string>());
        }
        public void Run(string nodeName, string nodeId, string connectionIdToNextNode, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            var usedCache = new List <string>();

            var outputDict = new Dictionary <string, List <InternalAssetData> >();


            // caution if import setting file is exists already or not.
            var samplingDirectoryPath = FileController.PathCombine(AssetBundleGraphSettings.IMPORTER_SETTINGS_PLACE, nodeId);

            var sampleAssetPath = string.Empty;

            ValidateImportSample(samplingDirectoryPath,
                                 (string samplePath) => {
                throw new AssetBundleGraphBuildException(nodeName + ": No ImportSettings Directory found for this node:" + nodeName + " please supply assets to this node.");
            },
                                 (string samplePath) => {
                throw new AssetBundleGraphBuildException(nodeName + ": No saved ImportSettings found for asset:" + samplePath);
            },
                                 (string samplePath) => {
                sampleAssetPath = samplePath;
            },
                                 (string samplePath) => {
                throw new AssetBundleGraphBuildException(nodeName + ": Too many ImportSettings found. please open editor and resolve issue:" + samplePath);
            }
                                 );

            if (groupedSources.Keys.Count == 0)
            {
                return;
            }

            var the1stGroupKey = groupedSources.Keys.ToList()[0];


            // ImportSetting merges multiple incoming groups into one, so warn this
            if (1 < groupedSources.Keys.Count)
            {
                Debug.LogWarning(nodeName + " ImportSetting merges incoming group into \"" + groupedSources.Keys.ToList()[0]);
            }

            var inputSources = new List <InternalAssetData>();

            foreach (var groupKey in groupedSources.Keys)
            {
                inputSources.AddRange(groupedSources[groupKey]);
            }

            var importSetOveredAssetsAndUpdatedFlagDict = new Dictionary <InternalAssetData, bool>();

            /*
             *      check file & setting.
             *      if need, apply importSetting to file.
             */
            var samplingAssetImporter = AssetImporter.GetAtPath(sampleAssetPath);

            var effector = new InternalSamplingImportEffector(samplingAssetImporter);
            var samplingAssetImporterTypeStr = samplingAssetImporter.GetType().ToString();

            foreach (var inputSource in inputSources)
            {
                var importer = AssetImporter.GetAtPath(inputSource.importedPath);

                /*
                 *      compare type of import setting effector.
                 */
                var importerTypeStr = importer.GetType().ToString();


                if (importerTypeStr != samplingAssetImporterTypeStr)
                {
                    throw new NodeException("for each importerSetting should be only treat 1 import setting. current import setting type of this node is:" + samplingAssetImporterTypeStr + " inputted error file path:" + inputSource.importedPath, nodeId);
                }

                importSetOveredAssetsAndUpdatedFlagDict[inputSource] = false;

                /*
                 *      kind of importer is matched.
                 *      check setting then apply setting or no changed.
                 */
                switch (importerTypeStr)
                {
                case "UnityEditor.TextureImporter": {
                    var texImporter = importer as TextureImporter;
                    var same        = InternalSamplingImportEffector.IsSameTextureSetting(texImporter, samplingAssetImporter as TextureImporter);

                    if (!same)
                    {
                        effector.ForceOnPreprocessTexture(texImporter);
                        importSetOveredAssetsAndUpdatedFlagDict[inputSource] = true;
                    }
                    break;
                }

                case "UnityEditor.ModelImporter": {
                    var modelImporter = importer as ModelImporter;
                    var same          = InternalSamplingImportEffector.IsSameModelSetting(modelImporter, samplingAssetImporter as ModelImporter);

                    if (!same)
                    {
                        effector.ForceOnPreprocessModel(modelImporter);
                        importSetOveredAssetsAndUpdatedFlagDict[inputSource] = true;
                    }
                    break;
                }

                case "UnityEditor.AudioImporter": {
                    var audioImporter = importer as AudioImporter;
                    var same          = InternalSamplingImportEffector.IsSameAudioSetting(audioImporter, samplingAssetImporter as AudioImporter);

                    if (!same)
                    {
                        effector.ForceOnPreprocessAudio(audioImporter);
                        importSetOveredAssetsAndUpdatedFlagDict[inputSource] = true;
                    }
                    break;
                }

                default: {
                    throw new NodeException("unhandled importer type:" + importerTypeStr, nodeId);
                }
                }
            }


            /*
             *      inputSetting sequence is over.
             */

            var outputSources = new List <InternalAssetData>();


            foreach (var inputAsset in inputSources)
            {
                var updated = importSetOveredAssetsAndUpdatedFlagDict[inputAsset];
                if (!updated)
                {
                    // already set completed.
                    var newInternalAssetData = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                        inputAsset.importedPath,
                        AssetDatabase.AssetPathToGUID(inputAsset.importedPath),
                        AssetBundleGraphInternalFunctions.GetAssetType(inputAsset.importedPath),
                        false,                        // not changed.
                        false
                        );
                    outputSources.Add(newInternalAssetData);
                }
                else
                {
                    // updated asset.
                    var newInternalAssetData = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                        inputAsset.importedPath,
                        AssetDatabase.AssetPathToGUID(inputAsset.importedPath),
                        AssetBundleGraphInternalFunctions.GetAssetType(inputAsset.importedPath),
                        true,                        // changed.
                        false
                        );
                    outputSources.Add(newInternalAssetData);
                }
            }

            outputDict[the1stGroupKey] = outputSources;

            Output(nodeId, connectionIdToNextNode, outputDict, usedCache);
        }
        public void Setup(string nodeName, string nodeId, string connectionIdToNextNode, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            // reserve importSetting type for limit asset.
            var importSettingSampleType = string.Empty;


            var outputDict = new Dictionary <string, List <InternalAssetData> >();

            var first = true;

            if (groupedSources.Keys.Count == 0)
            {
                return;
            }

            // ImportSetting merges multiple incoming groups into one, so warn this
            if (1 < groupedSources.Keys.Count)
            {
                Debug.LogWarning(nodeName + " ImportSetting merges incoming group into \"" + groupedSources.Keys.ToList()[0]);
            }

            var inputSources = new List <InternalAssetData>();

            foreach (var groupKey in groupedSources.Keys)
            {
                inputSources.AddRange(groupedSources[groupKey]);
            }

            var assumedImportedAssetDatas = new List <InternalAssetData>();


            var samplingDirectoryPath = FileController.PathCombine(AssetBundleGraphSettings.IMPORTER_SETTINGS_PLACE, nodeId);

            ValidateImportSample(samplingDirectoryPath,
                                 (string samplePath) => {
                // do nothing. keep importing new asset for sampling.
            },
                                 (string samplePath) => {
                // do nothing. keep importing new asset for sampling.
            },
                                 (string samplePath) => {
                importSettingSampleType = AssetImporter.GetAtPath(samplePath).GetType().ToString();
                first = false;
            },
                                 (string samplePath) => {
                throw new NodeException(
                    String.Format("Too many sample file found for this import setting node. Delete files in {0} or use \"Clear Saved ImportSettings\" menu.", samplePath),
                    nodeId);
            }
                                 );

            var alreadyImported = new List <string>();
            var ignoredResource = new List <string>();


            foreach (var inputSource in inputSources)
            {
                if (string.IsNullOrEmpty(inputSource.absoluteSourcePath))
                {
                    if (!string.IsNullOrEmpty(inputSource.importedPath))
                    {
                        alreadyImported.Add(inputSource.importedPath);
                        continue;
                    }

                    ignoredResource.Add(inputSource.fileNameAndExtension);
                    continue;
                }

                var assumedImportedPath = inputSource.importedPath;

                var assumedType     = AssetImporter.GetAtPath(assumedImportedPath).GetType();
                var importerTypeStr = assumedType.ToString();

                /*
                 *      only texture, model and audio importer is acceptable.
                 */
                switch (importerTypeStr)
                {
                case "UnityEditor.TextureImporter":
                case "UnityEditor.ModelImporter":
                case "UnityEditor.AudioImporter": {
                    break;
                }

                default: {
                    throw new NodeException("unhandled importer type:" + importerTypeStr, nodeId);
                }
                }

                var newData = InternalAssetData.InternalAssetDataByImporterOrModifier(
                    inputSource.traceId,
                    inputSource.absoluteSourcePath,
                    inputSource.sourceBasePath,
                    inputSource.fileNameAndExtension,
                    inputSource.pathUnderSourceBase,
                    assumedImportedPath,
                    null,
                    assumedType
                    );
                assumedImportedAssetDatas.Add(newData);

                if (first)
                {
                    if (!Directory.Exists(samplingDirectoryPath))
                    {
                        Directory.CreateDirectory(samplingDirectoryPath);
                    }

                    var absoluteFilePath = inputSource.absoluteSourcePath;
                    var targetFilePath   = FileController.PathCombine(samplingDirectoryPath, inputSource.fileNameAndExtension);

                    EditorUtility.DisplayProgressBar("AssetBundleGraph ImportSetting generating ImporterSetting...", targetFilePath, 0);
                    FileController.CopyFileFromGlobalToLocal(absoluteFilePath, targetFilePath);
                    first = false;
                    AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
                    EditorUtility.ClearProgressBar();

                    importSettingSampleType = AssetImporter.GetAtPath(targetFilePath).GetType().ToString();
                }
                else
                {
                    if (importerTypeStr != importSettingSampleType)
                    {
                        throw new NodeException("Multiple asset type is given to Importer Settings. ImporterSetting Takes only 1 asset type." + nodeName + " is configured for " + importSettingSampleType + ", but " + importerTypeStr + " found.", nodeId);
                    }
                }


                if (alreadyImported.Any())
                {
                    Debug.LogError("importSetting:" + string.Join(", ", alreadyImported.ToArray()) + " are already imported.");
                }
                if (ignoredResource.Any())
                {
                    Debug.LogError("importSetting:" + string.Join(", ", ignoredResource.ToArray()) + " are ignored.");
                }

                outputDict[groupedSources.Keys.ToList()[0]] = assumedImportedAssetDatas;
            }

            Output(nodeId, connectionIdToNextNode, outputDict, new List <string>());
        }