@@ -59,6 +59,11 @@ public static void Log(string format, params object[] p) {
59
59
60
60
/// <summary>
61
61
/// Utility function: create the object, which must be null.
62
+ ///
63
+ /// Used to make sure that we don't use fields before they're
64
+ /// initialized (for UpdateList): init the fields to null so
65
+ /// we get an NRE if we try to read them before they're set,
66
+ /// or an FPE here if we set them before we were supposed to.
62
67
/// </summary>
63
68
public static void Initialize < T > ( ref T item ) where T : new ( )
64
69
{
@@ -387,42 +392,66 @@ public List<string> GetComponentValues(string componentType) {
387
392
/// </summary>
388
393
public class UpdateList
389
394
{
390
-
391
395
// We build up a flat list of names for the nodes of the old fbx,
392
396
// the new fbx, and the prefab. We also figure out the parents.
393
397
class Data {
394
398
// Parent of each node, by name.
395
399
// The empty-string name is the root of the prefab/fbx.
396
- Dictionary < string , string > m_parents ;
400
+ // Never null.
401
+ Dictionary < string , string > m_parents = new Dictionary < string , string > ( ) ;
397
402
398
403
// Component value by name and type, with multiplicity.
399
- // name -> type -> list of value
400
- Dictionary < string , Dictionary < string , List < string > > > m_components ;
401
-
402
- public Data ( ) {
403
- m_parents = new Dictionary < string , string > ( ) ;
404
- m_components = new Dictionary < string , Dictionary < string , List < string > > > ( ) ;
404
+ // name -> type -> list of value. Never null.
405
+ Dictionary < string , Dictionary < string , List < string > > > m_components
406
+ = new Dictionary < string , Dictionary < string , List < string > > > ( ) ;
407
+
408
+ /// <summary>
409
+ /// Recursively explore the hierarchical representation and
410
+ /// store it with flat indices.
411
+ /// </summary>
412
+ void InitHelper ( FbxRepresentation fbxrep , string nodeName )
413
+ {
414
+ foreach ( var typename in fbxrep . ComponentTypes ) {
415
+ var jsonValues = fbxrep . GetComponentValues ( typename ) ;
416
+ foreach ( var jsonValue in jsonValues ) {
417
+ Append ( ref m_components , nodeName , typename , jsonValue ) ;
418
+ }
419
+ }
420
+ foreach ( var child in fbxrep . ChildNames ) {
421
+ m_parents . Add ( child , nodeName ) ;
422
+ InitHelper ( fbxrep . GetChild ( child ) , child ) ;
423
+ }
405
424
}
406
425
407
- public void AddNode ( string name , string parent ) {
408
- m_parents . Add ( name , parent ) ;
426
+ public Data ( FbxRepresentation fbxrep ) {
427
+ InitHelper ( fbxrep , "" ) ;
409
428
}
410
429
411
- public void AddComponent ( string name , string typename , string jsonValue ) {
412
- Append ( ref m_components , name , typename , jsonValue ) ;
430
+ public Data ( Transform xfo ) : this ( new FbxRepresentation ( xfo ) ) {
413
431
}
414
432
415
- public void AddComponents ( string name , string typename , IEnumerable < string > jsonValues ) {
416
- // todo: optimize this if needed. We only need to look up through the maps once.
417
- foreach ( var jsonValue in jsonValues ) {
418
- AddComponent ( name , typename , jsonValue ) ;
433
+ /// <summary>
434
+ /// Get the set of node names.
435
+ /// </summary>
436
+ public IEnumerable < string > NodeNames {
437
+ get {
438
+ // the names are the keys of the name -> parent map
439
+ return new HashSet < string > ( m_parents . Keys ) ;
419
440
}
420
441
}
421
442
443
+ /// <summary>
444
+ /// Does this data set have a node of this name?
445
+ /// </summary>
422
446
public bool HasNode ( string name ) {
423
447
return m_parents . ContainsKey ( name ) ;
424
448
}
425
449
450
+ /// <summary>
451
+ /// Get the parent of the node.
452
+ /// If the parent is the root of the fbx or the prefab,
453
+ /// returns the empty string.
454
+ /// </summary>
426
455
public string GetParent ( string name ) {
427
456
string parent ;
428
457
if ( m_parents . TryGetValue ( name , out parent ) ) {
@@ -432,6 +461,10 @@ public string GetParent(string name) {
432
461
}
433
462
}
434
463
464
+ /// <summary>
465
+ /// Get all the component types for a given node.
466
+ /// e.g. UnityEngine.Transform, UnityEngine.BoxCollider, etc.
467
+ /// </summary>
435
468
public IEnumerable < string > GetComponentTypes ( string name )
436
469
{
437
470
Dictionary < string , List < string > > components ;
@@ -442,6 +475,11 @@ public IEnumerable<string> GetComponentTypes(string name)
442
475
return components . Keys ;
443
476
}
444
477
478
+ /// <summary>
479
+ /// Get all the component values of a given type for a given node.
480
+ ///
481
+ /// Don't modify the list that gets returned.
482
+ /// </summary>
445
483
public List < string > GetComponentValues ( string name , string typename )
446
484
{
447
485
Dictionary < string , List < string > > components ;
@@ -454,16 +492,6 @@ public List<string> GetComponentValues(string name, string typename)
454
492
}
455
493
return jsonValues ;
456
494
}
457
-
458
-
459
- public static HashSet < string > GetAllNames ( params Data [ ] data ) {
460
- var names = new HashSet < string > ( ) ;
461
- foreach ( var d in data ) {
462
- // the names are the keys of the name -> parent map
463
- names . UnionWith ( d . m_parents . Keys ) ;
464
- }
465
- return names ;
466
- }
467
495
}
468
496
469
497
/// <summary>
@@ -512,48 +540,30 @@ public static HashSet<string> GetAllNames(params Data [] data) {
512
540
/// </summary>
513
541
Dictionary < string , List < Component > > m_componentsToUpdate ;
514
542
515
- static void SetupDataHelper ( Data data , FbxRepresentation fbxrep , string nodeName )
516
- {
517
- foreach ( var typename in fbxrep . ComponentTypes ) {
518
- var jsonValues = fbxrep . GetComponentValues ( typename ) ;
519
- data . AddComponents ( nodeName , typename , jsonValues ) ;
520
- }
521
- foreach ( var child in fbxrep . ChildNames ) {
522
- data . AddNode ( child , nodeName ) ;
523
- SetupDataHelper ( data , fbxrep . GetChild ( child ) , child ) ;
524
- }
525
- }
526
-
527
- static void SetupData ( ref Data data , FbxRepresentation fbxrep )
528
- {
529
- Initialize ( ref data ) ;
530
-
531
- // The root node has no name
532
- SetupDataHelper ( data , fbxrep , "" ) ;
533
- }
534
-
535
543
void ClassifyDestroyCreateNodes ( )
536
544
{
537
545
// Figure out which nodes to add to the prefab, which nodes in the prefab to destroy.
538
546
Initialize ( ref m_nodesToCreate ) ;
539
547
Initialize ( ref m_nodesToDestroy ) ;
540
- foreach ( var name in Data . GetAllNames ( m_old , m_new , m_prefab ) ) {
548
+ foreach ( var name in m_old . NodeNames . Union ( m_new . NodeNames ) ) {
541
549
var isOld = m_old . HasNode ( name ) ;
542
550
var isNew = m_new . HasNode ( name ) ;
543
- var isPrefab = m_prefab . HasNode ( name ) ;
544
- if ( isOld && ! isNew && isPrefab ) {
545
- // This node got deleted in the DCC, so delete it.
546
- m_nodesToDestroy . Add ( name ) ;
547
- } else if ( ! isOld && isNew && ! isPrefab ) {
548
- // This node was created in the DCC but not in Unity, so create it.
549
- m_nodesToCreate . Add ( name ) ;
551
+ if ( isOld != isNew ) {
552
+ // A node was added or deleted in the DCC.
553
+ // Do the same in Unity if it wasn't already done.
554
+ var isPrefab = m_prefab . HasNode ( name ) ;
555
+ if ( ! isNew && isPrefab ) {
556
+ m_nodesToDestroy . Add ( name ) ;
557
+ } else if ( isNew && ! isPrefab ) {
558
+ m_nodesToCreate . Add ( name ) ;
559
+ }
550
560
}
551
561
}
552
562
553
563
// Figure out what nodes will exist after we create and destroy.
554
564
Initialize ( ref m_nodesInUpdatedPrefab ) ;
555
565
m_nodesInUpdatedPrefab . Add ( "" ) ; // the root is nameless
556
- foreach ( var node in Data . GetAllNames ( m_prefab ) . Union ( m_nodesToCreate ) ) {
566
+ foreach ( var node in m_prefab . NodeNames . Union ( m_nodesToCreate ) ) {
557
567
if ( m_nodesToDestroy . Contains ( node ) ) {
558
568
continue ;
559
569
}
@@ -576,7 +586,7 @@ void ClassifyReparenting()
576
586
// x a a => no action
577
587
// x a b => conflict! switch to a for now (todo!)
578
588
// x x a => no action. Todo: what if a is being destroyed? conflict!
579
- foreach ( var name in Data . GetAllNames ( m_prefab ) ) {
589
+ foreach ( var name in m_prefab . NodeNames ) {
580
590
if ( m_nodesToDestroy . Contains ( name ) ) {
581
591
// Reparent to null. This is to avoid the nuisance of
582
592
// trying to destroy objects that are already destroyed
@@ -741,9 +751,9 @@ public UpdateList(
741
751
Transform newFbx ,
742
752
FbxPrefab prefab )
743
753
{
744
- SetupData ( ref m_old , oldFbx ) ;
745
- SetupData ( ref m_new , new FbxRepresentation ( newFbx ) ) ;
746
- SetupData ( ref m_prefab , new FbxRepresentation ( prefab . transform ) ) ;
754
+ m_old = new Data ( oldFbx ) ;
755
+ m_new = new Data ( newFbx ) ;
756
+ m_prefab = new Data ( prefab . transform ) ;
747
757
748
758
ClassifyDestroyCreateNodes ( ) ;
749
759
ClassifyReparenting ( ) ;
0 commit comments