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

150 lines
5.2 KiB
C#

using UnityEngine;
using UnityEditor;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using System.IO;
using UniHumanoid;
using UniGLTF;
[System.Serializable]
public class HumanPoseData
{
public Vector3 bodyPosition;
public Quaternion bodyRotation;
public float[] muscles;
}
public class HumanPoseClipApplier : EditorWindow
{
private const string CommonUssPath = "Assets/Scripts/Streamingle/StreamingleControl/Editor/UXML/StreamingleCommon.uss";
private ObjectField animatorField;
private ObjectField poseClipField;
private TextField jsonPathField;
private Toggle useJsonToggle;
private VisualElement jsonContainer;
private VisualElement clipContainer;
[MenuItem("Tools/Animation Tools/포즈 클립 적용기")]
public static void ShowWindow()
{
GetWindow<HumanPoseClipApplier>("포즈 클립 적용기");
}
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);
useJsonToggle = new Toggle("JSON 파일 사용") { value = false };
useJsonToggle.RegisterValueChangedCallback(evt =>
{
jsonContainer.style.display = evt.newValue ? DisplayStyle.Flex : DisplayStyle.None;
clipContainer.style.display = evt.newValue ? DisplayStyle.None : DisplayStyle.Flex;
});
root.Add(useJsonToggle);
// JSON mode
jsonContainer = new VisualElement { style = { display = DisplayStyle.None } };
jsonPathField = new TextField("JSON 파일 경로");
jsonContainer.Add(jsonPathField);
var browseBtn = new Button(() =>
{
string path = EditorUtility.OpenFilePanel("JSON 파일 선택", "", "json");
if (!string.IsNullOrEmpty(path)) jsonPathField.value = path;
}) { text = "파일 선택" };
jsonContainer.Add(browseBtn);
root.Add(jsonContainer);
// Clip mode
clipContainer = new VisualElement();
poseClipField = new ObjectField("포즈 클립") { objectType = typeof(HumanPoseClip), allowSceneObjects = false };
clipContainer.Add(poseClipField);
root.Add(clipContainer);
var applyBtn = new Button(ApplyPoseClip) { text = "포즈 적용" };
applyBtn.style.height = 30;
applyBtn.style.marginTop = 12;
applyBtn.AddToClassList("btn-primary");
root.Add(applyBtn);
root.schedule.Execute(() =>
{
bool canApply = animatorField.value != null &&
((useJsonToggle.value && !string.IsNullOrEmpty(jsonPathField.value)) ||
(!useJsonToggle.value && poseClipField.value != null));
applyBtn.SetEnabled(canApply);
}).Every(200);
}
private void ApplyPoseClip()
{
var targetAnimator = animatorField.value as Animator;
if (targetAnimator == null)
{
EditorUtility.DisplayDialog("오류", "Animator를 선택해주세요.", "확인");
return;
}
HumanPose pose;
if (useJsonToggle.value)
{
string jsonPath = jsonPathField.value;
if (string.IsNullOrEmpty(jsonPath) || !File.Exists(jsonPath))
{
EditorUtility.DisplayDialog("오류", "유효한 JSON 파일을 선택해주세요.", "확인");
return;
}
string jsonContent = File.ReadAllText(jsonPath);
HumanPoseData poseData = JsonUtility.FromJson<HumanPoseData>(jsonContent);
pose = new HumanPose
{
bodyPosition = poseData.bodyPosition,
bodyRotation = poseData.bodyRotation,
muscles = poseData.muscles
};
}
else
{
var poseClip = poseClipField.value as HumanPoseClip;
if (poseClip == null)
{
EditorUtility.DisplayDialog("오류", "포즈 클립을 선택해주세요.", "확인");
return;
}
pose = poseClip.GetPose();
}
var avatar = targetAnimator.avatar;
if (avatar == null || !avatar.isHuman)
{
EditorUtility.DisplayDialog("오류", "Humanoid Avatar가 필요합니다.", "확인");
return;
}
try
{
var handler = new HumanPoseHandler(avatar, targetAnimator.transform);
handler.SetHumanPose(ref pose);
EditorUtility.SetDirty(targetAnimator);
Debug.Log("포즈 클립이 적용되었습니다.");
EditorUtility.DisplayDialog("성공", "포즈 클립이 적용되었습니다.", "확인");
}
catch (System.Exception e)
{
Debug.LogError($"포즈 적용 오류: {e.Message}");
EditorUtility.DisplayDialog("오류", $"포즈 적용 실패: {e.Message}", "확인");
}
}
}