using System.IO; using UnityEditor; using UnityEngine; namespace AibisDream.SystemEditor { public class AnimationClipGenerator : EditorWindow { private Texture2D selectedTexture; private TextAsset selectedJson; private DefaultAsset outputFolder; private string outputPath = ""; // 动画类型选项 private enum AnimationTargetType { SpriteRenderer, // Sprite动画 Image // UIImage动画 } private AnimationTargetType animationType = AnimationTargetType.SpriteRenderer; // Pivot 设置选项 private enum PivotAlignment { Center, // 中心 (0.5, 0.5) TopLeft, // 左上 (0, 1) TopRight, // 右上 (1, 1) BottomLeft, // 左下 (0, 0) BottomRight, // 右下 (1, 0) TopCenter, // 上中 (0.5, 1) BottomCenter, // 下中 (0.5, 0) LeftCenter, // 左中 (0, 0.5) RightCenter, // 右中 (1, 0.5) Custom // 自定义 } private PivotAlignment pivotAlignment = PivotAlignment.Center; private Vector2 customPivot = new Vector2(0.5f, 0.5f); [MenuItem("Tools/动画片段生成器(Animation Clip Generator)")] public static void ShowWindow() { GetWindow("动画片段生成器(Animation Clip Generator)"); } private void OnGUI() { // 图片文件选择 EditorGUILayout.LabelField("图片文件 (PNG/JPG)", EditorStyles.boldLabel); selectedTexture = (Texture2D)EditorGUILayout.ObjectField( "Texture", selectedTexture, typeof(Texture2D), false); EditorGUILayout.Space(); // JSON文件选择 EditorGUILayout.LabelField("JSON文件", EditorStyles.boldLabel); selectedJson = (TextAsset)EditorGUILayout.ObjectField( "JSON", selectedJson, typeof(TextAsset), false); EditorGUILayout.Space(); // 动画类型选择 EditorGUILayout.LabelField("动画类型", EditorStyles.boldLabel); animationType = (AnimationTargetType)EditorGUILayout.EnumPopup( "Animation Type", animationType); EditorGUILayout.HelpBox( animationType == AnimationTargetType.SpriteRenderer ? "生成用于SpriteRenderer的动画(绑定到m_Sprite属性)" : "生成用于Unity UI Image的动画(绑定到m_Sprite属性)", MessageType.Info); EditorGUILayout.Space(); // Pivot 设置 EditorGUILayout.LabelField("Pivot 设置", EditorStyles.boldLabel); pivotAlignment = (PivotAlignment)EditorGUILayout.EnumPopup( "Pivot Alignment", pivotAlignment); if (pivotAlignment == PivotAlignment.Custom) { customPivot = EditorGUILayout.Vector2Field("Custom Pivot", customPivot); // 限制 pivot 值在 0-1 范围内 customPivot.x = Mathf.Clamp01(customPivot.x); customPivot.y = Mathf.Clamp01(customPivot.y); EditorGUILayout.HelpBox( "自定义 Pivot 值范围: X 和 Y 应在 0-1 之间\n" + "例如: (0, 0) = 左下角, (0.5, 0.5) = 中心, (1, 1) = 右上角", MessageType.Info); } else { Vector2 previewPivot = GetPivotFromAlignment(pivotAlignment); EditorGUILayout.HelpBox( $"当前 Pivot: ({previewPivot.x:F2}, {previewPivot.y:F2})", MessageType.Info); } EditorGUILayout.Space(); // 输出目录选择 EditorGUILayout.LabelField("输出目录", EditorStyles.boldLabel); outputFolder = (DefaultAsset)EditorGUILayout.ObjectField( "Output Folder", outputFolder, typeof(DefaultAsset), false); // 显示输出路径 if (outputFolder != null) { outputPath = AssetDatabase.GetAssetPath(outputFolder); EditorGUILayout.HelpBox($"输出路径: {outputPath}", MessageType.Info); } else { outputPath = ""; } EditorGUILayout.Space(); // 生成按钮 GUI.enabled = selectedTexture != null && selectedJson != null && outputFolder != null; if (GUILayout.Button("生成 AnimationClip", GUILayout.Height(30))) { GenerateAnimationClips(); } GUI.enabled = true; EditorGUILayout.Space(); // 说明信息 EditorGUILayout.HelpBox( "使用说明:\n" + "1. 选择PNG或JPG图片文件\n" + "2. 选择JSON文件(Aseprite格式或手动格式)\n" + "3. 选择输出目录\n" + "4. 点击生成按钮\n\n" + "注意: 如果图片的SpriteMode是Single,工具会自动根据JSON切图。", MessageType.Info); } private void GenerateAnimationClips() { if (selectedTexture == null || selectedJson == null || outputFolder == null) { EditorUtility.DisplayDialog("错误", "请选择图片文件、JSON文件和输出目录", "确定"); return; } string texturePath = AssetDatabase.GetAssetPath(selectedTexture); string jsonPath = AssetDatabase.GetAssetPath(selectedJson); // 验证文件扩展名 string textureExt = Path.GetExtension(texturePath).ToLower(); if (textureExt != ".png" && textureExt != ".jpg" && textureExt != ".jpeg") { EditorUtility.DisplayDialog("错误", "图片文件必须是PNG或JPG格式", "确定"); return; } try { bool isImageAnimation = animationType == AnimationTargetType.Image; Vector2 pivot = pivotAlignment == PivotAlignment.Custom ? customPivot : GetPivotFromAlignment(pivotAlignment); // 确保 pivot 值在有效范围内 pivot.x = Mathf.Clamp01(pivot.x); pivot.y = Mathf.Clamp01(pivot.y); AnimationClipGeneratorCore.GenerateClips(texturePath, jsonPath, outputPath, isImageAnimation, pivot); EditorUtility.DisplayDialog("成功", $"AnimationClip已生成到: {outputPath}", "确定"); // 刷新资源数据库 AssetDatabase.Refresh(); } catch (System.Exception e) { EditorUtility.DisplayDialog("错误", $"生成失败: {e.Message}", "确定"); Debug.LogError(e); } } private Vector2 GetPivotFromAlignment(PivotAlignment alignment) { switch (alignment) { case PivotAlignment.Center: return new Vector2(0.5f, 0.5f); case PivotAlignment.TopLeft: return new Vector2(0f, 1f); case PivotAlignment.TopRight: return new Vector2(1f, 1f); case PivotAlignment.BottomLeft: return new Vector2(0f, 0f); case PivotAlignment.BottomRight: return new Vector2(1f, 0f); case PivotAlignment.TopCenter: return new Vector2(0.5f, 1f); case PivotAlignment.BottomCenter: return new Vector2(0.5f, 0f); case PivotAlignment.LeftCenter: return new Vector2(0f, 0.5f); case PivotAlignment.RightCenter: return new Vector2(1f, 0.5f); case PivotAlignment.Custom: return customPivot; default: return new Vector2(0.5f, 0.5f); } } } }