166 lines
5.3 KiB
Python
166 lines
5.3 KiB
Python
"""
|
||
pyimgui管理器 - 在Panda3D引擎上集成ImGui界面
|
||
"""
|
||
import imgui
|
||
import OpenGL.GL as gl
|
||
from panda3d.core import RenderState, ShaderAttrib, Texture, CardMaker, NodePath
|
||
from panda3d.core import TransparencyAttrib, ColorBlendAttrib
|
||
from direct.task.Task import Task
|
||
import numpy as np
|
||
|
||
class ImGuiManager:
|
||
"""ImGui管理器,负责在Panda3D引擎上渲染ImGui界面"""
|
||
|
||
def __init__(self, world):
|
||
self.world = world
|
||
self.io = None
|
||
self.font_texture = None
|
||
self._setup_imgui()
|
||
self._create_imgui_task()
|
||
|
||
# UI状态
|
||
self.show_demo_window = False
|
||
self.show_test_button = True
|
||
self.button_clicked = False
|
||
|
||
def _setup_imgui(self):
|
||
"""初始化ImGui设置"""
|
||
# 初始化ImGui上下文
|
||
imgui.create_context()
|
||
self.io = imgui.get_io()
|
||
|
||
# 设置显示大小
|
||
win_props = self.world.win.getProperties()
|
||
self.io.display_size = (win_props.get_x_size(), win_props.get_y_size())
|
||
|
||
# 设置渲染回调
|
||
self.io.render_callback = self._render_imgui
|
||
|
||
# 创建字体纹理
|
||
self._create_font_texture()
|
||
|
||
print("✓ ImGui初始化完成")
|
||
|
||
def _create_font_texture(self):
|
||
"""创建ImGui字体纹理"""
|
||
# 获取字体数据
|
||
font_pixels = self.io.fonts.get_tex_data_as_rgba32()
|
||
width, height = self.io.fonts.get_tex_data_as_rgba32()[1]
|
||
|
||
# 创建Panda3D纹理
|
||
self.font_texture = Texture()
|
||
self.font_texture.setup_2d_texture(width, height, Texture.T_unsigned_byte, Texture.F_rgba8)
|
||
self.font_texture.set_ram_image(font_pixels)
|
||
|
||
# 设置纹理ID
|
||
self.io.fonts.tex_id = self.font_texture
|
||
|
||
# 清除字体数据
|
||
self.io.fonts.clear_tex_data()
|
||
|
||
def _render_imgui(self, draw_data):
|
||
"""渲染ImGui绘制数据"""
|
||
if not draw_data:
|
||
return
|
||
|
||
# 设置OpenGL状态
|
||
gl.glEnable(gl.GL_BLEND)
|
||
gl.glBlendEquation(gl.GL_FUNC_ADD)
|
||
gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
|
||
gl.glDisable(gl.GL_CULL_FACE)
|
||
gl.glDisable(gl.GL_DEPTH_TEST)
|
||
gl.glEnable(gl.GL_SCISSOR_TEST)
|
||
|
||
# 设置视口和投影矩阵
|
||
display_w, display_h = self.io.display_size
|
||
gl.glViewport(0, 0, int(display_w), int(display_h))
|
||
|
||
# 获取投影矩阵
|
||
projection_matrix = self._get_projection_matrix()
|
||
gl.glMatrixMode(gl.GL_PROJECTION)
|
||
gl.glLoadMatrixf(projection_matrix)
|
||
|
||
# 渲染每个命令列表
|
||
for commands in draw_data.commands_lists:
|
||
# 渲染命令
|
||
self._render_commands(commands)
|
||
|
||
# 恢复OpenGL状态
|
||
gl.glDisable(gl.GL_SCISSOR_TEST)
|
||
gl.glEnable(gl.GL_DEPTH_TEST)
|
||
|
||
def _get_projection_matrix(self):
|
||
"""获取正交投影矩阵"""
|
||
L, R, T, B = 0, self.io.display_size[0], self.io.display_size[1], 0
|
||
projection_matrix = np.array([
|
||
[2.0/(R-L), 0.0, 0.0, 0.0],
|
||
[0.0, 2.0/(T-B), 0.0, 0.0],
|
||
[0.0, 0.0, -1.0, 0.0],
|
||
[(R+L)/(L-R), (T+B)/(B-T), 0.0, 1.0]
|
||
], dtype=np.float32)
|
||
return projection_matrix
|
||
|
||
def _render_commands(self, commands):
|
||
"""渲染ImGui命令列表"""
|
||
# 这里需要实现具体的渲染逻辑
|
||
# 由于Panda3D的渲染管线与ImGui不完全兼容,我们需要创建一个自定义的渲染方法
|
||
pass
|
||
|
||
def _create_imgui_task(self):
|
||
"""创建ImGui更新任务"""
|
||
taskMgr.add(self._update_imgui, "update_imgui")
|
||
|
||
def _update_imgui(self, task):
|
||
"""更新ImGui界面"""
|
||
# 开始新帧
|
||
imgui.new_frame()
|
||
|
||
# 绘制UI
|
||
self._draw_ui()
|
||
|
||
# 渲染ImGui
|
||
imgui.render()
|
||
|
||
return Task.cont
|
||
|
||
def _draw_ui(self):
|
||
"""绘制UI元素"""
|
||
# 绘制测试按钮
|
||
if self.show_test_button:
|
||
imgui.begin("测试窗口", True)
|
||
if imgui.button("点击我!"):
|
||
self.button_clicked = True
|
||
print("按钮被点击了!")
|
||
|
||
if self.button_clicked:
|
||
imgui.text("按钮已被点击!")
|
||
|
||
imgui.end()
|
||
|
||
# 绘制演示窗口(可选)
|
||
if self.show_demo_window:
|
||
self.show_demo_window = imgui.show_demo_window(self.show_demo_window)
|
||
|
||
def toggle_demo_window(self):
|
||
"""切换演示窗口显示"""
|
||
self.show_demo_window = not self.show_demo_window
|
||
|
||
def toggle_test_button(self):
|
||
"""切换测试按钮显示"""
|
||
self.show_test_button = not self.show_test_button
|
||
|
||
def process_mouse_input(self, button_event):
|
||
"""处理鼠标输入"""
|
||
# 这里需要将Panda3D的鼠标事件转换为ImGui可以理解的事件
|
||
pass
|
||
|
||
def process_keyboard_input(self, key_event):
|
||
"""处理键盘输入"""
|
||
# 这里需要将Panda3D的键盘事件转换为ImGui可以理解的事件
|
||
pass
|
||
|
||
def cleanup(self):
|
||
"""清理资源"""
|
||
if self.font_texture:
|
||
self.font_texture = None
|
||
imgui.destroy_context() |