EG/ui/panels/dialog_panels.py
2026-02-25 11:49:31 +08:00

1462 lines
63 KiB
Python

import os
from imgui_bundle import imgui, imgui_ctx
class DialogPanels:
"""Project, import, and creation dialog panels."""
def __init__(self, app):
self.app = app
def __getattr__(self, name):
return getattr(self.app, name)
def __setattr__(self, name, value):
if name == "app" or name in self.__dict__ or hasattr(type(self), name):
object.__setattr__(self, name, value)
else:
setattr(self.app, name, value)
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()
# 显示文件(根据模式显示不同类型的文件)
if self.path_browser_mode == "open_project":
for item in self.path_browser_items:
if not item['is_dir'] and item['name'].endswith('.json'):
imgui.text_colored((1.0, 1.0, 0.7, 1.0), "[FILE]")
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()
elif self.path_browser_mode == "import_model":
for item in self.path_browser_items:
if not item['is_dir']:
file_ext = os.path.splitext(item['name'])[1].lower()
# 根据文件类型显示不同颜色
if file_ext in ['.gltf', '.glb']:
color = (0.7, 1.0, 0.7, 1.0) # 绿色 - glTF
elif file_ext == '.fbx':
color = (1.0, 0.7, 0.7, 1.0) # 红色 - FBX
elif file_ext in ['.bam', '.egg']:
color = (0.7, 0.7, 1.0, 1.0) # 蓝色 - Panda3D
elif file_ext == '.obj':
color = (1.0, 1.0, 0.7, 1.0) # 黄色 - OBJ
else:
color = (0.8, 0.8, 0.8, 1.0) # 灰色 - 其他
imgui.text_colored(color, f"[{file_ext[1:].upper()}]")
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):
self.path_browser_selected_path = 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 _draw_import_dialog(self):
"""绘制导入模型对话框"""
if not self.show_import_dialog:
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_import_dialog = False
return
imgui.text("选择要导入的模型文件")
imgui.separator()
# 文件路径输入
imgui.text("文件路径:")
changed, file_path = imgui.input_text("##import_file_path", self.import_file_path, 512)
if changed:
self.import_file_path = file_path
imgui.same_line()
if imgui.button("浏览..."):
self.path_browser_mode = "import_model"
self.path_browser_current_path = os.path.dirname(self.import_file_path) if self.import_file_path else os.getcwd()
self.show_path_browser = True
self._refresh_path_browser()
imgui.separator()
# 支持的格式说明
imgui.text("支持的文件格式:")
formats_text = ", ".join(self.supported_formats)
imgui.text_colored((0.7, 0.7, 0.7, 1.0), formats_text)
imgui.separator()
# 文件预览信息
if self.import_file_path and os.path.exists(self.import_file_path):
file_size = os.path.getsize(self.import_file_path)
imgui.text(f"文件大小: {file_size / 1024:.2f} KB")
file_ext = os.path.splitext(self.import_file_path)[1].lower()
if file_ext in self.supported_formats:
imgui.text_colored((0.176, 1.0, 0.769, 1.0), "✓ 文件格式支持")
else:
imgui.text_colored((1.0, 0.3, 0.3, 1.0), "✗ 不支持的文件格式")
else:
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "请选择有效的文件路径")
imgui.separator()
# 按钮区域
can_import = (self.import_file_path and
os.path.exists(self.import_file_path) and
os.path.splitext(self.import_file_path)[1].lower() in self.supported_formats)
# 根据状态设置按钮颜色
if can_import:
if imgui.button("导入"):
self._import_model()
self.show_import_dialog = False
else:
# 禁用状态的按钮(灰色显示)
imgui.push_style_color(imgui.Col_.button, (0.3, 0.3, 0.3, 1.0))
imgui.button("导入")
imgui.pop_style_color()
imgui.same_line()
if imgui.button("取消"):
self.show_import_dialog = False
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
# 根据模式过滤文件
if self.path_browser_mode == "import_model":
# 只显示支持的模型文件
filtered_items = []
for item in items:
if item['is_dir']:
filtered_items.append(item)
else:
file_ext = os.path.splitext(item['name'])[1].lower()
if file_ext in self.supported_formats:
filtered_items.append(item)
items = filtered_items
# 排序:目录在前,文件在后,按名称排序
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}")
elif self.path_browser_mode == "import_model":
# 导入模型模式:使用选择的文件路径
self.import_file_path = self.path_browser_selected_path
self.add_info_message(f"已选择文件: {self.import_file_path}")
except Exception as e:
self.add_error_message(f"应用路径失败: {e}")
# ==================== 创建功能对话框实现 ====================
def _draw_gui_button_dialog(self):
"""绘制GUI按钮创建对话框"""
if not self.show_gui_button_dialog:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("创建GUI按钮", self.show_gui_button_dialog, flags) as window:
if not window:
self.show_gui_button_dialog = False
return
# 初始化参数
if 'button_text' not in self.dialog_params:
self.dialog_params['button_text'] = "按钮"
if 'button_pos' not in self.dialog_params:
self.dialog_params['button_pos'] = [0.0, 0.0, 0.0]
if 'button_size' not in self.dialog_params:
self.dialog_params['button_size'] = [0.1, 0.1, 0.1]
imgui.text("GUI按钮参数设置")
imgui.separator()
# 文本输入
changed, self.dialog_params['button_text'] = imgui.input_text("按钮文本", self.dialog_params['button_text'], 256)
# 位置输入
changed, x = imgui.input_float("X坐标", self.dialog_params['button_pos'][0])
if changed:
self.dialog_params['button_pos'][0] = x
changed, y = imgui.input_float("Y坐标", self.dialog_params['button_pos'][1])
if changed:
self.dialog_params['button_pos'][1] = y
changed, z = imgui.input_float("Z坐标", self.dialog_params['button_pos'][2])
if changed:
self.dialog_params['button_pos'][2] = z
# 大小输入
changed, width = imgui.input_float("宽度", self.dialog_params['button_size'][0])
if changed:
self.dialog_params['button_size'][0] = width
changed, height = imgui.input_float("高度", self.dialog_params['button_size'][1])
if changed:
self.dialog_params['button_size'][1] = height
imgui.separator()
# 按钮
if imgui.button("创建"):
try:
pos = tuple(self.dialog_params['button_pos'])
text = self.dialog_params['button_text']
size = tuple(self.dialog_params['button_size'][:2])
result = self.createGUIButton(pos, text, size)
self.add_success_message(f"GUI按钮创建成功: {text}")
self.show_gui_button_dialog = False
except Exception as e:
self.add_error_message(f"创建GUI按钮失败: {str(e)}")
imgui.same_line()
if imgui.button("取消"):
self.show_gui_button_dialog = False
def _draw_gui_label_dialog(self):
"""绘制GUI标签创建对话框"""
if not self.show_gui_label_dialog:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("创建GUI标签", self.show_gui_label_dialog, flags) as window:
if not window:
self.show_gui_label_dialog = False
return
# 初始化参数
if 'label_text' not in self.dialog_params:
self.dialog_params['label_text'] = "标签"
if 'label_pos' not in self.dialog_params:
self.dialog_params['label_pos'] = [0.0, 0.0, 0.0]
if 'label_size' not in self.dialog_params:
self.dialog_params['label_size'] = [0.1, 0.1, 0.1]
imgui.text("GUI标签参数设置")
imgui.separator()
# 文本输入
changed, self.dialog_params['label_text'] = imgui.input_text("标签文本", self.dialog_params['label_text'], 256)
# 位置输入
changed, x = imgui.input_float("X坐标", self.dialog_params['label_pos'][0])
if changed:
self.dialog_params['label_pos'][0] = x
changed, y = imgui.input_float("Y坐标", self.dialog_params['label_pos'][1])
if changed:
self.dialog_params['label_pos'][1] = y
changed, z = imgui.input_float("Z坐标", self.dialog_params['label_pos'][2])
if changed:
self.dialog_params['label_pos'][2] = z
# 大小输入
changed, width = imgui.input_float("宽度", self.dialog_params['label_size'][0])
if changed:
self.dialog_params['label_size'][0] = width
changed, height = imgui.input_float("高度", self.dialog_params['label_size'][1])
if changed:
self.dialog_params['label_size'][1] = height
imgui.separator()
# 按钮
if imgui.button("创建"):
try:
pos = tuple(self.dialog_params['label_pos'])
text = self.dialog_params['label_text']
size = tuple(self.dialog_params['label_size'][:2])
result = self.createGUILabel(pos, text, size)
self.add_success_message(f"GUI标签创建成功: {text}")
self.show_gui_label_dialog = False
except Exception as e:
self.add_error_message(f"创建GUI标签失败: {str(e)}")
imgui.same_line()
if imgui.button("取消"):
self.show_gui_label_dialog = False
def _draw_gui_entry_dialog(self):
"""绘制GUI输入框创建对话框"""
if not self.show_gui_entry_dialog:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("创建GUI输入框", self.show_gui_entry_dialog, flags) as window:
if not window:
self.show_gui_entry_dialog = False
return
# 初始化参数
if 'entry_pos' not in self.dialog_params:
self.dialog_params['entry_pos'] = [0.0, 0.0, 0.0]
if 'entry_size' not in self.dialog_params:
self.dialog_params['entry_size'] = [0.2, 0.05, 0.1]
imgui.text("GUI输入框参数设置")
imgui.separator()
# 位置输入
changed, x = imgui.input_float("X坐标", self.dialog_params['entry_pos'][0])
if changed:
self.dialog_params['entry_pos'][0] = x
changed, y = imgui.input_float("Y坐标", self.dialog_params['entry_pos'][1])
if changed:
self.dialog_params['entry_pos'][1] = y
changed, z = imgui.input_float("Z坐标", self.dialog_params['entry_pos'][2])
if changed:
self.dialog_params['entry_pos'][2] = z
# 大小输入
changed, width = imgui.input_float("宽度", self.dialog_params['entry_size'][0])
if changed:
self.dialog_params['entry_size'][0] = width
changed, height = imgui.input_float("高度", self.dialog_params['entry_size'][1])
if changed:
self.dialog_params['entry_size'][1] = height
imgui.separator()
# 按钮
if imgui.button("创建"):
try:
pos = tuple(self.dialog_params['entry_pos'])
size = tuple(self.dialog_params['entry_size'][:2])
result = self.createGUIEntry(pos, size)
self.add_success_message("GUI输入框创建成功")
self.show_gui_entry_dialog = False
except Exception as e:
self.add_error_message(f"创建GUI输入框失败: {str(e)}")
imgui.same_line()
if imgui.button("取消"):
self.show_gui_entry_dialog = False
def _draw_gui_image_dialog(self):
"""绘制GUI图片创建对话框"""
if not self.show_gui_image_dialog:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("创建GUI图片", self.show_gui_image_dialog, flags) as window:
if not window:
self.show_gui_image_dialog = False
return
# 初始化参数
if 'image_pos' not in self.dialog_params:
self.dialog_params['image_pos'] = [0.0, 0.0, 0.0]
if 'image_size' not in self.dialog_params:
self.dialog_params['image_size'] = [0.2, 0.2, 0.1]
if 'image_path' not in self.dialog_params:
self.dialog_params['image_path'] = ""
imgui.text("GUI图片参数设置")
imgui.separator()
# 位置输入
changed, x = imgui.input_float("X坐标", self.dialog_params['image_pos'][0])
if changed:
self.dialog_params['image_pos'][0] = x
changed, y = imgui.input_float("Y坐标", self.dialog_params['image_pos'][1])
if changed:
self.dialog_params['image_pos'][1] = y
changed, z = imgui.input_float("Z坐标", self.dialog_params['image_pos'][2])
if changed:
self.dialog_params['image_pos'][2] = z
# 大小输入
changed, width = imgui.input_float("宽度", self.dialog_params['image_size'][0])
if changed:
self.dialog_params['image_size'][0] = width
changed, height = imgui.input_float("高度", self.dialog_params['image_size'][1])
if changed:
self.dialog_params['image_size'][1] = height
# 图片路径
changed, self.dialog_params['image_path'] = imgui.input_text("图片路径", self.dialog_params['image_path'], 512)
imgui.separator()
# 按钮
if imgui.button("创建"):
try:
pos = tuple(self.dialog_params['image_pos'])
size = tuple(self.dialog_params['image_size'][:2])
image_path = self.dialog_params['image_path']
result = self.createGUIImage(pos, image_path, size)
self.add_success_message("GUI图片创建成功")
self.show_gui_image_dialog = False
except Exception as e:
self.add_error_message(f"创建GUI图片失败: {str(e)}")
imgui.same_line()
if imgui.button("取消"):
self.show_gui_image_dialog = False
def _draw_3d_text_dialog(self):
"""绘制3D文本创建对话框"""
if not self.show_3d_text_dialog:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("创建3D文本", self.show_3d_text_dialog, flags) as window:
if not window:
self.show_3d_text_dialog = False
return
# 初始化参数
if 'text3d_text' not in self.dialog_params:
self.dialog_params['text3d_text'] = "3D文本"
if 'text3d_pos' not in self.dialog_params:
self.dialog_params['text3d_pos'] = [0.0, 0.0, 0.0]
if 'text3d_size' not in self.dialog_params:
self.dialog_params['text3d_size'] = 1.0
imgui.text("3D文本参数设置")
imgui.separator()
# 文本输入
changed, self.dialog_params['text3d_text'] = imgui.input_text("文本内容", self.dialog_params['text3d_text'], 256)
# 位置输入
changed, x = imgui.input_float("X坐标", self.dialog_params['text3d_pos'][0])
if changed:
self.dialog_params['text3d_pos'][0] = x
changed, y = imgui.input_float("Y坐标", self.dialog_params['text3d_pos'][1])
if changed:
self.dialog_params['text3d_pos'][1] = y
changed, z = imgui.input_float("Z坐标", self.dialog_params['text3d_pos'][2])
if changed:
self.dialog_params['text3d_pos'][2] = z
# 大小输入
changed, self.dialog_params['text3d_size'] = imgui.input_float("文本大小", self.dialog_params['text3d_size'])
imgui.separator()
# 按钮
if imgui.button("创建"):
try:
pos = tuple(self.dialog_params['text3d_pos'])
text = self.dialog_params['text3d_text']
size = self.dialog_params['text3d_size']
result = self.create3DText(pos, text, size)
self.add_success_message(f"3D文本创建成功: {text}")
self.show_3d_text_dialog = False
except Exception as e:
self.add_error_message(f"创建3D文本失败: {str(e)}")
imgui.same_line()
if imgui.button("取消"):
self.show_3d_text_dialog = False
def _draw_3d_image_dialog(self):
"""绘制3D图片创建对话框"""
if not self.show_3d_image_dialog:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("创建3D图片", self.show_3d_image_dialog, flags) as window:
if not window:
self.show_3d_image_dialog = False
return
# 初始化参数
if 'image3d_pos' not in self.dialog_params:
self.dialog_params['image3d_pos'] = [0.0, 0.0, 0.0]
if 'image3d_size' not in self.dialog_params:
self.dialog_params['image3d_size'] = [1.0, 1.0, 1.0]
if 'image3d_path' not in self.dialog_params:
self.dialog_params['image3d_path'] = ""
imgui.text("3D图片参数设置")
imgui.separator()
# 位置输入
changed, x = imgui.input_float("X坐标", self.dialog_params['image3d_pos'][0])
if changed:
self.dialog_params['image3d_pos'][0] = x
changed, y = imgui.input_float("Y坐标", self.dialog_params['image3d_pos'][1])
if changed:
self.dialog_params['image3d_pos'][1] = y
changed, z = imgui.input_float("Z坐标", self.dialog_params['image3d_pos'][2])
if changed:
self.dialog_params['image3d_pos'][2] = z
# 大小输入
changed, width = imgui.input_float("宽度", self.dialog_params['image3d_size'][0])
if changed:
self.dialog_params['image3d_size'][0] = width
changed, height = imgui.input_float("高度", self.dialog_params['image3d_size'][1])
if changed:
self.dialog_params['image3d_size'][1] = height
# 图片路径
changed, self.dialog_params['image3d_path'] = imgui.input_text("图片路径", self.dialog_params['image3d_path'], 512)
imgui.separator()
# 按钮
if imgui.button("创建"):
try:
pos = tuple(self.dialog_params['image3d_pos'])
size = tuple(self.dialog_params['image3d_size'][:2])
image_path = self.dialog_params['image3d_path']
result = self.create3DImage(pos, image_path, size)
self.add_success_message("3D图片创建成功")
self.show_3d_image_dialog = False
except Exception as e:
self.add_error_message(f"创建3D图片失败: {str(e)}")
imgui.same_line()
if imgui.button("取消"):
self.show_3d_image_dialog = False
# 添加其他创建对话框的占位符方法
def _draw_video_screen_dialog(self):
"""绘制视频屏幕创建对话框"""
if not self.show_video_screen_dialog:
return
self.show_video_screen_dialog = False
self.add_info_message("视频屏幕创建功能开发中...")
def _draw_2d_video_screen_dialog(self):
"""绘制2D视频屏幕创建对话框"""
if not self.show_2d_video_screen_dialog:
return
self.show_2d_video_screen_dialog = False
self.add_info_message("2D视频屏幕创建功能开发中...")
def _draw_spherical_video_dialog(self):
"""绘制球形视频创建对话框"""
if not self.show_spherical_video_dialog:
return
self.show_spherical_video_dialog = False
self.add_info_message("球形视频创建功能开发中...")
def _draw_virtual_screen_dialog(self):
"""绘制虚拟屏幕创建对话框"""
if not self.show_virtual_screen_dialog:
return
self.show_virtual_screen_dialog = False
self.add_info_message("虚拟屏幕创建功能开发中...")
def _draw_spot_light_dialog(self):
"""绘制聚光灯创建对话框"""
if not self.show_spot_light_dialog:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("创建聚光灯", self.show_spot_light_dialog, flags) as window:
if not window:
self.show_spot_light_dialog = False
return
# 初始化参数
if 'spotlight_pos' not in self.dialog_params:
self.dialog_params['spotlight_pos'] = [0.0, 0.0, 5.0]
if 'spotlight_color' not in self.dialog_params:
self.dialog_params['spotlight_color'] = [1.0, 1.0, 1.0]
if 'spotlight_intensity' not in self.dialog_params:
self.dialog_params['spotlight_intensity'] = 1.0
imgui.text("聚光灯参数设置")
imgui.separator()
# 位置输入
changed, x = imgui.input_float("X坐标", self.dialog_params['spotlight_pos'][0])
if changed:
self.dialog_params['spotlight_pos'][0] = x
changed, y = imgui.input_float("Y坐标", self.dialog_params['spotlight_pos'][1])
if changed:
self.dialog_params['spotlight_pos'][1] = y
changed, z = imgui.input_float("Z坐标", self.dialog_params['spotlight_pos'][2])
if changed:
self.dialog_params['spotlight_pos'][2] = z
# 颜色输入
changed, r = imgui.input_float("红色 (R)", self.dialog_params['spotlight_color'][0], 0.0, 1.0)
if changed:
self.dialog_params['spotlight_color'][0] = max(0.0, min(1.0, r))
changed, g = imgui.input_float("绿色 (G)", self.dialog_params['spotlight_color'][1], 0.0, 1.0)
if changed:
self.dialog_params['spotlight_color'][1] = max(0.0, min(1.0, g))
changed, b = imgui.input_float("蓝色 (B)", self.dialog_params['spotlight_color'][2], 0.0, 1.0)
if changed:
self.dialog_params['spotlight_color'][2] = max(0.0, min(1.0, b))
# 强度输入
changed, self.dialog_params['spotlight_intensity'] = imgui.input_float("强度", self.dialog_params['spotlight_intensity'], 0.1, 2.0)
if changed:
self.dialog_params['spotlight_intensity'] = max(0.1, self.dialog_params['spotlight_intensity'])
imgui.separator()
# 按钮
if imgui.button("创建"):
try:
pos = tuple(self.dialog_params['spotlight_pos'])
result = self.createSpotLight(pos)
if result:
# 设置颜色和强度
light = result.node()
if hasattr(light, 'setColor'):
color = tuple(self.dialog_params['spotlight_color'])
light.setColor(color + (1.0,)) # 添加alpha通道
if hasattr(light, 'setEnergy'):
light.setEnergy(self.dialog_params['spotlight_intensity'])
self.add_success_message("聚光灯创建成功")
self.show_spot_light_dialog = False
else:
self.add_error_message("聚光灯创建失败")
except Exception as e:
self.add_error_message(f"创建聚光灯失败: {str(e)}")
imgui.same_line()
if imgui.button("取消"):
self.show_spot_light_dialog = False
def _draw_point_light_dialog(self):
"""绘制点光源创建对话框"""
if not self.show_point_light_dialog:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("创建点光源", self.show_point_light_dialog, flags) as window:
if not window:
self.show_point_light_dialog = False
return
# 初始化参数
if 'pointlight_pos' not in self.dialog_params:
self.dialog_params['pointlight_pos'] = [0.0, 0.0, 5.0]
if 'pointlight_color' not in self.dialog_params:
self.dialog_params['pointlight_color'] = [1.0, 1.0, 1.0]
if 'pointlight_intensity' not in self.dialog_params:
self.dialog_params['pointlight_intensity'] = 1.0
if 'pointlight_radius' not in self.dialog_params:
self.dialog_params['pointlight_radius'] = 10.0
imgui.text("点光源参数设置")
imgui.separator()
# 位置输入
changed, x = imgui.input_float("X坐标", self.dialog_params['pointlight_pos'][0])
if changed:
self.dialog_params['pointlight_pos'][0] = x
changed, y = imgui.input_float("Y坐标", self.dialog_params['pointlight_pos'][1])
if changed:
self.dialog_params['pointlight_pos'][1] = y
changed, z = imgui.input_float("Z坐标", self.dialog_params['pointlight_pos'][2])
if changed:
self.dialog_params['pointlight_pos'][2] = z
# 颜色输入
changed, r = imgui.input_float("红色 (R)", self.dialog_params['pointlight_color'][0], 0.0, 1.0)
if changed:
self.dialog_params['pointlight_color'][0] = max(0.0, min(1.0, r))
changed, g = imgui.input_float("绿色 (G)", self.dialog_params['pointlight_color'][1], 0.0, 1.0)
if changed:
self.dialog_params['pointlight_color'][1] = max(0.0, min(1.0, g))
changed, b = imgui.input_float("蓝色 (B)", self.dialog_params['pointlight_color'][2], 0.0, 1.0)
if changed:
self.dialog_params['pointlight_color'][2] = max(0.0, min(1.0, b))
# 强度输入
changed, self.dialog_params['pointlight_intensity'] = imgui.input_float("强度", self.dialog_params['pointlight_intensity'], 0.1, 2.0)
if changed:
self.dialog_params['pointlight_intensity'] = max(0.1, self.dialog_params['pointlight_intensity'])
# 半径输入
changed, self.dialog_params['pointlight_radius'] = imgui.input_float("影响半径", self.dialog_params['pointlight_radius'], 1.0, 50.0)
if changed:
self.dialog_params['pointlight_radius'] = max(1.0, self.dialog_params['pointlight_radius'])
imgui.separator()
# 按钮
if imgui.button("创建"):
try:
pos = tuple(self.dialog_params['pointlight_pos'])
result = self.createPointLight(pos)
if result:
# 设置颜色和强度
light = result.node()
if hasattr(light, 'setColor'):
color = tuple(self.dialog_params['pointlight_color'])
light.setColor(color + (1.0,)) # 添加alpha通道
if hasattr(light, 'setEnergy'):
light.setEnergy(self.dialog_params['pointlight_intensity'])
if hasattr(light, 'setAttenuation'):
# 设置衰减: (constant, linear, quadratic)
radius = self.dialog_params['pointlight_radius']
light.setAttenuation((1.0, 0.5/radius, 0.5/(radius*radius)))
self.add_success_message("点光源创建成功")
self.show_point_light_dialog = False
else:
self.add_error_message("点光源创建失败")
except Exception as e:
self.add_error_message(f"创建点光源失败: {str(e)}")
imgui.same_line()
if imgui.button("取消"):
self.show_point_light_dialog = False
def _draw_terrain_dialog(self):
"""绘制地形创建对话框"""
if not self.show_terrain_dialog:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("创建平面地形", self.show_terrain_dialog, flags) as window:
if not window:
self.show_terrain_dialog = False
return
# 初始化参数
if 'terrain_width' not in self.dialog_params:
self.dialog_params['terrain_width'] = 10.0
if 'terrain_height' not in self.dialog_params:
self.dialog_params['terrain_height'] = 10.0
if 'terrain_resolution' not in self.dialog_params:
self.dialog_params['terrain_resolution'] = 129
imgui.text("平面地形参数设置")
imgui.separator()
# 尺寸输入
changed, self.dialog_params['terrain_width'] = imgui.input_float("宽度", self.dialog_params['terrain_width'], 1.0, 100.0)
if changed:
self.dialog_params['terrain_width'] = max(1.0, self.dialog_params['terrain_width'])
changed, self.dialog_params['terrain_height'] = imgui.input_float("高度", self.dialog_params['terrain_height'], 1.0, 100.0)
if changed:
self.dialog_params['terrain_height'] = max(1.0, self.dialog_params['terrain_height'])
# 分辨率输入
changed, self.dialog_params['terrain_resolution'] = imgui.input_int("分辨率", self.dialog_params['terrain_resolution'])
if changed:
# 确保分辨率是有效的 (2的幂次方 + 1)
valid_resolutions = [17, 33, 65, 129, 257, 513, 1025]
if self.dialog_params['terrain_resolution'] not in valid_resolutions:
closest_res = min(valid_resolutions, key=lambda x: abs(x - self.dialog_params['terrain_resolution']))
self.dialog_params['terrain_resolution'] = closest_res
imgui.separator()
imgui.text("有效分辨率值: 17, 33, 65, 129, 257, 513, 1025")
imgui.separator()
# 按钮
if imgui.button("创建"):
try:
width = self.dialog_params['terrain_width']
height = self.dialog_params['terrain_height']
resolution = self.dialog_params['terrain_resolution']
# 转换为地形管理器期望的格式
size = (width, height)
result = self.createFlatTerrain(size, resolution)
if result:
self.add_success_message("平面地形创建成功")
self.show_terrain_dialog = False
else:
self.add_error_message("平面地形创建失败")
except Exception as e:
self.add_error_message(f"创建平面地形失败: {str(e)}")
imgui.same_line()
if imgui.button("取消"):
self.show_terrain_dialog = False
def _draw_script_dialog(self):
"""绘制脚本创建对话框"""
if not self.show_script_dialog:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("创建脚本", self.show_script_dialog, flags) as window:
if not window:
self.show_script_dialog = False
return
# 初始化参数
if 'script_name' not in self.dialog_params:
self.dialog_params['script_name'] = "new_script"
if 'script_template' not in self.dialog_params:
self.dialog_params['script_template'] = 0 # 0=basic, 1=movement
imgui.text("脚本参数设置")
imgui.separator()
# 脚本名称输入
changed, self.dialog_params['script_name'] = imgui.input_text("脚本名称", self.dialog_params['script_name'], 256)
# 模板选择
templates = ["基础模板", "移动模板"]
changed, self.dialog_params['script_template'] = imgui.combo("模板类型", self.dialog_params['script_template'], templates)
imgui.separator()
# 模板说明
if self.dialog_params['script_template'] == 0:
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "基础模板: 包含基本的脚本结构")
else:
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "移动模板: 包含移动相关的基本功能")
imgui.separator()
# 按钮
if imgui.button("创建"):
try:
script_name = self.dialog_params['script_name']
if not script_name:
self.add_error_message("请输入脚本名称")
return
template = "basic" if self.dialog_params['script_template'] == 0 else "movement"
result = self.createScript(script_name, template)
if result:
self.add_success_message(f"脚本创建成功: {script_name}")
# 如果启用了热重载,自动加载新脚本
if self.hotReloadEnabled:
try:
self.loadScript(result)
self.add_info_message(f"脚本已自动加载: {script_name}")
except Exception as e:
self.add_warning_message(f"脚本自动加载失败: {str(e)}")
self.show_script_dialog = False
else:
self.add_error_message("脚本创建失败")
except Exception as e:
self.add_error_message(f"创建脚本失败: {str(e)}")
imgui.same_line()
if imgui.button("取消"):
self.show_script_dialog = False
def _draw_script_browser(self):
"""绘制脚本文件浏览器"""
if not self.show_script_browser:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("选择脚本文件", self.show_script_browser, flags) as window:
if not window:
self.show_script_browser = False
return
imgui.text("选择脚本文件")
imgui.separator()
# 导航按钮
if imgui.button("上级目录"):
parent_path = os.path.dirname(self.script_browser_current_path)
if parent_path != self.script_browser_current_path:
self.script_browser_current_path = parent_path
self._refresh_script_browser()
imgui.same_line()
if imgui.button("脚本目录"):
# 切换到脚本目录
if hasattr(self, 'script_manager') and self.script_manager:
scripts_dir = self.script_manager.scripts_directory
if os.path.exists(scripts_dir):
self.script_browser_current_path = scripts_dir
self._refresh_script_browser()
imgui.same_line()
if imgui.button("当前目录"):
self.script_browser_current_path = os.getcwd()
self._refresh_script_browser()
imgui.separator()
# 当前路径显示
imgui.text("当前路径:")
imgui.same_line()
imgui.text_colored((0.7, 0.7, 0.7, 1.0), self.script_browser_current_path)
imgui.separator()
# 文件列表
if imgui.begin_child("script_file_list", (580, 300)):
for item in self.script_browser_items:
if item['is_dir']:
# 目录
imgui.text_colored((0.3, 0.8, 1.0, 1.0), f"📁 {item['name']}")
if imgui.is_item_clicked():
self.script_browser_current_path = item['path']
self._refresh_script_browser()
else:
# Python文件
imgui.text(f"📄 {item['name']}")
if imgui.is_item_clicked():
self.script_browser_selected_path = item['path']
imgui.end_child()
imgui.separator()
# 选中的文件信息
if self.script_browser_selected_path and os.path.exists(self.script_browser_selected_path):
file_size = os.path.getsize(self.script_browser_selected_path)
imgui.text(f"文件大小: {file_size / 1024:.2f} KB")
file_ext = os.path.splitext(self.script_browser_selected_path)[1].lower()
if file_ext == '.py':
imgui.text_colored((0.176, 1.0, 0.769, 1.0), "✓ Python脚本文件")
else:
imgui.text_colored((1.0, 0.3, 0.3, 1.0), "✗ 不是Python脚本文件")
else:
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "请选择有效的Python脚本文件")
imgui.separator()
# 按钮
can_load = (self.script_browser_selected_path and
os.path.exists(self.script_browser_selected_path) and
os.path.splitext(self.script_browser_selected_path)[1].lower() == '.py')
if can_load:
if imgui.button("加载脚本"):
try:
result = self.loadScript(self.script_browser_selected_path)
if result:
script_name = os.path.basename(self.script_browser_selected_path)
self.add_success_message(f"脚本加载成功: {script_name}")
self.show_script_browser = False
else:
self.add_error_message("脚本加载失败")
except Exception as e:
self.add_error_message(f"加载脚本失败: {str(e)}")
else:
imgui.push_style_var(imgui.StyleVar_.alpha, 0.5)
imgui.button("加载脚本")
imgui.pop_style_var()
imgui.same_line()
if imgui.button("取消"):
self.show_script_browser = False
self.script_browser_selected_path = ""
def _refresh_script_browser(self):
"""刷新脚本浏览器内容"""
try:
self.script_browser_items = []
if not os.path.exists(self.script_browser_current_path):
self.script_browser_current_path = os.getcwd()
# 获取目录中的所有项目
items = []
try:
for item_name in os.listdir(self.script_browser_current_path):
item_path = os.path.join(self.script_browser_current_path, item_name)
if os.path.isdir(item_path):
items.append({
'name': item_name,
'path': item_path,
'is_dir': True
})
elif os.path.isfile(item_path):
file_ext = os.path.splitext(item_name)[1].lower()
if file_ext == '.py': # 只显示Python文件
items.append({
'name': item_name,
'path': item_path,
'is_dir': False
})
except PermissionError:
print(f"权限错误: 无法访问目录 {self.script_browser_current_path}")
# 排序:目录在前,文件在后
items.sort(key=lambda x: (not x['is_dir'], x['name'].lower()))
self.script_browser_items = items
except Exception as e:
print(f"刷新脚本浏览器时出错: {e}")
self.script_browser_items = []
def _draw_heightmap_browser(self):
"""绘制高度图文件浏览器"""
if not self.show_heightmap_browser:
return
flags = (imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_collapse |
imgui.WindowFlags_.modal)
with imgui_ctx.begin("选择高度图文件", self.show_heightmap_browser, flags) as window:
if not window:
self.show_heightmap_browser = False
return
imgui.text("选择高度图文件")
imgui.separator()
# 导航按钮
if imgui.button("上级目录"):
parent_path = os.path.dirname(self.heightmap_browser_current_path)
if parent_path != self.heightmap_browser_current_path:
self.heightmap_browser_current_path = parent_path
self._refresh_heightmap_browser()
imgui.same_line()
if imgui.button("主目录"):
self.heightmap_browser_current_path = os.getcwd()
self._refresh_heightmap_browser()
imgui.same_line()
if imgui.button("当前目录"):
self.heightmap_browser_current_path = os.getcwd()
self._refresh_heightmap_browser()
imgui.separator()
# 当前路径显示
imgui.text("当前路径:")
imgui.same_line()
imgui.text_colored((0.7, 0.7, 0.7, 1.0), self.heightmap_browser_current_path)
imgui.separator()
# 文件列表
if imgui.begin_child("file_list", (580, 300)):
for item in self.heightmap_browser_items:
if item['is_dir']:
# 目录
imgui.text_colored((0.3, 0.8, 1.0, 1.0), f"📁 {item['name']}")
if imgui.is_item_clicked():
self.heightmap_browser_current_path = item['path']
self._refresh_heightmap_browser()
else:
# 文件
imgui.text(f"📄 {item['name']}")
if imgui.is_item_clicked():
self.heightmap_browser_selected_path = item['path']
self.heightmap_file_path = item['path']
imgui.end_child()
imgui.separator()
# 支持的格式说明
imgui.text("支持的文件格式:")
formats_text = ", ".join(self.supported_heightmap_formats)
imgui.text_colored((0.7, 0.7, 0.7, 1.0), formats_text)
imgui.separator()
# 选中的文件信息
if self.heightmap_file_path and os.path.exists(self.heightmap_file_path):
file_size = os.path.getsize(self.heightmap_file_path)
imgui.text(f"文件大小: {file_size / 1024:.2f} KB")
file_ext = os.path.splitext(self.heightmap_file_path)[1].lower()
if file_ext in self.supported_heightmap_formats:
imgui.text_colored((0.176, 1.0, 0.769, 1.0), "✓ 文件格式支持")
else:
imgui.text_colored((1.0, 0.3, 0.3, 1.0), "✗ 不支持的文件格式")
else:
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "请选择有效的高度图文件")
imgui.separator()
# 按钮
can_import = (self.heightmap_file_path and
os.path.exists(self.heightmap_file_path) and
os.path.splitext(self.heightmap_file_path)[1].lower() in self.supported_heightmap_formats)
if can_import:
if imgui.button("创建地形"):
try:
# 使用默认缩放参数创建地形
scale = (1.0, 1.0, 10.0) # X, Y, Z缩放
result = self.createTerrainFromHeightMap(self.heightmap_file_path, scale)
if result:
self.add_success_message("高度图地形创建成功")
self.show_heightmap_browser = False
else:
self.add_error_message("高度图地形创建失败")
except Exception as e:
self.add_error_message(f"创建高度图地形失败: {str(e)}")
else:
imgui.push_style_var(imgui.StyleVar_.alpha, 0.5)
imgui.button("创建地形")
imgui.pop_style_var()
imgui.same_line()
if imgui.button("取消"):
self.show_heightmap_browser = False
self.heightmap_file_path = ""
def _refresh_heightmap_browser(self):
"""刷新高度图浏览器内容"""
try:
self.heightmap_browser_items = []
if not os.path.exists(self.heightmap_browser_current_path):
self.heightmap_browser_current_path = os.getcwd()
# 获取目录中的所有项目
items = []
try:
for item_name in os.listdir(self.heightmap_browser_current_path):
item_path = os.path.join(self.heightmap_browser_current_path, item_name)
if os.path.isdir(item_path):
items.append({
'name': item_name,
'path': item_path,
'is_dir': True
})
elif os.path.isfile(item_path):
file_ext = os.path.splitext(item_name)[1].lower()
if file_ext in self.supported_heightmap_formats:
items.append({
'name': item_name,
'path': item_path,
'is_dir': False
})
except PermissionError:
print(f"权限错误: 无法访问目录 {self.heightmap_browser_current_path}")
# 排序:目录在前,文件在后
items.sort(key=lambda x: (not x['is_dir'], x['name'].lower()))
self.heightmap_browser_items = items
except Exception as e:
print(f"刷新高度图浏览器时出错: {e}")
self.heightmap_browser_items = []
# ==================== 导入功能实现 ====================