220 lines
8.9 KiB
C#
220 lines
8.9 KiB
C#
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEditor.UIElements;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.UIElements;
|
|
using Streamingle.Background;
|
|
|
|
namespace Streamingle.Background.Editor
|
|
{
|
|
[CustomPropertyDrawer(typeof(SkyboxTimeController.MaterialPropertyOverride))]
|
|
public class MaterialPropertyOverrideDrawer : PropertyDrawer
|
|
{
|
|
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
|
{
|
|
var root = new VisualElement();
|
|
root.style.backgroundColor = new Color(0f, 0f, 0f, 0.08f);
|
|
root.style.borderBottomLeftRadius = 4;
|
|
root.style.borderBottomRightRadius = 4;
|
|
root.style.borderTopLeftRadius = 4;
|
|
root.style.borderTopRightRadius = 4;
|
|
root.style.paddingTop = 4;
|
|
root.style.paddingBottom = 4;
|
|
root.style.paddingLeft = 4;
|
|
root.style.paddingRight = 4;
|
|
root.style.marginBottom = 4;
|
|
|
|
var matProp = property.FindPropertyRelative("targetMaterial");
|
|
var nameProp = property.FindPropertyRelative("propertyName");
|
|
var typeProp = property.FindPropertyRelative("propertyType");
|
|
|
|
// ── Material ──
|
|
var matField = new PropertyField(matProp, "Material");
|
|
root.Add(matField);
|
|
|
|
// ── Property Dropdown ──
|
|
var dropdownRow = new VisualElement();
|
|
dropdownRow.style.flexDirection = FlexDirection.Row;
|
|
dropdownRow.style.alignItems = Align.Center;
|
|
|
|
var dropdown = new PopupField<string>("Property", new List<string> { "(none)" }, 0);
|
|
dropdown.style.flexGrow = 1;
|
|
dropdownRow.Add(dropdown);
|
|
root.Add(dropdownRow);
|
|
|
|
// ── Type (자동 설정되지만 표시) ──
|
|
var typeField = new PropertyField(typeProp, "Type");
|
|
typeField.SetEnabled(false);
|
|
root.Add(typeField);
|
|
|
|
// ── Stage value containers ──
|
|
var floatContainer = CreateStageRow("Float",
|
|
property.FindPropertyRelative("floatStage1"),
|
|
property.FindPropertyRelative("floatStage2"),
|
|
property.FindPropertyRelative("floatStage3"));
|
|
|
|
var colorContainer = CreateStageRow("Color",
|
|
property.FindPropertyRelative("colorStage1"),
|
|
property.FindPropertyRelative("colorStage2"),
|
|
property.FindPropertyRelative("colorStage3"));
|
|
|
|
var vectorContainer = CreateStageRow("Vector",
|
|
property.FindPropertyRelative("vectorStage1"),
|
|
property.FindPropertyRelative("vectorStage2"),
|
|
property.FindPropertyRelative("vectorStage3"));
|
|
|
|
root.Add(floatContainer);
|
|
root.Add(colorContainer);
|
|
root.Add(vectorContainer);
|
|
|
|
// ── 셰이더 프로퍼티 목록 캐시 ──
|
|
var shaderProps = new List<ShaderPropertyInfo>();
|
|
|
|
// 드롭다운 rebuild
|
|
void RebuildDropdown()
|
|
{
|
|
shaderProps.Clear();
|
|
var choices = new List<string> { "(none)" };
|
|
|
|
var mat = matProp.objectReferenceValue as Material;
|
|
if (mat != null && mat.shader != null)
|
|
{
|
|
var shader = mat.shader;
|
|
int count = shader.GetPropertyCount();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
var sType = shader.GetPropertyType(i);
|
|
// Float, Range, Color, Vector만 지원 (텍스쳐 제외)
|
|
if (sType != ShaderPropertyType.Float &&
|
|
sType != ShaderPropertyType.Range &&
|
|
sType != ShaderPropertyType.Color &&
|
|
sType != ShaderPropertyType.Vector)
|
|
continue;
|
|
|
|
// HideInInspector 제외
|
|
var flags = shader.GetPropertyFlags(i);
|
|
if ((flags & ShaderPropertyFlags.HideInInspector) != 0) continue;
|
|
|
|
var propName = shader.GetPropertyName(i);
|
|
var propDesc = shader.GetPropertyDescription(i);
|
|
var displayName = string.IsNullOrEmpty(propDesc)
|
|
? propName
|
|
: $"{propDesc} ({propName})";
|
|
|
|
var mpType = SkyboxTimeController.MaterialPropertyType.Float;
|
|
if (sType == ShaderPropertyType.Color)
|
|
mpType = SkyboxTimeController.MaterialPropertyType.Color;
|
|
else if (sType == ShaderPropertyType.Vector)
|
|
mpType = SkyboxTimeController.MaterialPropertyType.Vector;
|
|
|
|
shaderProps.Add(new ShaderPropertyInfo
|
|
{
|
|
name = propName,
|
|
displayName = displayName,
|
|
type = mpType,
|
|
});
|
|
choices.Add(displayName);
|
|
}
|
|
}
|
|
|
|
// 현재 값 찾기
|
|
int selectedIdx = 0;
|
|
string currentName = nameProp.stringValue;
|
|
if (!string.IsNullOrEmpty(currentName))
|
|
{
|
|
for (int i = 0; i < shaderProps.Count; i++)
|
|
{
|
|
if (shaderProps[i].name == currentName)
|
|
{
|
|
selectedIdx = i + 1; // +1 for "(none)"
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
dropdown.choices = choices;
|
|
dropdown.index = selectedIdx;
|
|
}
|
|
|
|
// 드롭다운 선택 시 프로퍼티 이름 + 타입 자동 설정
|
|
dropdown.RegisterValueChangedCallback(evt =>
|
|
{
|
|
int idx = dropdown.index;
|
|
if (idx <= 0 || idx > shaderProps.Count)
|
|
{
|
|
nameProp.stringValue = "";
|
|
nameProp.serializedObject.ApplyModifiedProperties();
|
|
}
|
|
else
|
|
{
|
|
var info = shaderProps[idx - 1];
|
|
nameProp.stringValue = info.name;
|
|
typeProp.enumValueIndex = (int)info.type;
|
|
nameProp.serializedObject.ApplyModifiedProperties();
|
|
UpdateVisibility(info.type, floatContainer, colorContainer, vectorContainer);
|
|
}
|
|
});
|
|
|
|
// 머티리얼 변경 시 드롭다운 재구성
|
|
matField.RegisterValueChangeCallback(evt =>
|
|
{
|
|
// schedule로 다음 프레임에 rebuild (objectReference 반영 대기)
|
|
root.schedule.Execute(() => RebuildDropdown());
|
|
});
|
|
|
|
// 초기 세팅
|
|
root.schedule.Execute(() =>
|
|
{
|
|
RebuildDropdown();
|
|
UpdateVisibility(
|
|
(SkyboxTimeController.MaterialPropertyType)typeProp.enumValueIndex,
|
|
floatContainer, colorContainer, vectorContainer);
|
|
});
|
|
|
|
return root;
|
|
}
|
|
|
|
private void UpdateVisibility(
|
|
SkyboxTimeController.MaterialPropertyType type,
|
|
VisualElement floatContainer,
|
|
VisualElement colorContainer,
|
|
VisualElement vectorContainer)
|
|
{
|
|
floatContainer.style.display = type == SkyboxTimeController.MaterialPropertyType.Float
|
|
? DisplayStyle.Flex : DisplayStyle.None;
|
|
colorContainer.style.display = type == SkyboxTimeController.MaterialPropertyType.Color
|
|
? DisplayStyle.Flex : DisplayStyle.None;
|
|
vectorContainer.style.display = type == SkyboxTimeController.MaterialPropertyType.Vector
|
|
? DisplayStyle.Flex : DisplayStyle.None;
|
|
}
|
|
|
|
private VisualElement CreateStageRow(string label,
|
|
SerializedProperty s1, SerializedProperty s2, SerializedProperty s3)
|
|
{
|
|
var container = new VisualElement();
|
|
container.style.marginTop = 4;
|
|
|
|
var header = new Label($"── {label} Values ──");
|
|
header.style.unityFontStyleAndWeight = FontStyle.Bold;
|
|
header.style.unityTextAlign = TextAnchor.MiddleCenter;
|
|
header.style.marginBottom = 2;
|
|
header.style.color = new Color(0.6f, 0.8f, 1f);
|
|
container.Add(header);
|
|
|
|
container.Add(new PropertyField(s1, "Stage 1"));
|
|
container.Add(new PropertyField(s2, "Stage 2"));
|
|
container.Add(new PropertyField(s3, "Stage 3"));
|
|
|
|
return container;
|
|
}
|
|
|
|
private struct ShaderPropertyInfo
|
|
{
|
|
public string name;
|
|
public string displayName;
|
|
public SkyboxTimeController.MaterialPropertyType type;
|
|
}
|
|
}
|
|
}
|