Skip to content

Commit cf02048

Browse files
author
Benoit Hudson
committed
More refactoring, and switching from null-string to empty-string.
1 parent d4299b0 commit cf02048

File tree

2 files changed

+81
-59
lines changed

2 files changed

+81
-59
lines changed

Assets/FbxExporters/Editor/UnitTests/FbxPrefabTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void Init() {
6363
}
6464

6565
FbxPrefab.FbxRepresentation Rep(GameObject go) {
66-
return FbxPrefab.FbxRepresentation.FromTransform(go.transform);
66+
return new FbxPrefab.FbxRepresentation(go.transform);
6767
}
6868

6969
FbxPrefab.FbxRepresentation History(GameObject go) {

Assets/FbxExporters/FbxPrefab.cs

Lines changed: 80 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,24 @@ public static void Append<T>(ref List<T> thelist, T item)
6767
thelist.Add(item);
6868
}
6969

70+
public static void Add<K,V>(ref Dictionary<K,V> thedict, K key, V value)
71+
{
72+
if (thedict == null) {
73+
thedict = new Dictionary<K, V>();
74+
}
75+
thedict.Add(key, value);
76+
}
77+
78+
public static V GetOrCreate<K,V>(Dictionary<K,V> thedict, K key) where V : new()
79+
{
80+
V value;
81+
if (!thedict.TryGetValue(key, out value)) {
82+
value = new V();
83+
thedict[key] = value;
84+
}
85+
return value;
86+
}
87+
7088
/// <summary>
7189
/// Utility function: append an item to a list in a dictionary of lists.
7290
/// Create all the entries needed to append to the list.
@@ -77,12 +95,12 @@ public static void Append<K, V>(ref Dictionary<K, List<V>> thedict, K key, V ite
7795
if (thedict == null) {
7896
thedict = new Dictionary<K, List<V>>();
7997
}
80-
List<V> thelist;
81-
if (!thedict.TryGetValue(key, out thelist) || (thelist == null)) {
82-
thelist = new List<V>();
83-
thedict[key] = thelist;
84-
}
85-
thelist.Add(item);
98+
GetOrCreate(thedict, key).Add(item);
99+
}
100+
101+
public static void Append<K, V>(Dictionary<K, List<V>> thedict, K key, V item)
102+
{
103+
GetOrCreate(thedict, key).Add(item);
86104
}
87105

88106
/// <summary>
@@ -95,12 +113,8 @@ public static void Append<K1, K2, V>(ref Dictionary<K1, Dictionary<K2, List<V>>>
95113
if (thedict == null) {
96114
thedict = new Dictionary<K1, Dictionary<K2, List<V>>>();
97115
}
98-
Dictionary<K2, List<V>> thesubmap;
99-
if (!thedict.TryGetValue(key1, out thesubmap) || thesubmap == null) {
100-
thesubmap = new Dictionary<K2, List<V>>();
101-
thedict[key1] = thesubmap;
102-
}
103-
Append(ref thesubmap, key2, item);
116+
var thesubmap = GetOrCreate(thedict, key1);
117+
Append(thesubmap, key2, item);
104118
}
105119

106120
/// <summary>
@@ -120,30 +134,29 @@ public class FbxRepresentation
120134
/// The key is the name, which is assumed to be unique.
121135
/// The value is, recursively, the representation of that subtree.
122136
/// </summary>
123-
Dictionary<string, FbxRepresentation> children;
137+
Dictionary<string, FbxRepresentation> m_children;
124138

125139
/// <summary>
126140
/// Children of this node.
127141
/// The key is the name of the type of the Component. We accept that there may be several.
128142
/// The value is the json for the component, to be decoded with EditorJsonUtility.
129143
/// </summary>
130-
public Dictionary<string, List<string>> components { get; private set; }
144+
Dictionary<string, List<string>> m_components;
131145

