This commit is contained in:
Rowland 2026-01-19 09:46:16 +08:00
parent 9424ddd0c2
commit 35cecd6008
2 changed files with 693 additions and 53 deletions

687
demo.py
View File

@ -11,6 +11,7 @@ import p3dimgui
from imgui_bundle import imgui, imgui_ctx
import sys
import os
import warnings
# 导入MyWorld类和必要的模块
@ -45,6 +46,12 @@ class MyWorld(CoreWorld):
def __init__(self):
super().__init__()
# 设置窗口为最大化模式
props = WindowProperties()
props.set_maximized(True)
self.win.request_properties(props)
print("✓ 窗口已设置为最大化模式")
# 初始化选择和变换系统
self.selection = SelectionSystem(self)
@ -187,7 +194,7 @@ class MyWorld(CoreWorld):
# Disable the camera trackball controls.
self.disableMouse()
self.showDemoWindow = True
self.showDemoWindow = False
# UI状态管理
self.showSceneTree = True
@ -196,12 +203,55 @@ class MyWorld(CoreWorld):
self.showScriptPanel = True
self.showToolbar = True
# 菜单状态管理
self.show_new_project_dialog = False
self.show_open_project_dialog = False
self.show_save_as_dialog = False
# 路径选择对话框状态
self.show_path_browser = False
self.path_browser_mode = "" # "new_project" 或 "open_project"
self.path_browser_current_path = os.getcwd()
self.path_browser_selected_path = ""
self.path_browser_items = []
# 快捷键映射
self.shortcut_keys = {
'Ctrl+N': self._on_new_project,
'Ctrl+O': self._on_open_project,
'Ctrl+S': self._on_save_project,
'Alt+F4': self._on_exit
}
# 键盘状态跟踪
self.ctrl_pressed = False
self.alt_pressed = False
# 消息系统
self.messages = []
self.max_messages = 5 # 最多显示5条消息
self.accept('imgui-new-frame', self.__newFrame)
self.accept('`', self.__toggleImgui)
# 添加键盘事件监听用于快捷键
self.accept('control', self._on_ctrl_pressed)
self.accept('control-up', self._on_ctrl_released)
self.accept('alt', self._on_alt_pressed)
self.accept('alt-up', self._on_alt_released)
self.accept('n', self._on_n_pressed)
self.accept('o', self._on_o_pressed)
self.accept('s', self._on_s_pressed)
self.accept('f4', self._on_f4_pressed)
self.testTexture = None
self.icons = {} # 初始化图标字典
# 添加初始化消息
self.add_success_message("MyWorld 初始化完成")
self.add_info_message("ImGui菜单系统已就绪")
self.add_info_message("快捷键已启用 (Ctrl+N, Ctrl+O, Ctrl+S, Alt+F4)")
print("✓ MyWorld 初始化完成")
# ==================== 兼容性属性 ====================
@ -331,6 +381,8 @@ class MyWorld(CoreWorld):
'scale': self.style_manager.load_icon('scale_tool'),
'success': self.style_manager.load_icon('success_icon'),
'warning': self.style_manager.load_icon('warning_icon'),
'property_select_image': self.style_manager.load_icon('property_select_image'),
'delete_fail_icon': self.style_manager.load_icon('delete_fail_icon'),
}
# 确保中文字体被正确应用
@ -386,6 +438,11 @@ class MyWorld(CoreWorld):
# 绘制ImGui演示窗口
if self.showDemoWindow:
imgui.show_demo_window()
# 绘制对话框
self._draw_new_project_dialog()
self._draw_open_project_dialog()
self._draw_path_browser()
def _draw_docked_layout(self, window_width, window_height):
"""绘制可停靠的布局(支持拖拽)"""
@ -418,13 +475,18 @@ class MyWorld(CoreWorld):
# 文件菜单
with imgui_ctx.begin_menu("文件") as file_menu:
if file_menu:
imgui.menu_item("新建项目", "Ctrl+N", False, True)
imgui.menu_item("打开项目", "Ctrl+O", False, True)
if imgui.menu_item("新建项目", "Ctrl+N", False, True)[1]:
self._on_new_project()
if imgui.menu_item("打开项目", "Ctrl+O", False, True)[1]:
self._on_open_project()
imgui.separator()
imgui.menu_item("保存", "Ctrl+S", False, True)
imgui.menu_item("另存为", "", False, True)
if imgui.menu_item("保存", "Ctrl+S", False, True)[1]:
self._on_save_project()
if imgui.menu_item("另存为", "", False, True)[1]:
self._on_save_as_project()
imgui.separator()
imgui.menu_item("退出", "Alt+F4", False, True)
if imgui.menu_item("退出", "Alt+F4", False, True)[1]:
self._on_exit()
# 编辑菜单
with imgui_ctx.begin_menu("编辑") as edit_menu:
@ -611,37 +673,41 @@ class MyWorld(CoreWorld):
imgui.text("控制台输出")
imgui.separator()
# 模拟控制台输出
if self.icons.get('success'):
imgui.image(self.icons['success'], (12, 12))
# 显示消息系统中的消息
if hasattr(self, 'messages') and self.messages:
for message in self.messages:
# 显示时间戳
imgui.text_colored((0.7, 0.7, 0.7, 1.0), f"[{message['timestamp']}]")
imgui.same_line()
# 根据消息类型显示图标
if message['text'].startswith(''):
if self.icons.get('success'):
imgui.image(self.icons['success'], (12, 12))
imgui.same_line()
elif message['text'].startswith(''):
if self.icons.get('delete_fail_icon'):
imgui.image(self.icons['delete_fail_icon'], (12, 12))
imgui.same_line()
elif message['text'].startswith(''):
if self.icons.get('warning'):
imgui.image(self.icons['warning'], (12, 12))
imgui.same_line()
# 显示消息文本
imgui.text_colored(message['color'], message['text'])
else:
# 默认消息
imgui.text_colored((0.157, 0.620, 1.0, 1.0), "[系统]")
imgui.same_line()
imgui.text_colored((0.176, 1.0, 0.769, 1.0), "[INFO]") # 成功颜色
imgui.same_line()
imgui.text("引擎初始化完成")
imgui.text_colored((0.157, 0.620, 1.0, 1.0), "[INFO]") # 信息颜色
imgui.same_line()
imgui.text("渲染管线已加载")
if self.icons.get('warning'):
imgui.image(self.icons['warning'], (12, 12))
imgui.same_line()
imgui.text_colored((0.953, 0.616, 0.471, 1.0), "[WARN]") # 警告颜色
imgui.same_line()
imgui.text("视频管理器模块未找到")
if self.icons.get('success'):
imgui.image(self.icons['success'], (12, 12))
imgui.same_line()
imgui.text_colored((0.176, 1.0, 0.769, 1.0), "[INFO]") # 成功颜色
imgui.same_line()
imgui.text("VR管理器初始化完成")
imgui.text("引擎已就绪")
# 输入框
imgui.separator()
changed, command = imgui.input_text(">", "", 256)
if changed and command:
print(f"执行命令: {command}")
self.add_info_message(f"执行命令: {command}")
# TODO: 实现命令执行逻辑
def _draw_script_panel(self):
"""绘制脚本管理面板"""
@ -682,6 +748,565 @@ class MyWorld(CoreWorld):
imgui.text("脚本输出:")
imgui.text("脚本引擎已启动")
imgui.text("热重载监控已启动")
# ==================== 菜单处理函数 ====================
def _on_new_project(self):
"""处理新建项目菜单项"""
self.add_info_message("打开新建项目对话框")
self.show_new_project_dialog = True
def _on_open_project(self):
"""处理打开项目菜单项"""
self.add_info_message("打开项目对话框")
self.show_open_project_dialog = True
def _on_save_project(self):
"""处理保存项目菜单项"""
if hasattr(self, 'project_manager') and self.project_manager:
try:
# 检查是否有当前项目路径
if not self.project_manager.current_project_path:
self.add_warning_message("没有当前项目路径,请先创建或打开项目")
self.show_save_as_dialog = True
return
# 直接调用保存逻辑避免Qt依赖
if self._save_project_impl():
self.add_success_message("项目保存成功")
else:
self.add_error_message("项目保存失败")
except Exception as e:
self.add_error_message(f"项目保存失败: {e}")
else:
self.add_error_message("项目管理器未初始化")
def _on_save_as_project(self):
"""处理另存为项目菜单项"""
self.add_info_message("另存为项目(功能待实现)")
# TODO: 实现另存为对话框
# self.show_save_as_dialog = True
def _on_exit(self):
"""处理退出菜单项"""
self.add_info_message("退出应用程序")
self.userExit()
# ==================== 键盘事件处理函数 ====================
def _on_ctrl_pressed(self):
"""Ctrl键按下"""
self.ctrl_pressed = True
def _on_ctrl_released(self):
"""Ctrl键释放"""
self.ctrl_pressed = False
def _on_alt_pressed(self):
"""Alt键按下"""
self.alt_pressed = True
def _on_alt_released(self):
"""Alt键释放"""
self.alt_pressed = False
def _on_n_pressed(self):
"""N键按下 - 检查Ctrl+N组合键"""
if self.ctrl_pressed:
self._on_new_project()
def _on_o_pressed(self):
"""O键按下 - 检查Ctrl+O组合键"""
if self.ctrl_pressed:
self._on_open_project()
def _on_s_pressed(self):
"""S键按下 - 检查Ctrl+S组合键"""
if self.ctrl_pressed:
self._on_save_project()
def _on_f4_pressed(self):
"""F4键按下 - 检查Alt+F4组合键"""
if self.alt_pressed:
self._on_exit()
# ==================== 消息系统 ====================
def add_message(self, text, color=(1.0, 1.0, 1.0, 1.0)):
"""添加消息到消息列表"""
import datetime
timestamp = datetime.datetime.now().strftime("%H:%M:%S")
self.messages.append({
'text': text,
'color': color,
'timestamp': timestamp
})
# 限制消息数量
if len(self.messages) > self.max_messages:
self.messages = self.messages[-self.max_messages:]
def add_success_message(self, text):
"""添加成功消息"""
self.add_message(f"{text}", (0.176, 1.0, 0.769, 1.0))
def add_error_message(self, text):
"""添加错误消息"""
self.add_message(f"{text}", (1.0, 0.3, 0.3, 1.0))
def add_warning_message(self, text):
"""添加警告消息"""
self.add_message(f"{text}", (0.953, 0.616, 0.471, 1.0))
def add_info_message(self, text):
"""添加信息消息"""
self.add_message(f" {text}", (0.157, 0.620, 1.0, 1.0))
# ==================== 对话框绘制函数 ====================
def _draw_new_project_dialog(self):
"""绘制新建项目对话框"""
if not self.show_new_project_dialog:
return
# 初始化默认值
if not hasattr(self, 'new_project_name'):
self.new_project_name = "新项目"
if not hasattr(self, 'new_project_path'):
self.new_project_path = "./projects/"
# 设置对话框标志
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
# 获取屏幕尺寸,居中显示对话框
display_size = imgui.get_io().display_size
dialog_width = 400
dialog_height = 300
imgui.set_next_window_size((dialog_width, dialog_height))
imgui.set_next_window_pos(
((display_size.x - dialog_width) / 2, (display_size.y - dialog_height) / 2)
)
with imgui_ctx.begin("新建项目", True, flags) as window:
if not window.opened:
self.show_new_project_dialog = False
return
imgui.text("创建新项目")
imgui.separator()
# 项目名称输入
changed, project_name = imgui.input_text("项目名称", self.new_project_name, 256)
if changed:
self.new_project_name = project_name
# 项目路径输入
changed, project_path = imgui.input_text("项目路径", self.new_project_path, 256)
if changed:
self.new_project_path = project_path
imgui.same_line()
if imgui.button("浏览..."):
self.path_browser_mode = "new_project"
self.path_browser_current_path = os.path.dirname(self.new_project_path) if self.new_project_path else os.getcwd()
self.show_path_browser = True
self._refresh_path_browser()
imgui.separator()
# 按钮区域
if imgui.button("创建"):
if self.new_project_name and self.new_project_path:
self._create_new_project(self.new_project_name, self.new_project_path)
self.show_new_project_dialog = False
imgui.same_line()
if imgui.button("取消"):
self.show_new_project_dialog = False
def _draw_open_project_dialog(self):
"""绘制打开项目对话框"""
if not self.show_open_project_dialog:
return
# 初始化默认值
if not hasattr(self, 'open_project_path'):
self.open_project_path = "./projects/"
# 设置对话框标志
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
# 获取屏幕尺寸,居中显示对话框
display_size = imgui.get_io().display_size
dialog_width = 500
dialog_height = 400
imgui.set_next_window_size((dialog_width, dialog_height))
imgui.set_next_window_pos(
((display_size.x - dialog_width) / 2, (display_size.y - dialog_height) / 2)
)
with imgui_ctx.begin("打开项目", True, flags) as window:
if not window.opened:
self.show_open_project_dialog = False
return
imgui.text("选择项目")
imgui.separator()
imgui.text("项目路径:")
changed, project_path = imgui.input_text("##project_path", self.open_project_path, 512)
if changed:
self.open_project_path = project_path
imgui.same_line()
if imgui.button("浏览..."):
self.path_browser_mode = "open_project"
self.path_browser_current_path = self.open_project_path if self.open_project_path else os.getcwd()
self.show_path_browser = True
self._refresh_path_browser()
imgui.separator()
# 按钮区域
if imgui.button("打开"):
if self.open_project_path:
self._open_project_path(self.open_project_path)
self.show_open_project_dialog = False
imgui.same_line()
if imgui.button("取消"):
self.show_open_project_dialog = False
def _draw_path_browser(self):
"""绘制路径选择对话框"""
if not self.show_path_browser:
return
# 设置对话框标志
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
# 获取屏幕尺寸,居中显示对话框
display_size = imgui.get_io().display_size
dialog_width = 600
dialog_height = 500
imgui.set_next_window_size((dialog_width, dialog_height))
imgui.set_next_window_pos(
((display_size.x - dialog_width) / 2, (display_size.y - dialog_height) / 2)
)
with imgui_ctx.begin("选择路径", True, flags) as window:
if not window.opened:
self.show_path_browser = False
return
imgui.text("选择路径")
imgui.separator()
# 当前路径显示
imgui.text("当前路径:")
imgui.same_line()
imgui.text_colored((0.7, 0.7, 0.7, 1.0), self.path_browser_current_path)
imgui.separator()
# 路径导航按钮
if imgui.button("上级目录"):
parent_path = os.path.dirname(self.path_browser_current_path)
if parent_path != self.path_browser_current_path:
self.path_browser_current_path = parent_path
self._refresh_path_browser()
imgui.same_line()
if imgui.button("主目录"):
self.path_browser_current_path = os.path.expanduser("~")
self._refresh_path_browser()
imgui.same_line()
if imgui.button("当前目录"):
self.path_browser_current_path = os.getcwd()
self._refresh_path_browser()
imgui.separator()
# 文件和目录列表
if self.path_browser_items:
# 先显示目录
for item in self.path_browser_items:
if item['is_dir']:
# 尝试使用图标或文本标识目录
if self.icons.get('property_select_image'): # 使用现有图标作为文件夹图标
imgui.image(self.icons['property_select_image'], (16, 16))
imgui.same_line()
else:
imgui.text_colored((0.4, 0.6, 1.0, 1.0), ">")
imgui.same_line()
if imgui.selectable(item['name'], False)[0]:
self.path_browser_current_path = item['path']
self._refresh_path_browser()
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
self.path_browser_current_path = item['path']
self._refresh_path_browser()
# 显示文件(仅在打开项目模式下显示.json文件
if self.path_browser_mode == "open_project":
for item in self.path_browser_items:
if not item['is_dir'] and item['name'].endswith('.json'):
# 尝试使用图标或文本标识文件
if self.icons.get('success_icon'): # 使用成功图标作为文件图标
imgui.image(self.icons['success_icon'], (16, 16))
imgui.same_line()
else:
imgui.text_colored((1.0, 0.8, 0.4, 1.0), "-")
imgui.same_line()
if imgui.selectable(item['name'], False)[0]:
self.path_browser_selected_path = item['path']
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
# 选择包含project.json的目录
self.path_browser_current_path = os.path.dirname(item['path'])
self._apply_selected_path()
imgui.separator()
# 选中路径显示
if self.path_browser_selected_path:
imgui.text("选中路径:")
imgui.same_line()
imgui.text_colored((0.7, 0.7, 0.7, 1.0), self.path_browser_selected_path)
# 按钮区域
if imgui.button("确定"):
self._apply_selected_path()
self.show_path_browser = False
imgui.same_line()
if imgui.button("取消"):
self.show_path_browser = False
def _create_new_project(self, name, path):
"""创建新项目的实际实现"""
if not hasattr(self, 'project_manager') or not self.project_manager:
print("✗ 项目管理器未初始化")
return
try:
if self._create_new_project_impl(name, path):
print(f"✓ 项目创建成功: {name}")
else:
print(f"✗ 项目创建失败: {name}")
except Exception as e:
print(f"✗ 项目创建失败: {e}")
def _open_project_path(self, path):
"""打开项目的实际实现"""
if not hasattr(self, 'project_manager') or not self.project_manager:
print("✗ 项目管理器未初始化")
return
try:
print(f"打开项目: {path}")
if self._open_project_impl(path):
print(f"✓ 项目打开成功: {path}")
else:
print(f"✗ 项目打开失败: {path}")
except Exception as e:
print(f"✗ 项目打开失败: {e}")
# ==================== 项目管理具体实现 ====================
def _save_project_impl(self):
"""保存项目的具体实现不依赖Qt"""
import json
import datetime
import os
project_path = self.project_manager.current_project_path
scenes_path = os.path.join(project_path, "scenes")
# 固定的场景文件名
scene_file = os.path.join(scenes_path, "scene.bam")
# 如果存在旧文件,先删除
if os.path.exists(scene_file):
try:
os.remove(scene_file)
print(f"已删除旧场景文件: {scene_file}")
except Exception as e:
print(f"删除旧场景文件失败: {str(e)}")
return False
# 保存场景
if self.scene_manager.saveScene(scene_file, project_path):
# 更新项目配置文件
config_file = os.path.join(project_path, "project.json")
if os.path.exists(config_file):
with open(config_file, "r", encoding="utf-8") as f:
project_config = json.load(f)
# 更新最后修改时间
project_config["last_modified"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 记录场景文件路径
project_config["scene_file"] = os.path.relpath(scene_file, project_path)
with open(config_file, "w", encoding="utf-8") as f:
json.dump(project_config, f, ensure_ascii=False, indent=4)
# 更新项目配置
self.project_manager.project_config = project_config
return True
return False
def _open_project_impl(self, project_path):
"""打开项目的具体实现不依赖Qt"""
import json
import datetime
import os
# 检查是否是有效的项目文件夹
config_file = os.path.join(project_path, "project.json")
if not os.path.exists(config_file):
print(f"⚠ 选择的不是有效的项目文件夹: {project_path}")
return False
# 读取项目配置
with open(config_file, "r", encoding="utf-8") as f:
project_config = json.load(f)
# 检查场景文件
scene_file = os.path.join(project_path, "scenes", "scene.bam")
if os.path.exists(scene_file):
# 加载场景
if self.scene_manager.loadScene(scene_file):
# 更新项目配置
project_config["scene_file"] = os.path.relpath(scene_file, project_path)
project_config["last_modified"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(config_file, "w", encoding="utf-8") as f:
json.dump(project_config, f, ensure_ascii=False, indent=4)
# 更新项目状态
self.project_manager.current_project_path = project_path
self.project_manager.project_config = project_config
# 更新窗口标题
project_name = os.path.basename(project_path)
self._update_window_title(project_name)
return True
def _create_new_project_impl(self, name, path):
"""创建新项目的具体实现不依赖Qt"""
import json
import datetime
import os
full_project_path = os.path.normpath(os.path.join(path, name))
print(f"创建项目路径: {full_project_path}")
try:
# 创建项目文件夹结构
os.makedirs(full_project_path)
os.makedirs(os.path.join(full_project_path, "models")) # 模型文件夹
os.makedirs(os.path.join(full_project_path, "textures")) # 贴图文件夹
scenes_path = os.path.join(full_project_path, "scenes") # 场景文件夹
os.makedirs(scenes_path)
# 创建项目配置文件
project_config = {
"name": name,
"path": full_project_path,
"created": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"last_modified": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"version": "1.0",
"scene_file": "scenes/scene.bam"
}
# 保存项目配置
config_file = os.path.join(full_project_path, "project.json")
with open(config_file, "w", encoding="utf-8") as f:
json.dump(project_config, f, ensure_ascii=False, indent=4)
# 保存初始场景
scene_file = os.path.join(scenes_path, "scene.bam")
self.scene_manager.saveScene(scene_file, full_project_path)
# 更新项目管理器状态
self.project_manager.current_project_path = full_project_path
self.project_manager.project_config = project_config
# 更新窗口标题
self._update_window_title(name)
return True
except Exception as e:
print(f"创建项目失败: {e}")
return False
def _update_window_title(self, project_name):
"""更新窗口标题"""
try:
props = WindowProperties()
props.set_title(f"EG Engine - {project_name}")
self.win.request_properties(props)
print(f"窗口标题已更新: EG Engine - {project_name}")
except Exception as e:
print(f"更新窗口标题失败: {e}")
# ==================== 路径浏览器辅助方法 ====================
def _refresh_path_browser(self):
"""刷新路径浏览器内容"""
try:
self.path_browser_items = []
if not os.path.exists(self.path_browser_current_path):
self.add_error_message(f"路径不存在: {self.path_browser_current_path}")
return
# 获取目录中的所有项目
items = []
try:
for item_name in os.listdir(self.path_browser_current_path):
item_path = os.path.join(self.path_browser_current_path, item_name)
is_dir = os.path.isdir(item_path)
items.append({
'name': item_name,
'path': item_path,
'is_dir': is_dir
})
except PermissionError:
self.add_error_message(f"无法访问路径: {self.path_browser_current_path}")
return
# 排序:目录在前,文件在后,按名称排序
items.sort(key=lambda x: (not x['is_dir'], x['name'].lower()))
self.path_browser_items = items
except Exception as e:
self.add_error_message(f"刷新路径浏览器失败: {e}")
def _apply_selected_path(self):
"""应用选择的路径"""
try:
if self.path_browser_mode == "new_project":
# 新建项目模式:直接使用当前路径
self.new_project_path = self.path_browser_current_path
self.add_info_message(f"已选择项目路径: {self.new_project_path}")
elif self.path_browser_mode == "open_project":
# 打开项目模式:使用当前路径
self.open_project_path = self.path_browser_current_path
self.add_info_message(f"已选择项目路径: {self.open_project_path}")
except Exception as e:
self.add_error_message(f"应用路径失败: {e}")
demo = MyWorld()
demo.run()

View File

@ -20,36 +20,36 @@ Collapsed=0
[Window][Dear ImGui Demo]
Pos=241,149
Size=832,127
Size=832,45
Collapsed=0
[Window][工具栏]
Pos=287,20
Size=832,32
Size=1237,32
Collapsed=0
DockId=0x00000007,0
[Window][场景树]
Pos=0,20
Size=285,578
Size=285,861
Collapsed=0
DockId=0x00000001,0
[Window][属性面板]
Pos=1121,20
Size=259,214
Pos=1526,20
Size=324,498
Collapsed=0
DockId=0x00000005,0
[Window][控制台]
Pos=0,600
Size=1380,150
Pos=0,883
Size=1524,133
Collapsed=0
DockId=0x0000000A,0
[Window][脚本管理]
Pos=1121,236
Size=259,362
Pos=1526,520
Size=324,496
Collapsed=0
DockId=0x00000006,0
@ -60,7 +60,7 @@ Collapsed=0
[Window][WindowOverViewport_11111111]
Pos=0,20
Size=1380,730
Size=1850,996
Collapsed=0
[Window][测试窗口1]
@ -78,16 +78,31 @@ Pos=60,60
Size=93,65
Collapsed=0
[Docking][Data]
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,20 Size=1380,730 Split=Y
DockNode ID=0x00000009 Parent=0x08BD597D SizeRef=1380,578 Split=X
DockNode ID=0x00000003 Parent=0x00000009 SizeRef=1119,730 Split=X
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=285,730 HiddenTabBar=1 Selected=0xE0015051
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=832,730 Split=Y
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1380,32 HiddenTabBar=1 Selected=0x43A39006
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1380,696 CentralNode=1 Selected=0x5E5F7166
DockNode ID=0x00000004 Parent=0x00000009 SizeRef=259,730 Split=Y Selected=0x5DB6FF37
DockNode ID=0x00000005 Parent=0x00000004 SizeRef=259,270 HiddenTabBar=1 Selected=0x5DB6FF37
DockNode ID=0x00000006 Parent=0x00000004 SizeRef=259,458 HiddenTabBar=1 Selected=0x3188AB8D
DockNode ID=0x0000000A Parent=0x08BD597D SizeRef=1380,150 HiddenTabBar=1 Selected=0x5428E753
[Window][新建项目]
Pos=725,358
Size=400,300
Collapsed=0
[Window][选择路径]
Pos=625,258
Size=600,500
Collapsed=0
[Window][打开项目]
Pos=675,308
Size=500,400
Collapsed=0
[Docking][Data]
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=0,20 Size=1850,996 Split=X
DockNode ID=0x00000003 Parent=0x08BD597D SizeRef=1524,996 Split=Y
DockNode ID=0x00000009 Parent=0x00000003 SizeRef=1380,861 Split=X
DockNode ID=0x00000001 Parent=0x00000009 SizeRef=285,730 HiddenTabBar=1 Selected=0xE0015051
DockNode ID=0x00000002 Parent=0x00000009 SizeRef=1237,730 Split=Y
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1380,32 HiddenTabBar=1 Selected=0x43A39006
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1380,827 CentralNode=1 Selected=0x5E5F7166
DockNode ID=0x0000000A Parent=0x00000003 SizeRef=1380,133 HiddenTabBar=1 Selected=0x5428E753
DockNode ID=0x00000004 Parent=0x08BD597D SizeRef=324,996 Split=Y Selected=0x5DB6FF37
DockNode ID=0x00000005 Parent=0x00000004 SizeRef=304,498 HiddenTabBar=1 Selected=0x5DB6FF37
DockNode ID=0x00000006 Parent=0x00000004 SizeRef=304,496 HiddenTabBar=1 Selected=0x3188AB8D