0407
This commit is contained in:
parent
885535031c
commit
283c891554
@ -1189,15 +1189,31 @@ class ProjectManager:
|
||||
except Exception:
|
||||
pass
|
||||
ssbo_loaded = self._load_scene_description_via_ssbo(scene_description, project_path, asset_database)
|
||||
use_manual_asset_import = (
|
||||
not ssbo_loaded
|
||||
and callable(getattr(self.world, "_import_model_with_menu_logic", None))
|
||||
)
|
||||
|
||||
scene_root, keep_nodes = self._build_scene_root_from_description(
|
||||
scene_root, keep_nodes, built_nodes = self._build_scene_root_from_description(
|
||||
scene_description,
|
||||
project_path,
|
||||
asset_database,
|
||||
include_mode="all",
|
||||
skip_asset_nodes=ssbo_loaded,
|
||||
skip_asset_nodes=(ssbo_loaded or use_manual_asset_import),
|
||||
return_node_map=True,
|
||||
)
|
||||
|
||||
manually_imported_models = []
|
||||
if use_manual_asset_import:
|
||||
manually_imported_models = self._load_scene_assets_via_manual_import(
|
||||
scene_description,
|
||||
project_path,
|
||||
asset_database,
|
||||
scene_root,
|
||||
keep_nodes,
|
||||
built_nodes,
|
||||
)
|
||||
|
||||
scene_manager = getattr(self.world, "scene_manager", None)
|
||||
if scene_manager:
|
||||
scene_manager.models = []
|
||||
@ -1212,6 +1228,13 @@ class ProjectManager:
|
||||
except Exception:
|
||||
root_children = []
|
||||
|
||||
manual_model_keys = set()
|
||||
for manual_model in manually_imported_models:
|
||||
try:
|
||||
manual_model_keys.add(id(manual_model))
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
try:
|
||||
ssbo_editor = getattr(self.world, "ssbo_editor", None)
|
||||
runtime_model = getattr(ssbo_editor, "model", None) if ssbo_editor else None
|
||||
@ -1233,9 +1256,9 @@ class ProjectManager:
|
||||
if child.hasTag("is_model_root") or child.hasTag("asset_guid"):
|
||||
built_model_nodes.append(child)
|
||||
try:
|
||||
if scene_manager and hasattr(scene_manager, "setupCollision"):
|
||||
if scene_manager and hasattr(scene_manager, "setupCollision") and id(child) not in manual_model_keys:
|
||||
scene_manager.setupCollision(child)
|
||||
if scene_manager and hasattr(scene_manager, "_processModelAnimations"):
|
||||
if scene_manager and hasattr(scene_manager, "_processModelAnimations") and id(child) not in manual_model_keys:
|
||||
scene_manager._processModelAnimations(child)
|
||||
except Exception:
|
||||
pass
|
||||
@ -1248,7 +1271,14 @@ class ProjectManager:
|
||||
|
||||
if scene_manager:
|
||||
if not ssbo_loaded:
|
||||
scene_manager.models = built_model_nodes
|
||||
merged_models = []
|
||||
for candidate in list(manually_imported_models) + built_model_nodes:
|
||||
if not candidate or candidate.isEmpty():
|
||||
continue
|
||||
if any(existing == candidate for existing in merged_models):
|
||||
continue
|
||||
merged_models.append(candidate)
|
||||
scene_manager.models = merged_models
|
||||
else:
|
||||
merged_models = list(getattr(scene_manager, "models", []) or [])
|
||||
for child in built_model_nodes:
|
||||
@ -1352,6 +1382,83 @@ class ProjectManager:
|
||||
top_level_nodes.append(node)
|
||||
return top_level_nodes, node_lookup
|
||||
|
||||
def _load_scene_assets_via_manual_import(
|
||||
self,
|
||||
scene_description,
|
||||
project_path,
|
||||
asset_database,
|
||||
scene_root,
|
||||
keep_nodes,
|
||||
built_nodes,
|
||||
):
|
||||
import_with_menu = getattr(self.world, "_import_model_with_menu_logic", None)
|
||||
if not callable(import_with_menu):
|
||||
return []
|
||||
|
||||
top_level_nodes, node_lookup = self._iter_top_level_scene_asset_nodes(scene_description)
|
||||
imported_models = []
|
||||
for node in top_level_nodes:
|
||||
components = dict(node.get("components", {}) or {})
|
||||
model_component = dict(components.get("model", {}) or {})
|
||||
imported_node_key = str(
|
||||
model_component.get("imported_node_key", "")
|
||||
or node.get("imported_node_key", "")
|
||||
or ""
|
||||
).strip()
|
||||
if imported_node_key:
|
||||
return []
|
||||
|
||||
asset_guid = str(
|
||||
model_component.get("asset_guid", "")
|
||||
or node.get("asset_guid", "")
|
||||
or ""
|
||||
).strip()
|
||||
if not asset_guid:
|
||||
continue
|
||||
|
||||
asset_record = asset_database.get_asset(asset_guid)
|
||||
if not asset_record:
|
||||
return []
|
||||
|
||||
asset_rel = str(
|
||||
asset_record.get("asset_path", "")
|
||||
or model_component.get("asset_path", "")
|
||||
or node.get("asset_path", "")
|
||||
or ""
|
||||
).strip()
|
||||
if not asset_rel:
|
||||
return []
|
||||
|
||||
asset_abs = os.path.join(project_path, asset_rel.replace("/", os.sep))
|
||||
if not os.path.exists(asset_abs):
|
||||
return []
|
||||
|
||||
imported_np = import_with_menu(
|
||||
asset_abs,
|
||||
select_model=False,
|
||||
set_origin=False,
|
||||
show_info_message=False,
|
||||
show_success_message=False,
|
||||
)
|
||||
if not imported_np or imported_np.isEmpty():
|
||||
return []
|
||||
|
||||
parent_np = scene_root
|
||||
parent_id = self._resolve_scene_description_parent(node, keep_nodes, node_lookup)
|
||||
if parent_id in built_nodes:
|
||||
parent_np = built_nodes[parent_id]
|
||||
imported_np.reparentTo(parent_np)
|
||||
self._apply_scene_description_state_to_subtree(
|
||||
imported_np,
|
||||
node,
|
||||
project_path,
|
||||
node_lookup,
|
||||
apply_material_state=True,
|
||||
prune_missing_children=False,
|
||||
)
|
||||
imported_models.append(imported_np)
|
||||
return imported_models
|
||||
|
||||
def _apply_scene_description_state_to_node(self, target_np, node, project_path, apply_material_state=True):
|
||||
if not target_np or target_np.isEmpty() or not isinstance(node, dict):
|
||||
return
|
||||
@ -1447,9 +1554,17 @@ class ProjectManager:
|
||||
target_np.setTag("has_scripts", "true")
|
||||
target_np.setTag("scripts_info", json.dumps(scripts, ensure_ascii=False))
|
||||
|
||||
if apply_material_state:
|
||||
if apply_material_state and self._should_restore_saved_material_state(node):
|
||||
self._apply_saved_material_tags_to_node(target_np)
|
||||
|
||||
def _should_restore_saved_material_state(self, node):
|
||||
if not isinstance(node, dict):
|
||||
return False
|
||||
tags = dict(node.get("tags", {}) or {})
|
||||
if str(tags.get("scene_material_dirty", "") or "").strip().lower() == "true":
|
||||
return True
|
||||
return False
|
||||
|
||||
def _apply_saved_material_tags_to_node(self, target_np):
|
||||
"""Rebuild runtime material state from serialized material_* tags."""
|
||||
if not target_np or target_np.isEmpty():
|
||||
@ -1590,7 +1705,19 @@ class ProjectManager:
|
||||
|
||||
runtime_children = []
|
||||
try:
|
||||
runtime_children = [child for child in target_np.getChildren() if child and not child.isEmpty()]
|
||||
for child in target_np.getChildren():
|
||||
if not child or child.isEmpty():
|
||||
continue
|
||||
child_name = ""
|
||||
try:
|
||||
child_name = str(child.getName() or "")
|
||||
except Exception:
|
||||
child_name = ""
|
||||
if child_name.startswith("modelCollision_"):
|
||||
continue
|
||||
if child_name.startswith("selectionOutline"):
|
||||
continue
|
||||
runtime_children.append(child)
|
||||
except Exception:
|
||||
runtime_children = []
|
||||
|
||||
@ -1619,10 +1746,17 @@ class ProjectManager:
|
||||
return ""
|
||||
|
||||
runtime_children_by_key = {}
|
||||
runtime_children_by_name = {}
|
||||
for runtime_index, runtime_child in enumerate(runtime_children):
|
||||
key = _runtime_imported_key(runtime_child)
|
||||
if key and key not in runtime_children_by_key:
|
||||
runtime_children_by_key[key] = (runtime_index, runtime_child)
|
||||
try:
|
||||
runtime_name = str(runtime_child.getName() or "").strip()
|
||||
except Exception:
|
||||
runtime_name = ""
|
||||
if runtime_name:
|
||||
runtime_children_by_name.setdefault(runtime_name, []).append((runtime_index, runtime_child))
|
||||
|
||||
used_runtime_indices = set()
|
||||
for child_entry in child_nodes:
|
||||
@ -1638,6 +1772,15 @@ class ProjectManager:
|
||||
target_runtime_index = keyed_index
|
||||
target_runtime_child = keyed_child
|
||||
|
||||
if target_runtime_child is None:
|
||||
entry_name = str(child_entry.get("name", "") or "").strip()
|
||||
for named_index, named_child in runtime_children_by_name.get(entry_name, []):
|
||||
if named_index in used_runtime_indices:
|
||||
continue
|
||||
target_runtime_index = named_index
|
||||
target_runtime_child = named_child
|
||||
break
|
||||
|
||||
if target_runtime_child is None:
|
||||
child_index = _node_index(child_entry)
|
||||
if child_index < 0 or child_index >= len(runtime_children):
|
||||
@ -2148,7 +2291,7 @@ class ProjectManager:
|
||||
parent_id = parent_node.get("parent_id")
|
||||
return False
|
||||
|
||||
def _build_scene_root_from_description(self, scene_description, project_path, asset_database, include_mode="all", skip_asset_nodes=False):
|
||||
def _build_scene_root_from_description(self, scene_description, project_path, asset_database, include_mode="all", skip_asset_nodes=False, return_node_map=False):
|
||||
nodes = list(scene_description.get("nodes", []) or [])
|
||||
node_lookup = {
|
||||
str(node.get("node_id", "") or ""): dict(node)
|
||||
@ -2200,6 +2343,8 @@ class ProjectManager:
|
||||
)
|
||||
if rebuilt_np:
|
||||
built_nodes[node_id] = rebuilt_np
|
||||
if return_node_map:
|
||||
return scene_root, keep_nodes, built_nodes
|
||||
return scene_root, keep_nodes
|
||||
|
||||
def saveProject(self):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user