ADD : 네이밍 툴 추가
This commit is contained in:
parent
11112e9fcd
commit
540b8645f2
691
Assets/Scripts/Editor/MotionCaptureFileRenamer.cs
Normal file
691
Assets/Scripts/Editor/MotionCaptureFileRenamer.cs
Normal file
@ -0,0 +1,691 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user