ui替换
This commit is contained in:
parent
1ad2086525
commit
3f6ae9185e
@ -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()
|
||||
@ -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
|
||||
Loading…
Reference in New Issue
Block a user