EG/main.py

1972 lines
77 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from panda3d.core import loadPrcFileData, WindowProperties, Point3
from math import pi, sin, cos
from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import Sequence
from panda3d.core import NodePath
import p3dimgui
from imgui_bundle import imgui, imgui_ctx
import sys
import os
import warnings
from pathlib import Path
# 导入MyWorld类和必要的模块
from core.world import CoreWorld
from core.selection import SelectionSystem
from core.event_handler import EventHandler
from core.tool_manager import ToolManager
from core.script_system import ScriptManager
from core.patrol_system import PatrolSystem
from core.Command_System import CommandManager
from gui.gui_manager import GUIManager
from core.terrain_manager import TerrainManager
from scene.scene_manager import SceneManager
from project.project_manager import ProjectManager
from core.InfoPanelManager import InfoPanelManager
from core.collision_manager import CollisionManager
from core.CustomMouseController import CustomMouseController
from core.resource_manager import ResourceManager
from ui.lui_manager import LUIManager
from ui.panels.editor_panels import EditorPanels
from ui.panels.script_panels import ScriptPanels
from ui.panels.dialog_panels import DialogPanels
from ui.panels.interaction_panels import InteractionPanels
from ui.panels.create_actions import CreateActions
from ui.panels.object_factory import ObjectFactory
from ui.panels.animation_tools import AnimationTools
from ui.panels.property_helpers import PropertyHelpers
from ui.panels.app_actions import AppActions
from core.model_drag_drop import ModelDragDropService
from ssbo_component.ssbo_editor import SSBOEditor
from TransformGizmo.transform_gizmo import TransformGizmo
try:
# 尝试导入视频管理器,避免循环导入
import importlib.util
spec = importlib.util.spec_from_file_location("video_integration", "demo/video_integration.py")
video_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(video_module)
VideoManager = video_module.VideoManager
except:
# 如果video_integration模块不存在则跳过
VideoManager = None
print("⚠ 视频管理器模块未找到,视频功能将不可用")
warnings.filterwarnings("ignore", category=DeprecationWarning)
class MyWorld(CoreWorld):
def __init__(self):
super().__init__()
# 设置窗口为最大化模式
props = WindowProperties()
#props.set_maximized(True)
self.win.request_properties(props)
print("✓ 窗口已设置为最大化模式")
# 初始化选择和变换系统
self.selection = SelectionSystem(self)
# 绑定F键用于聚焦选中节点
self.accept("f", self.onFocusKeyPressed)
self.accept("F", self.onFocusKeyPressed) # 大写F
self.use_ssbo_mouse_picking = True
if not self.use_ssbo_mouse_picking:
self.accept("mouse1", self.onMouseClick)
# Keep release/move bindings even in SSBO mode so gizmo drag can work.
self.accept("mouse1-up", self.onMouseRelease)
self.accept("mouse-move", self.onMouseMove)
self.accept("drag", self.onMouseMove)
# 初始化事件处理系统
self.event_handler = EventHandler(self)
# 初始化工具管理系统
self.tool_manager = ToolManager(self)
# 初始化脚本管理系统
self.script_manager = ScriptManager(self)
# 初始化GUI管理系统
self.gui_manager = GUIManager(self)
# 初始化LUI管理系统
self.lui_manager = LUIManager(self)
# 新的坐标系
self.newTransform = TransformGizmo(self)
self._setup_transform_gizmo_light_sync()
# 初始化视频管理
if VideoManager is not None:
self.video_manager = VideoManager(self)
else:
self.video_manager = None
# 初始化场景管理系统
# print(f"[DEBUG] 初始化场景管理系统...")
self.scene_manager = SceneManager(self)
# print(f"[DEBUG] 场景管理系统初始化完成")
# 初始化项目管理系统
# print(f"[DEBUG] 初始化项目管理系统...")
self.project_manager = ProjectManager(self)
# print(f"[DEBUG] 项目管理系统初始化完成")
self.info_panel_manager = InfoPanelManager(self)
self.command_manager = CommandManager()
# 初始化碰撞管理器
self.collision_manager = CollisionManager(self)
# 初始化资源管理器
self.resource_manager = ResourceManager(self)
# 初始化Actor缓存系统用于动画控制
self._actor_cache = {}
print("✓ Actor缓存系统初始化完成")
# 初始化自定义鼠标控制器(视角移动)
self.mouse_controller = CustomMouseController(self)
self.mouse_controller.setUp(mouse_speed=25, move_speed=20)
print("✓ 自定义鼠标控制器初始化完成")
# 初始化VR管理器
try:
from core.vr import VRManager
self.vr_manager = VRManager(self)
print("✓ VR管理器初始化完成")
except Exception as e:
print(f"⚠ VR管理器初始化失败: {e}")
self.vr_manager = None
# VR调试相关变量
self.vr_debug_enabled = False
self.vr_detailed_mode = True
self.vr_performance_monitor = False
# 调试选项
self.debug_collision = True # 是否显示碰撞体
# 默认启用模型间碰撞检测(可选)
if self.use_ssbo_mouse_picking:
self.enableModelCollisionDetection(enable=False, frequency=0.1, threshold=0.5)
else:
self.enableModelCollisionDetection(enable=True, frequency=0.1, threshold=0.5)
# 碰撞检测UI相关变量
self._selected_collision_shape = "球形 (Sphere)" # 默认选择的碰撞形状
# 启动脚本系统
self.script_manager.start_system()
self.terrain_manager = TerrainManager(self)
self.terrain_edit_radius = 3.0
self.terrain_edit_strength=0.3
self.terrain_edit_operation = "add"
# Install Dear ImGui
p3dimgui.init(
wantPlaceManager=False,
wantExplorerManager=False,
wantTimeSliderManager=False,
)
# Let ssbo_component reuse the existing imgui backend instance.
self.imgui_backend = self.imgui
# Initialize SSBO editor and let it own mouse1 picking.
# Do not auto-load a default model here; models are loaded from import flow.
self.ssbo_editor = None
if self.use_ssbo_mouse_picking:
self.ssbo_editor = SSBOEditor(
base_app=self,
render_pipeline=self.render_pipeline,
model_path=None,
font_path=None,
)
self.ssbo_editor.bind_transform_gizmo(self.newTransform)
print("SSBOEditor mouse picking enabled (waiting for imported model)")
imgui.get_io().config_flags |= imgui.ConfigFlags_.docking_enable
print("✓ ImGui Docking功能已启用")
# 初始化样式管理器
from core.imgui_style_manager import ImGuiStyleManager
self.style_manager = ImGuiStyleManager(self.imgui, self)
self.editor_panels = EditorPanels(self)
self.script_panels = ScriptPanels(self)
self.dialog_panels = DialogPanels(self)
self.interaction_panels = InteractionPanels(self)
self.create_actions = CreateActions(self)
self.object_factory = ObjectFactory(self)
self.animation_tools = AnimationTools(self)
self.property_helpers = PropertyHelpers(self)
self.app_actions = AppActions(self)
# 简化的初始化字体设置(只使用中文字体)
try:
# 先清除默认字体
self.imgui.io.fonts.clear()
# 尝试加载中文字体
import platform
system = platform.system().lower()
if system == "linux":
font_path = "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"
elif system == "windows":
font_path = "C:/Windows/Fonts/msyh.ttc"
elif system == "darwin":
font_path = "/System/Library/Fonts/PingFang.ttc"
else:
font_path = None
if font_path and Path(font_path).exists():
self.imgui.io.fonts.add_font_from_file_ttf(font_path, 14.0)
print(f"✓ 初始化中文字体成功: {font_path}")
else:
# 回退到原来的字体
fallback_font_path = "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc"
if fallback_font_path and Path(fallback_font_path).exists():
self.imgui.io.fonts.add_font_from_file_ttf(fallback_font_path, 14.0)
print(f"✓ 初始化回退字体成功: {fallback_font_path}")
else:
self.imgui.io.fonts.add_font_default()
print("✓ 初始化使用默认字体")
except Exception as e:
print(f"⚠ 初始化字体系统失败: {e}")
# 备用方案:使用默认字体
try:
self.imgui.io.fonts.add_font_default()
print("✓ 使用备用默认字体")
except:
pass
# Disable the camera trackball controls.
self.disableMouse()
self.showDemoWindow = False
# UI状态管理
self.showSceneTree = True
self.showPropertyPanel = True
self.showConsole = True
self.showScriptPanel = not self.use_ssbo_mouse_picking
self.showToolbar = True
self.showResourceManager = True
# 脚本系统状态变量
self.hotReloadEnabled = True
self._new_script_name = "new_script"
self._selected_template = 0
self._mount_script_index = 0
# 变换监控相关
self._transform_monitoring = False
self._monitored_node = None
self._last_transform_values = {}
self._transform_update_timer = 0
self._transform_update_interval = 0.05 # 50ms检查一次
self._clipboard_pos = None # 位置剪贴板
# 颜色选择器相关
self._color_picker_active = False
self._color_picker_target = None # (target_object, property_name)
self._color_picker_current_color = (1.0, 1.0, 1.0, 1.0)
self._color_picker_callback = None
# 字体选择器相关
self._font_selector_active = False
self._font_selector_target = None # (target_object, property_name)
self._font_selector_current_font = ""
self._font_selector_callback = None
self._available_fonts = [] # 可用字体列表
self._refresh_available_fonts()
# 菜单状态管理
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.clipboard = []
self.clipboard_mode = "" # "copy" 或 "cut"
# 视角控制状态
self.camera_control_enabled = True
self.show_camera_info = False
# 拖拽导入状态
self.dragged_files = []
self.is_dragging = False
self.show_drag_overlay = False
self.drag_drop_monitor = None
self._resource_manager_window_rect = None
self._resource_drop_targets = []
self._scene_tree_window_rect = None
self._property_panel_window_rect = None
self._script_panel_window_rect = None
self._console_window_rect = None
self._toolbar_window_rect = None
self._drag_scene_tree_hover_node = None
self.model_drag_drop = ModelDragDropService(self)
self.showLUIEditor = not self.use_ssbo_mouse_picking
# 导入功能状态
self.show_import_dialog = False
self.import_file_path = ""
self.supported_formats = [".gltf", ".glb", ".fbx", ".bam", ".egg", ".obj"]
# 创建功能状态
self.show_3d_text_dialog = False
self.show_3d_image_dialog = False
self.show_gui_button_dialog = False
self.show_gui_label_dialog = False
self.show_gui_entry_dialog = False
self.show_gui_image_dialog = False
self.show_video_screen_dialog = False
self.show_2d_video_screen_dialog = False
self.show_spherical_video_dialog = False
self.show_virtual_screen_dialog = False
self.show_spot_light_dialog = False
self.show_point_light_dialog = False
self.show_terrain_dialog = False
self.show_heightmap_browser = False
self.show_script_dialog = False
self.show_script_browser = False
# 高度图浏览器状态
self.heightmap_browser_current_path = os.getcwd()
self.heightmap_browser_selected_path = ""
self.heightmap_browser_items = []
self.heightmap_file_path = ""
self.supported_heightmap_formats = [".png", ".jpg", ".jpeg", ".bmp", ".tiff", ".tif"]
# 脚本浏览器状态
self.script_browser_current_path = os.getcwd()
self.script_browser_selected_path = ""
self.script_browser_items = []
# 对话框参数存储
self.dialog_params = {} # 存储各种对话框的参数
# 脚本系统状态
self.hotReloadEnabled = False
# 初始化高度图浏览器
self._refresh_heightmap_browser()
# 初始化脚本浏览器
self._refresh_script_browser()
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('control-s', self._on_save_project)
self.accept('f4', self._on_f4_pressed)
# 编辑功能快捷键
self.accept('control-z', self._on_undo)
self.accept('control-y', self._on_redo)
self.accept('control-x', self._on_cut)
self.accept('control-c', self._on_copy)
self.accept('control-v', self._on_paste)
self.accept('delete', self._on_delete_pressed)
self.accept('escape', self._on_escape_pressed)
# 滚轮事件
self.accept('wheel_up', self._on_wheel_up)
self.accept('wheel_down', self._on_wheel_down)
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)")
# 启用拖拽导入功能
self.setup_drag_drop_support()
self.add_info_message("拖拽导入功能已启用 - 可将3D文件拖拽到窗口中导入")
print("✓ MyWorld 初始化完成")
# print(f"[DEBUG] MyWorld 初始化完成,所有管理器已就绪")
# print(f"[DEBUG] 场景管理器: {hasattr(self, 'scene_manager')}")
# print(f"[DEBUG] 项目管理器: {hasattr(self, 'project_manager')}")
# print(f"[DEBUG] GUI管理器: {hasattr(self, 'gui_manager')}")
# print(f"[DEBUG] 脚本管理器: {hasattr(self, 'script_manager')}")
# ==================== 兼容性属性 ====================
# 保留models属性以兼容现有代码
@property
def models(self):
"""模型列表的兼容性属性"""
return self.scene_manager.models
@models.setter
def models(self, value):
"""模型列表的兼容性设置器"""
self.scene_manager.models = value
# 保留gui_elements属性以兼容现有代码
@property
def gui_elements(self):
"""GUI元素列表的兼容性属性"""
return self.gui_manager.gui_elements
@gui_elements.setter
def gui_elements(self, value):
"""GUI元素列表的兼容性设置器"""
self.gui_manager.gui_elements = value
# 保留guiEditMode属性以兼容现有代码
@property
def guiEditMode(self):
"""GUI编辑模式的兼容性属性"""
return self.gui_manager.guiEditMode
@guiEditMode.setter
def guiEditMode(self, value):
"""GUI编辑模式的兼容性设置器"""
self.gui_manager.guiEditMode = value
# 保留currentTool属性以兼容现有代码
@property
def currentTool(self):
"""当前工具的兼容性属性"""
return self.tool_manager.currentTool
@currentTool.setter
def currentTool(self, value):
"""当前工具的兼容性设置器"""
self.tool_manager.currentTool = value
# 保留terrains属性以兼容现有代码
@property
def terrains(self):
"""地形列表的兼容性属性"""
return self.terrain_manager.terrains
@terrains.setter
def terrains(self,value):
"""地形列表的兼容性设置器"""
self.terrain_manager.terrains = value
def onFocusKeyPressed(self):
"""处理 F 键按下事件"""
try:
if hasattr(self, 'selection') and self.selection.selectedNode:
self.selection.focusCameraOnSelectedNodeAdvanced()
else:
print("当前没有选中任何节点")
except Exception as e:
print(f"处理 F 键事件失败: {e}")
def onMouseClick(self):
"""处理鼠标点击事件"""
print("\n=== 鼠标点击事件触发 ===")
try:
# 检查鼠标是否有效
if not self.mouseWatcherNode.hasMouse():
print("❌ 鼠标无效或不在窗口内")
return
print("✓ 鼠标位置有效")
# 获取鼠标位置
mouse_x = self.mouseWatcherNode.getMouseX()
mouse_y = self.mouseWatcherNode.getMouseY()
print(f"📍 鼠标标准化坐标: ({mouse_x:.3f}, {mouse_y:.3f})")
# 转换为窗口坐标
winWidth, winHeight = self.win.getSize()
window_x = (mouse_x + 1) * 0.5 * winWidth
window_y = (1 - mouse_y) * 0.5 * winHeight
print(f"📍 鼠标窗口坐标: ({window_x:.1f}, {window_y:.1f})")
print(f"📐 窗口尺寸: {winWidth} x {winHeight}")
# 检查ImGui是否捕获了鼠标
imgui_captured = self.processImGuiMouseClick(window_x, window_y)
print(f"🖱️ ImGui捕获状态: {imgui_captured}")
if imgui_captured:
print("❌ ImGui处理了该事件跳过3D场景选择")
return
# 调用事件处理器进行射线检测和选择
if hasattr(self, 'event_handler'):
print("✓ 找到事件处理器,开始处理选择")
self.event_handler.mousePressEventLeft({
'x': window_x,
'y': window_y
})
else:
print("❌ 未找到事件处理器")
except Exception as e:
print(f"❌ 处理鼠标点击事件失败: {e}")
import traceback
traceback.print_exc()
def onMouseRelease(self):
"""处理鼠标释放事件"""
try:
# 检查鼠标是否有效
if not self.mouseWatcherNode.hasMouse():
return
# 获取鼠标位置
mouse_x = self.mouseWatcherNode.getMouseX()
mouse_y = self.mouseWatcherNode.getMouseY()
# 转换为窗口坐标
winWidth, winHeight = self.win.getSize()
window_x = (mouse_x + 1) * 0.5 * winWidth
window_y = (1 - mouse_y) * 0.5 * winHeight
# 调用事件处理器
if hasattr(self, 'event_handler'):
self.event_handler.mouseReleaseEventLeft({
'x': window_x,
'y': window_y
})
except Exception as e:
print(f"处理鼠标释放事件失败: {e}")
def onMouseMove(self):
"""处理鼠标移动事件"""
try:
# 检查鼠标是否有效
if not self.mouseWatcherNode.hasMouse():
return
# 获取鼠标位置
mouse_x = self.mouseWatcherNode.getMouseX()
mouse_y = self.mouseWatcherNode.getMouseY()
# 转换为窗口坐标
winWidth, winHeight = self.win.getSize()
window_x = (mouse_x + 1) * 0.5 * winWidth
window_y = (1 - mouse_y) * 0.5 * winHeight
# 调用事件处理器
if hasattr(self, 'event_handler'):
self.event_handler.mouseMoveEvent({
'x': window_x,
'y': window_y
})
except Exception as e:
print(f"处理鼠标移动事件失败: {e}")
def enableModelCollisionDetection(self, enable=True, frequency=0.1, threshold=0.5):
"""启用模型间碰撞检测"""
return self.collision_manager.enableModelCollisionDetection(enable, frequency, threshold)
def __toggleImgui(self):
if not self.imgui.isKeyboardCaptured():
self.imgui.toggle()
def __newFrame(self):
# Dear ImGui commands can be placed here.
# 创建全屏DockSpace在第一帧之后创建
if imgui.get_frame_count() > 0:
viewport = imgui.get_main_viewport()
imgui.dock_space_over_viewport(0, viewport, imgui.DockNodeFlags_.passthru_central_node)
# 在第一帧应用样式
if imgui.get_frame_count() == 0:
self.style_manager.apply_style()
# 加载图标
self.icons = {
'select': self.style_manager.load_icon('select_tool'),
'move': self.style_manager.load_icon('move_tool'),
'rotate': self.style_manager.load_icon('rotate_tool'),
'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'),
}
# 简化字体加载(只使用中文字体)
try:
# 清除现有字体
self.imgui.io.fonts.clear()
# 尝试加载中文字体
import platform
from pathlib import Path
system = platform.system().lower()
if system == "linux":
font_path = "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"
elif system == "windows":
font_path = "C:/Windows/Fonts/msyh.ttc"
elif system == "darwin":
font_path = "/System/Library/Fonts/PingFang.ttc"
else:
font_path = None
if font_path and Path(font_path).exists():
self.imgui.io.fonts.add_font_from_file_ttf(font_path, 14.0)
print(f"✓ 中文字体加载成功: {font_path}")
else:
# 回退到原来的字体
fallback_font_path = "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc"
if fallback_font_path and Path(fallback_font_path).exists():
self.imgui.io.fonts.add_font_from_file_ttf(fallback_font_path, 14.0)
print(f"✓ 回退字体加载成功: {fallback_font_path}")
else:
self.imgui.io.fonts.add_font_default()
print("✓ 使用默认字体")
except Exception as e:
print(f"⚠ 字体初始化失败: {e}")
try:
self.imgui.io.fonts.add_font_default()
print("✓ 使用备用默认字体")
except:
pass
# 获取窗口尺寸
display_size = imgui.get_io().display_size
window_width = display_size.x
window_height = display_size.y
# 每帧重置窗口命中区域,由各面板绘制时重新填充
self._resource_manager_window_rect = None
self._resource_drop_targets = []
self._scene_tree_window_rect = None
self._property_panel_window_rect = None
self._script_panel_window_rect = None
self._console_window_rect = None
self._toolbar_window_rect = None
self._drag_scene_tree_hover_node = None
# 绘制菜单栏
self._draw_menu_bar()
# 绘制停靠布局
self._draw_docked_layout(window_width, window_height)
# 处理系统层外部拖入
self._process_external_drop_events()
# 绘制纹理测试窗口
if self.testTexture:
with self.style_manager.begin_styled_window("Texture Test", True,
imgui.WindowFlags_.always_auto_resize) as (_, windowOpen):
if not windowOpen:
self.imgui.removeTexture(self.testTexture)
self.testTexture = None
return
imgui.image(self.testTexture, (256, 256))
# 绘制ImGui演示窗口
if self.showDemoWindow:
imgui.show_demo_window()
# 绘制对话框
self._draw_new_project_dialog()
self._draw_open_project_dialog()
self._draw_path_browser()
self._draw_import_dialog()
# 绘制颜色选择器
self._draw_color_picker()
# 绘制字体选择器
self._draw_font_selector()
# 绘制创建功能对话框
self._draw_3d_text_dialog()
self._draw_3d_image_dialog()
self._draw_gui_button_dialog()
self._draw_gui_label_dialog()
self._draw_gui_entry_dialog()
self._draw_gui_image_dialog()
self._draw_video_screen_dialog()
self._draw_2d_video_screen_dialog()
self._draw_spherical_video_dialog()
self._draw_virtual_screen_dialog()
self._draw_spot_light_dialog()
self._draw_point_light_dialog()
self._draw_terrain_dialog()
self._draw_heightmap_browser()
self._draw_script_dialog()
# 绘制纹理选择对话框
self._draw_texture_file_dialog()
self._draw_script_browser()
# 绘制右键菜单
self._draw_context_menus()
# 绘制拖拽界面
self._draw_drag_drop_interface()
# 绘制LUI编辑器
if self.showLUIEditor and hasattr(self, 'lui_manager'):
self.lui_manager.draw_editor()
# 更新变换监控
dt = imgui.get_io().delta_time
self.update_transform_monitoring(dt)
def _draw_docked_layout(self, window_width, window_height):
"""绘制可停靠的布局(支持拖拽)"""
# 左侧场景树面板
if self.showSceneTree:
self._draw_scene_tree()
# 资源管理器面板
if self.showResourceManager:
self._draw_resource_manager()
# 属性面板
if self.showPropertyPanel:
self._draw_property_panel()
# 脚本面板
if self.showScriptPanel:
self._draw_script_panel()
# 底部控制台
if self.showConsole:
self._draw_console()
# 顶部工具栏
if self.showToolbar:
self._draw_toolbar()
def _sync_rp_light_from_node(self, node):
"""将灯光包装节点的位置同步到 RenderPipeline 灯光对象。"""
try:
if not node or node.isEmpty() or (not node.hasPythonTag("rp_light_object")):
# 兼容旧场景:仅有 light_type 标签时尝试补绑 rp_light_object
if not node or node.isEmpty() or (not node.hasTag("light_type")):
return False
scene_manager = getattr(self, "scene_manager", None)
if scene_manager:
try:
light_type = node.getTag("light_type")
if light_type == "spot_light" and hasattr(scene_manager, "_recreateSpotLight"):
scene_manager._recreateSpotLight(node)
elif light_type == "point_light" and hasattr(scene_manager, "_recreatePointLight"):
scene_manager._recreatePointLight(node)
except Exception:
pass
light_obj = node.getPythonTag("rp_light_object") if node.hasPythonTag("rp_light_object") else None
if not light_obj:
return False
world_pos = node.getPos(self.render)
try:
light_obj.setPos(world_pos)
except Exception:
try:
light_obj.setPos(world_pos.x, world_pos.y, world_pos.z)
except Exception:
try:
light_obj.pos = Point3(world_pos)
except Exception:
return False
return True
except Exception:
return False
def _on_transform_gizmo_drag_event(self, payload):
"""TransformGizmo 拖拽事件回调:实时同步灯光位置。"""
try:
node = payload.get("target") if isinstance(payload, dict) else None
if node and (not node.isEmpty()):
self._sync_rp_light_from_node(node)
except Exception:
pass
def _setup_transform_gizmo_light_sync(self):
"""为 newTransform 注册灯光同步事件钩子。"""
tg = getattr(self, "newTransform", None)
if not tg:
return
try:
from TransformGizmo.events import GizmoEvent
hooks = {
"move": {
GizmoEvent.DRAG_MOVE: [self._on_transform_gizmo_drag_event],
GizmoEvent.DRAG_END: [self._on_transform_gizmo_drag_event],
},
"rotate": {
GizmoEvent.DRAG_MOVE: [self._on_transform_gizmo_drag_event],
GizmoEvent.DRAG_END: [self._on_transform_gizmo_drag_event],
},
"scale": {
GizmoEvent.DRAG_MOVE: [self._on_transform_gizmo_drag_event],
GizmoEvent.DRAG_END: [self._on_transform_gizmo_drag_event],
},
}
tg.set_event_hooks(hooks, replace=False)
except Exception as e:
print(f"绑定 TransformGizmo 灯光同步事件失败: {e}")
def _draw_menu_bar(self):
self.editor_panels.draw_menu_bar()
def _draw_toolbar(self):
self.editor_panels.draw_toolbar()
def _draw_scene_tree(self, *args, **kwargs):
return self.editor_panels._draw_scene_tree(*args, **kwargs)
def _build_scene_tree(self, *args, **kwargs):
return self.editor_panels._build_scene_tree(*args, **kwargs)
def _draw_scene_node(self, *args, **kwargs):
return self.editor_panels._draw_scene_node(*args, **kwargs)
def _show_node_context_menu(self, *args, **kwargs):
return self.editor_panels._show_node_context_menu(*args, **kwargs)
def _draw_resource_manager(self, *args, **kwargs):
return self.editor_panels._draw_resource_manager(*args, **kwargs)
def _draw_property_panel(self, *args, **kwargs):
return self.editor_panels._draw_property_panel(*args, **kwargs)
def _draw_node_properties(self, *args, **kwargs):
return self.editor_panels._draw_node_properties(*args, **kwargs)
def _getActor(self, *args, **kwargs):
return self.animation_tools._getActor(*args, **kwargs)
def _getModelFormat(self, *args, **kwargs):
return self.animation_tools._getModelFormat(*args, **kwargs)
def _processAnimationNames(self, *args, **kwargs):
return self.animation_tools._processAnimationNames(*args, **kwargs)
def _isLikelyBoneGroup(self, *args, **kwargs):
return self.animation_tools._isLikelyBoneGroup(*args, **kwargs)
def _analyzeAnimationQuality(self, *args, **kwargs):
return self.animation_tools._analyzeAnimationQuality(*args, **kwargs)
def _playAnimation(self, *args, **kwargs):
return self.animation_tools._playAnimation(*args, **kwargs)
def _pauseAnimation(self, *args, **kwargs):
return self.animation_tools._pauseAnimation(*args, **kwargs)
def _stopAnimation(self, *args, **kwargs):
return self.animation_tools._stopAnimation(*args, **kwargs)
def _loopAnimation(self, *args, **kwargs):
return self.animation_tools._loopAnimation(*args, **kwargs)
def _setAnimationSpeed(self, *args, **kwargs):
return self.animation_tools._setAnimationSpeed(*args, **kwargs)
def _clear_animation_cache(self, *args, **kwargs):
return self.animation_tools._clear_animation_cache(*args, **kwargs)
def _get_node_type_from_node(self, node):
"""从节点判断其类型"""
# 检查是否为GUI元素
if hasattr(node, 'getPythonTag') and node.getPythonTag('gui_element'):
return "GUI元素"
# 检查是否为光源
node_name = node.getName() or ""
if "light" in node_name.lower() or "Light" in node_name:
return "光源"
# 检查是否为相机
if "camera" in node_name.lower() or "Camera" in node_name:
return "相机"
# 检查是否为模型
if hasattr(self, 'scene_manager') and self.scene_manager:
if hasattr(self.scene_manager, 'models') and node in self.scene_manager.models:
return "模型"
# 默认为几何体
return "几何体"
def _draw_status_badges(self, *args, **kwargs):
return self.editor_panels._draw_status_badges(*args, **kwargs)
def _draw_transform_properties(self, *args, **kwargs):
return self.editor_panels._draw_transform_properties(*args, **kwargs)
def _draw_gui_properties(self, *args, **kwargs):
return self.editor_panels._draw_gui_properties(*args, **kwargs)
def _draw_light_properties(self, *args, **kwargs):
return self.editor_panels._draw_light_properties(*args, **kwargs)
def _draw_model_properties(self, *args, **kwargs):
return self.editor_panels._draw_model_properties(*args, **kwargs)
def _draw_animation_properties(self, *args, **kwargs):
return self.editor_panels._draw_animation_properties(*args, **kwargs)
def _draw_collision_properties(self, *args, **kwargs):
return self.editor_panels._draw_collision_properties(*args, **kwargs)
def _draw_shape_specific_parameters(self, *args, **kwargs):
return self.editor_panels._draw_shape_specific_parameters(*args, **kwargs)
def _draw_sphere_parameters(self, *args, **kwargs):
return self.editor_panels._draw_sphere_parameters(*args, **kwargs)
def _draw_box_parameters(self, *args, **kwargs):
return self.editor_panels._draw_box_parameters(*args, **kwargs)
def _draw_capsule_parameters(self, *args, **kwargs):
return self.editor_panels._draw_capsule_parameters(*args, **kwargs)
def _draw_plane_parameters(self, *args, **kwargs):
return self.editor_panels._draw_plane_parameters(*args, **kwargs)
def _draw_property_actions(self, *args, **kwargs):
return self.editor_panels._draw_property_actions(*args, **kwargs)
def _draw_appearance_properties(self, *args, **kwargs):
return self.editor_panels._draw_appearance_properties(*args, **kwargs)
def _draw_material_properties(self, *args, **kwargs):
return self.editor_panels._draw_material_properties(*args, **kwargs)
def _draw_shading_model_panel(self, *args, **kwargs):
return self.editor_panels._draw_shading_model_panel(*args, **kwargs)
def _apply_gui_font(self, *args, **kwargs):
return self.property_helpers._apply_gui_font(*args, **kwargs)
def _apply_gui_font_size(self, *args, **kwargs):
return self.property_helpers._apply_gui_font_size(*args, **kwargs)
def _apply_gui_font_style(self, *args, **kwargs):
return self.property_helpers._apply_gui_font_style(*args, **kwargs)
def _has_collision(self, *args, **kwargs):
return self.property_helpers._has_collision(*args, **kwargs)
def _get_current_collision_shape(self, *args, **kwargs):
return self.property_helpers._get_current_collision_shape(*args, **kwargs)
def _get_current_collision_shape_type(self, *args, **kwargs):
return self.property_helpers._get_current_collision_shape_type(*args, **kwargs)
def _get_collision_position_offset(self, *args, **kwargs):
return self.property_helpers._get_collision_position_offset(*args, **kwargs)
def _is_collision_visible(self, *args, **kwargs):
return self.property_helpers._is_collision_visible(*args, **kwargs)
def _add_collision_to_node(self, *args, **kwargs):
return self.property_helpers._add_collision_to_node(*args, **kwargs)
def _remove_collision_from_node(self, *args, **kwargs):
return self.property_helpers._remove_collision_from_node(*args, **kwargs)
def _toggle_collision_visibility(self, *args, **kwargs):
return self.property_helpers._toggle_collision_visibility(*args, **kwargs)
def _update_collision_position(self, *args, **kwargs):
return self.property_helpers._update_collision_position(*args, **kwargs)
def _get_shape_type_from_name(self, *args, **kwargs):
return self.property_helpers._get_shape_type_from_name(*args, **kwargs)
def _get_sphere_radius(self, *args, **kwargs):
return self.property_helpers._get_sphere_radius(*args, **kwargs)
def _update_sphere_radius(self, *args, **kwargs):
return self.property_helpers._update_sphere_radius(*args, **kwargs)
def _get_box_size(self, *args, **kwargs):
return self.property_helpers._get_box_size(*args, **kwargs)
def _update_box_size(self, *args, **kwargs):
return self.property_helpers._update_box_size(*args, **kwargs)
def _get_capsule_radius(self, *args, **kwargs):
return self.property_helpers._get_capsule_radius(*args, **kwargs)
def _update_capsule_radius(self, *args, **kwargs):
return self.property_helpers._update_capsule_radius(*args, **kwargs)
def _get_capsule_height(self, *args, **kwargs):
return self.property_helpers._get_capsule_height(*args, **kwargs)
def _update_capsule_height(self, *args, **kwargs):
return self.property_helpers._update_capsule_height(*args, **kwargs)
def _get_plane_normal(self, *args, **kwargs):
return self.property_helpers._get_plane_normal(*args, **kwargs)
def _update_plane_normal(self, *args, **kwargs):
return self.property_helpers._update_plane_normal(*args, **kwargs)
def _manual_collision_detection(self, *args, **kwargs):
return self.property_helpers._manual_collision_detection(*args, **kwargs)
def _update_node_name(self, *args, **kwargs):
return self.property_helpers._update_node_name(*args, **kwargs)
def _get_material_base_color(self, *args, **kwargs):
return self.property_helpers._get_material_base_color(*args, **kwargs)
def _update_material_base_color(self, *args, **kwargs):
return self.property_helpers._update_material_base_color(*args, **kwargs)
def _update_material_roughness(self, *args, **kwargs):
return self.property_helpers._update_material_roughness(*args, **kwargs)
def _update_material_metallic(self, *args, **kwargs):
return self.property_helpers._update_material_metallic(*args, **kwargs)
def _update_material_ior(self, *args, **kwargs):
return self.property_helpers._update_material_ior(*args, **kwargs)
def _apply_material_preset(self, *args, **kwargs):
return self.property_helpers._apply_material_preset(*args, **kwargs)
def _apply_material_to_node(self, *args, **kwargs):
return self.property_helpers._apply_material_to_node(*args, **kwargs)
def _reset_material(self, *args, **kwargs):
return self.property_helpers._reset_material(*args, **kwargs)
def _select_texture_for_material(self, *args, **kwargs):
return self.property_helpers._select_texture_for_material(*args, **kwargs)
def _apply_texture_to_material(self, *args, **kwargs):
return self.property_helpers._apply_texture_to_material(*args, **kwargs)
def _clear_all_textures(self, *args, **kwargs):
return self.property_helpers._clear_all_textures(*args, **kwargs)
def _display_current_textures(self, *args, **kwargs):
return self.property_helpers._display_current_textures(*args, **kwargs)
def _update_shading_model(self, *args, **kwargs):
return self.property_helpers._update_shading_model(*args, **kwargs)
def _update_transparency(self, *args, **kwargs):
return self.property_helpers._update_transparency(*args, **kwargs)
def _draw_texture_file_dialog(self, *args, **kwargs):
return self.property_helpers._draw_texture_file_dialog(*args, **kwargs)
def start_transform_monitoring(self, *args, **kwargs):
return self.property_helpers.start_transform_monitoring(*args, **kwargs)
def stop_transform_monitoring(self, *args, **kwargs):
return self.property_helpers.stop_transform_monitoring(*args, **kwargs)
def _update_last_transform_values(self, *args, **kwargs):
return self.property_helpers._update_last_transform_values(*args, **kwargs)
def _check_transform_changes(self, *args, **kwargs):
return self.property_helpers._check_transform_changes(*args, **kwargs)
def update_transform_monitoring(self, *args, **kwargs):
return self.property_helpers.update_transform_monitoring(*args, **kwargs)
def show_color_picker(self, *args, **kwargs):
return self.property_helpers.show_color_picker(*args, **kwargs)
def _draw_color_picker(self, *args, **kwargs):
return self.property_helpers._draw_color_picker(*args, **kwargs)
def _apply_color_selection(self, *args, **kwargs):
return self.property_helpers._apply_color_selection(*args, **kwargs)
def _draw_color_button(self, *args, **kwargs):
return self.property_helpers._draw_color_button(*args, **kwargs)
def _refresh_available_fonts(self, *args, **kwargs):
return self.property_helpers._refresh_available_fonts(*args, **kwargs)
def show_font_selector(self, *args, **kwargs):
return self.property_helpers.show_font_selector(*args, **kwargs)
def _draw_font_selector(self, *args, **kwargs):
return self.property_helpers._draw_font_selector(*args, **kwargs)
def _apply_font_selection(self, *args, **kwargs):
return self.property_helpers._apply_font_selection(*args, **kwargs)
def _draw_font_selector_button(self, *args, **kwargs):
return self.property_helpers._draw_font_selector_button(*args, **kwargs)
def _draw_console(self, *args, **kwargs):
return self.script_panels._draw_console(*args, **kwargs)
def _draw_script_panel(self, *args, **kwargs):
return self.script_panels._draw_script_panel(*args, **kwargs)
def _draw_script_status_group(self, *args, **kwargs):
return self.script_panels._draw_script_status_group(*args, **kwargs)
def _draw_create_script_group(self, *args, **kwargs):
return self.script_panels._draw_create_script_group(*args, **kwargs)
def _draw_available_scripts_group(self, *args, **kwargs):
return self.script_panels._draw_available_scripts_group(*args, **kwargs)
def _draw_script_mounting_group(self, *args, **kwargs):
return self.script_panels._draw_script_mounting_group(*args, **kwargs)
def _toggle_hot_reload(self, *args, **kwargs):
return self.app_actions._toggle_hot_reload(*args, **kwargs)
def _create_new_script(self, *args, **kwargs):
return self.app_actions._create_new_script(*args, **kwargs)
def _refresh_scripts_list(self, *args, **kwargs):
return self.app_actions._refresh_scripts_list(*args, **kwargs)
def _reload_all_scripts(self, *args, **kwargs):
return self.app_actions._reload_all_scripts(*args, **kwargs)
def _on_script_selected(self, *args, **kwargs):
return self.app_actions._on_script_selected(*args, **kwargs)
def _edit_script(self, *args, **kwargs):
return self.app_actions._edit_script(*args, **kwargs)
def _mount_script_to_selected(self, *args, **kwargs):
return self.app_actions._mount_script_to_selected(*args, **kwargs)
def _unmount_script_from_selected(self, *args, **kwargs):
return self.app_actions._unmount_script_from_selected(*args, **kwargs)
def _on_new_project(self, *args, **kwargs):
return self.app_actions._on_new_project(*args, **kwargs)
def _on_open_project(self, *args, **kwargs):
return self.app_actions._on_open_project(*args, **kwargs)
def _on_save_project(self, *args, **kwargs):
return self.app_actions._on_save_project(*args, **kwargs)
def _on_save_as_project(self, *args, **kwargs):
return self.app_actions._on_save_as_project(*args, **kwargs)
def _on_exit(self, *args, **kwargs):
return self.app_actions._on_exit(*args, **kwargs)
def _on_ctrl_pressed(self, *args, **kwargs):
return self.app_actions._on_ctrl_pressed(*args, **kwargs)
def _on_ctrl_released(self, *args, **kwargs):
return self.app_actions._on_ctrl_released(*args, **kwargs)
def _on_alt_pressed(self, *args, **kwargs):
return self.app_actions._on_alt_pressed(*args, **kwargs)
def _on_alt_released(self, *args, **kwargs):
return self.app_actions._on_alt_released(*args, **kwargs)
def _on_n_pressed(self, *args, **kwargs):
return self.app_actions._on_n_pressed(*args, **kwargs)
def _on_o_pressed(self, *args, **kwargs):
return self.app_actions._on_o_pressed(*args, **kwargs)
def _on_f4_pressed(self, *args, **kwargs):
return self.app_actions._on_f4_pressed(*args, **kwargs)
def _on_delete_pressed(self, *args, **kwargs):
return self.app_actions._on_delete_pressed(*args, **kwargs)
def _on_escape_pressed(self, *args, **kwargs):
return self.app_actions._on_escape_pressed(*args, **kwargs)
def _on_wheel_up(self, *args, **kwargs):
return self.app_actions._on_wheel_up(*args, **kwargs)
def _on_wheel_down(self, *args, **kwargs):
return self.app_actions._on_wheel_down(*args, **kwargs)
def _is_mouse_over_imgui(self, *args, **kwargs):
return self.app_actions._is_mouse_over_imgui(*args, **kwargs)
def processImGuiMouseClick(self, *args, **kwargs):
return self.app_actions.processImGuiMouseClick(*args, **kwargs)
def add_message(self, *args, **kwargs):
return self.app_actions.add_message(*args, **kwargs)
def add_success_message(self, *args, **kwargs):
return self.app_actions.add_success_message(*args, **kwargs)
def add_error_message(self, *args, **kwargs):
return self.app_actions.add_error_message(*args, **kwargs)
def add_warning_message(self, *args, **kwargs):
return self.app_actions.add_warning_message(*args, **kwargs)
def add_info_message(self, *args, **kwargs):
return self.app_actions.add_info_message(*args, **kwargs)
def _on_undo(self, *args, **kwargs):
return self.app_actions._on_undo(*args, **kwargs)
def _on_redo(self, *args, **kwargs):
return self.app_actions._on_redo(*args, **kwargs)
def _on_copy(self, *args, **kwargs):
return self.app_actions._on_copy(*args, **kwargs)
def _on_cut(self, *args, **kwargs):
return self.app_actions._on_cut(*args, **kwargs)
def _on_paste(self, *args, **kwargs):
return self.app_actions._on_paste(*args, **kwargs)
def _on_delete(self, *args, **kwargs):
return self.app_actions._on_delete(*args, **kwargs)
def _delete_node(self, *args, **kwargs):
return self.app_actions._delete_node(*args, **kwargs)
def _perform_node_cleanup(self, *args, **kwargs):
return self.app_actions._perform_node_cleanup(*args, **kwargs)
def _create_new_project(self, *args, **kwargs):
return self.app_actions._create_new_project(*args, **kwargs)
def _open_project_path(self, *args, **kwargs):
return self.app_actions._open_project_path(*args, **kwargs)
def _save_project_impl(self, *args, **kwargs):
return self.app_actions._save_project_impl(*args, **kwargs)
def _open_project_impl(self, *args, **kwargs):
return self.app_actions._open_project_impl(*args, **kwargs)
def _create_new_project_impl(self, *args, **kwargs):
return self.app_actions._create_new_project_impl(*args, **kwargs)
def _update_window_title(self, *args, **kwargs):
return self.app_actions._update_window_title(*args, **kwargs)
def _import_model_for_runtime(self, *args, **kwargs):
return self.app_actions._import_model_for_runtime(*args, **kwargs)
def _on_import_model(self, *args, **kwargs):
return self.app_actions._on_import_model(*args, **kwargs)
def _import_model(self, *args, **kwargs):
return self.app_actions._import_model(*args, **kwargs)
def _draw_new_project_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_new_project_dialog(*args, **kwargs)
def _draw_open_project_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_open_project_dialog(*args, **kwargs)
def _draw_path_browser(self, *args, **kwargs):
return self.dialog_panels._draw_path_browser(*args, **kwargs)
def _draw_import_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_import_dialog(*args, **kwargs)
def _refresh_path_browser(self, *args, **kwargs):
return self.dialog_panels._refresh_path_browser(*args, **kwargs)
def _apply_selected_path(self, *args, **kwargs):
return self.dialog_panels._apply_selected_path(*args, **kwargs)
def _draw_gui_button_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_gui_button_dialog(*args, **kwargs)
def _draw_gui_label_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_gui_label_dialog(*args, **kwargs)
def _draw_gui_entry_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_gui_entry_dialog(*args, **kwargs)
def _draw_gui_image_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_gui_image_dialog(*args, **kwargs)
def _draw_3d_text_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_3d_text_dialog(*args, **kwargs)
def _draw_3d_image_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_3d_image_dialog(*args, **kwargs)
def _draw_video_screen_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_video_screen_dialog(*args, **kwargs)
def _draw_2d_video_screen_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_2d_video_screen_dialog(*args, **kwargs)
def _draw_spherical_video_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_spherical_video_dialog(*args, **kwargs)
def _draw_virtual_screen_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_virtual_screen_dialog(*args, **kwargs)
def _draw_spot_light_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_spot_light_dialog(*args, **kwargs)
def _draw_point_light_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_point_light_dialog(*args, **kwargs)
def _draw_terrain_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_terrain_dialog(*args, **kwargs)
def _draw_script_dialog(self, *args, **kwargs):
return self.dialog_panels._draw_script_dialog(*args, **kwargs)
def _draw_script_browser(self, *args, **kwargs):
return self.dialog_panels._draw_script_browser(*args, **kwargs)
def _refresh_script_browser(self, *args, **kwargs):
return self.dialog_panels._refresh_script_browser(*args, **kwargs)
def _draw_heightmap_browser(self, *args, **kwargs):
return self.dialog_panels._draw_heightmap_browser(*args, **kwargs)
def _refresh_heightmap_browser(self, *args, **kwargs):
return self.dialog_panels._refresh_heightmap_browser(*args, **kwargs)
def setup_drag_drop_support(self):
"""初始化拖拽支持。"""
return self.model_drag_drop.setup_drag_drop_support()
def _is_point_in_resource_manager(self, drop_pos):
"""判断投放坐标是否命中资源管理器窗口。"""
return self.model_drag_drop.is_point_in_resource_manager(drop_pos)
def _resolve_resource_drop_target_dir(self, drop_pos):
"""根据投放坐标解析资源管理器中的目标目录。"""
return self.model_drag_drop.resolve_resource_drop_target_dir(drop_pos)
def _process_external_drop_events(self):
"""处理外部拖入(系统文件拖拽)事件。"""
return self.model_drag_drop.process_external_drop_events()
def _handle_external_drop(self, file_paths, drop_pos=None):
"""把外部拖入文件分发到资源管理器或场景。"""
return self.model_drag_drop.handle_external_drop(file_paths, drop_pos)
def add_dragged_file(self, file_path):
"""添加拖拽的文件"""
return self.model_drag_drop.add_dragged_file(file_path)
def clear_dragged_files(self):
"""清空拖拽文件列表"""
return self.model_drag_drop.clear_dragged_files()
def process_dragged_files(self):
"""处理拖拽的文件"""
return self.model_drag_drop.process_dragged_files()
def _import_model_from_path(self, file_path):
"""从路径导入模型的内部方法"""
return self.model_drag_drop.import_model_from_path(file_path)
def _draw_drag_drop_interface(self, *args, **kwargs):
return self.interaction_panels._draw_drag_drop_interface(*args, **kwargs)
def _handle_drag_drop_completion(self, *args, **kwargs):
return self.interaction_panels._handle_drag_drop_completion(*args, **kwargs)
def _draw_drag_overlay(self, *args, **kwargs):
return self.interaction_panels._draw_drag_overlay(*args, **kwargs)
def _draw_drag_status(self, *args, **kwargs):
return self.interaction_panels._draw_drag_status(*args, **kwargs)
def _draw_context_menus(self, *args, **kwargs):
return self.interaction_panels._draw_context_menus(*args, **kwargs)
def _delete_node_simple(self, *args, **kwargs):
return self.interaction_panels._delete_node_simple(*args, **kwargs)
def _copy_node(self, *args, **kwargs):
return self.interaction_panels._copy_node(*args, **kwargs)
def _on_create_empty_object(self, *args, **kwargs):
return self.create_actions._on_create_empty_object(*args, **kwargs)
def _on_create_cube(self, *args, **kwargs):
return self.create_actions._on_create_cube(*args, **kwargs)
def _on_create_sphere(self, *args, **kwargs):
return self.create_actions._on_create_sphere(*args, **kwargs)
def _on_create_cylinder(self, *args, **kwargs):
return self.create_actions._on_create_cylinder(*args, **kwargs)
def _on_create_plane(self, *args, **kwargs):
return self.create_actions._on_create_plane(*args, **kwargs)
def _on_create_3d_text(self, *args, **kwargs):
return self.create_actions._on_create_3d_text(*args, **kwargs)
def _on_create_3d_image(self, *args, **kwargs):
return self.create_actions._on_create_3d_image(*args, **kwargs)
def _on_create_gui_button(self, *args, **kwargs):
return self.create_actions._on_create_gui_button(*args, **kwargs)
def _on_create_gui_label(self, *args, **kwargs):
return self.create_actions._on_create_gui_label(*args, **kwargs)
def _on_create_gui_entry(self, *args, **kwargs):
return self.create_actions._on_create_gui_entry(*args, **kwargs)
def _on_create_gui_image(self, *args, **kwargs):
return self.create_actions._on_create_gui_image(*args, **kwargs)
def _on_create_video_screen(self, *args, **kwargs):
return self.create_actions._on_create_video_screen(*args, **kwargs)
def _on_create_2d_video_screen(self, *args, **kwargs):
return self.create_actions._on_create_2d_video_screen(*args, **kwargs)
def _on_create_spherical_video(self, *args, **kwargs):
return self.create_actions._on_create_spherical_video(*args, **kwargs)
def _on_create_virtual_screen(self, *args, **kwargs):
return self.create_actions._on_create_virtual_screen(*args, **kwargs)
def _on_create_spot_light(self, *args, **kwargs):
return self.create_actions._on_create_spot_light(*args, **kwargs)
def _on_create_point_light(self, *args, **kwargs):
return self.create_actions._on_create_point_light(*args, **kwargs)
def _on_create_flat_terrain(self, *args, **kwargs):
return self.create_actions._on_create_flat_terrain(*args, **kwargs)
def _on_create_heightmap_terrain(self, *args, **kwargs):
return self.create_actions._on_create_heightmap_terrain(*args, **kwargs)
def _on_create_script(self, *args, **kwargs):
return self.create_actions._on_create_script(*args, **kwargs)
def _on_load_script(self, *args, **kwargs):
return self.create_actions._on_load_script(*args, **kwargs)
def _on_reload_all_scripts(self, *args, **kwargs):
return self.create_actions._on_reload_all_scripts(*args, **kwargs)
def _on_open_scripts_manager(self, *args, **kwargs):
return self.create_actions._on_open_scripts_manager(*args, **kwargs)
def _on_create_2d_sample_panel(self, *args, **kwargs):
return self.create_actions._on_create_2d_sample_panel(*args, **kwargs)
def _on_create_3d_sample_panel(self, *args, **kwargs):
return self.create_actions._on_create_3d_sample_panel(*args, **kwargs)
def _on_create_web_panel(self, *args, **kwargs):
return self.create_actions._on_create_web_panel(*args, **kwargs)
def createEmptyObject(self, *args, **kwargs):
return self.object_factory.createEmptyObject(*args, **kwargs)
def create3DText(self, *args, **kwargs):
return self.object_factory.create3DText(*args, **kwargs)
def create3DImage(self, *args, **kwargs):
return self.object_factory.create3DImage(*args, **kwargs)
def createCube(self, *args, **kwargs):
return self.object_factory.createCube(*args, **kwargs)
def createSphere(self, *args, **kwargs):
return self.object_factory.createSphere(*args, **kwargs)
def createCylinder(self, *args, **kwargs):
return self.object_factory.createCylinder(*args, **kwargs)
def createPlane(self, *args, **kwargs):
return self.object_factory.createPlane(*args, **kwargs)
def create2DSamplePanel(self, *args, **kwargs):
return self.object_factory.create2DSamplePanel(*args, **kwargs)
def create3DSamplePanel(self, *args, **kwargs):
return self.object_factory.create3DSamplePanel(*args, **kwargs)
def createWebPanel(self, *args, **kwargs):
return self.object_factory.createWebPanel(*args, **kwargs)
def createGUIButton(self, pos=(0, 0, 0), text="按钮", size=0.1):
"""创建2D GUI按钮"""
try:
if hasattr(self, 'gui_manager') and self.gui_manager:
# 使用简化的创建方法不依赖QT树形控件
return self._create_simple_gui_button(pos, text, size)
return None
except Exception as e:
print(f"创建GUI按钮失败: {e}")
return None
def _create_simple_gui_button(self, pos=(0, 0, 0), text="按钮", size=0.1):
"""创建简单的GUI按钮不依赖QT树形控件"""
try:
from direct.gui.DirectGui import DirectButton
from panda3d.core import TextNode
# 转换坐标系统
gui_pos = (pos[0] * 0.1, 0, pos[2] * 0.1)
# 设置中文字体
font = self._get_chinese_font()
# 处理scale参数
if isinstance(size, (list, tuple)) and len(size) >= 2:
scale_value = size[0] # 使用宽度作为缩放值
else:
scale_value = size
# 创建按钮
button = DirectButton(
text=text,
pos=gui_pos,
scale=scale_value,
text_font=font,
command=self._on_gui_button_click
)
# 创建包装对象
button_wrapper = type('GUIElement', (), {})()
button_wrapper.node = button
button_wrapper.name = text
button_wrapper.gui_type = "GUI_BUTTON"
button_wrapper.position = pos
button_wrapper.size = size
# 添加到GUI管理器
self.gui_manager.gui_elements.append(button_wrapper)
print(f"✓ GUI按钮创建成功: {text}")
return button_wrapper
except Exception as e:
print(f"✗ 创建简单GUI按钮失败: {e}")
return None
def _on_gui_button_click(self):
"""GUI按钮点击事件处理"""
print("GUI按钮被点击了")
def _toggle_vr_mode(self):
"""切换VR模式"""
if self.vr_manager:
if self.vr_manager.is_enabled():
self._exit_vr_mode()
else:
self.vr_manager.enable()
self.add_info_message("已进入VR模式")
else:
self.add_error_message("VR管理器未初始化")
def _exit_vr_mode(self):
"""退出VR模式"""
if self.vr_manager:
self.vr_manager.disable()
self.add_info_message("已退出VR模式")
def _show_vr_status(self):
"""显示VR状态"""
if self.vr_manager:
status = "已启用" if self.vr_manager.is_enabled() else "未启用"
self.add_info_message(f"VR状态: {status}")
# 显示设备信息
if self.vr_manager.is_enabled():
devices = self.vr_manager.get_connected_devices()
if devices:
self.add_info_message(f"连接的设备: {', '.join(devices)}")
else:
self.add_info_message("未检测到VR设备")
else:
self.add_error_message("VR管理器未初始化")
def _show_vr_settings(self):
"""显示VR设置"""
if self.vr_manager:
self.add_info_message("VR设置对话框待实现")
else:
self.add_error_message("VR管理器未初始化")
def _show_vr_performance_report(self):
"""显示VR性能报告"""
if self.vr_manager and self.vr_manager.is_enabled():
report = self.vr_manager.get_performance_report()
self.add_info_message(f"VR性能报告: {report}")
else:
self.add_info_message("VR未启用或管理器未初始化")
def _get_chinese_font(self):
"""获取中文字体"""
try:
from panda3d.core import TextNode
import os
from pathlib import Path
# 尝试加载中文字体
font_paths = [
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc", # Linux文泉驿微米黑
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", # Noto Sans CJK
"/System/Library/Fonts/PingFang.ttc", # macOS
"C:/Windows/Fonts/simhei.ttf", # Windows
"C:/Windows/Fonts/msyh.ttc" # Windows微软雅黑
]
for font_path in font_paths:
if Path(font_path).exists():
font = TextNode.getDefaultFont()
# 尝试加载字体
try:
font = self.loader.loadFont(font_path)
print(f"✓ 为GUI加载中文字体成功: {font_path}")
return font
except:
print(f"⚠️ 字体加载失败,尝试下一个: {font_path}")
continue
# 如果所有字体都加载失败,返回默认字体
print("⚠️ 无法加载中文字体,使用默认字体")
return TextNode.getDefaultFont()
except Exception as e:
print(f"⚠️ 获取中文字体失败: {e}")
from panda3d.core import TextNode
return TextNode.getDefaultFont()
def createGUILabel(self, pos=(0, 0, 0), text="标签", size=0.08):
"""创建2D GUI标签"""
try:
if hasattr(self, 'gui_manager') and self.gui_manager:
# 使用简化的创建方法不依赖QT树形控件
return self._create_simple_gui_label(pos, text, size)
return None
except Exception as e:
print(f"创建GUI标签失败: {e}")
return None
def _create_simple_gui_label(self, pos=(0, 0, 0), text="标签", size=0.08):
"""创建简单的GUI标签不依赖QT树形控件"""
try:
from direct.gui.DirectGui import DirectLabel
# 转换坐标系统
gui_pos = (pos[0] * 0.1, 0, pos[2] * 0.1)
# 设置中文字体
font = self._get_chinese_font()
# 处理scale参数
if isinstance(size, (list, tuple)) and len(size) >= 2:
scale_value = size[0] # 使用宽度作为缩放值
else:
scale_value = size
# 创建标签
label = DirectLabel(
text=text,
pos=gui_pos,
scale=scale_value,
text_font=font,
text_fg=(1, 1, 1, 1) # 白色文字
)
# 创建包装对象
label_wrapper = type('GUIElement', (), {})()
label_wrapper.node = label
label_wrapper.name = text
label_wrapper.gui_type = "GUI_LABEL"
label_wrapper.position = pos
label_wrapper.size = size
# 添加到GUI管理器
self.gui_manager.gui_elements.append(label_wrapper)
print(f"✓ GUI标签创建成功: {text}")
return label_wrapper
except Exception as e:
print(f"✗ 创建简单GUI标签失败: {e}")
return None
def createGUIEntry(self, pos=(0, 0, 0), placeholder="输入文本...", size=0.08):
"""创建2D GUI文本输入框"""
try:
if hasattr(self, 'gui_manager') and self.gui_manager:
# 使用简化的创建方法不依赖QT树形控件
return self._create_simple_gui_entry(pos, placeholder, size)
return None
except Exception as e:
print(f"创建GUI输入框失败: {e}")
return None
def _create_simple_gui_entry(self, pos=(0, 0, 0), placeholder="输入文本...", size=0.08):
"""创建简单的GUI输入框不依赖QT树形控件"""
try:
from direct.gui.DirectGui import DirectEntry
# 转换坐标系统
gui_pos = (pos[0] * 0.1, 0, pos[2] * 0.1)
# 设置中文字体
font = self._get_chinese_font()
# 处理scale参数
if isinstance(size, (list, tuple)) and len(size) >= 2:
scale_value = size[0] # 使用宽度作为缩放值
else:
scale_value = size
# 创建输入框
entry = DirectEntry(
text=placeholder,
pos=gui_pos,
scale=scale_value,
text_font=font,
width=20, # 字符宽度
numLines=1, # 行数
focus=1 # 自动获取焦点
)
# 创建包装对象
entry_wrapper = type('GUIElement', (), {})()
entry_wrapper.node = entry
entry_wrapper.name = placeholder
entry_wrapper.gui_type = "GUI_ENTRY"
entry_wrapper.position = pos
entry_wrapper.size = size
# 添加到GUI管理器
self.gui_manager.gui_elements.append(entry_wrapper)
print(f"✓ GUI输入框创建成功: {placeholder}")
return entry_wrapper
except Exception as e:
print(f"✗ 创建简单GUI输入框失败: {e}")
return None
def createGUIImage(self, pos=(0, 0, 0), image_path=None, size=2):
"""创建2D GUI图片"""
try:
if hasattr(self, 'gui_manager') and self.gui_manager:
# 使用简化的创建方法不依赖QT树形控件
return self._create_simple_gui_image(pos, image_path, size)
return None
except Exception as e:
print(f"创建GUI图片失败: {e}")
return None
def _create_simple_gui_image(self, pos=(0, 0, 0), image_path=None, size=2):
"""创建简单的GUI图片不依赖QT树形控件"""
try:
from direct.gui.DirectGui import DirectFrame
from panda3d.core import Filename
# 转换坐标系统
gui_pos = (pos[0] * 0.1, 0, pos[2] * 0.1)
# 处理scale参数
if isinstance(size, (list, tuple)) and len(size) >= 2:
scale_value = size[0] # 使用宽度作为缩放值
else:
scale_value = size
# 创建图片框架
if image_path and os.path.exists(image_path):
# 加载纹理
tex = self.loader.loadTexture(Filename.fromOsSpecific(image_path))
image = DirectFrame(
image=tex,
pos=gui_pos,
scale=scale_value
)
image_name = os.path.basename(image_path)
else:
# 创建一个彩色框架作为占位符
image = DirectFrame(
frameColor=(0.5, 0.5, 0.5, 1.0), # 灰色
frameSize=(-scale_value, scale_value, -scale_value, scale_value),
pos=gui_pos
)
image_name = "占位符图片"
# 创建包装对象
image_wrapper = type('GUIElement', (), {})()
image_wrapper.node = image
image_wrapper.name = image_name
image_wrapper.gui_type = "GUI_IMAGE"
image_wrapper.position = pos
image_wrapper.size = size
image_wrapper.image_path = image_path
# 添加到GUI管理器
self.gui_manager.gui_elements.append(image_wrapper)
print(f"✓ GUI图片创建成功: {image_name}")
return image_wrapper
except Exception as e:
print(f"✗ 创建简单GUI图片失败: {e}")
return None
def createVideoScreen(self, pos=(0, 0, 0), size=1, video_path=None):
"""创建视频屏幕"""
try:
if hasattr(self, 'gui_manager') and self.gui_manager:
return self.gui_manager.createVideoScreen(pos, size, video_path)
return None
except Exception as e:
print(f"创建视频屏幕失败: {e}")
return None
def create2DVideoScreen(self, pos=(0, 0, 0), size=0.2, video_path=None):
"""创建2D视频屏幕"""
try:
if hasattr(self, 'gui_manager') and self.gui_manager:
return self.gui_manager.createGUI2DVideoScreen(pos, size, video_path)
return None
except Exception as e:
print(f"创建2D视频屏幕失败: {e}")
return None
def createSphericalVideo(self, pos=(0, 0, 0), radius=5.0, video_path=None):
"""创建360度视频"""
try:
if hasattr(self, 'gui_manager') and self.gui_manager:
return self.gui_manager.createSphericalVideo(pos, radius, video_path)
return None
except Exception as e:
print(f"创建球形视频失败: {e}")
return None
def createVirtualScreen(self, pos=(0, 0, 0), size=(2, 1), text="虚拟屏幕"):
"""创建虚拟屏幕"""
try:
if hasattr(self, 'gui_manager') and self.gui_manager:
return self.gui_manager.createGUIVirtualScreen(pos, size, text)
return None
except Exception as e:
print(f"创建虚拟屏幕失败: {e}")
return None
# ==================== 光源创建方法 ====================
def createSpotLight(self, pos=(0, 0, 5)):
"""创建聚光灯"""
try:
if hasattr(self, 'scene_manager') and self.scene_manager:
return self.scene_manager.createSpotLight(pos)
return None
except Exception as e:
print(f"创建聚光灯失败: {e}")
return None
def createPointLight(self, pos=(0, 0, 5)):
"""创建点光源"""
try:
if hasattr(self, 'scene_manager') and self.scene_manager:
return self.scene_manager.createPointLight(pos)
return None
except Exception as e:
print(f"创建点光源失败: {e}")
return None
# ==================== 地形创建方法 ====================
def createFlatTerrain(self, size=(10, 10), resolution=129):
"""创建平面地形"""
try:
if hasattr(self, 'terrain_manager') and self.terrain_manager:
return self.terrain_manager.createFlatTerrain(size, resolution)
return None
except Exception as e:
print(f"创建平面地形失败: {e}")
return None
def createTerrainFromHeightMap(self, heightmap_path, scale=(1.0, 1.0, 10.0)):
"""从高度图创建地形"""
try:
if hasattr(self, 'terrain_manager') and self.terrain_manager:
return self.terrain_manager.createTerrainFromHeightMap(heightmap_path, scale)
return None
except Exception as e:
print(f"创建高度图地形失败: {e}")
return None
# ==================== 脚本创建方法 ====================
def createScript(self, script_name, template="basic"):
"""创建脚本"""
try:
if hasattr(self, 'script_manager') and self.script_manager:
return self.script_manager.createScript(script_name, template)
return None
except Exception as e:
print(f"创建脚本失败: {e}")
return None
def loadScript(self, script_path):
"""加载脚本"""
try:
if hasattr(self, 'script_manager') and self.script_manager:
return self.script_manager.loadScript(script_path)
return None
except Exception as e:
print(f"加载脚本失败: {e}")
return None
demo = MyWorld()
demo.run()