Skip to content
This repository was archived by the owner on May 9, 2023. It is now read-only.

Commit c748be7

Browse files
committed
Rewrite InteractiveUnityStruct, now called InteractiveFloatStruct
InteractiveFloatStruct supports any struct where all the fields are floats.
1 parent 09dae6f commit c748be7

File tree

5 files changed

+203
-301
lines changed

5 files changed

+203
-301
lines changed

src/UI/InteractiveValues/InteractiveFlags.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public override void RefreshUIForValue()
4848
GetDefaultLabel();
4949
m_baseLabel.text = DefaultLabel;
5050

51+
base.RefreshUIForValue();
52+
5153
if (m_subContentConstructed)
5254
{
5355
for (int i = 0; i < m_values.Length; i++)
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using UnityEngine;
6+
using UnityEngine.UI;
7+
using System.Reflection;
8+
9+
namespace UnityExplorer.UI.InteractiveValues
10+
{
11+
// Class for supporting any "float struct" (ie Vector, Rect, etc).
12+
// Supports any struct where all the public instance fields are floats (or types assignable to float)
13+
14+
public class StructInfo
15+
{
16+
public string[] FieldNames { get; }
17+
private readonly FieldInfo[] m_fields;
18+
19+
public StructInfo(Type type)
20+
{
21+
m_fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
22+
.Where(it => !it.IsLiteral)
23+
.ToArray();
24+
25+
FieldNames = m_fields.Select(it => it.Name)
26+
.ToArray();
27+
}
28+
29+
public object SetValue(ref object instance, int fieldIndex, float val)
30+
{
31+
m_fields[fieldIndex].SetValue(instance, val);
32+
return instance;
33+
}
34+
35+
public float GetValue(object instance, int fieldIndex)
36+
=> (float)m_fields[fieldIndex].GetValue(instance);
37+
38+
public void RefreshUI(InputField[] inputs, object instance)
39+
{
40+
try
41+
{
42+
for (int i = 0; i < m_fields.Length; i++)
43+
{
44+
var field = m_fields[i];
45+
float val = (float)field.GetValue(instance);
46+
inputs[i].text = val.ToString();
47+
}
48+
}
49+
catch (Exception ex)
50+
{
51+
ExplorerCore.Log(ex);
52+
}
53+
}
54+
}
55+
56+
public class InteractiveFloatStruct : InteractiveValue
57+
{
58+
private static readonly Dictionary<string, bool> _typeSupportCache = new Dictionary<string, bool>();
59+
public static bool IsTypeSupported(Type type)
60+
{
61+
if (!type.IsValueType)
62+
return false;
63+
64+
if (_typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out bool ret))
65+
return ret;
66+
67+
ret = true;
68+
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
69+
foreach (var field in fields)
70+
{
71+
if (field.IsLiteral)
72+
continue;
73+
74+
if (!typeof(float).IsAssignableFrom(field.FieldType))
75+
{
76+
ret = false;
77+
break;
78+
}
79+
}
80+
_typeSupportCache.Add(type.AssemblyQualifiedName, ret);
81+
return ret;
82+
}
83+
84+
//~~~~~~~~~ Instance ~~~~~~~~~~
85+
86+
public InteractiveFloatStruct(object value, Type valueType) : base(value, valueType) { }
87+
88+
public override bool HasSubContent => true;
89+
public override bool SubContentWanted => true;
90+
91+
public StructInfo StructInfo;
92+
93+
public override void RefreshUIForValue()
94+
{
95+
InitializeStructInfo();
96+
97+
base.RefreshUIForValue();
98+
99+
if (m_subContentConstructed)
100+
StructInfo.RefreshUI(m_inputs, this.Value);
101+
}
102+
103+
internal override void OnToggleSubcontent(bool toggle)
104+
{
105+
InitializeStructInfo();
106+
107+
base.OnToggleSubcontent(toggle);
108+
109+
StructInfo.RefreshUI(m_inputs, this.Value);
110+
}
111+
112+
internal Type m_lastStructType;
113+
114+
internal void InitializeStructInfo()
115+
{
116+
var type = Value?.GetType() ?? FallbackType;
117+
118+
if (StructInfo != null && type == m_lastStructType)
119+
return;
120+
121+
if (StructInfo != null && m_subContentConstructed)
122+
DestroySubContent();
123+
124+
m_lastStructType = type;
125+
126+
StructInfo = new StructInfo(type);
127+
128+
if (m_subContentParent.activeSelf)
129+
ConstructSubcontent();
130+
}
131+
132+
#region UI CONSTRUCTION
133+
134+
internal InputField[] m_inputs;
135+
136+
public override void ConstructUI(GameObject parent, GameObject subGroup)
137+
{
138+
base.ConstructUI(parent, subGroup);
139+
}
140+
141+
public override void ConstructSubcontent()
142+
{
143+
base.ConstructSubcontent();
144+
145+
if (StructInfo == null)
146+
{
147+
ExplorerCore.LogWarning("Setting up subcontent but structinfo is null");
148+
return;
149+
}
150+
151+
var editorContainer = UIFactory.CreateVerticalGroup(m_subContentParent, "EditorContent", false, true, true, true, 2, new Vector4(4, 4, 4, 4),
152+
new Color(0.08f, 0.08f, 0.08f));
153+
154+
m_inputs = new InputField[StructInfo.FieldNames.Length];
155+
156+
for (int i = 0; i < StructInfo.FieldNames.Length; i++)
157+
AddEditorRow(i, editorContainer);
158+
159+
RefreshUIForValue();
160+
}
161+
162+
internal void AddEditorRow(int index, GameObject groupObj)
163+
{
164+
try
165+
{
166+
var row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow", false, true, true, true, 5, default, new Color(1, 1, 1, 0));
167+
168+
string name = StructInfo.FieldNames[index];
169+
170+
var label = UIFactory.CreateLabel(row, "RowLabel", $"{name}:", TextAnchor.MiddleRight, Color.cyan);
171+
UIFactory.SetLayoutElement(label.gameObject, minWidth: 30, flexibleWidth: 0, minHeight: 25);
172+
173+
var inputFieldObj = UIFactory.CreateInputField(row, "InputField", "...", 14, 3, 1);
174+
UIFactory.SetLayoutElement(inputFieldObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
175+
176+
var inputField = inputFieldObj.GetComponent<InputField>();
177+
m_inputs[index] = inputField;
178+
179+
inputField.onValueChanged.AddListener((string val) =>
180+
{
181+
try
182+
{
183+
float f = float.Parse(val);
184+
Value = StructInfo.SetValue(ref this.Value, index, f);
185+
Owner.SetValue();
186+
}
187+
catch { }
188+
});
189+
}
190+
catch (Exception ex)
191+
{
192+
ExplorerCore.Log(ex);
193+
}
194+
}
195+
196+
#endregion
197+
}
198+
}

0 commit comments

Comments
 (0)