/// <summary> /// インポート用のツールだけ生成 /// </summary> /// <param name="file"></param> private static void CreateImportTool(string file) { string path = Path.GetDirectoryName(file); // インポート用ツール生成 SSPJImportTool tool = SSPJImportTool.Create(Path.GetFileNameWithoutExtension(file)); // sspjのインポート var projectInformation = new SSPJImporter().Import(file); Tracer.Log(projectInformation.ToString()); foreach (var cell in projectInformation.cellMaps) { tool.AddCell(Path.GetFileNameWithoutExtension(cell)); } foreach (var animation in projectInformation.animePacks) { // ssaeをパース var ssaeInformation = new SSAEImporter().ImportNamesOnly(path + '\\' + animation); Tracer.Log(ssaeInformation.ToString()); var name = Path.GetFileNameWithoutExtension(animation); foreach (var fragment in ssaeInformation) { tool.AddAnimation(name, fragment); } } AssetDatabase.CreateAsset(tool, file + ".asset"); }
/// <summary> /// インポート /// </summary> /// <param name="file"></param> /// <param name="targets"></param> internal static void Import( string file, SSPJImportTool.TargetAnimation[] targets ) { // TODO: 出力先は自由に出来るようにする string exportPath = (MenuItems.ExportPath + Path.GetFileNameWithoutExtension( file ) + "/").Trim(); // 出力先が妥当かを簡単にチェック if ( !IsValidExportPath( exportPath ) ) { if ( !EditorUtility.DisplayDialog( "注意", "出力先パスが不正な可能性があります。\n" + exportPath, "続行", "キャンセル" ) ) { return; } } string path = Path.GetDirectoryName( file ); // インポート用ツール生成 SSPJImportTool tool = targets == null ? SSPJImportTool.Create( Path.GetFileNameWithoutExtension( file ) ) : null; // マテリアル Dictionary<types.AlphaBlendType, Material> materials = new Dictionary<types.AlphaBlendType, Material>() { { types.AlphaBlendType.kAdd, AssetDatabase.LoadAssetAtPath( "Assets/SpriteStudioPlayerForUGUI/Materials/Add.mat", typeof( Material ) ) as Material }, { types.AlphaBlendType.kMix, AssetDatabase.LoadAssetAtPath( "Assets/SpriteStudioPlayerForUGUI/Materials/Mix.mat", typeof( Material ) ) as Material }, { types.AlphaBlendType.kMul, AssetDatabase.LoadAssetAtPath( "Assets/SpriteStudioPlayerForUGUI/Materials/Mul.mat", typeof( Material ) ) as Material }, { types.AlphaBlendType.kSub, AssetDatabase.LoadAssetAtPath( "Assets/SpriteStudioPlayerForUGUI/Materials/Sub.mat", typeof( Material ) ) as Material }, }; // sspjのインポート var projectInformation = new SSPJImporter().Import( file ); // ssceのインポート List<CellMap> cellMap = new List<CellMap>(); foreach ( var cell in projectInformation.cellMaps ) { // ssceをパース var importer = new SSCEImporter(); var ssceInformation = importer.Import( path + '\\' + cell ); Tracer.Log( ssceInformation.ToString() ); // エンジン側の形式へ変更 var converter = new SSCEConverter(); cellMap.Add( converter.Convert( path + '\\', ssceInformation ) ); if ( tool != null ) { tool.AddCell( Path.GetFileNameWithoutExtension( cell ) ); } } // セルマップの保存 CreateFolders( exportPath + "CellMaps" ); for ( int i = 0; i < cellMap.Count; ++i ) { var cell = cellMap[i]; string fileName = exportPath + "CellMaps/" + cell.name + ".asset"; var savedCellMap = AssetDatabase.LoadAssetAtPath( fileName, typeof( CellMap ) ); if ( savedCellMap == null ) { AssetDatabase.CreateAsset( cell, fileName ); } else { // 既にあるので上書きする cell.CopyTo( savedCellMap as CellMap ); EditorUtility.SetDirty( savedCellMap ); } cellMap[i] = (CellMap) AssetDatabase.LoadAssetAtPath( fileName, typeof( CellMap ) ); Tracer.Log( "Save CellMap:" + fileName ); } // ssaeのインポート List<GameObject> prefabs = new List<GameObject>(); try { string basePath = exportPath + "Sprites/"; foreach ( var animation in projectInformation.animePacks ) { var ssceName = Path.GetFileNameWithoutExtension( animation ); if ( targets != null ) { // 対象に含まれているか判定 bool isLoad = System.Array.Find( targets, ( o ) => o.File == ssceName ) != null; if ( !isLoad ) { continue; } } // ssaeをパース var ssaeInformation = new SSAEImporter().Import( path + '\\' + animation, ssceName, targets ); Tracer.Log( ssaeInformation.ToString() ); // GameObjectへ変換 var converter = new SSAEConverter(); var result = converter.Convert( projectInformation, ssaeInformation, cellMap, materials, path ); prefabs.AddRange( result.animations ); // prefab保存 string name = Path.GetFileNameWithoutExtension( animation ); CreateFolders( basePath + name ); CreateFolders( basePath + name + "/motions" ); // パーツ構成のみでモーションが存在しないモノを保存 if ( prefabs.Count > 0 ) { var skelton = (GameObject) Object.Instantiate( prefabs[0] ); prefabs.Add( skelton ); var parts = skelton.transform.GetComponentsInChildren<SpritePart>(); foreach ( var part in parts ) { part.SetKeyFrames( null ); } string fileName = basePath + name + "/" + name + ".prefab"; var savedPrefab = AssetDatabase.LoadAssetAtPath( fileName, typeof( GameObject ) ); if ( savedPrefab == null ) { Tracer.Log( "Create Skelton Prefab:" + fileName ); PrefabUtility.CreatePrefab( fileName, skelton ); } else { // 既にあるので置き換え Tracer.Log( "Replace Skelton Prefab:" + fileName ); PrefabUtility.ReplacePrefab( skelton, savedPrefab, ReplacePrefabOptions.Default ); } } foreach ( var prefab in result.animations ) { // パーツ+モーションのprefab生成 string fileName = basePath + name + "/" + name + "_" + prefab.name + ".prefab"; var savedPrefab = AssetDatabase.LoadAssetAtPath( fileName, typeof( GameObject ) ); if ( savedPrefab == null ) { Tracer.Log( "Create Prefab:" + fileName ); PrefabUtility.CreatePrefab( fileName, prefab ); } else { // 既にあるので置き換え Tracer.Log( "Replace Prefab:" + fileName + "/" + savedPrefab ); // XXX: 置換方式がDefaultだと、Prefab内にPrefabが格納されてしまう。。。 PrefabUtility.ReplacePrefab( prefab, savedPrefab, ReplacePrefabOptions.ReplaceNameBased ); } // モーションのみのリソースを生成 var resource = CreateKeyFrameResource( prefab ); fileName = basePath + name + "/motions/" + prefab.name + ".asset"; var savedKeys = AssetDatabase.LoadAssetAtPath( fileName, typeof( KeyFrameResource ) ) as KeyFrameResource; if ( savedPrefab == null ) { Tracer.Log( "Create Motion:" + fileName ); AssetDatabase.CreateAsset( resource, fileName ); } else { // 既にあるので置き換え resource.CopyTo( savedKeys ); EditorUtility.SetDirty( savedKeys ); Tracer.Log( "Replace Motion:" + fileName ); } if ( tool != null ) { tool.AddAnimation( name, prefab.name ); } } } if ( tool != null ) { AssetDatabase.CreateAsset( tool, file + ".asset" ); } } finally { // ヒエラルキーにGOが残らないようにする if ( prefabs != null ) { foreach ( var p in prefabs ) { GameObject.DestroyImmediate( p ); } } AssetDatabase.SaveAssets(); } }
/// <summary> /// インポート用のツールだけ生成 /// </summary> /// <param name="file"></param> private static void CreateImportTool( string file ) { string path = Path.GetDirectoryName( file ); // インポート用ツール生成 SSPJImportTool tool = SSPJImportTool.Create( Path.GetFileNameWithoutExtension( file ) ); // sspjのインポート var projectInformation = new SSPJImporter().Import( file ); Tracer.Log( projectInformation.ToString() ); foreach ( var cell in projectInformation.cellMaps ) { tool.AddCell( Path.GetFileNameWithoutExtension( cell ) ); } foreach ( var animation in projectInformation.animePacks ) { // ssaeをパース var ssaeInformation = new SSAEImporter().ImportNamesOnly( path + '\\' + animation ); Tracer.Log( ssaeInformation.ToString() ); var name = Path.GetFileNameWithoutExtension( animation ); foreach ( var fragment in ssaeInformation ) { tool.AddAnimation( name, fragment ); } } AssetDatabase.CreateAsset( tool, file + ".asset" ); }
/// <summary> /// ssaeのパース結果を変換して、GameObjectを生成 /// </summary> /// <param name="projectInformation"></param> /// <param name="animationData"></param> /// <param name="cellMaps"></param> /// <param name="materials"></param> /// <param name="path"></param> /// <returns></returns> public Result Convert(SSPJImporter.Information projectInformation, SSAEImporter.Information animationData, List <CellMap> cellMaps, Dictionary <types.AlphaBlendType, Material> materials, string path) { List <GameObject> results = new List <GameObject>(animationData.animations.Count); try { // 使用するセル List <CellMap> requiredCellMap = new List <CellMap>(); foreach (var cell in animationData.cellMapNames) { var cellName = System.IO.Path.GetFileNameWithoutExtension(cell); var found = cellMaps.Find((o) => o.name == cellName); if (found == null) { foreach (var o in cellMaps) { UnityEngine.Debug.Log(o.name); } throw new System.ArgumentException("Cell '" + cell + "' dose not find."); } Tracer.Log(found); requiredCellMap.Add(found); } // アニメーションの生成 foreach (var anime in animationData.animations) { var o = new GameObject(anime.name, typeof(SpriteRoot), typeof(RectTransform)); results.Add(o); var root = o.GetComponent <SpriteRoot>(); InitializeRoot(root, projectInformation, anime.settings, requiredCellMap); SortedDictionary <int, GameObject> partsObjects = new SortedDictionary <int, GameObject>(); // パーツの生成 foreach (var part in animationData.parts) { var p = new GameObject(part.name, typeof(SpritePart)); try { // 親子の設定 if (part.parent < 0) { p.transform.SetParent(o.transform, false); } else { p.transform.SetParent(partsObjects[part.parent].transform, false); } if (part.type == types.NodeType.kInstance) { // インスタンス string[] names = part.name.Split(':'); SSAEImporter.Information instanceData = new SSAEImporter().Import(path + '\\' + names[0] + ".ssae", null, null); Result instance = Convert(projectInformation, instanceData, cellMaps, materials, path); foreach (var i in instance.animations) { if (i.name == names[1]) { var prefix = part.name + ':'; var r = i.GetComponent <SpriteRoot>(); r.name = prefix + r.name; foreach (var c in r.GetComponentsInChildren <SpritePart>()) { c.name = prefix + c.name; } i.transform.SetParent(p.transform); } else { GameObject.DestroyImmediate(i); } } } else { var sp = p.GetComponent <SpritePart>(); // 通常パーツ partsObjects.Add(part.index, p); // パーツの初期化 Material material; materials.TryGetValue(part.blendType, out material); sp.Setup(root, part.type, material); // このパーツに対するアニメーションを探す foreach (var a in anime.parts) { if (a.partName == part.name) { MakeAttributes(sp, a); break; } } // 0フレーム目で初期化 if (sp.GetKeyFrames() != null) { sp.SetFrame(0); } } } catch { // ヒエラルキーにGOが残らないようにする GameObject.DestroyImmediate(p); throw; } } } return(new Result() { animations = results, }); } catch { // ヒエラルキーにGOが残らないようにする foreach (var o in results) { GameObject.DestroyImmediate(o); } throw; } }
/// <summary> /// インポート /// </summary> /// <param name="file"></param> /// <param name="targets"></param> internal static void Import(string file, SSPJImportTool.TargetAnimation[] targets) { // TODO: 出力先は自由に出来るようにする string exportPath = (MenuItems.ExportPath + Path.GetFileNameWithoutExtension(file) + "/").Trim(); // 出力先が妥当かを簡単にチェック if (!IsValidExportPath(exportPath)) { if (!EditorUtility.DisplayDialog("注意", "出力先パスが不正な可能性があります。\n" + exportPath, "続行", "キャンセル")) { return; } } string path = Path.GetDirectoryName(file); // インポート用ツール生成 SSPJImportTool tool = targets == null?SSPJImportTool.Create(Path.GetFileNameWithoutExtension(file)) : null; // マテリアル Dictionary <types.AlphaBlendType, Material> materials = new Dictionary <types.AlphaBlendType, Material>() { { types.AlphaBlendType.kAdd, AssetDatabase.LoadAssetAtPath("Assets/SpriteStudioPlayerForUGUI/Materials/Add.mat", typeof(Material)) as Material }, { types.AlphaBlendType.kMix, AssetDatabase.LoadAssetAtPath("Assets/SpriteStudioPlayerForUGUI/Materials/Mix.mat", typeof(Material)) as Material }, { types.AlphaBlendType.kMul, AssetDatabase.LoadAssetAtPath("Assets/SpriteStudioPlayerForUGUI/Materials/Mul.mat", typeof(Material)) as Material }, { types.AlphaBlendType.kSub, AssetDatabase.LoadAssetAtPath("Assets/SpriteStudioPlayerForUGUI/Materials/Sub.mat", typeof(Material)) as Material }, }; // sspjのインポート var projectInformation = new SSPJImporter().Import(file); // ssceのインポート List <CellMap> cellMap = new List <CellMap>(); foreach (var cell in projectInformation.cellMaps) { // ssceをパース var importer = new SSCEImporter(); var ssceInformation = importer.Import(path + '\\' + cell); Tracer.Log(ssceInformation.ToString()); // エンジン側の形式へ変更 var converter = new SSCEConverter(); cellMap.Add(converter.Convert(path + '\\', ssceInformation)); if (tool != null) { tool.AddCell(Path.GetFileNameWithoutExtension(cell)); } } // セルマップの保存 CreateFolders(exportPath + "CellMaps"); for (int i = 0; i < cellMap.Count; ++i) { var cell = cellMap[i]; string fileName = exportPath + "CellMaps/" + cell.name + ".asset"; var savedCellMap = AssetDatabase.LoadAssetAtPath(fileName, typeof(CellMap)); if (savedCellMap == null) { AssetDatabase.CreateAsset(cell, fileName); } else { // 既にあるので上書きする cell.CopyTo(savedCellMap as CellMap); EditorUtility.SetDirty(savedCellMap); } cellMap[i] = (CellMap)AssetDatabase.LoadAssetAtPath(fileName, typeof(CellMap)); Tracer.Log("Save CellMap:" + fileName); } // ssaeのインポート List <GameObject> prefabs = new List <GameObject>(); try { string basePath = exportPath + "Sprites/"; foreach (var animation in projectInformation.animePacks) { var ssceName = Path.GetFileNameWithoutExtension(animation); if (targets != null) { // 対象に含まれているか判定 bool isLoad = System.Array.Find(targets, (o) => o.File == ssceName) != null; if (!isLoad) { continue; } } // ssaeをパース var ssaeInformation = new SSAEImporter().Import(path + '\\' + animation, ssceName, targets); Tracer.Log(ssaeInformation.ToString()); // GameObjectへ変換 var converter = new SSAEConverter(); var result = converter.Convert(projectInformation, ssaeInformation, cellMap, materials, path); prefabs.AddRange(result.animations); // prefab保存 string name = Path.GetFileNameWithoutExtension(animation); CreateFolders(basePath + name); CreateFolders(basePath + name + "/motions"); // パーツ構成のみでモーションが存在しないモノを保存 if (prefabs.Count > 0) { var skelton = (GameObject)Object.Instantiate(prefabs[0]); prefabs.Add(skelton); var parts = skelton.transform.GetComponentsInChildren <SpritePart>(); foreach (var part in parts) { part.SetKeyFrames(null); } string fileName = basePath + name + "/" + name + ".prefab"; var savedPrefab = AssetDatabase.LoadAssetAtPath(fileName, typeof(GameObject)); if (savedPrefab == null) { Tracer.Log("Create Skelton Prefab:" + fileName); PrefabUtility.CreatePrefab(fileName, skelton); } else { // 既にあるので置き換え Tracer.Log("Replace Skelton Prefab:" + fileName); PrefabUtility.ReplacePrefab(skelton, savedPrefab, ReplacePrefabOptions.Default); } } foreach (var prefab in result.animations) { // パーツ+モーションのprefab生成 string fileName = basePath + name + "/" + name + "_" + prefab.name + ".prefab"; var savedPrefab = AssetDatabase.LoadAssetAtPath(fileName, typeof(GameObject)); if (savedPrefab == null) { Tracer.Log("Create Prefab:" + fileName); PrefabUtility.CreatePrefab(fileName, prefab); } else { // 既にあるので置き換え Tracer.Log("Replace Prefab:" + fileName + "/" + savedPrefab); // XXX: 置換方式がDefaultだと、Prefab内にPrefabが格納されてしまう。。。 PrefabUtility.ReplacePrefab(prefab, savedPrefab, ReplacePrefabOptions.ReplaceNameBased); } // モーションのみのリソースを生成 var resource = CreateKeyFrameResource(prefab); fileName = basePath + name + "/motions/" + prefab.name + ".asset"; var savedKeys = AssetDatabase.LoadAssetAtPath(fileName, typeof(KeyFrameResource)) as KeyFrameResource; if (savedPrefab == null) { Tracer.Log("Create Motion:" + fileName); AssetDatabase.CreateAsset(resource, fileName); } else { // 既にあるので置き換え resource.CopyTo(savedKeys); EditorUtility.SetDirty(savedKeys); Tracer.Log("Replace Motion:" + fileName); } if (tool != null) { tool.AddAnimation(name, prefab.name); } } } if (tool != null) { AssetDatabase.CreateAsset(tool, file + ".asset"); } } finally { // ヒエラルキーにGOが残らないようにする if (prefabs != null) { foreach (var p in prefabs) { GameObject.DestroyImmediate(p); } } AssetDatabase.SaveAssets(); } }