优化项目资源结构和保存项目
This commit is contained in:
parent
776d3c01aa
commit
4ef6ce97d4
@ -10,7 +10,7 @@
|
||||
"importer": "model_importer",
|
||||
"import_settings": {},
|
||||
"dependency_guids": [],
|
||||
"updated_at": "2026-03-18 18:31:18",
|
||||
"updated_at": "2026-03-19 10:14:56",
|
||||
"imported_cache": {
|
||||
"root": "Library/Imported/90ece77e67b54ccda38d2de71cb4694d",
|
||||
"model_bam": "Library/Imported/90ece77e67b54ccda38d2de71cb4694d/model.bam",
|
||||
|
||||
@ -3,5 +3,5 @@
|
||||
"asset_path": "Assets/Models/box1.glb",
|
||||
"asset_type": "model",
|
||||
"source_hash": "fc694905c47a9b0005d77b701cc41852b56ef08c7406829a306e98f3ce158a64",
|
||||
"generated_at": "2026-03-18 18:31:18"
|
||||
"generated_at": "2026-03-19 10:14:56"
|
||||
}
|
||||
@ -14,13 +14,22 @@ import time
|
||||
|
||||
class ResourceManager:
|
||||
"""ImGui资源管理器类"""
|
||||
|
||||
DEFAULT_ASSET_SUBDIRS = (
|
||||
"Models",
|
||||
"Textures",
|
||||
"Audio",
|
||||
"Video",
|
||||
"UI",
|
||||
"Scripts",
|
||||
)
|
||||
|
||||
def __init__(self, world):
|
||||
self.world = world
|
||||
self.project_root = Path(__file__).resolve().parent.parent
|
||||
self.project_path: Optional[Path] = None
|
||||
|
||||
# 当前浏览路径,默认从Resources目录开始
|
||||
# 当前浏览路径,默认从统一的 Assets 结构开始
|
||||
self.current_path = self._get_default_root_path()
|
||||
|
||||
# 历史记录,用于前进后退导航
|
||||
@ -63,15 +72,29 @@ class ResourceManager:
|
||||
assets_root = Path(current_project_path) / "Assets"
|
||||
elif self.project_path:
|
||||
assets_root = self.project_path / "Assets"
|
||||
else:
|
||||
assets_root = self.project_root / "Assets"
|
||||
|
||||
if assets_root and assets_root.exists():
|
||||
return assets_root.resolve()
|
||||
if assets_root:
|
||||
self._ensure_assets_structure(assets_root)
|
||||
if assets_root.exists():
|
||||
return assets_root.resolve()
|
||||
|
||||
legacy_resources = self.project_root / "Resources"
|
||||
if legacy_resources.exists():
|
||||
return legacy_resources.resolve()
|
||||
return self.project_root.resolve()
|
||||
|
||||
def _ensure_assets_structure(self, assets_root: Path):
|
||||
"""确保资源浏览器默认使用统一的 Assets 目录结构。"""
|
||||
try:
|
||||
assets_root.mkdir(parents=True, exist_ok=True)
|
||||
for subdir in self.DEFAULT_ASSET_SUBDIRS:
|
||||
(assets_root / subdir).mkdir(parents=True, exist_ok=True)
|
||||
except OSError:
|
||||
# 目录创建失败时,保留后续兼容回退逻辑。
|
||||
pass
|
||||
|
||||
def set_project_path(self, project_path: str):
|
||||
self.project_path = Path(project_path).resolve() if project_path else None
|
||||
self.current_path = self._get_default_root_path()
|
||||
|
||||
@ -189,6 +189,9 @@ class SelectionSystem:
|
||||
node = ssbo_editor.get_selection_scene_node()
|
||||
if self._is_valid_node(node, require_attached=True):
|
||||
return node
|
||||
fallback_model = getattr(ssbo_editor, "model", None)
|
||||
if self._is_valid_node(fallback_model, require_attached=True):
|
||||
return fallback_model
|
||||
return None
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@ -84,12 +84,12 @@ Size=400,300
|
||||
Collapsed=0
|
||||
|
||||
[Window][选择路径]
|
||||
Pos=724,302
|
||||
Pos=980,446
|
||||
Size=600,500
|
||||
Collapsed=0
|
||||
|
||||
[Window][打开项目]
|
||||
Pos=774,352
|
||||
Pos=1030,496
|
||||
Size=500,400
|
||||
Collapsed=0
|
||||
|
||||
@ -206,7 +206,7 @@ Collapsed=0
|
||||
DockId=0x00000005,2
|
||||
|
||||
[Window][项目另存为]
|
||||
Pos=794,432
|
||||
Pos=1050,576
|
||||
Size=460,240
|
||||
Collapsed=0
|
||||
|
||||
@ -220,7 +220,7 @@ DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,20 Size=2048,1084 Split=
|
||||
DockNode ID=0x00000001 Parent=0x08BD597D SizeRef=1525,1012 Split=X
|
||||
DockNode ID=0x00000007 Parent=0x00000001 SizeRef=274,1084 Selected=0xE0015051
|
||||
DockNode ID=0x00000008 Parent=0x00000001 SizeRef=1249,1084 Split=Y
|
||||
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=2048,610 Split=Y
|
||||
DockNode ID=0x00000005 Parent=0x00000008 SizeRef=2048,970 Split=Y
|
||||
DockNode ID=0x0000000D Parent=0x00000005 SizeRef=1318,383 HiddenTabBar=1 Selected=0x43A39006
|
||||
DockNode ID=0x0000000E Parent=0x00000005 SizeRef=1318,363 CentralNode=1 Selected=0xE0015051
|
||||
DockNode ID=0x00000006 Parent=0x00000008 SizeRef=2048,400 Selected=0x3A2E05C3
|
||||
|
||||
@ -899,6 +899,50 @@ class SSBOEditor:
|
||||
self._rebuild_or_clear_runtime_from_current_source()
|
||||
return target
|
||||
|
||||
def delete_selected_source_node(self):
|
||||
"""Delete the current SSBO selection from source_model_root and rebuild runtime."""
|
||||
if not self.controller or self.selected_name is None:
|
||||
return False
|
||||
|
||||
target = self._resolve_source_node_by_tree_key(self.selected_name)
|
||||
if not self._node_is_valid(target):
|
||||
return False
|
||||
|
||||
source_root = self._ensure_source_model_root()
|
||||
if target == source_root:
|
||||
children = self._get_source_root_children()
|
||||
if not children:
|
||||
return False
|
||||
if self.controller and self.model:
|
||||
self._snapshot_top_level_transforms_to_source_root()
|
||||
self._clear_runtime_state(preserve_source_models=True)
|
||||
for child in children:
|
||||
try:
|
||||
child.detach_node()
|
||||
except Exception:
|
||||
try:
|
||||
child.detachNode()
|
||||
except Exception:
|
||||
continue
|
||||
self.clear_selection(sync_world_selection=False)
|
||||
self._rebuild_or_clear_runtime_from_current_source()
|
||||
return True
|
||||
|
||||
if self.controller and self.model:
|
||||
self._snapshot_top_level_transforms_to_source_root()
|
||||
self._clear_runtime_state(preserve_source_models=True)
|
||||
try:
|
||||
target.detach_node()
|
||||
except Exception:
|
||||
try:
|
||||
target.detachNode()
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
self.clear_selection(sync_world_selection=False)
|
||||
self._rebuild_or_clear_runtime_from_current_source()
|
||||
return True
|
||||
|
||||
def attach_source_child(self, child_np, highlight_root_name=None):
|
||||
if not self._node_is_valid(child_np):
|
||||
return None
|
||||
|
||||
@ -1003,6 +1003,42 @@ class AppActions:
|
||||
ssbo_editor = getattr(self, "ssbo_editor", None)
|
||||
ssbo_model = getattr(ssbo_editor, "model", None) if ssbo_editor else None
|
||||
deleting_ssbo_root = bool(ssbo_model and (node == ssbo_model))
|
||||
deleting_ssbo_selection = bool(
|
||||
ssbo_editor and
|
||||
hasattr(ssbo_editor, "has_active_selection") and
|
||||
ssbo_editor.has_active_selection()
|
||||
)
|
||||
|
||||
if deleting_ssbo_selection and hasattr(ssbo_editor, "delete_selected_source_node"):
|
||||
deleted = bool(ssbo_editor.delete_selected_source_node())
|
||||
if deleted:
|
||||
scene_manager = getattr(self, "scene_manager", None)
|
||||
if scene_manager and hasattr(scene_manager, "models"):
|
||||
rebuilt_model = getattr(ssbo_editor, "model", None)
|
||||
scene_manager.models = []
|
||||
if rebuilt_model and not rebuilt_model.isEmpty():
|
||||
scene_manager.models.append(rebuilt_model)
|
||||
print(f"[SSBO] 已从源场景树删除当前选择并重建: {node_name}")
|
||||
return True
|
||||
|
||||
if deleting_ssbo_root and ssbo_editor and hasattr(ssbo_editor, "detach_source_child"):
|
||||
detached = ssbo_editor.detach_source_child(child_name=node_name)
|
||||
scene_manager = getattr(self, "scene_manager", None)
|
||||
if scene_manager and hasattr(scene_manager, "models"):
|
||||
scene_manager.models = [
|
||||
model for model in scene_manager.models
|
||||
if model and not model.isEmpty() and model != node
|
||||
]
|
||||
rebuilt_model = getattr(ssbo_editor, "model", None)
|
||||
if rebuilt_model and not rebuilt_model.isEmpty() and rebuilt_model not in scene_manager.models:
|
||||
scene_manager.models.append(rebuilt_model)
|
||||
if detached is not None:
|
||||
try:
|
||||
ssbo_editor.clear_selection(sync_world_selection=False)
|
||||
except Exception:
|
||||
pass
|
||||
print(f"[SSBO] 已从源模型树移除并重建运行时: {node_name}")
|
||||
return True
|
||||
|
||||
# 创建删除命令
|
||||
if hasattr(self, 'command_manager') and self.command_manager:
|
||||
|
||||
@ -212,9 +212,11 @@ class EditorPanelsLeftMixin:
|
||||
|
||||
for i, model in enumerate(models):
|
||||
if ssbo_model and controller and model == ssbo_model:
|
||||
for child_key in self._get_ssbo_top_level_model_keys():
|
||||
self._draw_ssbo_virtual_tree_node(ssbo_editor, controller, child_key)
|
||||
continue
|
||||
top_level_keys = self._get_ssbo_top_level_model_keys()
|
||||
if top_level_keys:
|
||||
for child_key in top_level_keys:
|
||||
self._draw_ssbo_virtual_tree_node(ssbo_editor, controller, child_key)
|
||||
continue
|
||||
self._draw_scene_node(model, model.getName() or f"模型_{i + 1}", "model")
|
||||
imgui.tree_pop()
|
||||
elif not render_entries and not camera_entries and not model_display_count and self._get_scene_tree_filter():
|
||||
@ -403,6 +405,12 @@ class EditorPanelsLeftMixin:
|
||||
ssbo_editor.select_node(key)
|
||||
if hasattr(self.app, "lui_manager"):
|
||||
self.app.lui_manager.selected_index = -1
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_clicked(1):
|
||||
try:
|
||||
ssbo_editor.select_node(key)
|
||||
except Exception:
|
||||
pass
|
||||
self._show_node_context_menu(getattr(ssbo_editor, "model", None), display, "model")
|
||||
else:
|
||||
# Branch node: tree node
|
||||
flags = imgui.TreeNodeFlags_.open_on_arrow
|
||||
@ -414,6 +422,12 @@ class EditorPanelsLeftMixin:
|
||||
ssbo_editor.select_node(key)
|
||||
if hasattr(self.app, "lui_manager"):
|
||||
self.app.lui_manager.selected_index = -1
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_clicked(1):
|
||||
try:
|
||||
ssbo_editor.select_node(key)
|
||||
except Exception:
|
||||
pass
|
||||
self._show_node_context_menu(getattr(ssbo_editor, "model", None), display, "model")
|
||||
if opened:
|
||||
for child_key in children:
|
||||
self._draw_ssbo_virtual_tree_node(ssbo_editor, controller, child_key)
|
||||
|
||||
@ -30,6 +30,9 @@ class PanelDelegates:
|
||||
ssbo_node = ssbo_editor.get_selection_scene_node()
|
||||
if ssbo_node and self._node_is_valid(ssbo_node, require_attached=False):
|
||||
return ssbo_node
|
||||
fallback_model = getattr(ssbo_editor, "model", None)
|
||||
if fallback_model and self._node_is_valid(fallback_model, require_attached=False):
|
||||
return fallback_model
|
||||
return None
|
||||
|
||||
selection = getattr(self, "selection", None)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user