This commit is contained in:
Rowland 2026-01-08 16:32:44 +08:00
parent 1ad2086525
commit 3f6ae9185e
2 changed files with 0 additions and 370 deletions

View File

@ -1,166 +0,0 @@
"""
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()

View File

@ -1,204 +0,0 @@
"""
pyimgui管理器 - 在Panda3D引擎上集成ImGui界面
使用更简单的方法通过创建覆盖层来实现
"""
import imgui
import numpy as np
from panda3d.core import RenderState, ShaderAttrib, Texture, CardMaker, NodePath
from panda3d.core import TransparencyAttrib, ColorBlendAttrib, PNMImage
from panda3d.core import GraphicsOutput, RenderBuffer, TextureStage, TexGenAttrib
from direct.task.Task import Task
from direct.gui.OnscreenImage import OnscreenImage
from direct.gui.OnscreenText import OnscreenText
import PIL.Image
import PIL.ImageDraw
import io
class SimpleImGuiManager:
"""简化的ImGui管理器使用2D覆盖层在Panda3D引擎上显示ImGui界面"""
def __init__(self, world):
self.world = world
self.io = None
self._setup_imgui()
self._create_imgui_task()
# UI状态
self.show_demo_window = False
self.show_test_button = True
self.button_clicked = False
self.counter = 0
# 渲染相关
self.imgui_texture = None
self.imgui_image = None
self.texture_buffer = None
# 创建渲染纹理
self._create_render_texture()
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())
# 设置字体大小
font_size = 16
self.io.font_global_scale = font_size / 13.0
print("✓ ImGui初始化完成")
def _create_render_texture(self):
"""创建用于渲染ImGui的纹理"""
win_props = self.world.win.getProperties()
width = win_props.get_x_size()
height = win_props.get_y_size()
# 创建纹理
self.imgui_texture = Texture()
self.imgui_texture.setup_2d_texture(width, height, Texture.T_unsigned_byte, Texture.F_rgba8)
# 创建屏幕图像
self.imgui_image = OnscreenImage(
image=self.imgui_texture,
pos=(0, 0, 0),
scale=(1, 1, 1)
)
self.imgui_image.setTransparency(TransparencyAttrib.MAlpha)
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到纹理
self._render_to_texture()
return Task.cont
def _draw_ui(self):
"""绘制UI元素"""
# 绘制测试窗口
if self.show_test_button:
imgui.begin("测试窗口", True)
if imgui.button("点击我!"):
self.button_clicked = True
self.counter += 1
print(f"按钮被点击了! 计数: {self.counter}")
if self.button_clicked:
imgui.text(f"按钮已被点击 {self.counter} 次!")
imgui.text("这是一个在Panda3D引擎上显示的ImGui按钮")
imgui.text(f"帧率: {globalClock.getAverageFrameRate():.1f} FPS")
imgui.end()
# 绘制演示窗口(可选)
if self.show_demo_window:
self.show_demo_window = imgui.show_demo_window(self.show_demo_window)
def _render_to_texture(self):
"""将ImGui渲染到纹理"""
# 渲染ImGui
imgui.render()
# 获取绘制数据
draw_data = imgui.get_draw_data()
if draw_data:
# 创建PIL图像
width, height = int(self.io.display_size[0]), int(self.io.display_size[1])
image = PIL.Image.new('RGBA', (width, height), (0, 0, 0, 0))
draw = PIL.ImageDraw.Draw(image)
# 简单的文本渲染这里只是示例实际需要完整的ImGui渲染
if self.show_test_button:
# 绘制简单的按钮模拟
button_x, button_y = 50, 50
button_width, button_height = 100, 30
draw.rectangle([button_x, button_y, button_x + button_width, button_y + button_height],
fill=(100, 100, 200, 255), outline=(255, 255, 255, 255))
draw.text((button_x + 10, button_y + 5), "点击我!", fill=(255, 255, 255, 255))
# 显示点击计数
if self.counter > 0:
draw.text((button_x, button_y + button_height + 10),
f"点击次数: {self.counter}", fill=(255, 255, 255, 255))
# 将PIL图像转换为Panda3D纹理
img_buffer = io.BytesIO()
image.save(img_buffer, format='RGBA')
img_buffer.seek(0)
pnm_image = PNMImage()
pnm_image.read(StringStream(img_buffer.read()))
self.imgui_texture.load(pnm_image)
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_click(self, x, y):
"""处理鼠标点击"""
# 检查是否点击了按钮区域
if self.show_test_button:
button_x, button_y = 50, 50
button_width, button_height = 100, 30
# 转换坐标系Panda3D坐标系原点在屏幕中心
screen_x = (x + self.io.display_size[0] / 2)
screen_y = (self.io.display_size[1] / 2 - y)
if (button_x <= screen_x <= button_x + button_width and
button_y <= screen_y <= button_y + button_height):
self.button_clicked = True
self.counter += 1
print(f"按钮被点击了! 计数: {self.counter}")
def cleanup(self):
"""清理资源"""
if self.imgui_image:
self.imgui_image.removeNode()
if self.imgui_texture:
self.imgui_texture = None
imgui.destroy_context()
# 辅助类用于内存中的字符串流
class StringStream:
"""简单的内存字符串流用于PNMImage读取"""
def __init__(self, data):
self.data = data
self.position = 0
def read(self, size=-1):
if size == -1:
result = self.data[self.position:]
self.position = len(self.data)
else:
result = self.data[self.position:self.position + size]
self.position += size
return result
def seek(self, position):
self.position = position
def tell(self):
return self.position