- BackgroundSceneLoaderWindow: OnGUI → CreateGUI (Toolbar + ToolbarSearchField) - PropBrowserWindow: OnGUI → CreateGUI (Toolbar + ToolbarSearchField) - StreamingleCommon.uss: 브라우저 공통 스타일 추가 (그리드/리스트/뷰토글/액션바/상태바) - excludeFromWeb 상태 새로고침 시 보존 수정 - 삭제된 배경 리소스 정리 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
194 lines
7.9 KiB
C#
194 lines
7.9 KiB
C#
using UnityEngine;
|
|
using UnityEditor;
|
|
using UnityEngine.UIElements;
|
|
using UnityEditor.UIElements;
|
|
|
|
[CustomEditor(typeof(FingerShapedController))]
|
|
public class FingerShapedControllerEditor : Editor
|
|
{
|
|
private const string CommonUssPath = "Assets/Scripts/Streamingle/StreamingleControl/Editor/UXML/StreamingleCommon.uss";
|
|
private static readonly string[] fingerPropNames = { "ThumbCurl", "IndexCurl", "MiddleCurl", "RingCurl", "PinkyCurl" };
|
|
private static readonly string[] fingerKoreanNames = { "엄지", "검지", "중지", "약지", "새끼" };
|
|
|
|
private FingerShapedController controller;
|
|
|
|
public override VisualElement CreateInspectorGUI()
|
|
{
|
|
controller = target as FingerShapedController;
|
|
if (controller == null) return new VisualElement();
|
|
var root = new VisualElement();
|
|
|
|
var commonUss = AssetDatabase.LoadAssetAtPath<StyleSheet>(CommonUssPath);
|
|
if (commonUss != null) root.styleSheets.Add(commonUss);
|
|
|
|
// 활성화 토글
|
|
var enabledProp = serializedObject.FindProperty("m_Enabled");
|
|
var enableToggle = new PropertyField(enabledProp, "손가락 제어 활성화");
|
|
root.Add(enableToggle);
|
|
|
|
// 왼손
|
|
var leftFoldout = new Foldout { text = "왼손", value = true };
|
|
leftFoldout.Add(BuildHandControls("left"));
|
|
root.Add(leftFoldout);
|
|
|
|
// 오른손
|
|
var rightFoldout = new Foldout { text = "오른손", value = true };
|
|
rightFoldout.Add(BuildHandControls("right"));
|
|
root.Add(rightFoldout);
|
|
|
|
// 프리셋 버튼
|
|
root.Add(BuildPresetButtons());
|
|
|
|
return root;
|
|
}
|
|
|
|
private VisualElement BuildHandControls(string prefix)
|
|
{
|
|
var container = new VisualElement();
|
|
container.style.backgroundColor = new Color(0, 0, 0, 0.08f);
|
|
container.style.borderTopLeftRadius = container.style.borderTopRightRadius =
|
|
container.style.borderBottomLeftRadius = container.style.borderBottomRightRadius = 4;
|
|
container.style.paddingTop = container.style.paddingBottom =
|
|
container.style.paddingLeft = container.style.paddingRight = 6;
|
|
|
|
// 헤더: 활성화 토글 + 초기화 버튼
|
|
var header = new VisualElement { style = { flexDirection = FlexDirection.Row, alignItems = Align.Center, marginBottom = 4 } };
|
|
var handEnabledProp = serializedObject.FindProperty($"{prefix}HandEnabled");
|
|
header.Add(new PropertyField(handEnabledProp, "제어 활성화") { style = { flexGrow = 1 } });
|
|
var resetBtn = new Button(() => ResetHandValues(prefix)) { text = "초기화" };
|
|
resetBtn.style.width = 60;
|
|
header.Add(resetBtn);
|
|
container.Add(header);
|
|
|
|
// 손가락 슬라이더 (가로 배치)
|
|
var slidersRow = new VisualElement { style = { flexDirection = FlexDirection.Row, justifyContent = Justify.Center, marginTop = 4 } };
|
|
|
|
for (int i = 0; i < fingerPropNames.Length; i++)
|
|
{
|
|
var fingerProp = serializedObject.FindProperty($"{prefix}{fingerPropNames[i]}");
|
|
slidersRow.Add(BuildVerticalSlider(fingerKoreanNames[i], fingerProp));
|
|
}
|
|
container.Add(slidersRow);
|
|
|
|
// 벌리기 슬라이더
|
|
var spreadProp = serializedObject.FindProperty($"{prefix}SpreadFingers");
|
|
var spreadSlider = new Slider("벌리기", -1f, 1f) { showInputField = true };
|
|
spreadSlider.BindProperty(spreadProp);
|
|
spreadSlider.style.marginTop = 8;
|
|
container.Add(spreadSlider);
|
|
|
|
// 비활성 시 숨기기
|
|
container.TrackPropertyValue(handEnabledProp, prop =>
|
|
{
|
|
slidersRow.style.display = prop.boolValue ? DisplayStyle.Flex : DisplayStyle.None;
|
|
spreadSlider.style.display = prop.boolValue ? DisplayStyle.Flex : DisplayStyle.None;
|
|
});
|
|
slidersRow.style.display = handEnabledProp.boolValue ? DisplayStyle.Flex : DisplayStyle.None;
|
|
spreadSlider.style.display = handEnabledProp.boolValue ? DisplayStyle.Flex : DisplayStyle.None;
|
|
|
|
return container;
|
|
}
|
|
|
|
private VisualElement BuildVerticalSlider(string label, SerializedProperty prop)
|
|
{
|
|
var column = new VisualElement { style = { alignItems = Align.Center, width = 45, marginLeft = 2, marginRight = 2 } };
|
|
|
|
column.Add(new Label(label) { style = { fontSize = 10, color = new Color(0.6f, 0.6f, 0.6f) } });
|
|
|
|
var valueLabel = new Label(prop.floatValue.ToString("F1")) { style = { fontSize = 10, color = new Color(0.6f, 0.6f, 0.6f) } };
|
|
column.Add(valueLabel);
|
|
|
|
// UI Toolkit Slider in vertical mode (direction: Vertical 대신 세로용 Slider 사용)
|
|
// SliderDirection.Vertical 사용
|
|
var slider = new Slider(-1f, 1f) { direction = SliderDirection.Vertical };
|
|
slider.style.height = 100;
|
|
slider.style.width = 25;
|
|
slider.BindProperty(prop);
|
|
slider.RegisterValueChangedCallback(evt => valueLabel.text = evt.newValue.ToString("F1"));
|
|
|
|
// 초기값 동기화
|
|
column.TrackPropertyValue(prop, p => valueLabel.text = p.floatValue.ToString("F1"));
|
|
|
|
column.Add(slider);
|
|
return column;
|
|
}
|
|
|
|
private VisualElement BuildPresetButtons()
|
|
{
|
|
var container = new VisualElement { style = { marginTop = 10 } };
|
|
container.Add(new Label("손 모양 프리셋") { style = { unityFontStyleAndWeight = FontStyle.Bold, marginBottom = 4 } });
|
|
|
|
string[,] presets = {
|
|
{ "가위", "바위", "보" },
|
|
{ "브이", "검지", "초기화" }
|
|
};
|
|
|
|
for (int row = 0; row < 2; row++)
|
|
{
|
|
var btnRow = new VisualElement { style = { flexDirection = FlexDirection.Row, justifyContent = Justify.Center, marginBottom = 4 } };
|
|
for (int col = 0; col < 3; col++)
|
|
{
|
|
string presetName = presets[row, col];
|
|
var btn = new Button(() => ApplyPreset(presetName)) { text = presetName };
|
|
btn.style.height = 30;
|
|
btn.style.width = 100;
|
|
btn.style.marginLeft = btn.style.marginRight = 4;
|
|
btnRow.Add(btn);
|
|
}
|
|
container.Add(btnRow);
|
|
}
|
|
|
|
return container;
|
|
}
|
|
|
|
private void ResetHandValues(string prefix)
|
|
{
|
|
serializedObject.Update();
|
|
string[] props = { "ThumbCurl", "IndexCurl", "MiddleCurl", "RingCurl", "PinkyCurl", "SpreadFingers" };
|
|
foreach (var prop in props)
|
|
serializedObject.FindProperty($"{prefix}{prop}").floatValue = 0f;
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
private void ApplyPreset(string presetName)
|
|
{
|
|
if (!controller.enabled)
|
|
controller.enabled = true;
|
|
|
|
switch (presetName)
|
|
{
|
|
case "가위": SetPreset(1f, 1f, -1f, -1f, -1f, 0.3f); break;
|
|
case "바위": SetPreset(-1f, -1f, -1f, -1f, -1f, 0f); break;
|
|
case "보": SetPreset(1f, 1f, 1f, 1f, 1f, 1f); break;
|
|
case "브이": SetPreset(-1f, 1f, 1f, -1f, -1f, 1f); break;
|
|
case "검지": SetPreset(-1f, 1f, -1f, -1f, -1f, 0f); break;
|
|
case "초기화": SetPreset(0.8f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f); break;
|
|
}
|
|
}
|
|
|
|
private void SetPreset(float thumb, float index, float middle, float ring, float pinky, float spread)
|
|
{
|
|
if (controller.leftHandEnabled)
|
|
{
|
|
controller.leftThumbCurl = thumb;
|
|
controller.leftIndexCurl = index;
|
|
controller.leftMiddleCurl = middle;
|
|
controller.leftRingCurl = ring;
|
|
controller.leftPinkyCurl = pinky;
|
|
controller.leftSpreadFingers = spread;
|
|
}
|
|
|
|
if (controller.rightHandEnabled)
|
|
{
|
|
controller.rightThumbCurl = thumb;
|
|
controller.rightIndexCurl = index;
|
|
controller.rightMiddleCurl = middle;
|
|
controller.rightRingCurl = ring;
|
|
controller.rightPinkyCurl = pinky;
|
|
controller.rightSpreadFingers = spread;
|
|
}
|
|
|
|
EditorUtility.SetDirty(controller);
|
|
}
|
|
}
|