132-
public static FbxRepresentation FromTransform(Transform xfo) {
133-
var children = new Dictionary<string, FbxRepresentation>();
146+
/// <summary>
147+
/// Build a hierarchical representation based on a transform.
148+
/// </summary>
149+
public FbxRepresentation(Transform xfo)
150+
{
151+
m_children = new Dictionary<string, FbxRepresentation>();
134152
foreach(Transform child in xfo) {
135-
children.Add(child.name, FromTransform(child));
153+
m_children.Add(child.name, new FbxRepresentation(child));
136154
}
137-
Dictionary<string, List<string>> components = null;
138155
foreach(var component in xfo.GetComponents<Component>()) {
139156
var typeName = component.GetType().ToString();
140157
var jsonValue = UnityEditor.EditorJsonUtility.ToJson(component);
141-
Append(ref components, typeName, jsonValue);
158+
Append(ref m_components, typeName, jsonValue);
142159
}
143-
var fbxrep = new FbxRepresentation();
144-
fbxrep.children = children;
145-
fbxrep.components = components;
146-
return fbxrep;
147160
}
148161

149162
// todo: use a real json parser
@@ -195,14 +208,13 @@ static string UnEscapeString(string str, int index, int len) {
195208
return builder.ToString();
196209
}
197210

198-
static FbxRepresentation FromJsonHelper(string json, ref int index) {
211+
void InitFromJson(string json, ref int index)
212+
{
199213
Consume('{', json, ref index);
200214
if (Consume('}', json, ref index, required: false)) {
201215
// this is a leaf; we're done.
202-
return new FbxRepresentation();
216+
return;
203217
} else {
204-
Dictionary<string, FbxRepresentation> children = null;
205-
Dictionary<string, List<string>> components = null;
206218
do {
207219
Consume('"', json, ref index);
208220
int nameStart = index;
@@ -214,9 +226,8 @@ static FbxRepresentation FromJsonHelper(string json, ref int index) {
214226
// component (which can't start with a - because it's
215227
// the name of a C# type)
216228
if (name[0] == '-') {
217-
var subrep = FromJsonHelper(json, ref index);
218-
if (children == null) { children = new Dictionary<string, FbxRepresentation>(); }
219-
children.Add(name.Substring(1), subrep);
229+
var subrep = new FbxRepresentation(json, ref index);
230+
Add(ref m_children, name.Substring(1), subrep);
220231
} else {
221232
// Read the string. It won't have any quote marks
222233
// in it, because we escape them using %-encoding
@@ -231,29 +242,28 @@ static FbxRepresentation FromJsonHelper(string json, ref int index) {
231242
// json parsers), now undo that.
232243
var jsonComponent =
233244
UnEscapeString(json, componentStart, index - componentStart);
234-
Append(ref components, name, jsonComponent);
245+
Append(ref m_components, name, jsonComponent);
235246
}
236247
} while(Consume(',', json, ref index, required: false));
237248
Consume('}', json, ref index);
238-
239-
var fbxrep = new FbxRepresentation();
240-
fbxrep.children = children;
241-
fbxrep.components = components;
242-
return fbxrep;
243249
}
244250
}
245251

246-
public static FbxRepresentation FromJson(string json) {
247-
if (json.Length == 0) { return new FbxRepresentation(); }
252+
public FbxRepresentation(string json, ref int index) {
253+
InitFromJson(json, ref index);
254+
}
255+
256+
public FbxRepresentation(string json) {
257+
if (json.Length == 0) { return; }
248258
int index = 0;
249-
return FromJsonHelper(json, ref index);
259+
InitFromJson(json, ref index);
250260
}
251261

252262
void ToJsonHelper(System.Text.StringBuilder builder) {
253263
builder.Append("{");
254264
bool first = true;
255-
if (children != null) {
256-
foreach(var kvp in children.OrderBy(kvp => kvp.Key)) {
265+
if (m_children != null) {
266+
foreach(var kvp in m_children.OrderBy(kvp => kvp.Key)) {
257267
if (!first) { builder.Append(','); }
258268
else { first = false; }
259269

@@ -262,8 +272,8 @@ void ToJsonHelper(System.Text.StringBuilder builder) {
262272
kvp.Value.ToJsonHelper(builder);
263273
}
264274
}
265-
if (components != null) {
266-
foreach(var kvp in components.OrderBy(kvp => kvp.Key)) {
275+
if (m_components != null) {
276+
foreach(var kvp in m_components.OrderBy(kvp => kvp.Key)) {
267277
var name = kvp.Key;
268278
foreach(var componentValue in kvp.Value) {
269279
if (!first) { builder.Append(','); }
@@ -286,22 +296,30 @@ public string ToJson() {
286296
}
287297

288298
public static bool IsLeaf(FbxRepresentation rep) {
289-
return rep == null || rep.children == null;
299+
return rep == null || rep.m_children == null;
290300
}
291301

292302
public static HashSet<string> GetChildren(FbxRepresentation rep) {
293303
if (IsLeaf(rep)) {
294304
return new HashSet<string>();
295305
} else {
296-
return new HashSet<string>(rep.children.Keys);
306+
return new HashSet<string>(rep.m_children.Keys);
307+
}
308+
}
309+
310+
public static IEnumerable<KeyValuePair<string, List<string>>> GetComponents(FbxRepresentation rep) {
311+
if (rep == null || rep.m_components == null) {
312+
return new KeyValuePair<string, List<string>>[0];
313+
} else {
314+
return rep.m_components;
297315
}
298316
}
299317

300318
public static FbxRepresentation Find(FbxRepresentation rep, string key) {
301319
if (IsLeaf(rep)) { return null; }
302320

303321
FbxRepresentation child;
304-
if (rep.children.TryGetValue(key, out child)) {
322+
if (rep.m_children.TryGetValue(key, out child)) {
305323
return child;
306324
}
307325
return null;
@@ -323,7 +341,7 @@ public class UpdateList
323341
// the new fbx, and the prefab. We also figure out the parents.
324342
class Data {
325343
// Parent of each node, by name.
326-
// Value (parent) may be null, key (node) is never null.
344+
// The empty-string name is the root of the prefab/fbx.
327345
Dictionary<string, string> m_parents;
328346

329347
// Component value by name and type, with multiplicity.
@@ -359,7 +377,7 @@ public string GetParent(string name) {
359377
if (m_parents.TryGetValue(name, out parent)) {
360378
return parent;
361379
} else {
362-
return null;
380+
return "";
363381
}
364382
}
365383

@@ -445,10 +463,10 @@ public static HashSet<string> GetAllNames(params Data [] data) {
445463

446464
static void SetupDataHelper(Data data, FbxRepresentation fbxrep, string parent)
447465
{
448-
foreach(var kvp in fbxrep.components) {
466+
foreach(var kvp in FbxRepresentation.GetComponents(fbxrep)) {
449467
var typename = kvp.Key;
450468
var jsonValues = kvp.Value;
451-
data.AddComponents(parent == null ? "" : parent, typename, jsonValues);
469+
data.AddComponents(parent, typename, jsonValues);
452470
}
453471
foreach(var child in FbxRepresentation.GetChildren(fbxrep)) {
454472
data.AddNode(child, parent);
@@ -459,7 +477,7 @@ static void SetupDataHelper(Data data, FbxRepresentation fbxrep, string parent)
459477
static void SetupData(ref Data data, FbxRepresentation fbxrep)
460478
{
461479
Initialize(ref data);
462-
SetupDataHelper(data, fbxrep, null);
480+
SetupDataHelper(data, fbxrep, "");
463481
}
464482

465483
void ClassifyDestroyCreateNodes()
@@ -512,7 +530,7 @@ void ClassifyReparenting()
512530
// trying to destroy objects that are already destroyed
513531
// because a parent got there first. Maybe there's a
514532
// faster way to do it, but performance seems OK.
515-
m_reparentings.Add(name, null);
533+
m_reparentings.Add(name, "");
516534
continue;
517535
}
518536

@@ -638,6 +656,10 @@ void ClassifyComponents(Transform newFbx)
638656

639657
// Figure out the types so we can destroy them.
640658
if (typesToDestroy != null) {
659+
// TODO: handle monobehaviour in other assemblies
660+
// Sample use: using custom attributes in fbx to drive
661+
// unity behaviour by adding a monobehaviour in an
662+
// assetpostprocessor.
641663
var unityEngine = typeof(Component).Assembly;
642664
foreach (var typename in typesToDestroy) {
643665
var thetype = unityEngine.GetType (typename);
@@ -675,8 +697,8 @@ public UpdateList(
675697
FbxPrefab prefab)
676698
{
677699
SetupData(ref m_old, oldFbx);
678-
SetupData(ref m_new, FbxRepresentation.FromTransform(newFbx));
679-
SetupData(ref m_prefab, FbxRepresentation.FromTransform(prefab.transform));
700+
SetupData(ref m_new, new FbxRepresentation(newFbx));
701+
SetupData(ref m_prefab, new FbxRepresentation(prefab.transform));
680702

681703
ClassifyDestroyCreateNodes();
682704
ClassifyReparenting();
@@ -733,7 +755,7 @@ public void ImplementUpdates(FbxPrefab prefabInstance)
733755
var name = kvp.Key;
734756
var parent = kvp.Value;
735757
Transform parentNode;
736-
if (parent == null) {
758+
if (string.IsNullOrEmpty(parent)) {
737759
parentNode = prefabInstance.transform;
738760
} else {
739761
parentNode = prefabNodes[parent];
@@ -847,7 +869,7 @@ void CompareAndUpdate()
847869
updates.ImplementUpdates(fbxPrefab);
848870

849871
// Update the representation of the history to match the new fbx.
850-
var newFbxRep = FbxRepresentation.FromTransform(m_fbxModel.transform);
872+
var newFbxRep = new FbxRepresentation(m_fbxModel.transform);
851873
var newFbxRepString = newFbxRep.ToJson();
852874
fbxPrefab.m_fbxHistory = newFbxRepString;
853875

@@ -880,7 +902,7 @@ public string GetFbxAssetPath()
880902
/// </summary>
881903
public FbxRepresentation GetFbxHistory()
882904
{
883-
return FbxRepresentation.FromJson(m_fbxHistory);
905+
return new FbxRepresentation(m_fbxHistory);
884906
}
885907

886908
/// <summary>
@@ -937,7 +959,7 @@ public void SetSourceModel(GameObject fbxModel) {
937959
// This is the first time we've seen the FBX file. Assume that
938960
// it's the original FBX. Further assume that the user is happy
939961
// with the prefab as it is now, so don't update it to match the FBX.
940-
m_fbxHistory = FbxRepresentation.FromTransform(m_fbxModel.transform).ToJson();
962+
m_fbxHistory = new FbxRepresentation(m_fbxModel.transform).ToJson();
941963
} else {
942964
// Case 3.
943965
// User wants to reconnect or change the connection.

0 commit comments

Comments
 (0)