virtual_tree_builder.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import sys
  2. from pathlib import Path
  3. import ruamel.yaml
  4. # Add the utils directory to the Python path
  5. utils_path = Path(__file__).parent
  6. sys.path.append(str(utils_path))
  7. from yaml_utils import load_unity_yaml, convert_to_plain_python_types
  8. def build_virtual_tree(file_path, object_map, guid_map):
  9. """
  10. Parses a Unity scene/prefab's data to build a nested dictionary
  11. representing the GameObject hierarchy with resolved component names and correct children.
  12. """
  13. nodes = {}
  14. transform_to_gameobject = {}
  15. child_to_parent_transform = {}
  16. # --- Pass 1: Create all nodes and map all relationships ---
  17. for file_id, obj_data in object_map.items():
  18. if 'GameObject' in obj_data:
  19. go_info = obj_data['GameObject']
  20. resolved_components = []
  21. for comp_ref in go_info.get('m_Component', []):
  22. comp_id = str(comp_ref['component']['fileID'])
  23. if comp_id not in object_map:
  24. continue
  25. comp_data = object_map[comp_id]
  26. if 'MonoBehaviour' in comp_data:
  27. script_guid = comp_data['MonoBehaviour'].get('m_Script', {}).get('guid')
  28. if script_guid:
  29. resolved_components.append({"script": {"guid": script_guid}})
  30. else:
  31. comp_name = next((key for key in comp_data if key != 'm_ObjectHideFlags'), None)
  32. if comp_name:
  33. resolved_components.append(comp_name)
  34. nodes[file_id] = {
  35. 'fileID': file_id,
  36. 'm_Name': go_info.get('m_Name'),
  37. 'm_IsActive': go_info.get('m_IsActive', 1),
  38. 'm_TagString': go_info.get('m_TagString'),
  39. 'm_Layer': go_info.get('m_Layer'),
  40. 'm_Components': resolved_components,
  41. 'm_Children': []
  42. }
  43. elif 'Transform' in obj_data:
  44. # Map the parent-child relationship between transforms
  45. father_id = str(obj_data['Transform'].get('m_Father', {}).get('fileID', '0'))
  46. if father_id != '0':
  47. child_to_parent_transform[file_id] = father_id
  48. # Map the transform back to its owning GameObject
  49. gameobject_id = str(obj_data['Transform'].get('m_GameObject', {}).get('fileID', '0'))
  50. if gameobject_id != '0':
  51. transform_to_gameobject[file_id] = gameobject_id
  52. # --- Pass 2: Build the hierarchy ---
  53. root_nodes = []
  54. for transform_id, gameobject_id in transform_to_gameobject.items():
  55. if gameobject_id in nodes:
  56. parent_transform_id = child_to_parent_transform.get(transform_id)
  57. if parent_transform_id and parent_transform_id in transform_to_gameobject:
  58. parent_gameobject_id = transform_to_gameobject[parent_transform_id]
  59. if parent_gameobject_id in nodes:
  60. # This is a child, append it to its parent
  61. nodes[parent_gameobject_id]['m_Children'].append(nodes[gameobject_id])
  62. else:
  63. # This is a root GameObject
  64. root_nodes.append(nodes[gameobject_id])
  65. return root_nodes