EG/core/imgui_manager.py
2026-01-08 16:30:59 +08:00

166 lines
5.3 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.

"""
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()