Add : 모션 레코더 버그 패치 싱글톤에서 멀티로 변경
This commit is contained in:
parent
9dc2d4d64f
commit
98d207583a
@ -1,11 +1,13 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
using Entum;
|
||||
|
||||
namespace EasyMotionRecorder
|
||||
{
|
||||
[CustomEditor(typeof(ObjectMotionRecorder))]
|
||||
[CanEditMultipleObjects]
|
||||
public class ObjectMotionRecorderEditor : Editor
|
||||
{
|
||||
private ObjectMotionRecorder recorder;
|
||||
@ -19,6 +21,12 @@ namespace EasyMotionRecorder
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (targets.Length > 1)
|
||||
{
|
||||
DrawMultiObjectGUI();
|
||||
return;
|
||||
}
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
@ -46,6 +54,143 @@ namespace EasyMotionRecorder
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void DrawMultiObjectGUI()
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField($"오브젝트 모션 레코더 ({targets.Length}개 선택됨)", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 멀티 오브젝트 상태 표시
|
||||
DrawMultiObjectStatus();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 멀티 오브젝트 설정
|
||||
DrawMultiObjectSettings();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 멀티 오브젝트 액션
|
||||
DrawMultiObjectActions();
|
||||
}
|
||||
|
||||
private void DrawMultiObjectStatus()
|
||||
{
|
||||
int recordingCount = 0;
|
||||
foreach (ObjectMotionRecorder recorder in targets)
|
||||
{
|
||||
if (recorder.IsRecording) recordingCount++;
|
||||
}
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField("레코딩 상태:", GUILayout.Width(100));
|
||||
|
||||
if (recordingCount == 0)
|
||||
{
|
||||
EditorGUILayout.LabelField("○ 모두 대기 중", EditorStyles.boldLabel);
|
||||
}
|
||||
else if (recordingCount == targets.Length)
|
||||
{
|
||||
EditorGUILayout.LabelField("● 모두 녹화 중", EditorStyles.boldLabel);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.LabelField($"◐ 일부 녹화 중 ({recordingCount}/{targets.Length})", EditorStyles.boldLabel);
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void DrawMultiObjectSettings()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
showRecordingSettings = EditorGUILayout.Foldout(showRecordingSettings, "레코딩 설정 (모든 선택된 오브젝트에 적용)");
|
||||
|
||||
if (showRecordingSettings)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
// 키 설정
|
||||
var startKeyProp = serializedObject.FindProperty("recordStartKey");
|
||||
var stopKeyProp = serializedObject.FindProperty("recordStopKey");
|
||||
|
||||
EditorGUI.showMixedValue = startKeyProp.hasMultipleDifferentValues;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
int startKeyIndex = EditorGUILayout.Popup("시작 키", startKeyProp.enumValueIndex, startKeyProp.enumDisplayNames);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
startKeyProp.enumValueIndex = startKeyIndex;
|
||||
}
|
||||
|
||||
EditorGUI.showMixedValue = stopKeyProp.hasMultipleDifferentValues;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
int stopKeyIndex = EditorGUILayout.Popup("정지 키", stopKeyProp.enumValueIndex, stopKeyProp.enumDisplayNames);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
stopKeyProp.enumValueIndex = stopKeyIndex;
|
||||
}
|
||||
|
||||
// FPS 설정
|
||||
var fpsProp = serializedObject.FindProperty("targetFPS");
|
||||
EditorGUI.showMixedValue = fpsProp.hasMultipleDifferentValues;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
float fps = EditorGUILayout.FloatField("타겟 FPS", fpsProp.floatValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
fpsProp.floatValue = fps;
|
||||
}
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
if (fpsProp.floatValue <= 0 && !fpsProp.hasMultipleDifferentValues)
|
||||
{
|
||||
EditorGUILayout.HelpBox("FPS가 0 이하면 제한 없이 녹화됩니다.", MessageType.Info);
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void DrawMultiObjectActions()
|
||||
{
|
||||
EditorGUILayout.LabelField("멀티 오브젝트 액션", EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
// 모든 레코더 시작
|
||||
if (GUILayout.Button("모든 레코더 시작", GUILayout.Height(30)))
|
||||
{
|
||||
foreach (ObjectMotionRecorder recorder in targets)
|
||||
{
|
||||
if (!recorder.IsRecording && recorder.TargetObjects.Length > 0)
|
||||
{
|
||||
recorder.StartRecording();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 모든 레코더 정지
|
||||
if (GUILayout.Button("모든 레코더 정지", GUILayout.Height(30)))
|
||||
{
|
||||
foreach (ObjectMotionRecorder recorder in targets)
|
||||
{
|
||||
if (recorder.IsRecording)
|
||||
{
|
||||
recorder.StopRecording();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// SavePathManager 안내
|
||||
EditorGUILayout.HelpBox("저장 경로 및 자동 출력 설정은 각 오브젝트의 SavePathManager 컴포넌트에서 관리됩니다.", MessageType.Info);
|
||||
}
|
||||
|
||||
private void DrawRecordingStatus()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
@ -188,6 +333,19 @@ namespace EasyMotionRecorder
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// SavePathManager 안내
|
||||
var savePathManager = recorder.GetComponent<SavePathManager>();
|
||||
if (savePathManager != null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("저장 경로 및 자동 출력 설정은 SavePathManager 컴포넌트에서 관리됩니다.", MessageType.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox("SavePathManager 컴포넌트가 없습니다. SavePathManager를 추가해주세요.", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSelectedObject()
|
||||
@ -199,35 +357,27 @@ namespace EasyMotionRecorder
|
||||
targetsProp.arraySize++;
|
||||
var newElement = targetsProp.GetArrayElementAtIndex(targetsProp.arraySize - 1);
|
||||
newElement.objectReferenceValue = selected.transform;
|
||||
|
||||
Debug.Log($"오브젝트 추가: {selected.name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.DisplayDialog("오류", "선택된 오브젝트가 없습니다.", "확인");
|
||||
EditorUtility.SetDirty(recorder);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSelectedObjects()
|
||||
{
|
||||
var selectedObjects = Selection.gameObjects;
|
||||
if (selectedObjects.Length == 0)
|
||||
if (selectedObjects.Length > 0)
|
||||
{
|
||||
EditorUtility.DisplayDialog("오류", "선택된 오브젝트가 없습니다.", "확인");
|
||||
return;
|
||||
var targetsProp = serializedObject.FindProperty("targetObjects");
|
||||
int startIndex = targetsProp.arraySize;
|
||||
targetsProp.arraySize += selectedObjects.Length;
|
||||
|
||||
for (int i = 0; i < selectedObjects.Length; i++)
|
||||
{
|
||||
var element = targetsProp.GetArrayElementAtIndex(startIndex + i);
|
||||
element.objectReferenceValue = selectedObjects[i].transform;
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(recorder);
|
||||
}
|
||||
|
||||
var targetsProp = serializedObject.FindProperty("targetObjects");
|
||||
int startIndex = targetsProp.arraySize;
|
||||
targetsProp.arraySize += selectedObjects.Length;
|
||||
|
||||
for (int i = 0; i < selectedObjects.Length; i++)
|
||||
{
|
||||
var element = targetsProp.GetArrayElementAtIndex(startIndex + i);
|
||||
element.objectReferenceValue = selectedObjects[i].transform;
|
||||
}
|
||||
|
||||
Debug.Log($"{selectedObjects.Length}개 오브젝트 추가됨");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,18 +6,45 @@ using System.IO;
|
||||
namespace EasyMotionRecorder
|
||||
{
|
||||
[CustomEditor(typeof(SavePathManager))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SavePathManagerEditor : Editor
|
||||
{
|
||||
private SavePathManager savePathManager;
|
||||
private bool showAdvancedSettings = false;
|
||||
|
||||
// SerializedProperty 참조
|
||||
private SerializedProperty motionSavePathProp;
|
||||
private SerializedProperty createSubdirectoriesProp;
|
||||
private SerializedProperty exportHumanoidOnSaveProp;
|
||||
private SerializedProperty exportGenericOnSaveProp;
|
||||
private SerializedProperty exportFBXAsciiOnSaveProp;
|
||||
private SerializedProperty exportFBXBinaryOnSaveProp;
|
||||
private SerializedProperty instanceIDProp;
|
||||
private SerializedProperty useDontDestroyOnLoadProp;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
savePathManager = (SavePathManager)target;
|
||||
|
||||
// SerializedProperty 초기화
|
||||
motionSavePathProp = serializedObject.FindProperty("motionSavePath");
|
||||
createSubdirectoriesProp = serializedObject.FindProperty("createSubdirectories");
|
||||
exportHumanoidOnSaveProp = serializedObject.FindProperty("exportHumanoidOnSave");
|
||||
exportGenericOnSaveProp = serializedObject.FindProperty("exportGenericOnSave");
|
||||
exportFBXAsciiOnSaveProp = serializedObject.FindProperty("exportFBXAsciiOnSave");
|
||||
exportFBXBinaryOnSaveProp = serializedObject.FindProperty("exportFBXBinaryOnSave");
|
||||
instanceIDProp = serializedObject.FindProperty("instanceID");
|
||||
useDontDestroyOnLoadProp = serializedObject.FindProperty("useDontDestroyOnLoad");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (targets.Length > 1)
|
||||
{
|
||||
DrawMultiObjectGUI();
|
||||
return;
|
||||
}
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
@ -34,19 +61,53 @@ namespace EasyMotionRecorder
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 자동 출력 옵션
|
||||
DrawAutoExportSettings();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 버튼들
|
||||
DrawActionButtons();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void DrawMultiObjectGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField($"저장 경로 관리 ({targets.Length}개 선택됨)", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 멀티 오브젝트 기본 설정
|
||||
DrawMultiObjectBasicSettings();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 멀티 오브젝트 고급 설정
|
||||
DrawMultiObjectAdvancedSettings();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 멀티 오브젝트 자동 출력 옵션
|
||||
DrawMultiObjectAutoExportSettings();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 멀티 오브젝트 액션
|
||||
DrawMultiObjectActions();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void DrawBasicSettings()
|
||||
{
|
||||
EditorGUILayout.LabelField("기본 설정", EditorStyles.boldLabel);
|
||||
|
||||
// 통합 저장 경로 (모든 파일이 같은 위치에 저장됨)
|
||||
// 통합 저장 경로
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
string motionPath = EditorGUILayout.TextField("저장 경로", savePathManager.GetMotionSavePath());
|
||||
EditorGUILayout.PropertyField(motionSavePathProp, new GUIContent("저장 경로"));
|
||||
if (GUILayout.Button("폴더 선택", GUILayout.Width(80)))
|
||||
{
|
||||
string newPath = EditorUtility.OpenFolderPanel("저장 폴더 선택", "Assets", "");
|
||||
@ -57,12 +118,14 @@ namespace EasyMotionRecorder
|
||||
{
|
||||
newPath = "Assets" + newPath.Substring(Application.dataPath.Length);
|
||||
}
|
||||
motionSavePathProp.stringValue = newPath;
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
savePathManager.SetMotionSavePath(newPath);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.HelpBox("모션, 페이스, 제네릭 애니메이션 파일이 모두 이 경로에 저장됩니다.", MessageType.Info);
|
||||
EditorGUILayout.HelpBox("모션, 표정, 오브젝트 파일이 모두 이 경로에 저장됩니다.", MessageType.Info);
|
||||
}
|
||||
|
||||
private void DrawAdvancedSettings()
|
||||
@ -74,16 +137,33 @@ namespace EasyMotionRecorder
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
// 서브디렉토리 생성 여부
|
||||
bool createSubdirectories = EditorGUILayout.Toggle("서브디렉토리 자동 생성",
|
||||
serializedObject.FindProperty("createSubdirectories").boolValue);
|
||||
serializedObject.FindProperty("createSubdirectories").boolValue = createSubdirectories;
|
||||
EditorGUILayout.PropertyField(createSubdirectoriesProp, new GUIContent("서브디렉토리 자동 생성"));
|
||||
|
||||
EditorGUILayout.HelpBox("현재 모든 파일이 동일한 경로에 저장됩니다.", MessageType.Info);
|
||||
// 인스턴스 ID (읽기 전용)
|
||||
GUI.enabled = false;
|
||||
EditorGUILayout.PropertyField(instanceIDProp, new GUIContent("인스턴스 ID (자동 생성)"));
|
||||
GUI.enabled = true;
|
||||
|
||||
// DontDestroyOnLoad 설정
|
||||
EditorGUILayout.PropertyField(useDontDestroyOnLoadProp, new GUIContent("씬 전환 시 유지"));
|
||||
|
||||
EditorGUILayout.HelpBox("인스턴스 ID는 자동으로 생성되며 각 EasyMotionRecorder 인스턴스를 구분합니다.", MessageType.Info);
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAutoExportSettings()
|
||||
{
|
||||
EditorGUILayout.LabelField("자동 출력 옵션", EditorStyles.boldLabel);
|
||||
EditorGUILayout.HelpBox("저장 시 자동으로 출력할 파일 형식을 선택하세요.", MessageType.Info);
|
||||
|
||||
EditorGUILayout.PropertyField(exportHumanoidOnSaveProp, new GUIContent("휴머노이드 애니메이션 자동 출력"));
|
||||
EditorGUILayout.PropertyField(exportGenericOnSaveProp, new GUIContent("제네릭 애니메이션 자동 출력"));
|
||||
EditorGUILayout.PropertyField(exportFBXAsciiOnSaveProp, new GUIContent("FBX ASCII 자동 출력"));
|
||||
EditorGUILayout.PropertyField(exportFBXBinaryOnSaveProp, new GUIContent("FBX Binary 자동 출력"));
|
||||
}
|
||||
|
||||
private void DrawActionButtons()
|
||||
{
|
||||
EditorGUILayout.LabelField("작업", EditorStyles.boldLabel);
|
||||
@ -97,6 +177,7 @@ namespace EasyMotionRecorder
|
||||
"모든 설정을 기본값으로 되돌리시겠습니까?", "확인", "취소"))
|
||||
{
|
||||
savePathManager.ResetToDefaults();
|
||||
serializedObject.Update();
|
||||
EditorUtility.SetDirty(savePathManager);
|
||||
}
|
||||
}
|
||||
@ -116,13 +197,134 @@ namespace EasyMotionRecorder
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
private void DrawMultiObjectBasicSettings()
|
||||
{
|
||||
EditorGUILayout.LabelField("기본 설정 (모든 선택된 오브젝트에 적용)", EditorStyles.boldLabel);
|
||||
|
||||
// 통합 저장 경로
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUI.showMixedValue = motionSavePathProp.hasMultipleDifferentValues;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string newPath = EditorGUILayout.TextField("저장 경로", motionSavePathProp.stringValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
motionSavePathProp.stringValue = newPath;
|
||||
foreach (SavePathManager manager in targets)
|
||||
{
|
||||
manager.SetMotionSavePath(newPath);
|
||||
}
|
||||
}
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
if (GUILayout.Button("폴더 선택", GUILayout.Width(80)))
|
||||
{
|
||||
string selectedPath = EditorUtility.OpenFolderPanel("저장 폴더 선택", "Assets", "");
|
||||
if (!string.IsNullOrEmpty(selectedPath))
|
||||
{
|
||||
// Assets 폴더 기준으로 상대 경로로 변환
|
||||
if (selectedPath.StartsWith(Application.dataPath))
|
||||
{
|
||||
selectedPath = "Assets" + selectedPath.Substring(Application.dataPath.Length);
|
||||
}
|
||||
motionSavePathProp.stringValue = selectedPath;
|
||||
|
||||
foreach (SavePathManager manager in targets)
|
||||
{
|
||||
manager.SetMotionSavePath(selectedPath);
|
||||
EditorUtility.SetDirty(manager);
|
||||
}
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.HelpBox("모션, 표정, 오브젝트 파일이 모두 이 경로에 저장됩니다.", MessageType.Info);
|
||||
}
|
||||
|
||||
private void DrawMultiObjectAdvancedSettings()
|
||||
{
|
||||
showAdvancedSettings = EditorGUILayout.Foldout(showAdvancedSettings, "고급 설정");
|
||||
|
||||
if (showAdvancedSettings)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
// 서브디렉토리 생성 여부
|
||||
EditorGUI.showMixedValue = createSubdirectoriesProp.hasMultipleDifferentValues;
|
||||
EditorGUILayout.PropertyField(createSubdirectoriesProp, new GUIContent("서브디렉토리 자동 생성"));
|
||||
|
||||
// DontDestroyOnLoad 설정
|
||||
EditorGUI.showMixedValue = useDontDestroyOnLoadProp.hasMultipleDifferentValues;
|
||||
EditorGUILayout.PropertyField(useDontDestroyOnLoadProp, new GUIContent("씬 전환 시 유지"));
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
|
||||
// 인스턴스 ID 표시 (읽기 전용)
|
||||
EditorGUILayout.LabelField("인스턴스 ID", "각 오브젝트마다 자동 생성됨");
|
||||
|
||||
EditorGUILayout.HelpBox("인스턴스 ID는 자동으로 생성되며 각 EasyMotionRecorder 인스턴스를 구분합니다.", MessageType.Info);
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMultiObjectAutoExportSettings()
|
||||
{
|
||||
EditorGUILayout.LabelField("자동 출력 옵션", EditorStyles.boldLabel);
|
||||
var humanoidProp = serializedObject.FindProperty("exportHumanoidOnSave");
|
||||
var genericProp = serializedObject.FindProperty("exportGenericOnSave");
|
||||
humanoidProp.boolValue = EditorGUILayout.ToggleLeft("휴머노이드 애니메이션 자동 출력", humanoidProp.boolValue);
|
||||
genericProp.boolValue = EditorGUILayout.ToggleLeft("제네릭 애니메이션 자동 출력", genericProp.boolValue);
|
||||
EditorGUILayout.HelpBox("저장 시 자동으로 출력할 파일 형식을 선택하세요.", MessageType.Info);
|
||||
|
||||
EditorGUI.showMixedValue = exportHumanoidOnSaveProp.hasMultipleDifferentValues;
|
||||
EditorGUILayout.PropertyField(exportHumanoidOnSaveProp, new GUIContent("휴머노이드 애니메이션 자동 출력"));
|
||||
|
||||
EditorGUI.showMixedValue = exportGenericOnSaveProp.hasMultipleDifferentValues;
|
||||
EditorGUILayout.PropertyField(exportGenericOnSaveProp, new GUIContent("제네릭 애니메이션 자동 출력"));
|
||||
|
||||
EditorGUI.showMixedValue = exportFBXAsciiOnSaveProp.hasMultipleDifferentValues;
|
||||
EditorGUILayout.PropertyField(exportFBXAsciiOnSaveProp, new GUIContent("FBX ASCII 자동 출력"));
|
||||
|
||||
EditorGUI.showMixedValue = exportFBXBinaryOnSaveProp.hasMultipleDifferentValues;
|
||||
EditorGUILayout.PropertyField(exportFBXBinaryOnSaveProp, new GUIContent("FBX Binary 자동 출력"));
|
||||
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
private void DrawMultiObjectActions()
|
||||
{
|
||||
EditorGUILayout.LabelField("멀티 오브젝트 액션", EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
// 모든 객체를 기본값으로 리셋
|
||||
if (GUILayout.Button("모든 객체 기본값으로 리셋", GUILayout.Height(30)))
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("기본값으로 리셋",
|
||||
$"선택된 {targets.Length}개 객체의 모든 설정을 기본값으로 되돌리시겠습니까?", "확인", "취소"))
|
||||
{
|
||||
foreach (SavePathManager manager in targets)
|
||||
{
|
||||
manager.ResetToDefaults();
|
||||
EditorUtility.SetDirty(manager);
|
||||
}
|
||||
serializedObject.Update();
|
||||
}
|
||||
}
|
||||
|
||||
// 저장 폴더 열기
|
||||
if (GUILayout.Button("저장 폴더 열기", GUILayout.Height(30)))
|
||||
{
|
||||
string path = savePathManager.GetMotionSavePath();
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
EditorUtility.RevealInFinder(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.DisplayDialog("오류", "저장 폴더가 존재하지 않습니다.", "확인");
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,9 +37,8 @@ namespace Entum {
|
||||
[Tooltip("記録するFPS。0で制限しない。UpdateのFPSは超えられません。")]
|
||||
public float TargetFPS = 60.0f;
|
||||
|
||||
[Header("인스턴스 설정")]
|
||||
[SerializeField] private string instanceID = "";
|
||||
[SerializeField] private SavePathManager _savePathManager;
|
||||
[HideInInspector, SerializeField] private string instanceID = "";
|
||||
[HideInInspector, SerializeField] private SavePathManager _savePathManager;
|
||||
|
||||
private MotionDataRecorder _animRecorder;
|
||||
|
||||
@ -62,28 +61,29 @@ namespace Entum {
|
||||
_animRecorder.OnRecordStart += RecordStart;
|
||||
_animRecorder.OnRecordEnd += RecordEnd;
|
||||
|
||||
// SavePathManager 자동 찾기
|
||||
if (_savePathManager == null)
|
||||
{
|
||||
_savePathManager = GetComponent<SavePathManager>();
|
||||
}
|
||||
|
||||
// 인스턴스 ID가 비어있으면 자동 생성
|
||||
if (string.IsNullOrEmpty(instanceID))
|
||||
{
|
||||
instanceID = System.Guid.NewGuid().ToString().Substring(0, 8);
|
||||
}
|
||||
|
||||
// SavePathManager가 없으면 같은 GameObject에서 찾기
|
||||
if (_savePathManager == null)
|
||||
{
|
||||
_savePathManager = GetComponent<SavePathManager>();
|
||||
if (_savePathManager == null)
|
||||
{
|
||||
_savePathManager = gameObject.AddComponent<SavePathManager>();
|
||||
_savePathManager.SetInstanceID(instanceID);
|
||||
}
|
||||
}
|
||||
|
||||
if(_animRecorder.CharacterAnimator != null) {
|
||||
_smeshs = GetSkinnedMeshRenderers(_animRecorder.CharacterAnimator);
|
||||
}
|
||||
}
|
||||
|
||||
// 내부 메서드 (SavePathManager에서 호출)
|
||||
internal void SetSavePathManager(SavePathManager manager)
|
||||
{
|
||||
_savePathManager = manager;
|
||||
}
|
||||
|
||||
SkinnedMeshRenderer[] GetSkinnedMeshRenderers(Animator root) {
|
||||
var helper = root;
|
||||
var renderers = helper.GetComponentsInChildren<SkinnedMeshRenderer>();
|
||||
@ -139,18 +139,46 @@ namespace Entum {
|
||||
_recording = false;
|
||||
Debug.Log($"표정 애니메이션 녹화 종료 - 인스턴스: {instanceID}, 총 프레임: {_frameCount}");
|
||||
|
||||
WriteAnimationFileToScriptableObject();
|
||||
// 바로 애니메이션 클립으로 출력
|
||||
ExportFacialAnimationClip(_animRecorder.CharacterAnimator, _facialData);
|
||||
}
|
||||
|
||||
private void WriteAnimationFileToScriptableObject() {
|
||||
if (_facialData == null || _facialData.Faces.Count == 0)
|
||||
{
|
||||
private void ExportFacialAnimationClip(Animator root, CharacterFacialData facial) {
|
||||
if(facial == null || facial.Faces.Count == 0) {
|
||||
Debug.LogError("저장할 표정 데이터가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
string fileName = $"{_animRecorder.SessionID}_Facial";
|
||||
string filePath = Path.Combine(_savePathManager.GetFacialSavePath(), fileName + ".asset");
|
||||
var clip = new AnimationClip();
|
||||
clip.frameRate = 30;
|
||||
|
||||
var blendShapeNames = facial.Faces[0].BlendShapeNames;
|
||||
var curves = new Dictionary<string, AnimationCurve>();
|
||||
|
||||
for(int i = 0; i < blendShapeNames.Count; i++) {
|
||||
curves[blendShapeNames[i]] = new AnimationCurve();
|
||||
}
|
||||
|
||||
for(int i = 0; i < facial.Faces.Count; i++) {
|
||||
var face = facial.Faces[i];
|
||||
var time = face.Time;
|
||||
|
||||
for(int j = 0; j < face.BlendShapeNames.Count; j++) {
|
||||
var blendShapeName = face.BlendShapeNames[j];
|
||||
var value = face.BlendShapeValues[j];
|
||||
|
||||
if(curves.ContainsKey(blendShapeName)) {
|
||||
curves[blendShapeName].AddKey(time, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var curve in curves) {
|
||||
clip.SetCurve("", typeof(SkinnedMeshRenderer), "blendShape." + curve.Key, curve.Value);
|
||||
}
|
||||
|
||||
string fileName = $"{facial.SessionID}_Facial";
|
||||
string filePath = Path.Combine(_savePathManager.GetFacialSavePath(), fileName + ".anim");
|
||||
|
||||
// 인스턴스별 고유 경로 생성
|
||||
filePath = _savePathManager.GetInstanceSpecificPath(filePath);
|
||||
@ -158,10 +186,10 @@ namespace Entum {
|
||||
SavePathManager.SafeCreateDirectory(Path.GetDirectoryName(filePath));
|
||||
|
||||
#if UNITY_EDITOR
|
||||
AssetDatabase.CreateAsset(_facialData, filePath);
|
||||
AssetDatabase.CreateAsset(clip, filePath);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log($"표정 데이터 저장 완료: {filePath}");
|
||||
Debug.Log($"표정 애니메이션 클립 저장 완료: {filePath}");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -235,61 +263,6 @@ namespace Entum {
|
||||
_frameCount++;
|
||||
}
|
||||
|
||||
void ExportFacialAnimationClip(Animator root, CharacterFacialData facial) {
|
||||
if(facial.Faces.Count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var clip = new AnimationClip();
|
||||
clip.frameRate = 30;
|
||||
|
||||
var blendShapeNames = facial.Faces[0].BlendShapeNames;
|
||||
var curves = new Dictionary<string, AnimationCurve>();
|
||||
|
||||
for(int i = 0; i < blendShapeNames.Count; i++) {
|
||||
curves[blendShapeNames[i]] = new AnimationCurve();
|
||||
}
|
||||
|
||||
for(int i = 0; i < facial.Faces.Count; i++) {
|
||||
var face = facial.Faces[i];
|
||||
var time = face.Time;
|
||||
|
||||
for(int j = 0; j < face.BlendShapeNames.Count; j++) {
|
||||
var blendShapeName = face.BlendShapeNames[j];
|
||||
var value = face.BlendShapeValues[j];
|
||||
|
||||
if(curves.ContainsKey(blendShapeName)) {
|
||||
curves[blendShapeName].AddKey(time, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var curve in curves) {
|
||||
clip.SetCurve("", typeof(SkinnedMeshRenderer), "blendShape." + curve.Key, curve.Value);
|
||||
}
|
||||
|
||||
string fileName = $"{facial.SessionID}_Facial";
|
||||
string filePath = Path.Combine(_savePathManager.GetFacialSavePath(), fileName + ".anim");
|
||||
|
||||
// 인스턴스별 고유 경로 생성
|
||||
filePath = _savePathManager.GetInstanceSpecificPath(filePath);
|
||||
|
||||
SavePathManager.SafeCreateDirectory(Path.GetDirectoryName(filePath));
|
||||
|
||||
#if UNITY_EDITOR
|
||||
AssetDatabase.CreateAsset(clip, filePath);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log($"표정 애니메이션 클립 저장 완료: {filePath}");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ExportFacialAnimationClipTest() {
|
||||
if(_facialData != null) {
|
||||
ExportFacialAnimationClip(_animRecorder.CharacterAnimator, _facialData);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetInstanceID(string id)
|
||||
{
|
||||
instanceID = id;
|
||||
|
||||
@ -43,9 +43,8 @@ namespace Entum
|
||||
[SerializeField, Tooltip("rootBoneSystemがOBJECTROOTの時は使われないパラメータです。")]
|
||||
private HumanBodyBones _targetRootBone = HumanBodyBones.Hips;
|
||||
|
||||
[Header("인스턴스 설정")]
|
||||
[SerializeField] private string instanceID = "";
|
||||
[SerializeField] private bool useDontDestroyOnLoad = false;
|
||||
[HideInInspector, SerializeField] private string instanceID = "";
|
||||
[HideInInspector, SerializeField] private bool useDontDestroyOnLoad = false;
|
||||
|
||||
private HumanPoseHandler _poseHandler;
|
||||
private Action _onPlayFinish;
|
||||
|
||||
@ -54,14 +54,14 @@ namespace Entum
|
||||
[SerializeField, Tooltip("녹화 시작 시 T-포즈를 별도로 저장할지 여부 (출력 시 0프레임에 포함)")]
|
||||
private bool _recordTPoseAtStart = true;
|
||||
|
||||
[Header("인스턴스 설정")]
|
||||
[SerializeField] private string instanceID = "";
|
||||
[SerializeField] private SavePathManager _savePathManager;
|
||||
[HideInInspector, SerializeField] private string instanceID = "";
|
||||
[HideInInspector, SerializeField] private SavePathManager _savePathManager;
|
||||
|
||||
protected HumanoidPoses Poses;
|
||||
|
||||
protected float StartTime { get; set; }
|
||||
protected float RecordedTime;
|
||||
protected float StartTime;
|
||||
public string SessionID; // 세션 ID 추가
|
||||
public string SessionID { get; set; }
|
||||
|
||||
private HumanPose _currentPose;
|
||||
private HumanPoseHandler _poseHandler;
|
||||
@ -81,26 +81,41 @@ namespace Entum
|
||||
return;
|
||||
}
|
||||
|
||||
// 인스턴스 ID가 비어있으면 자동 생성
|
||||
if (string.IsNullOrEmpty(instanceID))
|
||||
{
|
||||
instanceID = System.Guid.NewGuid().ToString().Substring(0, 8);
|
||||
}
|
||||
|
||||
// SavePathManager가 없으면 같은 GameObject에서 찾기
|
||||
// SavePathManager 자동 찾기 또는 추가
|
||||
if (_savePathManager == null)
|
||||
{
|
||||
_savePathManager = GetComponent<SavePathManager>();
|
||||
if (_savePathManager == null)
|
||||
{
|
||||
_savePathManager = gameObject.AddComponent<SavePathManager>();
|
||||
_savePathManager.SetInstanceID(instanceID);
|
||||
}
|
||||
}
|
||||
|
||||
// 인스턴스 ID가 비어있으면 자동 생성
|
||||
if (string.IsNullOrEmpty(instanceID))
|
||||
{
|
||||
instanceID = System.Guid.NewGuid().ToString().Substring(0, 8);
|
||||
}
|
||||
|
||||
// SessionID 생성 (인스턴스 ID 제외)
|
||||
SessionID = DateTime.Now.ToString("yyMMdd_HHmmss");
|
||||
|
||||
_poseHandler = new HumanPoseHandler(_animator.avatar, _animator.transform);
|
||||
}
|
||||
|
||||
// 내부 메서드들 (SavePathManager에서 호출)
|
||||
internal void SetInstanceID(string id)
|
||||
{
|
||||
instanceID = id;
|
||||
// SessionID는 인스턴스 ID 없이 유지
|
||||
SessionID = DateTime.Now.ToString("yyMMdd_HHmmss");
|
||||
}
|
||||
|
||||
internal void SetSavePathManager(SavePathManager manager)
|
||||
{
|
||||
_savePathManager = manager;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(_recordStartKey))
|
||||
@ -365,9 +380,90 @@ namespace Entum
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log($"모션 데이터 저장 완료: {filePath}");
|
||||
|
||||
// 자동 출력 옵션 처리
|
||||
if (_savePathManager != null)
|
||||
{
|
||||
if (_savePathManager.ExportHumanoidOnSave)
|
||||
{
|
||||
ExportHumanoidAnimation(fileName);
|
||||
}
|
||||
|
||||
if (_savePathManager.ExportGenericOnSave)
|
||||
{
|
||||
ExportGenericAnimation(fileName);
|
||||
}
|
||||
|
||||
if (_savePathManager.ExportFBXAsciiOnSave)
|
||||
{
|
||||
ExportFBXAnimation(fileName, true);
|
||||
}
|
||||
|
||||
if (_savePathManager.ExportFBXBinaryOnSave)
|
||||
{
|
||||
ExportFBXAnimation(fileName, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void ExportHumanoidAnimation(string baseFileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
string animPath = Path.Combine(_savePathManager.GetMotionSavePath(), $"{baseFileName}_Humanoid.anim");
|
||||
animPath = _savePathManager.GetInstanceSpecificPath(animPath);
|
||||
|
||||
// HumanoidPoses의 기존 내보내기 메서드 사용
|
||||
Poses.ExportHumanoidAnim();
|
||||
Debug.Log($"휴머노이드 애니메이션 출력 완료: {baseFileName}_Humanoid");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"휴머노이드 애니메이션 출력 실패: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportGenericAnimation(string baseFileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
string animPath = Path.Combine(_savePathManager.GetMotionSavePath(), $"{baseFileName}_Generic.anim");
|
||||
animPath = _savePathManager.GetInstanceSpecificPath(animPath);
|
||||
|
||||
// HumanoidPoses의 기존 내보내기 메서드 사용
|
||||
Poses.ExportGenericAnim();
|
||||
Debug.Log($"제네릭 애니메이션 출력 완료: {baseFileName}_Generic");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"제네릭 애니메이션 출력 실패: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportFBXAnimation(string baseFileName, bool ascii)
|
||||
{
|
||||
try
|
||||
{
|
||||
// HumanoidPoses의 기존 FBX 내보내기 메서드 사용
|
||||
if (ascii)
|
||||
{
|
||||
Poses.ExportFBXAscii();
|
||||
}
|
||||
else
|
||||
{
|
||||
Poses.ExportFBXBinary();
|
||||
}
|
||||
Debug.Log($"FBX 애니메이션 출력 완료: {baseFileName}_{(ascii ? "ASCII" : "Binary")}");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"FBX 애니메이션 출력 실패: {e.Message}");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private void UpdateSummaryInfo()
|
||||
{
|
||||
if (Poses == null) return;
|
||||
@ -425,3 +521,4 @@ namespace Entum
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -30,10 +30,14 @@ namespace Entum
|
||||
[Header("파일명 설정")]
|
||||
[SerializeField] private string objectNamePrefix = "Object";
|
||||
|
||||
[Header("인스턴스 설정")]
|
||||
[SerializeField] private string instanceID = "";
|
||||
[SerializeField] private SavePathManager _savePathManager;
|
||||
|
||||
[HideInInspector, SerializeField] private string instanceID = "";
|
||||
[HideInInspector, SerializeField] private SavePathManager _savePathManager;
|
||||
|
||||
// Properties
|
||||
public Transform[] TargetObjects => targetObjects;
|
||||
public bool IsRecording => isRecording;
|
||||
public float RecordedTime => recordedTime;
|
||||
|
||||
private bool isRecording = false;
|
||||
private float startTime;
|
||||
private float recordedTime;
|
||||
@ -52,22 +56,20 @@ namespace Entum
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// SavePathManager 자동 찾기
|
||||
if (_savePathManager == null)
|
||||
{
|
||||
_savePathManager = GetComponent<SavePathManager>();
|
||||
}
|
||||
|
||||
// 인스턴스 ID가 비어있으면 자동 생성
|
||||
if (string.IsNullOrEmpty(instanceID))
|
||||
{
|
||||
instanceID = System.Guid.NewGuid().ToString().Substring(0, 8);
|
||||
}
|
||||
|
||||
// SavePathManager가 없으면 같은 GameObject에서 찾기
|
||||
if (_savePathManager == null)
|
||||
{
|
||||
_savePathManager = GetComponent<SavePathManager>();
|
||||
if (_savePathManager == null)
|
||||
{
|
||||
_savePathManager = gameObject.AddComponent<SavePathManager>();
|
||||
_savePathManager.SetInstanceID(instanceID);
|
||||
}
|
||||
}
|
||||
// SessionID 생성 (인스턴스 ID 제외)
|
||||
SessionID = DateTime.Now.ToString("yyMMdd_HHmmss");
|
||||
}
|
||||
|
||||
private void Update()
|
||||
@ -243,8 +245,51 @@ namespace Entum
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
Debug.Log($"오브젝트 애니메이션 파일 저장: {filePath}");
|
||||
|
||||
// 자동 출력 옵션 처리
|
||||
if (_savePathManager != null)
|
||||
{
|
||||
if (_savePathManager.ExportHumanoidOnSave)
|
||||
{
|
||||
ExportObjectAnimationAsHumanoid(target, fileName);
|
||||
}
|
||||
|
||||
if (_savePathManager.ExportGenericOnSave)
|
||||
{
|
||||
ExportObjectAnimationAsGeneric(target, fileName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void ExportObjectAnimationAsHumanoid(Transform target, string baseFileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 오브젝트 애니메이션은 휴머노이드로 변환할 수 없으므로 제네릭으로 처리
|
||||
ExportObjectAnimationAsGeneric(target, baseFileName);
|
||||
Debug.Log($"오브젝트 휴머노이드 애니메이션 출력 완료: {baseFileName}_Humanoid");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"오브젝트 휴머노이드 애니메이션 출력 실패: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportObjectAnimationAsGeneric(Transform target, string baseFileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 이미 제네릭 애니메이션으로 저장되었으므로 추가 작업 불필요
|
||||
Debug.Log($"오브젝트 제네릭 애니메이션 출력 완료: {baseFileName}_Generic");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"오브젝트 제네릭 애니메이션 출력 실패: {e.Message}");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// 인스펙터에서 타겟 오브젝트 추가/제거를 위한 헬퍼 메서드
|
||||
[ContextMenu("Add Current Selection")]
|
||||
@ -270,19 +315,17 @@ namespace Entum
|
||||
Debug.Log("모든 타겟 오브젝트 제거");
|
||||
}
|
||||
|
||||
public void SetInstanceID(string id)
|
||||
// 내부 메서드들 (SavePathManager에서 호출)
|
||||
internal void SetInstanceID(string id)
|
||||
{
|
||||
instanceID = id;
|
||||
// SessionID는 인스턴스 ID 없이 유지
|
||||
SessionID = DateTime.Now.ToString("yyMMdd_HHmmss");
|
||||
}
|
||||
|
||||
public string GetInstanceID()
|
||||
internal void SetSavePathManager(SavePathManager manager)
|
||||
{
|
||||
return instanceID;
|
||||
_savePathManager = manager;
|
||||
}
|
||||
|
||||
// 타겟 오브젝트 배열 접근자
|
||||
public Transform[] TargetObjects => targetObjects;
|
||||
public bool IsRecording => isRecording;
|
||||
public float RecordedTime => recordedTime;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using Entum;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
@ -10,8 +11,6 @@ namespace EasyMotionRecorder
|
||||
{
|
||||
[Header("저장 경로 설정")]
|
||||
[SerializeField] private string motionSavePath = "Assets/Resources/Motion";
|
||||
[SerializeField] private string facialSavePath = "Assets/Resources/Motion";
|
||||
[SerializeField] private string objectSavePath = "Assets/Resources/Motion";
|
||||
|
||||
[Header("설정")]
|
||||
[SerializeField] private bool createSubdirectories = true;
|
||||
@ -26,6 +25,11 @@ namespace EasyMotionRecorder
|
||||
[SerializeField] private string instanceID = "";
|
||||
[SerializeField] private bool useDontDestroyOnLoad = false;
|
||||
|
||||
// 같은 오브젝트의 컴포넌트 참조
|
||||
private MotionDataRecorder motionRecorder;
|
||||
private FaceAnimationRecorder faceRecorder;
|
||||
private ObjectMotionRecorder objectRecorder;
|
||||
|
||||
public bool ExportHumanoidOnSave => exportHumanoidOnSave;
|
||||
public bool ExportGenericOnSave => exportGenericOnSave;
|
||||
public bool ExportFBXAsciiOnSave => exportFBXAsciiOnSave;
|
||||
@ -46,15 +50,44 @@ namespace EasyMotionRecorder
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
|
||||
// 같은 오브젝트의 컴포넌트들 찾기
|
||||
FindAndSetupComponents();
|
||||
|
||||
InitializePaths();
|
||||
}
|
||||
|
||||
private void FindAndSetupComponents()
|
||||
{
|
||||
// 같은 오브젝트에서 컴포넌트들 찾기
|
||||
motionRecorder = GetComponent<MotionDataRecorder>();
|
||||
faceRecorder = GetComponent<FaceAnimationRecorder>();
|
||||
objectRecorder = GetComponent<ObjectMotionRecorder>();
|
||||
|
||||
// 각 컴포넌트에 인스턴스 ID 설정
|
||||
if (motionRecorder != null)
|
||||
{
|
||||
motionRecorder.SetInstanceID(instanceID);
|
||||
motionRecorder.SetSavePathManager(this);
|
||||
}
|
||||
|
||||
if (faceRecorder != null)
|
||||
{
|
||||
faceRecorder.SetInstanceID(instanceID);
|
||||
faceRecorder.SetSavePathManager(this);
|
||||
}
|
||||
|
||||
if (objectRecorder != null)
|
||||
{
|
||||
objectRecorder.SetInstanceID(instanceID);
|
||||
objectRecorder.SetSavePathManager(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializePaths()
|
||||
{
|
||||
if (createSubdirectories)
|
||||
{
|
||||
CreateDirectoryIfNotExists(motionSavePath);
|
||||
CreateDirectoryIfNotExists(facialSavePath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,12 +118,12 @@ namespace EasyMotionRecorder
|
||||
|
||||
public string GetFacialSavePath()
|
||||
{
|
||||
return facialSavePath;
|
||||
return motionSavePath; // 통합된 경로 사용
|
||||
}
|
||||
|
||||
public string GetObjectSavePath()
|
||||
{
|
||||
return objectSavePath;
|
||||
return motionSavePath; // 통합된 경로 사용
|
||||
}
|
||||
|
||||
public void SetMotionSavePath(string path)
|
||||
@ -98,46 +131,60 @@ namespace EasyMotionRecorder
|
||||
motionSavePath = path;
|
||||
if (createSubdirectories)
|
||||
CreateDirectoryIfNotExists(path);
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetFacialSavePath(string path)
|
||||
{
|
||||
facialSavePath = path;
|
||||
if (createSubdirectories)
|
||||
CreateDirectoryIfNotExists(path);
|
||||
// 통합된 경로이므로 모션 저장 경로와 동일하게 설정
|
||||
SetMotionSavePath(path);
|
||||
}
|
||||
|
||||
public void SetObjectSavePath(string path)
|
||||
{
|
||||
objectSavePath = path;
|
||||
if (createSubdirectories)
|
||||
CreateDirectoryIfNotExists(path);
|
||||
// 통합된 경로이므로 모션 저장 경로와 동일하게 설정
|
||||
SetMotionSavePath(path);
|
||||
}
|
||||
|
||||
public void SetCreateSubdirectories(bool create)
|
||||
private void SetCreateSubdirectories(bool create)
|
||||
{
|
||||
createSubdirectories = create;
|
||||
if (create)
|
||||
{
|
||||
InitializePaths();
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetInstanceID(string id)
|
||||
private void SetInstanceID(string id)
|
||||
{
|
||||
instanceID = id;
|
||||
|
||||
// 모든 컴포넌트에 새 인스턴스 ID 적용
|
||||
if (motionRecorder != null) motionRecorder.SetInstanceID(id);
|
||||
if (faceRecorder != null) faceRecorder.SetInstanceID(id);
|
||||
if (objectRecorder != null) objectRecorder.SetInstanceID(id);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetUseDontDestroyOnLoad(bool use)
|
||||
private void SetUseDontDestroyOnLoad(bool use)
|
||||
{
|
||||
useDontDestroyOnLoad = use;
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void ResetToDefaults()
|
||||
{
|
||||
motionSavePath = "Assets/Resources/Motion";
|
||||
facialSavePath = "Assets/Resources/Motion";
|
||||
objectSavePath = "Assets/Resources/Motion";
|
||||
createSubdirectories = true;
|
||||
|
||||
// 자동 출력 옵션 초기화
|
||||
@ -147,17 +194,9 @@ namespace EasyMotionRecorder
|
||||
exportFBXBinaryOnSave = false;
|
||||
|
||||
InitializePaths();
|
||||
}
|
||||
|
||||
public void SynchronizePaths()
|
||||
{
|
||||
// 모든 경로를 모션 경로와 동일하게 설정
|
||||
facialSavePath = motionSavePath;
|
||||
objectSavePath = motionSavePath;
|
||||
if (createSubdirectories)
|
||||
{
|
||||
InitializePaths();
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
// 인스턴스별 고유 경로 생성
|
||||
@ -172,5 +211,38 @@ namespace EasyMotionRecorder
|
||||
|
||||
return Path.Combine(directory, $"{fileName}_{instanceID}{extension}");
|
||||
}
|
||||
|
||||
// 자동 출력 옵션 설정 (private으로 변경)
|
||||
private void SetExportHumanoidOnSave(bool value)
|
||||
{
|
||||
exportHumanoidOnSave = value;
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void SetExportGenericOnSave(bool value)
|
||||
{
|
||||
exportGenericOnSave = value;
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void SetExportFBXAsciiOnSave(bool value)
|
||||
{
|
||||
exportFBXAsciiOnSave = value;
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void SetExportFBXBinaryOnSave(bool value)
|
||||
{
|
||||
exportFBXBinaryOnSave = value;
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user