修复拖动按钮闪退,保存和加载LUI信息
This commit is contained in:
parent
74b6a3307c
commit
bdd4d0f1b5
42
imgui.ini
42
imgui.ini
@ -25,25 +25,25 @@ Collapsed=0
|
||||
|
||||
[Window][工具栏]
|
||||
Pos=285,20
|
||||
Size=1190,62
|
||||
Size=1221,62
|
||||
Collapsed=0
|
||||
DockId=0x00000009,0
|
||||
|
||||
[Window][场景树]
|
||||
Pos=0,20
|
||||
Size=283,506
|
||||
Size=283,494
|
||||
Collapsed=0
|
||||
DockId=0x00000007,0
|
||||
|
||||
[Window][属性面板]
|
||||
Pos=1477,20
|
||||
Size=443,1012
|
||||
Pos=1508,20
|
||||
Size=412,360
|
||||
Collapsed=0
|
||||
DockId=0x0000000B,0
|
||||
|
||||
[Window][控制台]
|
||||
Pos=0,528
|
||||
Size=283,504
|
||||
Pos=0,516
|
||||
Size=283,493
|
||||
Collapsed=0
|
||||
DockId=0x00000008,0
|
||||
|
||||
@ -60,7 +60,7 @@ Collapsed=0
|
||||
|
||||
[Window][WindowOverViewport_11111111]
|
||||
Pos=0,20
|
||||
Size=1920,1012
|
||||
Size=1920,989
|
||||
Collapsed=0
|
||||
|
||||
[Window][测试窗口1]
|
||||
@ -84,12 +84,12 @@ Size=400,300
|
||||
Collapsed=0
|
||||
|
||||
[Window][选择路径]
|
||||
Pos=660,266
|
||||
Pos=660,254
|
||||
Size=600,500
|
||||
Collapsed=0
|
||||
|
||||
[Window][打开项目]
|
||||
Pos=710,316
|
||||
Pos=715,312
|
||||
Size=500,400
|
||||
Collapsed=0
|
||||
|
||||
@ -99,8 +99,8 @@ Size=600,500
|
||||
Collapsed=0
|
||||
|
||||
[Window][资源管理器]
|
||||
Pos=285,727
|
||||
Size=1190,305
|
||||
Pos=285,788
|
||||
Size=1221,221
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
@ -150,8 +150,8 @@ Size=101,226
|
||||
Collapsed=0
|
||||
|
||||
[Window][LUI编辑器]
|
||||
Pos=1477,749
|
||||
Size=443,283
|
||||
Pos=1508,382
|
||||
Size=412,627
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
|
||||
@ -212,17 +212,17 @@ Size=460,240
|
||||
Collapsed=0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,20 Size=1920,1012 Split=X
|
||||
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,20 Size=1920,989 Split=X
|
||||
DockNode ID=0x00000005 Parent=0x08BD597D SizeRef=283,1012 Split=Y Selected=0xE0015051
|
||||
DockNode ID=0x00000007 Parent=0x00000005 SizeRef=283,506 Selected=0xE0015051
|
||||
DockNode ID=0x00000008 Parent=0x00000005 SizeRef=283,504 Selected=0x5428E753
|
||||
DockNode ID=0x00000006 Parent=0x08BD597D SizeRef=1635,1012 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000006 SizeRef=1190,989 Split=Y
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1321,666 Split=Y
|
||||
DockNode ID=0x00000001 Parent=0x00000006 SizeRef=1221,989 Split=Y
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1321,789 Split=Y
|
||||
DockNode ID=0x00000009 Parent=0x00000003 SizeRef=1304,62 Selected=0x43A39006
|
||||
DockNode ID=0x0000000A Parent=0x00000003 SizeRef=1304,618 CentralNode=1
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1321,305 Selected=0x3A2E05C3
|
||||
DockNode ID=0x00000002 Parent=0x00000006 SizeRef=443,989 Split=Y Selected=0x5DB6FF37
|
||||
DockNode ID=0x0000000B Parent=0x00000002 SizeRef=443,727 Selected=0x5DB6FF37
|
||||
DockNode ID=0x0000000C Parent=0x00000002 SizeRef=443,283 Selected=0x1EB923B7
|
||||
DockNode ID=0x0000000A Parent=0x00000003 SizeRef=1304,725 CentralNode=1
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1321,221 Selected=0x3A2E05C3
|
||||
DockNode ID=0x00000002 Parent=0x00000006 SizeRef=412,989 Split=Y Selected=0x5DB6FF37
|
||||
DockNode ID=0x0000000B Parent=0x00000002 SizeRef=443,368 Selected=0x5DB6FF37
|
||||
DockNode ID=0x0000000C Parent=0x00000002 SizeRef=443,642 Selected=0x1EB923B7
|
||||
|
||||
|
||||
@ -299,8 +299,10 @@ class ProjectManager:
|
||||
temp_scene_file = os.path.join(scene_dir, f"{scene_name}.tmp{scene_ext}")
|
||||
final_gui_info_file = scene_file.replace('.bam', '_gui.json')
|
||||
temp_gui_info_file = temp_scene_file.replace('.bam', '_gui.json')
|
||||
final_lui_info_file = scene_file.replace('.bam', '_lui.json')
|
||||
temp_lui_info_file = temp_scene_file.replace('.bam', '_lui.json')
|
||||
|
||||
for temp_path in (temp_scene_file, temp_gui_info_file):
|
||||
for temp_path in (temp_scene_file, temp_gui_info_file, temp_lui_info_file):
|
||||
if os.path.exists(temp_path):
|
||||
try:
|
||||
os.remove(temp_path)
|
||||
@ -316,12 +318,15 @@ class ProjectManager:
|
||||
if os.path.exists(temp_gui_info_file):
|
||||
os.replace(temp_gui_info_file, final_gui_info_file)
|
||||
|
||||
if os.path.exists(temp_lui_info_file):
|
||||
os.replace(temp_lui_info_file, final_lui_info_file)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"原子保存场景失败: {e}")
|
||||
return False
|
||||
finally:
|
||||
for temp_path in (temp_scene_file, temp_gui_info_file):
|
||||
for temp_path in (temp_scene_file, temp_gui_info_file, temp_lui_info_file):
|
||||
if os.path.exists(temp_path):
|
||||
try:
|
||||
os.remove(temp_path)
|
||||
|
||||
@ -62,6 +62,104 @@ class SceneManagerIOMixin:
|
||||
except Exception as e:
|
||||
print(f"清理残留场景节点失败: {e}")
|
||||
|
||||
def _get_scene_sidecar_path(self, filename, suffix):
|
||||
scene_root, _ = os.path.splitext(os.path.normpath(filename))
|
||||
return f"{scene_root}{suffix}"
|
||||
|
||||
def _reset_lui_runtime_state(self, lui_manager):
|
||||
if lui_manager is None or getattr(lui_manager, "lui_enabled", True) is False:
|
||||
return True
|
||||
|
||||
apply_fn = getattr(lui_manager, "_apply_lui_structure_snapshot", None)
|
||||
if callable(apply_fn):
|
||||
try:
|
||||
apply_fn({})
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"清空LUI结构失败: {e}")
|
||||
return False
|
||||
|
||||
clear_fn = getattr(lui_manager, "_clear_lui_structure_runtime", None)
|
||||
if callable(clear_fn):
|
||||
try:
|
||||
clear_fn()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"清空LUI结构失败: {e}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _save_lui_snapshot_file(self, filename):
|
||||
lui_manager = getattr(self.world, "lui_manager", None)
|
||||
if lui_manager is None or getattr(lui_manager, "lui_enabled", True) is False:
|
||||
print("ℹ️ 当前会话未启用LUI,跳过LUI结构保存")
|
||||
return True
|
||||
|
||||
capture_fn = getattr(lui_manager, "_capture_lui_structure_snapshot", None)
|
||||
if not callable(capture_fn):
|
||||
print("ℹ️ 未找到LUI结构快照接口,跳过LUI结构保存")
|
||||
return True
|
||||
|
||||
try:
|
||||
snapshot = capture_fn() or {}
|
||||
lui_info_file = self._get_scene_sidecar_path(filename, "_lui.json")
|
||||
with open(lui_info_file, "w", encoding="utf-8") as f:
|
||||
json.dump(snapshot, f, ensure_ascii=False, indent=4)
|
||||
|
||||
canvas_count = len(snapshot.get("canvases", []) or [])
|
||||
component_count = len(snapshot.get("components", []) or [])
|
||||
print(
|
||||
f"✓ LUI信息已保存: {lui_info_file} "
|
||||
f"(Canvas: {canvas_count}, Components: {component_count})"
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"✗ 保存LUI信息失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def _load_lui_snapshot_file(self, filename):
|
||||
lui_manager = getattr(self.world, "lui_manager", None)
|
||||
if lui_manager is None or getattr(lui_manager, "lui_enabled", True) is False:
|
||||
print("ℹ️ 当前会话未启用LUI,跳过LUI结构恢复")
|
||||
return True
|
||||
|
||||
lui_info_file = self._get_scene_sidecar_path(filename, "_lui.json")
|
||||
apply_fn = getattr(lui_manager, "_apply_lui_structure_snapshot", None)
|
||||
|
||||
if not os.path.exists(lui_info_file):
|
||||
print("ℹ️ 未找到LUI信息文件,清空当前LUI结构")
|
||||
return self._reset_lui_runtime_state(lui_manager)
|
||||
|
||||
if not callable(apply_fn):
|
||||
print("ℹ️ 未找到LUI结构恢复接口,跳过LUI结构恢复")
|
||||
return True
|
||||
|
||||
try:
|
||||
with open(lui_info_file, "r", encoding="utf-8") as f:
|
||||
content = f.read().strip()
|
||||
|
||||
snapshot = json.loads(content) if content else {}
|
||||
apply_fn(snapshot)
|
||||
|
||||
canvas_count = len(snapshot.get("canvases", []) or [])
|
||||
component_count = len(snapshot.get("components", []) or [])
|
||||
print(
|
||||
f"✓ LUI信息已恢复: {lui_info_file} "
|
||||
f"(Canvas: {canvas_count}, Components: {component_count})"
|
||||
)
|
||||
return True
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"✗ LUI信息文件格式错误: {e}")
|
||||
except Exception as e:
|
||||
print(f"✗ 加载LUI信息失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
return self._reset_lui_runtime_state(lui_manager)
|
||||
|
||||
def _collectGUIElementInfo(self, gui_node):
|
||||
"""收集GUI元素的信息用于保存"""
|
||||
try:
|
||||
@ -594,6 +692,8 @@ class SceneManagerIOMixin:
|
||||
|
||||
if success:
|
||||
print(f"✓ 场景保存成功: {filename}")
|
||||
if not self._save_lui_snapshot_file(filename):
|
||||
return False
|
||||
else:
|
||||
print("✗ 场景保存失败")
|
||||
|
||||
@ -1529,6 +1629,8 @@ class SceneManagerIOMixin:
|
||||
else:
|
||||
print("ℹ️ 未找到GUI信息文件")
|
||||
|
||||
self._load_lui_snapshot_file(filename)
|
||||
|
||||
# 移除临时场景节点
|
||||
if not scene.isEmpty():
|
||||
scene.removeNode()
|
||||
|
||||
@ -324,7 +324,7 @@ class LUIFunctionPropertiesMixin:
|
||||
manager.luiFunction._draw_text_font_size_editor(manager, index, comp_data, comp_obj)
|
||||
|
||||
draw_color = manager.luiFunction._draw_text_color_editor(manager, index, comp_data)
|
||||
manager.luiFunction._sync_text_or_button_color(comp_obj, comp_type, draw_color)
|
||||
manager.luiFunction._sync_text_or_button_color(manager, comp_obj, comp_type, draw_color)
|
||||
|
||||
if comp_type == 'Button':
|
||||
manager.luiFunction._draw_button_texture_controls(manager, index, comp_data, comp_obj)
|
||||
@ -387,9 +387,9 @@ class LUIFunctionPropertiesMixin:
|
||||
def _sync_text_or_button_color(manager, comp_obj, comp_type, draw_color):
|
||||
# 保留原行为:每帧同步当前编辑色,避免按钮状态贴图切换后颜色不同步。
|
||||
if comp_type == 'Button':
|
||||
manager.luiFunction._apply_button_layout_color(comp_obj, draw_color)
|
||||
manager.luiFunction._apply_button_layout_color(manager, comp_obj, draw_color)
|
||||
else:
|
||||
manager.luiFunction._apply_text_color(comp_obj, draw_color)
|
||||
manager.luiFunction._apply_text_color(manager, comp_obj, draw_color)
|
||||
|
||||
imgui.separator()
|
||||
imgui.spacing()
|
||||
@ -436,7 +436,7 @@ class LUIFunctionPropertiesMixin:
|
||||
lambda: manager.luiFunction._clear_button_custom_textures(manager, comp_data, comp_obj),
|
||||
)
|
||||
|
||||
manager.luiFunction._draw_button_texture_path_labels(comp_data)
|
||||
manager.luiFunction._draw_button_texture_path_labels(manager, comp_data)
|
||||
|
||||
def _draw_button_texture_pick_button(manager, index, comp_data, comp_obj, button_label, variant):
|
||||
if not imgui.button(button_label, (160, 20)):
|
||||
@ -1382,7 +1382,7 @@ class LUIFunctionPropertiesMixin:
|
||||
if changed:
|
||||
manager._apply_component_change_with_history(
|
||||
index,
|
||||
lambda: manager.luiFunction._set_checkbox_checked(comp_data, comp_obj, new_checked),
|
||||
lambda: manager.luiFunction._set_checkbox_checked(manager, comp_data, comp_obj, new_checked),
|
||||
)
|
||||
|
||||
def _set_checkbox_checked(manager, comp_data, comp_obj, new_checked):
|
||||
@ -1497,7 +1497,7 @@ class LUIFunctionPropertiesMixin:
|
||||
sel_id = opt_ids[new_index]
|
||||
manager._apply_component_change_with_history(
|
||||
index,
|
||||
lambda: manager.luiFunction._set_selectbox_selected_option(comp_data, comp_obj, sel_id),
|
||||
lambda: manager.luiFunction._set_selectbox_selected_option(manager, comp_data, comp_obj, sel_id),
|
||||
)
|
||||
|
||||
imgui.spacing()
|
||||
@ -1526,7 +1526,7 @@ class LUIFunctionPropertiesMixin:
|
||||
if dirty:
|
||||
manager._apply_component_change_with_history(
|
||||
index,
|
||||
lambda: manager.luiFunction._apply_selectbox_options(comp_data, comp_obj, new_labels, current_selected),
|
||||
lambda: manager.luiFunction._apply_selectbox_options(manager, comp_data, comp_obj, new_labels, current_selected),
|
||||
)
|
||||
|
||||
def _set_selectbox_selected_option(manager, comp_data, comp_obj, selected_option_id):
|
||||
@ -1682,7 +1682,7 @@ class LUIFunctionPropertiesMixin:
|
||||
if imgui.button("清除音频", (90, 24)):
|
||||
manager._apply_component_change_with_history(
|
||||
index,
|
||||
lambda: manager.luiFunction._clear_audio_for_component(comp_data),
|
||||
lambda: manager.luiFunction._clear_audio_for_component(manager, comp_data),
|
||||
)
|
||||
|
||||
if imgui.button("Select Audio", (110, 24)):
|
||||
@ -1928,7 +1928,7 @@ class LUIFunctionPropertiesMixin:
|
||||
|
||||
def _clear_video_source(manager, comp_data, comp_obj=None):
|
||||
if comp_data.get("audio_from_video"):
|
||||
manager.luiFunction._clear_audio_for_component(comp_data)
|
||||
manager.luiFunction._clear_audio_for_component(manager, comp_data)
|
||||
manager.luiFunction._clear_video_audio_runtime(manager, comp_data)
|
||||
target_obj = comp_obj or comp_data.get("object")
|
||||
if target_obj is not None:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user