user 4a49ecd772 Refactor: 배경/프랍 브라우저 IMGUI→UI Toolkit 전환 + USS 리디자인
- BackgroundSceneLoaderWindow: OnGUI → CreateGUI (Toolbar + ToolbarSearchField)
- PropBrowserWindow: OnGUI → CreateGUI (Toolbar + ToolbarSearchField)
- StreamingleCommon.uss: 브라우저 공통 스타일 추가 (그리드/리스트/뷰토글/액션바/상태바)
- excludeFromWeb 상태 새로고침 시 보존 수정
- 삭제된 배경 리소스 정리

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 01:55:48 +09:00

116 lines
4.2 KiB
C#

using UnityEngine;
using UnityEditor;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using System.IO;
using UniHumanoid;
public class HumanPoseClipCreator : EditorWindow
{
private const string CommonUssPath = "Assets/Scripts/Streamingle/StreamingleControl/Editor/UXML/StreamingleCommon.uss";
private ObjectField animatorField;
private TextField nameField;
private TextField pathField;
[MenuItem("Tools/Animation Tools/포즈 클립 생성기")]
public static void ShowWindow()
{
GetWindow<HumanPoseClipCreator>("포즈 클립 생성기");
}
public void CreateGUI()
{
var root = rootVisualElement;
root.AddToClassList("tool-root");
var commonUss = AssetDatabase.LoadAssetAtPath<StyleSheet>(CommonUssPath);
if (commonUss != null) root.styleSheets.Add(commonUss);
root.Add(new Label("휴먼 포즈 클립 생성") { name = "title" });
root.Q<Label>("title").AddToClassList("tool-title");
animatorField = new ObjectField("타겟 Animator") { objectType = typeof(Animator), allowSceneObjects = true };
root.Add(animatorField);
nameField = new TextField("에셋 이름") { value = "NewPoseClip" };
root.Add(nameField);
pathField = new TextField("저장 경로") { value = "Assets/Resources" };
root.Add(pathField);
var browseBtn = new Button(() =>
{
string path = EditorUtility.SaveFolderPanel("저장 폴더 선택", "Assets", "");
if (!string.IsNullOrEmpty(path))
{
if (path.StartsWith(Application.dataPath))
pathField.value = "Assets" + path.Substring(Application.dataPath.Length);
else
EditorUtility.DisplayDialog("오류", "Assets 폴더 내부를 선택해주세요.", "확인");
}
}) { text = "폴더 선택" };
root.Add(browseBtn);
var createBtn = new Button(CreatePoseClip) { text = "포즈 클립 생성" };
createBtn.style.height = 30;
createBtn.style.marginTop = 12;
createBtn.AddToClassList("btn-primary");
root.Add(createBtn);
root.schedule.Execute(() => createBtn.SetEnabled(animatorField.value != null)).Every(200);
}
private void CreatePoseClip()
{
var selectedAnimator = animatorField.value as Animator;
if (selectedAnimator == null)
{
EditorUtility.DisplayDialog("오류", "Animator를 선택해주세요.", "확인");
return;
}
string savePath = pathField.value;
if (!savePath.StartsWith("Assets/"))
{
EditorUtility.DisplayDialog("오류", "저장 경로는 'Assets/'로 시작해야 합니다.", "확인");
return;
}
var avatar = selectedAnimator.avatar;
if (avatar == null || !avatar.isHuman)
{
EditorUtility.DisplayDialog("오류", "Humanoid Avatar가 필요합니다.", "확인");
return;
}
try
{
var handler = new HumanPoseHandler(avatar, selectedAnimator.transform);
HumanPose pose = new HumanPose();
handler.GetHumanPose(ref pose);
HumanPoseClip poseClip = ScriptableObject.CreateInstance<HumanPoseClip>();
poseClip.ApplyPose(ref pose);
string assetName = nameField.value;
string fullPath = Path.Combine(savePath, $"{assetName}.pose.asset");
string directory = Path.GetDirectoryName(fullPath);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
AssetDatabase.CreateAsset(poseClip, fullPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"포즈 클립이 생성되었습니다: {fullPath}");
EditorUtility.DisplayDialog("성공", $"포즈 클립이 생성되었습니다:\n{fullPath}", "확인");
}
catch (System.Exception e)
{
Debug.LogError($"포즈 클립 생성 오류: {e.Message}");
EditorUtility.DisplayDialog("오류", $"포즈 클립 생성 실패: {e.Message}", "확인");
}
}
}