A game about forced loneliness, made by TACStudios
1using System;
2using System.Reflection;
3using UnityEngine;
4using UnityEditor.Graphing;
5using System.Globalization;
6using UnityEditor.UIElements;
7using UnityEngine.UIElements;
8
9
10namespace UnityEditor.ShaderGraph.Drawing.Controls
11{
12 [AttributeUsage(AttributeTargets.Property)]
13 class SliderControlAttribute : Attribute, IControlAttribute
14 {
15 string m_Label;
16 bool m_DisplayMinMax;
17
18 public SliderControlAttribute(string label = null, bool displayMinMax = false)
19 {
20 m_Label = label;
21 m_DisplayMinMax = displayMinMax;
22 }
23
24 public VisualElement InstantiateControl(AbstractMaterialNode node, PropertyInfo propertyInfo)
25 {
26 return new SliderControlView(m_Label, m_DisplayMinMax, node, propertyInfo);
27 }
28 }
29
30 class SliderControlView : VisualElement, AbstractMaterialNodeModificationListener
31 {
32 AbstractMaterialNode m_Node;
33 PropertyInfo m_PropertyInfo;
34 bool m_DisplayMinMax;
35 Vector3 m_Value;
36
37 VisualElement m_SliderPanel;
38 Slider m_Slider;
39 FloatField m_SliderInput;
40 FloatField m_MinField;
41 FloatField m_MaxField;
42
43 public SliderControlView(string label, bool displayMinMax, AbstractMaterialNode node, PropertyInfo propertyInfo)
44 {
45 m_Node = node;
46 m_PropertyInfo = propertyInfo;
47 styleSheets.Add(Resources.Load<StyleSheet>("Styles/Controls/SliderControlView"));
48 m_DisplayMinMax = displayMinMax;
49
50 if (propertyInfo.PropertyType != typeof(Vector3))
51 throw new ArgumentException("Property must be of type Vector3.", "propertyInfo");
52 new GUIContent(label ?? ObjectNames.NicifyVariableName(propertyInfo.Name));
53 m_Value = (Vector3)m_PropertyInfo.GetValue(m_Node, null);
54
55 m_Slider = new Slider(m_Value.y, m_Value.z) { value = m_Value.x };
56 m_Slider.RegisterValueChangedCallback((evt) => OnChangeSlider(evt.newValue));
57
58 m_SliderInput = new FloatField { value = m_Value.x };
59 m_SliderInput.RegisterValueChangedCallback(evt =>
60 {
61 var value = (float)evt.newValue;
62 m_Value.x = value;
63 m_PropertyInfo.SetValue(m_Node, m_Value, null);
64 this.MarkDirtyRepaint();
65 });
66 m_SliderInput.Q("unity-text-input").RegisterCallback<FocusOutEvent>(evt =>
67 {
68 float minValue = Mathf.Min(m_Value.x, m_Value.y);
69 float maxValue = Mathf.Max(m_Value.x, m_Value.z);
70 m_Value = new Vector3(m_Value.x, minValue, maxValue);
71 m_MinField.value = minValue;
72 m_MaxField.value = maxValue;
73 UpdateSlider();
74 m_PropertyInfo.SetValue(m_Node, m_Value, null);
75 this.MarkDirtyRepaint();
76 }, TrickleDown.TrickleDown);
77
78 m_SliderPanel = new VisualElement { name = "SliderPanel" };
79 if (!string.IsNullOrEmpty(label))
80 m_SliderPanel.Add(new Label(label));
81
82 m_SliderPanel.Add(m_Slider);
83 m_SliderPanel.Add(m_SliderInput);
84 Add(m_SliderPanel);
85
86 if (m_DisplayMinMax)
87 {
88 var fieldsPanel = new VisualElement { name = "FieldsPanel" };
89 m_MinField = AddMinMaxField(fieldsPanel, "Min", 1);
90 m_MaxField = AddMinMaxField(fieldsPanel, "Max", 2);
91 Add(fieldsPanel);
92 }
93 }
94
95 public void OnNodeModified(ModificationScope scope)
96 {
97 if (scope == ModificationScope.Graph)
98 {
99 this.MarkDirtyRepaint();
100 }
101 }
102
103 void OnChangeSlider(float newValue)
104 {
105 m_Node.owner.owner.RegisterCompleteObjectUndo("Slider Change");
106 var value = (Vector3)m_PropertyInfo.GetValue(m_Node, null);
107 value.x = newValue;
108 m_PropertyInfo.SetValue(m_Node, value, null);
109 if (m_SliderInput != null)
110 m_SliderInput.value = newValue;
111 m_PropertyInfo.SetValue(m_Node, m_Value, null);
112 this.MarkDirtyRepaint();
113 }
114
115 void UpdateSlider()
116 {
117 m_SliderPanel.Remove(m_Slider);
118 m_Slider = new Slider(m_Value.y, m_Value.z) { value = m_Value.x };
119 m_Slider.RegisterValueChangedCallback((evt) => OnChangeSlider(evt.newValue));
120 m_SliderPanel.Add(m_Slider);
121 m_SliderPanel.Add(m_SliderInput);
122 }
123
124 FloatField AddMinMaxField(VisualElement panel, string label, int index)
125 {
126 var floatField = new FloatField { value = m_Value[index] };
127 if (label != null)
128 {
129 var labelField = new Label(label);
130 panel.Add(labelField);
131 }
132
133 floatField.RegisterValueChangedCallback(evt =>
134 {
135 m_Value[index] = (float)evt.newValue;
136 m_PropertyInfo.SetValue(m_Node, m_Value, null);
137 this.MarkDirtyRepaint();
138 });
139 floatField.Q("unity-text-input").RegisterCallback<FocusOutEvent>(evt =>
140 {
141 if (index == 1)
142 {
143 m_Value[index] = Mathf.Min(m_Value[index], m_Value.z);
144 m_MinField.value = m_Value[index];
145 }
146 else
147 {
148 m_Value[index] = Mathf.Max(m_Value[index], m_Value.y);
149 m_MaxField.value = m_Value[index];
150 }
151 float newValue = Mathf.Max(Mathf.Min(m_Value.x, m_Value.z), m_Value.y);
152 m_Value.x = newValue;
153 m_SliderInput.value = newValue;
154 UpdateSlider();
155 m_PropertyInfo.SetValue(m_Node, m_Value, null);
156 this.MarkDirtyRepaint();
157 }, TrickleDown.TrickleDown);
158
159 panel.Add(floatField);
160 return floatField;
161 }
162
163 void Repaint<T>(MouseEventBase<T> evt) where T : MouseEventBase<T>, new()
164 {
165 evt.StopPropagation();
166 this.MarkDirtyRepaint();
167 }
168 }
169}