EG/ui/panels/runtime_actions.py

426 lines
15 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.

import os
from pathlib import Path
from core.editor_context import get_editor_context
class RuntimeActions:
"""Runtime-facing creation and utility actions extracted from main world."""
def __init__(self, app):
self.app = app
object.__setattr__(self, "_editor_context", get_editor_context(app))
def __getattr__(self, name):
return getattr(self.app, name)
def __setattr__(self, name, value):
if name == "app" or name.startswith("_") or name in self.__dict__ or hasattr(type(self), name):
object.__setattr__(self, name, value)
else:
setattr(self.app, name, value)
def _get_editor_context(self):
context = getattr(self, "_editor_context", None)
if context is None:
context = get_editor_context(self.app)
object.__setattr__(self, "_editor_context", context)
return context
def _get_gui_manager(self):
"""统一获取 GUI 管理器,避免散落的 hasattr 判空。"""
return self._get_editor_context().get_gui_manager()
def _append_gui_element(self, element_wrapper):
"""统一维护 gui_elements 列表。"""
gui_manager = self._get_gui_manager()
if not gui_manager:
return False
self._get_editor_context().append_gui_element(element_wrapper)
return True
def createGUIButton(self, pos=(0, 0, 0), text="按钮", size=0.1):
"""创建2D GUI按钮"""
try:
if self._get_gui_manager():
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
gui_pos = (pos[0] * 0.1, 0, pos[2] * 0.1)
font = self._get_chinese_font()
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
if not self._append_gui_element(button_wrapper):
return None
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
font_paths = [
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
"/System/Library/Fonts/PingFang.ttc",
"C:/Windows/Fonts/simhei.ttf",
"C:/Windows/Fonts/msyh.ttc",
]
for font_path in font_paths:
if Path(font_path).exists():
try:
font = self.loader.loadFont(font_path)
print(f"✓ 为GUI加载中文字体成功: {font_path}")
return font
except Exception:
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 self._get_gui_manager():
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()
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
if not self._append_gui_element(label_wrapper):
return None
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 self._get_gui_manager():
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()
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
if not self._append_gui_element(entry_wrapper):
return None
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 self._get_gui_manager():
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)
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
if not self._append_gui_element(image_wrapper):
return None
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:
gui_manager = self._get_gui_manager()
if gui_manager:
return 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:
gui_manager = self._get_gui_manager()
if gui_manager:
return 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:
gui_manager = self._get_gui_manager()
if gui_manager:
return 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:
gui_manager = self._get_gui_manager()
if gui_manager:
return 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