Fix : 전반적인 스크립트 리스트 정리, 모션 에셋파일 눌러도 랙 안걸리게 패치, 모캡 ok파일 리네이머 추가
This commit is contained in:
parent
1ed9aa919c
commit
86cd3e9671
BIN
.claude/settings.local.json
(Stored with Git LFS)
BIN
.claude/settings.local.json
(Stored with Git LFS)
Binary file not shown.
@ -19,6 +19,15 @@ namespace Entum
|
|||||||
private int _currentFrameIndex = 0;
|
private int _currentFrameIndex = 0;
|
||||||
private Vector2 _scrollPosition;
|
private Vector2 _scrollPosition;
|
||||||
|
|
||||||
|
// 성능 최적화: 에디터 초기화 플래그
|
||||||
|
private bool _isInitialized = false;
|
||||||
|
|
||||||
|
// 캐싱된 데이터 (매번 접근하지 않도록)
|
||||||
|
private int _cachedPoseCount = -1;
|
||||||
|
private float _cachedTotalTime = -1f;
|
||||||
|
private int _cachedBoneCount = -1;
|
||||||
|
private int _cachedMuscleCount = -1;
|
||||||
|
|
||||||
// UI 스타일
|
// UI 스타일
|
||||||
private GUIStyle _cardStyle;
|
private GUIStyle _cardStyle;
|
||||||
private GUIStyle _headerStyle;
|
private GUIStyle _headerStyle;
|
||||||
@ -35,11 +44,18 @@ namespace Entum
|
|||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
Repaint();
|
// 캐시 초기화
|
||||||
|
_cachedPoseCount = -1;
|
||||||
|
_cachedTotalTime = -1f;
|
||||||
|
_cachedBoneCount = -1;
|
||||||
|
_cachedMuscleCount = -1;
|
||||||
|
_isInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeStyles()
|
private void InitializeStyles()
|
||||||
{
|
{
|
||||||
|
if (_isInitialized) return; // 이미 초기화되었으면 스킵
|
||||||
|
|
||||||
// 카드 스타일
|
// 카드 스타일
|
||||||
_cardStyle = new GUIStyle();
|
_cardStyle = new GUIStyle();
|
||||||
_cardStyle.normal.background = CreateTexture(2, 2, new Color(0.15f, 0.15f, 0.15f, 1f));
|
_cardStyle.normal.background = CreateTexture(2, 2, new Color(0.15f, 0.15f, 0.15f, 1f));
|
||||||
@ -65,6 +81,8 @@ namespace Entum
|
|||||||
// 섹션 스타일
|
// 섹션 스타일
|
||||||
_sectionStyle = new GUIStyle();
|
_sectionStyle = new GUIStyle();
|
||||||
_sectionStyle.margin = new RectOffset(0, 0, 8, 8);
|
_sectionStyle.margin = new RectOffset(0, 0, 8, 8);
|
||||||
|
|
||||||
|
_isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Texture2D CreateTexture(int width, int height, Color color)
|
private Texture2D CreateTexture(int width, int height, Color color)
|
||||||
@ -130,9 +148,14 @@ namespace Entum
|
|||||||
|
|
||||||
EditorGUILayout.LabelField("📊 데이터 상태", _headerStyle);
|
EditorGUILayout.LabelField("📊 데이터 상태", _headerStyle);
|
||||||
|
|
||||||
if (humanoidPoses.Poses != null && humanoidPoses.Poses.Count > 0)
|
// Summary 데이터 우선 사용
|
||||||
|
int poseCount = (humanoidPoses.Summary != null && humanoidPoses.Summary.TotalPoses > 0)
|
||||||
|
? humanoidPoses.Summary.TotalPoses
|
||||||
|
: (humanoidPoses.Poses != null ? humanoidPoses.Poses.Count : 0);
|
||||||
|
|
||||||
|
if (poseCount > 0)
|
||||||
{
|
{
|
||||||
EditorGUILayout.LabelField($"✅ {humanoidPoses.Poses.Count}개의 포즈 데이터 로드됨", _infoStyle);
|
EditorGUILayout.LabelField($"✅ {poseCount}개의 포즈 데이터 로드됨", _infoStyle);
|
||||||
|
|
||||||
// T-포즈 상태 표시
|
// T-포즈 상태 표시
|
||||||
EditorGUILayout.Space(3);
|
EditorGUILayout.Space(3);
|
||||||
@ -187,8 +210,26 @@ namespace Entum
|
|||||||
|
|
||||||
EditorGUILayout.LabelField("📈 기본 정보", _headerStyle);
|
EditorGUILayout.LabelField("📈 기본 정보", _headerStyle);
|
||||||
|
|
||||||
if (humanoidPoses.Poses != null && humanoidPoses.Poses.Count > 0)
|
// Summary 데이터가 있으면 우선 사용 (성능 최적화)
|
||||||
|
if (humanoidPoses.Summary != null && humanoidPoses.Summary.TotalPoses > 0)
|
||||||
{
|
{
|
||||||
|
DrawInfoRow("🎭 총 포즈 수", humanoidPoses.Summary.TotalPoses.ToString());
|
||||||
|
DrawInfoRow("⏱️ 총 시간", $"{humanoidPoses.Summary.TotalTime:F2}초");
|
||||||
|
DrawInfoRow("🦴 본 수", humanoidPoses.Summary.TotalBones.ToString());
|
||||||
|
DrawInfoRow("💪 근육 수", humanoidPoses.Summary.TotalMuscles.ToString());
|
||||||
|
DrawInfoRow("🎬 평균 FPS", $"{humanoidPoses.Summary.AverageFPS:F1}");
|
||||||
|
|
||||||
|
float fileSize = EstimateFileSizeFromSummary(humanoidPoses.Summary);
|
||||||
|
DrawInfoRow("💾 예상 크기", $"{fileSize:F1}KB");
|
||||||
|
|
||||||
|
// T-포즈 정보 추가
|
||||||
|
DrawInfoRow("🎯 T-포즈", humanoidPoses.HasTPoseData ? "✅ 포함" : "❌ 없음");
|
||||||
|
}
|
||||||
|
else if (humanoidPoses.Poses != null && humanoidPoses.Poses.Count > 0)
|
||||||
|
{
|
||||||
|
// Summary가 없으면 직접 계산 (느림 - 경고 표시)
|
||||||
|
EditorGUILayout.HelpBox("⚠️ Summary 데이터가 없어서 직접 계산 중입니다. 성능이 느릴 수 있습니다.", MessageType.Warning);
|
||||||
|
|
||||||
var firstPose = humanoidPoses.Poses[0];
|
var firstPose = humanoidPoses.Poses[0];
|
||||||
var lastPose = humanoidPoses.Poses[humanoidPoses.Poses.Count - 1];
|
var lastPose = humanoidPoses.Poses[humanoidPoses.Poses.Count - 1];
|
||||||
|
|
||||||
@ -576,6 +617,17 @@ namespace Entum
|
|||||||
return (poseSize + boneSize + muscleSize) * humanoidPoses.Poses.Count / 1024f;
|
return (poseSize + boneSize + muscleSize) * humanoidPoses.Poses.Count / 1024f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float EstimateFileSizeFromSummary(HumanoidPoses.SummaryInfo summary)
|
||||||
|
{
|
||||||
|
if (summary == null || summary.TotalPoses == 0) return 0;
|
||||||
|
|
||||||
|
int poseSize = 4 * 3 + 4 * 4 + 4 * 3 + 4 * 4 + 4 * 3 + 4 * 4 + 4 + 4 + 4;
|
||||||
|
int boneSize = (4 * 3 + 4 * 4 + 50) * summary.TotalBones;
|
||||||
|
int muscleSize = 4 * summary.TotalMuscles;
|
||||||
|
|
||||||
|
return (poseSize + boneSize + muscleSize) * summary.TotalPoses / 1024f;
|
||||||
|
}
|
||||||
|
|
||||||
private long EstimateMemoryUsage(HumanoidPoses humanoidPoses)
|
private long EstimateMemoryUsage(HumanoidPoses humanoidPoses)
|
||||||
{
|
{
|
||||||
if (humanoidPoses.Poses == null || humanoidPoses.Poses.Count == 0) return 0;
|
if (humanoidPoses.Poses == null || humanoidPoses.Poses.Count == 0) return 0;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 3a53342f3b4a81240ada88d8ca085116
|
guid: 20ac0b0b555cf8240a87cc7062d409b1
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@ -19,7 +19,7 @@ public class HumanPoseClipApplier : EditorWindow
|
|||||||
private string jsonPath;
|
private string jsonPath;
|
||||||
private bool useJsonFile = false;
|
private bool useJsonFile = false;
|
||||||
|
|
||||||
[MenuItem("Tools/Animation/Apply Human Pose Clip")]
|
[MenuItem("Tools/Animation Tools/Human Pose Clip Applier")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<HumanPoseClipApplier>("Human Pose Clip Applier");
|
GetWindow<HumanPoseClipApplier>("Human Pose Clip Applier");
|
||||||
@ -9,7 +9,7 @@ public class HumanPoseClipCreator : EditorWindow
|
|||||||
private string assetName = "NewPoseClip";
|
private string assetName = "NewPoseClip";
|
||||||
private string savePath = "Assets/Resources";
|
private string savePath = "Assets/Resources";
|
||||||
|
|
||||||
[MenuItem("Tools/Animation/Create Human Pose Clip")]
|
[MenuItem("Tools/Animation Tools/Human Pose Clip Creator")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<HumanPoseClipCreator>("Human Pose Clip Creator");
|
GetWindow<HumanPoseClipCreator>("Human Pose Clip Creator");
|
||||||
@ -75,7 +75,7 @@ namespace Streamingle.Editor
|
|||||||
HumanBodyBones.RightLittleDistal
|
HumanBodyBones.RightLittleDistal
|
||||||
};
|
};
|
||||||
|
|
||||||
[MenuItem("Tools/Pose Recorder")]
|
[MenuItem("Tools/Animation Tools/Pose Recorder")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<PoseRecorderWindow>("포즈 기록기");
|
GetWindow<PoseRecorderWindow>("포즈 기록기");
|
||||||
@ -22,7 +22,7 @@ namespace Streamingle.Editor
|
|||||||
// 미리보기 옵션
|
// 미리보기 옵션
|
||||||
private bool showBoneInfo = true;
|
private bool showBoneInfo = true;
|
||||||
|
|
||||||
[MenuItem("Tools/Pose Rotation Baker")]
|
[MenuItem("Tools/Animation Tools/Pose Rotation Baker")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<PoseRotationBaker>("포즈 로테이션 베이커");
|
GetWindow<PoseRotationBaker>("포즈 로테이션 베이커");
|
||||||
@ -1,5 +1,6 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 7a76ec1c32272a242936808ac20449ad
|
guid: 5e26c5e61de10ef428871a3d3fdb4eb9
|
||||||
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
@ -6,7 +6,7 @@ public class FindUnusedBones : EditorWindow
|
|||||||
{
|
{
|
||||||
private List<string> excludeStrings = new List<string>(); // 제외할 문자열 리스트
|
private List<string> excludeStrings = new List<string>(); // 제외할 문자열 리스트
|
||||||
|
|
||||||
[MenuItem("Tools/Find Unused Bones")]
|
[MenuItem("Tools/Bone Tools/Find Unused Bones")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<FindUnusedBones>("Find Unused Bones");
|
GetWindow<FindUnusedBones>("Find Unused Bones");
|
||||||
@ -83,7 +83,7 @@ public class HumanBoneRenamer : EditorWindow
|
|||||||
{ HumanBodyBones.RightLittleDistal, "RightLittleDistal" }
|
{ HumanBodyBones.RightLittleDistal, "RightLittleDistal" }
|
||||||
};
|
};
|
||||||
|
|
||||||
[MenuItem("Tools/Human Bone Renamer")]
|
[MenuItem("Tools/Bone Tools/Human Bone Renamer")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<HumanBoneRenamer>("Human Bone Renamer");
|
GetWindow<HumanBoneRenamer>("Human Bone Renamer");
|
||||||
@ -1,691 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using UnityEditor;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 모션 캡쳐 파일 네이밍 편의성 툴
|
|
||||||
/// - 선택한 파일들에 일괄적으로 접미사/접두사 추가
|
|
||||||
/// - 번호 매기기, 날짜 스탬프 등 다양한 네이밍 패턴 지원
|
|
||||||
/// </summary>
|
|
||||||
public class MotionCaptureFileRenamer : EditorWindow
|
|
||||||
{
|
|
||||||
#region Nested Classes
|
|
||||||
[Serializable]
|
|
||||||
public class NamingPreset
|
|
||||||
{
|
|
||||||
public string presetName = "New Preset";
|
|
||||||
public NamingMode mode = NamingMode.Suffix;
|
|
||||||
public string customText = "";
|
|
||||||
public int startNumber = 1;
|
|
||||||
public int numberPadding = 3;
|
|
||||||
public bool includeDate = false;
|
|
||||||
public bool includeTime = false;
|
|
||||||
public string dateFormat = "yyyyMMdd";
|
|
||||||
public string timeFormat = "HHmmss";
|
|
||||||
public string separator = "_";
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum NamingMode
|
|
||||||
{
|
|
||||||
Suffix, // 파일명 뒤에 추가
|
|
||||||
Prefix, // 파일명 앞에 추가
|
|
||||||
Replace, // 전체 이름 변경
|
|
||||||
Sequential // 순차 번호
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Fields
|
|
||||||
private List<UnityEngine.Object> selectedFiles = new List<UnityEngine.Object>();
|
|
||||||
private Vector2 scrollPosition;
|
|
||||||
|
|
||||||
// Naming settings
|
|
||||||
private NamingMode namingMode = NamingMode.Suffix;
|
|
||||||
private string customText = "_ok";
|
|
||||||
private int startNumber = 1;
|
|
||||||
private int numberPadding = 3;
|
|
||||||
private bool includeDate = false;
|
|
||||||
private bool includeTime = false;
|
|
||||||
private string dateFormat = "yyyyMMdd";
|
|
||||||
private string timeFormat = "HHmmss";
|
|
||||||
private string separator = "_";
|
|
||||||
|
|
||||||
// Preview
|
|
||||||
private bool showPreview = true;
|
|
||||||
private Dictionary<string, string> previewNames = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
// Presets
|
|
||||||
private List<NamingPreset> presets = new List<NamingPreset>();
|
|
||||||
private int selectedPresetIndex = -1;
|
|
||||||
private bool showPresetSection = false;
|
|
||||||
private string newPresetName = "My Preset";
|
|
||||||
|
|
||||||
// UI Style
|
|
||||||
private GUIStyle headerStyle;
|
|
||||||
private GUIStyle boxStyle;
|
|
||||||
private Color successColor = new Color(0.5f, 1f, 0.5f, 0.3f);
|
|
||||||
private Color warningColor = new Color(1f, 1f, 0.5f, 0.3f);
|
|
||||||
private Color errorColor = new Color(1f, 0.5f, 0.5f, 0.3f);
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Window Initialization
|
|
||||||
[MenuItem("Tools/Motion Capture/File Renamer")]
|
|
||||||
public static void ShowWindow()
|
|
||||||
{
|
|
||||||
var window = GetWindow<MotionCaptureFileRenamer>("MoCap File Renamer");
|
|
||||||
window.minSize = new Vector2(450, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
LoadPresets();
|
|
||||||
RefreshSelectedFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDisable()
|
|
||||||
{
|
|
||||||
SavePresets();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeStyles()
|
|
||||||
{
|
|
||||||
if (headerStyle == null)
|
|
||||||
{
|
|
||||||
headerStyle = new GUIStyle(EditorStyles.boldLabel)
|
|
||||||
{
|
|
||||||
fontSize = 14,
|
|
||||||
alignment = TextAnchor.MiddleLeft
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boxStyle == null)
|
|
||||||
{
|
|
||||||
boxStyle = new GUIStyle(EditorStyles.helpBox)
|
|
||||||
{
|
|
||||||
padding = new RectOffset(10, 10, 10, 10)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region GUI
|
|
||||||
private void OnGUI()
|
|
||||||
{
|
|
||||||
InitializeStyles();
|
|
||||||
|
|
||||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
|
||||||
|
|
||||||
DrawHeader();
|
|
||||||
DrawFileSelectionSection();
|
|
||||||
DrawNamingOptionsSection();
|
|
||||||
DrawPreviewSection();
|
|
||||||
DrawPresetsSection();
|
|
||||||
DrawActionButtons();
|
|
||||||
|
|
||||||
EditorGUILayout.EndScrollView();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawHeader()
|
|
||||||
{
|
|
||||||
EditorGUILayout.Space(10);
|
|
||||||
EditorGUILayout.LabelField("Motion Capture File Renamer", headerStyle);
|
|
||||||
EditorGUILayout.LabelField("모션 캡쳐 파일 일괄 네이밍 도구", EditorStyles.miniLabel);
|
|
||||||
EditorGUILayout.Space(10);
|
|
||||||
EditorGUILayout.HelpBox("프로젝트 뷰에서 파일을 선택하거나 아래 영역에 드래그 앤 드롭하세요.", MessageType.Info);
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawFileSelectionSection()
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginVertical(boxStyle);
|
|
||||||
EditorGUILayout.LabelField("📁 File Selection", EditorStyles.boldLabel);
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
|
|
||||||
// Drag and drop area
|
|
||||||
Rect dropArea = GUILayoutUtility.GetRect(0f, 50f, GUILayout.ExpandWidth(true));
|
|
||||||
GUI.Box(dropArea, "Drag & Drop Files Here\n또는 'Load Selected Files' 버튼 클릭", EditorStyles.helpBox);
|
|
||||||
|
|
||||||
HandleDragAndDrop(dropArea);
|
|
||||||
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
if (GUILayout.Button("Load Selected Files", GUILayout.Height(30)))
|
|
||||||
{
|
|
||||||
RefreshSelectedFiles();
|
|
||||||
}
|
|
||||||
if (GUILayout.Button("Clear", GUILayout.Width(80), GUILayout.Height(30)))
|
|
||||||
{
|
|
||||||
selectedFiles.Clear();
|
|
||||||
previewNames.Clear();
|
|
||||||
}
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
EditorGUILayout.LabelField($"Selected Files: {selectedFiles.Count}", EditorStyles.miniLabel);
|
|
||||||
|
|
||||||
if (selectedFiles.Count > 0)
|
|
||||||
{
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
EditorGUILayout.LabelField("Current Files:", EditorStyles.miniBoldLabel);
|
|
||||||
|
|
||||||
var rect = EditorGUILayout.BeginVertical(GUILayout.MaxHeight(100));
|
|
||||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.MaxHeight(100));
|
|
||||||
|
|
||||||
for (int i = 0; i < selectedFiles.Count; i++)
|
|
||||||
{
|
|
||||||
if (selectedFiles[i] != null)
|
|
||||||
{
|
|
||||||
EditorGUILayout.LabelField($"{i + 1}. {selectedFiles[i].name}", EditorStyles.miniLabel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndScrollView();
|
|
||||||
EditorGUILayout.EndVertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndVertical();
|
|
||||||
EditorGUILayout.Space(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawNamingOptionsSection()
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginVertical(boxStyle);
|
|
||||||
EditorGUILayout.LabelField("⚙️ Naming Options", EditorStyles.boldLabel);
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
|
|
||||||
// Naming mode
|
|
||||||
namingMode = (NamingMode)EditorGUILayout.EnumPopup("Naming Mode", namingMode);
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
|
|
||||||
switch (namingMode)
|
|
||||||
{
|
|
||||||
case NamingMode.Suffix:
|
|
||||||
DrawSuffixOptions();
|
|
||||||
break;
|
|
||||||
case NamingMode.Prefix:
|
|
||||||
DrawPrefixOptions();
|
|
||||||
break;
|
|
||||||
case NamingMode.Replace:
|
|
||||||
DrawReplaceOptions();
|
|
||||||
break;
|
|
||||||
case NamingMode.Sequential:
|
|
||||||
DrawSequentialOptions();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
|
|
||||||
// Common options
|
|
||||||
EditorGUILayout.LabelField("Additional Options", EditorStyles.miniBoldLabel);
|
|
||||||
separator = EditorGUILayout.TextField("Separator", separator);
|
|
||||||
includeDate = EditorGUILayout.Toggle("Include Date", includeDate);
|
|
||||||
if (includeDate)
|
|
||||||
{
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
dateFormat = EditorGUILayout.TextField("Date Format", dateFormat);
|
|
||||||
EditorGUILayout.LabelField($"Example: {DateTime.Now.ToString(dateFormat)}", EditorStyles.miniLabel);
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
|
|
||||||
includeTime = EditorGUILayout.Toggle("Include Time", includeTime);
|
|
||||||
if (includeTime)
|
|
||||||
{
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
timeFormat = EditorGUILayout.TextField("Time Format", timeFormat);
|
|
||||||
EditorGUILayout.LabelField($"Example: {DateTime.Now.ToString(timeFormat)}", EditorStyles.miniLabel);
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndVertical();
|
|
||||||
EditorGUILayout.Space(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSuffixOptions()
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("파일명 뒤에 텍스트를 추가합니다.\n예: Animation.anim → Animation_ok.anim", MessageType.None);
|
|
||||||
customText = EditorGUILayout.TextField("Suffix Text", customText);
|
|
||||||
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
EditorGUILayout.LabelField("Quick Presets:", EditorStyles.miniBoldLabel);
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
if (GUILayout.Button("_ok")) customText = "_ok";
|
|
||||||
if (GUILayout.Button("_final")) customText = "_final";
|
|
||||||
if (GUILayout.Button("_test")) customText = "_test";
|
|
||||||
if (GUILayout.Button("_backup")) customText = "_backup";
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawPrefixOptions()
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("파일명 앞에 텍스트를 추가합니다.\n예: Animation.anim → Take001_Animation.anim", MessageType.None);
|
|
||||||
customText = EditorGUILayout.TextField("Prefix Text", customText);
|
|
||||||
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
EditorGUILayout.LabelField("Quick Presets:", EditorStyles.miniBoldLabel);
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
if (GUILayout.Button("Take001")) customText = "Take001";
|
|
||||||
if (GUILayout.Button("MoCap")) customText = "MoCap";
|
|
||||||
if (GUILayout.Button("Test")) customText = "Test";
|
|
||||||
if (GUILayout.Button("WIP")) customText = "WIP";
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawReplaceOptions()
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("파일명을 완전히 새로운 이름으로 변경합니다.\n(확장자는 유지됩니다)", MessageType.Warning);
|
|
||||||
customText = EditorGUILayout.TextField("New Base Name", customText);
|
|
||||||
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
bool autoNumber = EditorGUILayout.Toggle("Auto Number", true);
|
|
||||||
if (autoNumber)
|
|
||||||
{
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
startNumber = EditorGUILayout.IntField("Start Number", startNumber);
|
|
||||||
numberPadding = EditorGUILayout.IntSlider("Number Padding", numberPadding, 1, 5);
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSequentialOptions()
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("선택한 파일들에 순차적으로 번호를 부여합니다.\n예: Take001, Take002, Take003...", MessageType.None);
|
|
||||||
|
|
||||||
customText = EditorGUILayout.TextField("Base Name", customText);
|
|
||||||
startNumber = EditorGUILayout.IntField("Start Number", startNumber);
|
|
||||||
numberPadding = EditorGUILayout.IntSlider("Number Padding", numberPadding, 1, 5);
|
|
||||||
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
EditorGUILayout.LabelField($"Example: {customText}{startNumber.ToString().PadLeft(numberPadding, '0')}", EditorStyles.miniLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawPreviewSection()
|
|
||||||
{
|
|
||||||
showPreview = EditorGUILayout.Foldout(showPreview, "🔍 Preview", true, EditorStyles.foldoutHeader);
|
|
||||||
|
|
||||||
if (showPreview)
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginVertical(boxStyle);
|
|
||||||
|
|
||||||
if (selectedFiles.Count == 0)
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("파일을 먼저 선택하세요.", MessageType.Info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("Generate Preview", GUILayout.Height(25)))
|
|
||||||
{
|
|
||||||
GeneratePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previewNames.Count > 0)
|
|
||||||
{
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
EditorGUILayout.LabelField("변경 예정:", EditorStyles.miniBoldLabel);
|
|
||||||
|
|
||||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
||||||
Vector2 previewScroll = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.MaxHeight(150));
|
|
||||||
|
|
||||||
foreach (var kvp in previewNames)
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
EditorGUILayout.LabelField(kvp.Key, GUILayout.Width(150));
|
|
||||||
EditorGUILayout.LabelField("→", GUILayout.Width(20));
|
|
||||||
EditorGUILayout.LabelField(kvp.Value, EditorStyles.boldLabel);
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndScrollView();
|
|
||||||
EditorGUILayout.EndVertical();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndVertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.Space(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawPresetsSection()
|
|
||||||
{
|
|
||||||
showPresetSection = EditorGUILayout.Foldout(showPresetSection, "💾 Presets", true, EditorStyles.foldoutHeader);
|
|
||||||
|
|
||||||
if (showPresetSection)
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginVertical(boxStyle);
|
|
||||||
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
newPresetName = EditorGUILayout.TextField("Preset Name", newPresetName);
|
|
||||||
if (GUILayout.Button("Save Current", GUILayout.Width(100)))
|
|
||||||
{
|
|
||||||
SaveCurrentAsPreset();
|
|
||||||
}
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
EditorGUILayout.Space(5);
|
|
||||||
|
|
||||||
if (presets.Count > 0)
|
|
||||||
{
|
|
||||||
EditorGUILayout.LabelField("Saved Presets:", EditorStyles.miniBoldLabel);
|
|
||||||
|
|
||||||
for (int i = 0; i < presets.Count; i++)
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
|
|
||||||
if (GUILayout.Button(presets[i].presetName, GUILayout.Height(25)))
|
|
||||||
{
|
|
||||||
LoadPreset(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUILayout.Button("×", GUILayout.Width(25), GUILayout.Height(25)))
|
|
||||||
{
|
|
||||||
if (EditorUtility.DisplayDialog("Delete Preset",
|
|
||||||
$"'{presets[i].presetName}' 프리셋을 삭제하시겠습니까?", "Delete", "Cancel"))
|
|
||||||
{
|
|
||||||
presets.RemoveAt(i);
|
|
||||||
SavePresets();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("저장된 프리셋이 없습니다.", MessageType.Info);
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndVertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.Space(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawActionButtons()
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginVertical(boxStyle);
|
|
||||||
|
|
||||||
GUI.enabled = selectedFiles.Count > 0;
|
|
||||||
|
|
||||||
EditorGUILayout.BeginHorizontal();
|
|
||||||
|
|
||||||
if (GUILayout.Button("Apply Rename", GUILayout.Height(40)))
|
|
||||||
{
|
|
||||||
if (EditorUtility.DisplayDialog("Confirm Rename",
|
|
||||||
$"{selectedFiles.Count}개의 파일 이름을 변경하시겠습니까?\n\n이 작업은 Undo로 되돌릴 수 있습니다.",
|
|
||||||
"Rename", "Cancel"))
|
|
||||||
{
|
|
||||||
ApplyRename();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
GUI.enabled = true;
|
|
||||||
|
|
||||||
EditorGUILayout.EndVertical();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region File Selection
|
|
||||||
private void RefreshSelectedFiles()
|
|
||||||
{
|
|
||||||
selectedFiles.Clear();
|
|
||||||
|
|
||||||
var selected = Selection.objects;
|
|
||||||
foreach (var obj in selected)
|
|
||||||
{
|
|
||||||
string path = AssetDatabase.GetAssetPath(obj);
|
|
||||||
if (!string.IsNullOrEmpty(path) && !AssetDatabase.IsValidFolder(path))
|
|
||||||
{
|
|
||||||
selectedFiles.Add(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
previewNames.Clear();
|
|
||||||
Debug.Log($"Loaded {selectedFiles.Count} files");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleDragAndDrop(Rect dropArea)
|
|
||||||
{
|
|
||||||
Event evt = Event.current;
|
|
||||||
|
|
||||||
if (dropArea.Contains(evt.mousePosition))
|
|
||||||
{
|
|
||||||
if (evt.type == EventType.DragUpdated)
|
|
||||||
{
|
|
||||||
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
|
||||||
evt.Use();
|
|
||||||
}
|
|
||||||
else if (evt.type == EventType.DragPerform)
|
|
||||||
{
|
|
||||||
DragAndDrop.AcceptDrag();
|
|
||||||
|
|
||||||
foreach (var obj in DragAndDrop.objectReferences)
|
|
||||||
{
|
|
||||||
string path = AssetDatabase.GetAssetPath(obj);
|
|
||||||
if (!string.IsNullOrEmpty(path) && !AssetDatabase.IsValidFolder(path))
|
|
||||||
{
|
|
||||||
if (!selectedFiles.Contains(obj))
|
|
||||||
{
|
|
||||||
selectedFiles.Add(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
evt.Use();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Naming Logic
|
|
||||||
private void GeneratePreview()
|
|
||||||
{
|
|
||||||
previewNames.Clear();
|
|
||||||
|
|
||||||
for (int i = 0; i < selectedFiles.Count; i++)
|
|
||||||
{
|
|
||||||
var file = selectedFiles[i];
|
|
||||||
if (file == null) continue;
|
|
||||||
|
|
||||||
string originalName = file.name;
|
|
||||||
string newName = GenerateNewName(originalName, i);
|
|
||||||
|
|
||||||
previewNames[originalName] = newName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GenerateNewName(string originalName, int index)
|
|
||||||
{
|
|
||||||
string baseName = originalName;
|
|
||||||
string result = "";
|
|
||||||
|
|
||||||
// Build timestamp if needed
|
|
||||||
string timestamp = "";
|
|
||||||
if (includeDate)
|
|
||||||
{
|
|
||||||
timestamp += DateTime.Now.ToString(dateFormat);
|
|
||||||
}
|
|
||||||
if (includeTime)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(timestamp))
|
|
||||||
timestamp += separator;
|
|
||||||
timestamp += DateTime.Now.ToString(timeFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (namingMode)
|
|
||||||
{
|
|
||||||
case NamingMode.Suffix:
|
|
||||||
result = baseName + separator + customText;
|
|
||||||
if (!string.IsNullOrEmpty(timestamp))
|
|
||||||
result += separator + timestamp;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NamingMode.Prefix:
|
|
||||||
result = customText + separator + baseName;
|
|
||||||
if (!string.IsNullOrEmpty(timestamp))
|
|
||||||
result += separator + timestamp;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NamingMode.Replace:
|
|
||||||
string number = (startNumber + index).ToString().PadLeft(numberPadding, '0');
|
|
||||||
result = customText + separator + number;
|
|
||||||
if (!string.IsNullOrEmpty(timestamp))
|
|
||||||
result += separator + timestamp;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NamingMode.Sequential:
|
|
||||||
string seqNumber = (startNumber + index).ToString().PadLeft(numberPadding, '0');
|
|
||||||
result = customText + seqNumber;
|
|
||||||
if (!string.IsNullOrEmpty(timestamp))
|
|
||||||
result += separator + timestamp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove invalid characters
|
|
||||||
result = string.Join("_", result.Split(Path.GetInvalidFileNameChars()));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ApplyRename()
|
|
||||||
{
|
|
||||||
if (selectedFiles.Count == 0)
|
|
||||||
{
|
|
||||||
EditorUtility.DisplayDialog("Error", "선택된 파일이 없습니다.", "OK");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int successCount = 0;
|
|
||||||
int failCount = 0;
|
|
||||||
|
|
||||||
AssetDatabase.StartAssetEditing();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (int i = 0; i < selectedFiles.Count; i++)
|
|
||||||
{
|
|
||||||
var file = selectedFiles[i];
|
|
||||||
if (file == null) continue;
|
|
||||||
|
|
||||||
string assetPath = AssetDatabase.GetAssetPath(file);
|
|
||||||
string directory = Path.GetDirectoryName(assetPath);
|
|
||||||
string extension = Path.GetExtension(assetPath);
|
|
||||||
string oldName = file.name;
|
|
||||||
string newName = GenerateNewName(oldName, i);
|
|
||||||
string newPath = Path.Combine(directory, newName + extension);
|
|
||||||
|
|
||||||
// Check if file already exists
|
|
||||||
if (File.Exists(newPath) && assetPath != newPath)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"File already exists: {newPath}. Skipping {oldName}.");
|
|
||||||
failCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rename asset
|
|
||||||
string error = AssetDatabase.RenameAsset(assetPath, newName);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(error))
|
|
||||||
{
|
|
||||||
Debug.Log($"Renamed: {oldName} → {newName}");
|
|
||||||
successCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogError($"Failed to rename {oldName}: {error}");
|
|
||||||
failCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AssetDatabase.StopAssetEditing();
|
|
||||||
AssetDatabase.SaveAssets();
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
string message = $"Rename completed!\n\nSuccess: {successCount}\nFailed: {failCount}";
|
|
||||||
EditorUtility.DisplayDialog("Rename Result", message, "OK");
|
|
||||||
|
|
||||||
// Clear selection and preview
|
|
||||||
selectedFiles.Clear();
|
|
||||||
previewNames.Clear();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Presets
|
|
||||||
private void SaveCurrentAsPreset()
|
|
||||||
{
|
|
||||||
var preset = new NamingPreset
|
|
||||||
{
|
|
||||||
presetName = newPresetName,
|
|
||||||
mode = namingMode,
|
|
||||||
customText = customText,
|
|
||||||
startNumber = startNumber,
|
|
||||||
numberPadding = numberPadding,
|
|
||||||
includeDate = includeDate,
|
|
||||||
includeTime = includeTime,
|
|
||||||
dateFormat = dateFormat,
|
|
||||||
timeFormat = timeFormat,
|
|
||||||
separator = separator
|
|
||||||
};
|
|
||||||
|
|
||||||
presets.Add(preset);
|
|
||||||
SavePresets();
|
|
||||||
|
|
||||||
Debug.Log($"Preset saved: {newPresetName}");
|
|
||||||
EditorUtility.DisplayDialog("Success", $"프리셋 '{newPresetName}'이(가) 저장되었습니다.", "OK");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadPreset(int index)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= presets.Count) return;
|
|
||||||
|
|
||||||
var preset = presets[index];
|
|
||||||
namingMode = preset.mode;
|
|
||||||
customText = preset.customText;
|
|
||||||
startNumber = preset.startNumber;
|
|
||||||
numberPadding = preset.numberPadding;
|
|
||||||
includeDate = preset.includeDate;
|
|
||||||
includeTime = preset.includeTime;
|
|
||||||
dateFormat = preset.dateFormat;
|
|
||||||
timeFormat = preset.timeFormat;
|
|
||||||
separator = preset.separator;
|
|
||||||
|
|
||||||
Debug.Log($"Preset loaded: {preset.presetName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SavePresets()
|
|
||||||
{
|
|
||||||
string json = JsonUtility.ToJson(new PresetList { presets = presets }, true);
|
|
||||||
EditorPrefs.SetString("MotionCaptureFileRenamer_Presets", json);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadPresets()
|
|
||||||
{
|
|
||||||
string json = EditorPrefs.GetString("MotionCaptureFileRenamer_Presets", "");
|
|
||||||
if (!string.IsNullOrEmpty(json))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var presetList = JsonUtility.FromJson<PresetList>(json);
|
|
||||||
presets = presetList.presets ?? new List<NamingPreset>();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
presets = new List<NamingPreset>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
private class PresetList
|
|
||||||
{
|
|
||||||
public List<NamingPreset> presets = new List<NamingPreset>();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@ -1,8 +1,8 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 0085861f604b4b243ba02d059d2dd867
|
guid: 9bb84e74216a1f54cbeceefb27c95899
|
||||||
NativeFormatImporter:
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 2100000
|
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
assetBundleVariant:
|
assetBundleVariant:
|
||||||
@ -20,7 +20,7 @@ public class StreamingleAvatarExporter : EditorWindow
|
|||||||
Color.magenta // Other
|
Color.magenta // Other
|
||||||
};
|
};
|
||||||
|
|
||||||
[MenuItem("Tools/Streamingle Avatar Exporter")]
|
[MenuItem("Tools/Streamingle/Avatar Exporter")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<StreamingleAvatarExporter>("Streamingle Exporter");
|
GetWindow<StreamingleAvatarExporter>("Streamingle Exporter");
|
||||||
8
Assets/Scripts/Editor/TimelineTools.meta
Normal file
8
Assets/Scripts/Editor/TimelineTools.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bbab7799f67203d4c86443651fd45fc3
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -25,7 +25,7 @@ namespace Streamingle.Editor
|
|||||||
|
|
||||||
private List<TrackMap> previewMappings = new List<TrackMap>();
|
private List<TrackMap> previewMappings = new List<TrackMap>();
|
||||||
|
|
||||||
[MenuItem("Tools/Timeline/Transfer Bindings")]
|
[MenuItem("Tools/Timeline Tools/Transfer Bindings")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<TimelineBindingTransferWindow>("Timeline Binding Transfer");
|
GetWindow<TimelineBindingTransferWindow>("Timeline Binding Transfer");
|
||||||
8
Assets/Scripts/Editor/Utilities.meta
Normal file
8
Assets/Scripts/Editor/Utilities.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b8decd084ae90044ca3e5777d7ef5013
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -17,7 +17,7 @@ public class MaterialAndTextureTool : EditorWindow
|
|||||||
private HashSet<Texture> collectedTextures = new HashSet<Texture>();
|
private HashSet<Texture> collectedTextures = new HashSet<Texture>();
|
||||||
private Vector2 scroll;
|
private Vector2 scroll;
|
||||||
|
|
||||||
[MenuItem("Tools/Material & Texture Tool")]
|
[MenuItem("Tools/Utilities/Material & Texture Tool")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
var window = GetWindow<MaterialAndTextureTool>("MatTex Tool");
|
var window = GetWindow<MaterialAndTextureTool>("MatTex Tool");
|
||||||
@ -5,7 +5,7 @@ using System.Linq;
|
|||||||
|
|
||||||
public class MaterialObjectSelector : EditorWindow
|
public class MaterialObjectSelector : EditorWindow
|
||||||
{
|
{
|
||||||
[MenuItem("Tools/Select Objects Using Material")]
|
[MenuItem("Tools/Utilities/Select Objects Using Material")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<MaterialObjectSelector>("Material Object Selector");
|
GetWindow<MaterialObjectSelector>("Material Object Selector");
|
||||||
466
Assets/Scripts/Editor/Utilities/MotionCaptureFileRenamer.cs
Normal file
466
Assets/Scripts/Editor/Utilities/MotionCaptureFileRenamer.cs
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 모션 캡쳐 파일 네이밍 편의성 툴
|
||||||
|
/// - 선택한 파일들에 일괄적으로 접미사/접두사 추가
|
||||||
|
/// - 번호 매기기, 날짜 스탬프 등 다양한 네이밍 패턴 지원
|
||||||
|
/// </summary>
|
||||||
|
public class MotionCaptureFileRenamer : EditorWindow
|
||||||
|
{
|
||||||
|
#region Nested Classes
|
||||||
|
[Serializable]
|
||||||
|
public class NamingPreset
|
||||||
|
{
|
||||||
|
public string presetName = "New Preset";
|
||||||
|
public NamingMode mode = NamingMode.Suffix;
|
||||||
|
public string customText = "";
|
||||||
|
public int startNumber = 1;
|
||||||
|
public int numberPadding = 3;
|
||||||
|
public string separator = "_";
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum NamingMode
|
||||||
|
{
|
||||||
|
Suffix, // 파일명 뒤에 추가
|
||||||
|
Prefix, // 파일명 앞에 추가
|
||||||
|
Replace, // 전체 이름 변경
|
||||||
|
Sequential // 순차 번호
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Fields
|
||||||
|
private List<UnityEngine.Object> selectedFiles = new List<UnityEngine.Object>();
|
||||||
|
private Vector2 scrollPosition;
|
||||||
|
private Vector2 fileListScrollPosition;
|
||||||
|
private Vector2 previewScrollPosition;
|
||||||
|
|
||||||
|
// Naming settings
|
||||||
|
private NamingMode namingMode = NamingMode.Suffix;
|
||||||
|
private string customText = "_ok";
|
||||||
|
private int startNumber = 1;
|
||||||
|
private int numberPadding = 3;
|
||||||
|
private string separator = "_";
|
||||||
|
|
||||||
|
// Presets
|
||||||
|
private List<NamingPreset> presets = new List<NamingPreset>();
|
||||||
|
private int selectedPresetIndex = -1;
|
||||||
|
private bool showPresetSection = false;
|
||||||
|
private string newPresetName = "My Preset";
|
||||||
|
|
||||||
|
// UI Style
|
||||||
|
private GUIStyle headerStyle;
|
||||||
|
private GUIStyle boxStyle;
|
||||||
|
private Color successColor = new Color(0.5f, 1f, 0.5f, 0.3f);
|
||||||
|
private Color warningColor = new Color(1f, 1f, 0.5f, 0.3f);
|
||||||
|
private Color errorColor = new Color(1f, 0.5f, 0.5f, 0.3f);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Window Initialization
|
||||||
|
[MenuItem("Tools/Motion Capture Tools/File Renamer")]
|
||||||
|
public static void ShowWindow()
|
||||||
|
{
|
||||||
|
var window = GetWindow<MotionCaptureFileRenamer>("MoCap File Renamer");
|
||||||
|
window.minSize = new Vector2(450, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
LoadPresets();
|
||||||
|
RefreshSelectedFiles();
|
||||||
|
Selection.selectionChanged += OnSelectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
SavePresets();
|
||||||
|
Selection.selectionChanged -= OnSelectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelectionChanged()
|
||||||
|
{
|
||||||
|
RefreshSelectedFiles();
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeStyles()
|
||||||
|
{
|
||||||
|
if (headerStyle == null)
|
||||||
|
{
|
||||||
|
headerStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||||
|
{
|
||||||
|
fontSize = 14,
|
||||||
|
alignment = TextAnchor.MiddleLeft
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boxStyle == null)
|
||||||
|
{
|
||||||
|
boxStyle = new GUIStyle(EditorStyles.helpBox)
|
||||||
|
{
|
||||||
|
padding = new RectOffset(10, 10, 10, 10)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region GUI
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
InitializeStyles();
|
||||||
|
|
||||||
|
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||||
|
|
||||||
|
DrawHeader();
|
||||||
|
DrawFileSelectionSection();
|
||||||
|
DrawNamingOptionsSection();
|
||||||
|
DrawPresetsSection();
|
||||||
|
DrawActionButtons();
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawHeader()
|
||||||
|
{
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
EditorGUILayout.LabelField("🎬 MoCap File Renamer", headerStyle);
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawFileSelectionSection()
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginVertical(boxStyle);
|
||||||
|
|
||||||
|
// 선택된 파일 수 표시
|
||||||
|
GUIStyle countStyle = new GUIStyle(EditorStyles.boldLabel);
|
||||||
|
countStyle.fontSize = 13;
|
||||||
|
|
||||||
|
if (selectedFiles.Count > 0)
|
||||||
|
{
|
||||||
|
countStyle.normal.textColor = new Color(0.3f, 0.8f, 0.3f);
|
||||||
|
EditorGUILayout.LabelField($"📁 {selectedFiles.Count} files selected", countStyle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
countStyle.normal.textColor = Color.gray;
|
||||||
|
EditorGUILayout.LabelField($"📁 No files selected", countStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawNamingOptionsSection()
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginVertical(boxStyle);
|
||||||
|
EditorGUILayout.LabelField("⚙️ Naming Options", EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
|
||||||
|
// Naming mode
|
||||||
|
namingMode = (NamingMode)EditorGUILayout.EnumPopup("Mode", namingMode);
|
||||||
|
|
||||||
|
switch (namingMode)
|
||||||
|
{
|
||||||
|
case NamingMode.Suffix:
|
||||||
|
customText = EditorGUILayout.TextField("Suffix", customText);
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("_ok")) customText = "_ok";
|
||||||
|
if (GUILayout.Button("_final")) customText = "_final";
|
||||||
|
if (GUILayout.Button("_test")) customText = "_test";
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
break;
|
||||||
|
case NamingMode.Prefix:
|
||||||
|
customText = EditorGUILayout.TextField("Prefix", customText);
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
if (GUILayout.Button("Take001")) customText = "Take001";
|
||||||
|
if (GUILayout.Button("MoCap")) customText = "MoCap";
|
||||||
|
if (GUILayout.Button("Test")) customText = "Test";
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
break;
|
||||||
|
case NamingMode.Replace:
|
||||||
|
customText = EditorGUILayout.TextField("New Name", customText);
|
||||||
|
startNumber = EditorGUILayout.IntField("Start Number", startNumber);
|
||||||
|
numberPadding = EditorGUILayout.IntSlider("Padding", numberPadding, 1, 5);
|
||||||
|
break;
|
||||||
|
case NamingMode.Sequential:
|
||||||
|
customText = EditorGUILayout.TextField("Base Name", customText);
|
||||||
|
startNumber = EditorGUILayout.IntField("Start Number", startNumber);
|
||||||
|
numberPadding = EditorGUILayout.IntSlider("Padding", numberPadding, 1, 5);
|
||||||
|
EditorGUILayout.LabelField($"Ex: {customText}{startNumber.ToString().PadLeft(numberPadding, '0')}", EditorStyles.miniLabel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void DrawPresetsSection()
|
||||||
|
{
|
||||||
|
showPresetSection = EditorGUILayout.Foldout(showPresetSection, "💾 Presets", true, EditorStyles.foldoutHeader);
|
||||||
|
|
||||||
|
if (showPresetSection)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginVertical(boxStyle);
|
||||||
|
|
||||||
|
if (presets.Count > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < presets.Count; i++)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
|
||||||
|
if (GUILayout.Button(presets[i].presetName, GUILayout.Height(22)))
|
||||||
|
{
|
||||||
|
LoadPreset(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("×", GUILayout.Width(25), GUILayout.Height(22)))
|
||||||
|
{
|
||||||
|
presets.RemoveAt(i);
|
||||||
|
SavePresets();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.Space(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
newPresetName = EditorGUILayout.TextField(newPresetName);
|
||||||
|
if (GUILayout.Button("Save", GUILayout.Width(60)))
|
||||||
|
{
|
||||||
|
SaveCurrentAsPreset();
|
||||||
|
}
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.Space(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawActionButtons()
|
||||||
|
{
|
||||||
|
GUI.enabled = selectedFiles.Count > 0;
|
||||||
|
|
||||||
|
GUI.backgroundColor = new Color(0.3f, 0.8f, 0.3f);
|
||||||
|
if (GUILayout.Button("✓ Apply Rename", GUILayout.Height(50)))
|
||||||
|
{
|
||||||
|
ApplyRename();
|
||||||
|
}
|
||||||
|
GUI.backgroundColor = Color.white;
|
||||||
|
|
||||||
|
GUI.enabled = true;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region File Selection
|
||||||
|
private void RefreshSelectedFiles()
|
||||||
|
{
|
||||||
|
selectedFiles.Clear();
|
||||||
|
|
||||||
|
var selected = Selection.objects;
|
||||||
|
foreach (var obj in selected)
|
||||||
|
{
|
||||||
|
string path = AssetDatabase.GetAssetPath(obj);
|
||||||
|
if (!string.IsNullOrEmpty(path) && !AssetDatabase.IsValidFolder(path))
|
||||||
|
{
|
||||||
|
selectedFiles.Add(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleDragAndDrop(Rect dropArea)
|
||||||
|
{
|
||||||
|
Event evt = Event.current;
|
||||||
|
|
||||||
|
if (dropArea.Contains(evt.mousePosition))
|
||||||
|
{
|
||||||
|
if (evt.type == EventType.DragUpdated)
|
||||||
|
{
|
||||||
|
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
||||||
|
evt.Use();
|
||||||
|
}
|
||||||
|
else if (evt.type == EventType.DragPerform)
|
||||||
|
{
|
||||||
|
DragAndDrop.AcceptDrag();
|
||||||
|
|
||||||
|
foreach (var obj in DragAndDrop.objectReferences)
|
||||||
|
{
|
||||||
|
string path = AssetDatabase.GetAssetPath(obj);
|
||||||
|
if (!string.IsNullOrEmpty(path) && !AssetDatabase.IsValidFolder(path))
|
||||||
|
{
|
||||||
|
if (!selectedFiles.Contains(obj))
|
||||||
|
{
|
||||||
|
selectedFiles.Add(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evt.Use();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Naming Logic
|
||||||
|
private string GenerateNewName(string originalName, int index)
|
||||||
|
{
|
||||||
|
string baseName = originalName;
|
||||||
|
string result = "";
|
||||||
|
|
||||||
|
switch (namingMode)
|
||||||
|
{
|
||||||
|
case NamingMode.Suffix:
|
||||||
|
result = baseName + separator + customText;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NamingMode.Prefix:
|
||||||
|
result = customText + separator + baseName;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NamingMode.Replace:
|
||||||
|
string number = (startNumber + index).ToString().PadLeft(numberPadding, '0');
|
||||||
|
result = customText + separator + number;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NamingMode.Sequential:
|
||||||
|
string seqNumber = (startNumber + index).ToString().PadLeft(numberPadding, '0');
|
||||||
|
result = customText + seqNumber;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove invalid characters
|
||||||
|
result = string.Join("_", result.Split(Path.GetInvalidFileNameChars()));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyRename()
|
||||||
|
{
|
||||||
|
if (selectedFiles.Count == 0) return;
|
||||||
|
|
||||||
|
int successCount = 0;
|
||||||
|
int failCount = 0;
|
||||||
|
|
||||||
|
AssetDatabase.StartAssetEditing();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (int i = 0; i < selectedFiles.Count; i++)
|
||||||
|
{
|
||||||
|
var file = selectedFiles[i];
|
||||||
|
if (file == null) continue;
|
||||||
|
|
||||||
|
string assetPath = AssetDatabase.GetAssetPath(file);
|
||||||
|
string directory = Path.GetDirectoryName(assetPath);
|
||||||
|
string extension = Path.GetExtension(assetPath);
|
||||||
|
string oldName = file.name;
|
||||||
|
string newName = GenerateNewName(oldName, i);
|
||||||
|
string newPath = Path.Combine(directory, newName + extension);
|
||||||
|
|
||||||
|
// Check if file already exists
|
||||||
|
if (File.Exists(newPath) && assetPath != newPath)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Skipped (exists): {oldName}");
|
||||||
|
failCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename asset
|
||||||
|
string error = AssetDatabase.RenameAsset(assetPath, newName);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(error))
|
||||||
|
{
|
||||||
|
Debug.Log($"✓ {oldName} → {newName}");
|
||||||
|
successCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError($"✗ {oldName}: {error}");
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AssetDatabase.StopAssetEditing();
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($"<b>Rename Complete:</b> {successCount} success, {failCount} failed");
|
||||||
|
|
||||||
|
// Clear selection
|
||||||
|
selectedFiles.Clear();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Presets
|
||||||
|
private void SaveCurrentAsPreset()
|
||||||
|
{
|
||||||
|
var preset = new NamingPreset
|
||||||
|
{
|
||||||
|
presetName = newPresetName,
|
||||||
|
mode = namingMode,
|
||||||
|
customText = customText,
|
||||||
|
startNumber = startNumber,
|
||||||
|
numberPadding = numberPadding,
|
||||||
|
separator = separator
|
||||||
|
};
|
||||||
|
|
||||||
|
presets.Add(preset);
|
||||||
|
SavePresets();
|
||||||
|
|
||||||
|
Debug.Log($"Preset saved: {newPresetName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadPreset(int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= presets.Count) return;
|
||||||
|
|
||||||
|
var preset = presets[index];
|
||||||
|
namingMode = preset.mode;
|
||||||
|
customText = preset.customText;
|
||||||
|
startNumber = preset.startNumber;
|
||||||
|
numberPadding = preset.numberPadding;
|
||||||
|
separator = preset.separator;
|
||||||
|
|
||||||
|
Debug.Log($"Preset loaded: {preset.presetName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SavePresets()
|
||||||
|
{
|
||||||
|
string json = JsonUtility.ToJson(new PresetList { presets = presets }, true);
|
||||||
|
EditorPrefs.SetString("MotionCaptureFileRenamer_Presets", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadPresets()
|
||||||
|
{
|
||||||
|
string json = EditorPrefs.GetString("MotionCaptureFileRenamer_Presets", "");
|
||||||
|
if (!string.IsNullOrEmpty(json))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var presetList = JsonUtility.FromJson<PresetList>(json);
|
||||||
|
presets = presetList.presets ?? new List<NamingPreset>();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
presets = new List<NamingPreset>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
private class PresetList
|
||||||
|
{
|
||||||
|
public List<NamingPreset> presets = new List<NamingPreset>();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@ -42,7 +42,7 @@ namespace Bitd
|
|||||||
|
|
||||||
private Vector2 scrollPosObjects; // 오브젝트 목록 스크롤 위치
|
private Vector2 scrollPosObjects; // 오브젝트 목록 스크롤 위치
|
||||||
|
|
||||||
[MenuItem("Bitd/닐로툰 매트캡 자동 인식기", false, 153)]
|
[MenuItem("Tools/Utilities/Nilotoon Material Matcap Setter")]
|
||||||
public static void ShowWindow()
|
public static void ShowWindow()
|
||||||
{
|
{
|
||||||
GetWindow<NiloMaterialMatcapSetter>("닐로툰 매트캡 자동 인식기");
|
GetWindow<NiloMaterialMatcapSetter>("닐로툰 매트캡 자동 인식기");
|
||||||
@ -2,7 +2,7 @@ using UnityEditor;
|
|||||||
|
|
||||||
public class RecompileScript
|
public class RecompileScript
|
||||||
{
|
{
|
||||||
[MenuItem("Tools/Recompile")]
|
[MenuItem("Tools/Utilities/Recompile")]
|
||||||
public static void Recompile()
|
public static void Recompile()
|
||||||
{
|
{
|
||||||
// 현재의 에디터 애플리케이션의 상태를 강제로 리컴파일합니다.
|
// 현재의 에디터 애플리케이션의 상태를 강제로 리컴파일합니다.
|
||||||
@ -1,64 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using UnityEditor;
|
|
||||||
using UniHumanoid;
|
|
||||||
|
|
||||||
public class HumanPoseClipEditor : EditorWindow
|
|
||||||
{
|
|
||||||
private Animator sourceAnimator;
|
|
||||||
private string savePath = "Assets/NewPose.pose";
|
|
||||||
|
|
||||||
[MenuItem("Tools/Human Pose Clip Creator")]
|
|
||||||
static void ShowWindow()
|
|
||||||
{
|
|
||||||
var window = GetWindow<HumanPoseClipEditor>("포즈 생성기");
|
|
||||||
window.minSize = new Vector2(300, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnGUI()
|
|
||||||
{
|
|
||||||
EditorGUILayout.Space(10);
|
|
||||||
EditorGUILayout.LabelField("휴머노이드 포즈 생성", EditorStyles.boldLabel);
|
|
||||||
EditorGUILayout.Space(10);
|
|
||||||
|
|
||||||
sourceAnimator = EditorGUILayout.ObjectField("소스 애니메이터",
|
|
||||||
sourceAnimator, typeof(Animator), true) as Animator;
|
|
||||||
|
|
||||||
savePath = EditorGUILayout.TextField("저장 경로", savePath);
|
|
||||||
|
|
||||||
EditorGUILayout.Space(10);
|
|
||||||
|
|
||||||
GUI.enabled = sourceAnimator != null;
|
|
||||||
if (GUILayout.Button("현재 포즈로 에셋 생성"))
|
|
||||||
{
|
|
||||||
CreatePoseClip();
|
|
||||||
}
|
|
||||||
GUI.enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreatePoseClip()
|
|
||||||
{
|
|
||||||
if (!sourceAnimator.isHuman)
|
|
||||||
{
|
|
||||||
EditorUtility.DisplayDialog("오류",
|
|
||||||
"선택된 애니메이터가 휴머노이드가 아닙니다.", "확인");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var clip = ScriptableObject.CreateInstance<HumanPoseClip>();
|
|
||||||
var handler = new HumanPoseHandler(sourceAnimator.avatar, sourceAnimator.transform);
|
|
||||||
var pose = new HumanPose();
|
|
||||||
|
|
||||||
handler.GetHumanPose(ref pose);
|
|
||||||
clip.ApplyPose(ref pose);
|
|
||||||
|
|
||||||
// 에셋 저장
|
|
||||||
AssetDatabase.CreateAsset(clip, savePath + ".asset");
|
|
||||||
AssetDatabase.SaveAssets();
|
|
||||||
|
|
||||||
EditorUtility.DisplayDialog("완료",
|
|
||||||
"포즈 클립이 생성되었습니다.", "확인");
|
|
||||||
|
|
||||||
// 생성된 에셋 선택
|
|
||||||
Selection.activeObject = clip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2cf677b8ffaf4aa45a26179e80a8ac23
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/Scripts/YAMO_Scripts/Camera Composition/Camera Composition.zip
(Stored with Git LFS)
BIN
Assets/Scripts/YAMO_Scripts/Camera Composition/Camera Composition.zip
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/Scripts/YAMO_Scripts/Camera Composition/CameraComposition.pdf
(Stored with Git LFS)
BIN
Assets/Scripts/YAMO_Scripts/Camera Composition/CameraComposition.pdf
(Stored with Git LFS)
Binary file not shown.
@ -1,14 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 403187bd32b8502488efe4583bc51110
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
AssetOrigin:
|
|
||||||
serializedVersion: 1
|
|
||||||
productId: 202816
|
|
||||||
packageName: Camera Composition - Grid Overlay Tool
|
|
||||||
packageVersion: 1.0.2
|
|
||||||
assetPath: Assets/Camera Composition/CameraComposition.pdf
|
|
||||||
uploadId: 471102
|
|
||||||
BIN
Assets/Scripts/YAMO_Scripts/Camera Composition/Changelog.txt
(Stored with Git LFS)
BIN
Assets/Scripts/YAMO_Scripts/Camera Composition/Changelog.txt
(Stored with Git LFS)
Binary file not shown.
@ -1,14 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1c03e5c3741df0b408c8e81db15780ef
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
AssetOrigin:
|
|
||||||
serializedVersion: 1
|
|
||||||
productId: 202816
|
|
||||||
packageName: Camera Composition - Grid Overlay Tool
|
|
||||||
packageVersion: 1.0.2
|
|
||||||
assetPath: Assets/Camera Composition/Changelog.txt
|
|
||||||
uploadId: 471102
|
|
||||||
BIN
Assets/Scripts/YAMO_Scripts/Camera Composition/README.txt
(Stored with Git LFS)
BIN
Assets/Scripts/YAMO_Scripts/Camera Composition/README.txt
(Stored with Git LFS)
Binary file not shown.
@ -1,14 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 583d2b0c7a3fb5146baec6c15b419b8b
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
AssetOrigin:
|
|
||||||
serializedVersion: 1
|
|
||||||
productId: 202816
|
|
||||||
packageName: Camera Composition - Grid Overlay Tool
|
|
||||||
packageVersion: 1.0.2
|
|
||||||
assetPath: Assets/Camera Composition/README.txt
|
|
||||||
uploadId: 471102
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d90295d3945afb04dbf6709ab5c26a3e
|
|
||||||
Loading…
x
Reference in New Issue
Block a user