123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- import sys
- from pathlib import Path
- import ruamel.yaml
- # Add the utils directory to the Python path
- utils_path = Path(__file__).parent
- sys.path.append(str(utils_path))
- from yaml_utils import load_unity_yaml, convert_to_plain_python_types
- from file_utils import create_guid_to_path_map
- def parse_scene_or_prefab(file_path, guid_map=None, assets_dir=None):
- """
- Parses a Unity scene or prefab file and returns a flat list of
- GameObject dictionaries with embedded component data.
- """
- if guid_map is None or assets_dir is None:
- p = Path(file_path).resolve()
- while p.name != 'Assets' and p.parent != p:
- p = p.parent
- if p.name == 'Assets':
- assets_dir = str(p)
- else:
- assets_dir = str(Path(file_path).resolve().parent.parent)
- guid_map = create_guid_to_path_map(assets_dir)
- documents = load_unity_yaml(file_path)
- if not documents:
- return None
- raw_object_map = {int(doc.anchor.value): doc for doc in documents if hasattr(doc, 'anchor') and doc.anchor is not None}
- object_map = {file_id: convert_to_plain_python_types(obj) for file_id, obj in raw_object_map.items()}
- flat_gameobject_list = []
- transform_to_gameobject = {}
- parent_to_children_transforms = {}
- # First pass: Populate relationship maps
- for file_id, obj_data in object_map.items():
- if 'Transform' in obj_data:
- parent_id = obj_data['Transform'].get('m_Father', {}).get('fileID')
- if parent_id:
- if parent_id not in parent_to_children_transforms:
- parent_to_children_transforms[parent_id] = []
- parent_to_children_transforms[parent_id].append(file_id)
-
- for file_id, obj_data in object_map.items():
- if 'GameObject' in obj_data:
- for comp in obj_data['GameObject'].get('m_Component', []):
- comp_id = comp['component']['fileID']
- if comp_id in object_map and 'Transform' in object_map.get(comp_id, {}):
- transform_to_gameobject[comp_id] = file_id
- break
- # Second pass: Process each GameObject
- for file_id, obj_data in object_map.items():
- if 'GameObject' in obj_data:
- go_info = obj_data['GameObject']
-
- source_obj_info = go_info.get('m_CorrespondingSourceObject')
- if source_obj_info and source_obj_info.get('guid'):
- guid = source_obj_info['guid']
- source_prefab_path = guid_map.get(guid)
- if source_prefab_path:
- modifications = go_info.get('m_Modification')
- flat_gameobject_list.append({
- 'fileID': file_id,
- 'm_Name': go_info.get('m_Name'),
- 'isPrefab': True,
- 'sourcePrefabGUID': guid,
- 'm_Modification': modifications
- })
- continue
- components_data = []
- for comp_ref in go_info.get('m_Component', []):
- comp_id = comp_ref['component']['fileID']
- if comp_id in object_map:
- components_data.append(object_map[comp_id])
-
- children_ids = []
- my_transform_id = None
- for t_id, go_id in transform_to_gameobject.items():
- if go_id == file_id:
- my_transform_id = t_id
- break
-
- if my_transform_id in parent_to_children_transforms:
- child_transform_ids = parent_to_children_transforms[my_transform_id]
- for child_t_id in child_transform_ids:
- child_go_id = transform_to_gameobject.get(child_t_id)
- if child_go_id:
- children_ids.append(child_go_id)
- flat_gameobject_list.append({
- 'fileID': file_id,
- 'm_Name': go_info.get('m_Name'),
- 'm_IsActive': go_info.get('m_IsActive', 1),
- 'm_TagString': go_info.get('m_TagString'),
- 'm_Layer': go_info.get('m_Layer'),
- 'm_ComponentsData': components_data,
- 'm_Children': children_ids
- })
- return flat_gameobject_list
|