This commit is contained in:
Rowland 2026-01-26 10:39:27 +08:00
parent 385103e252
commit 403c4d34f8
4 changed files with 2971 additions and 2803 deletions

View File

@ -6,7 +6,7 @@ class CustomMouseController:
self.showbase = showbase
# This is used to store which keys are currently pressed.
self.keyMap = {
"mouse1": 0,
# "mouse1": 0, # 移除左键,用于选择功能
"mouse3": 0, # 右键
"cam-forward": 0,
"cam-backward": 0,
@ -16,9 +16,9 @@ class CustomMouseController:
"cam-down": 0
}
# 添加鼠标控制
self.showbase.accept("mouse1", self.setKey, ["mouse1", True])
self.showbase.accept("mouse1-up", self.setKey, ["mouse1", False])
# 添加鼠标控制 - 只保留右键控制,左键用于选择
# self.showbase.accept("mouse1", self.setKey, ["mouse1", True]) # 移除左键绑定
# self.showbase.accept("mouse1-up", self.setKey, ["mouse1", False]) # 移除左键绑定
self.showbase.accept("mouse3", self.setKey, ["mouse3", True]) # 右键
self.showbase.accept("mouse3-up", self.setKey, ["mouse3", False]) # 右键释放
@ -49,7 +49,8 @@ class CustomMouseController:
def setKey(self, key, value, arg: str = None):
self.keyMap[key] = value
if (key == "mouse1" or key == "mouse3") and value == True:
# 只在右键按下时记录鼠标位置
if key == "mouse3" and value == True:
mouse_pos = self.showbase.mouseWatcherNode.getMouse()
if mouse_pos:
self.last_mouse_x = mouse_pos.get_x()
@ -72,7 +73,7 @@ class CustomMouseController:
self.showbase.camera.setZ(self.showbase.camera, +self.move_speed * dt)
if self.keyMap["cam-down"]:
self.showbase.camera.setZ(self.showbase.camera, -self.move_speed * dt)
if self.keyMap["mouse1"] or self.keyMap["mouse3"]: # 左键或右键按下
if self.keyMap["mouse3"]: # 只使用右键控制视角旋转
try:
# 检查是否应该处理鼠标事件避免与ImGui冲突
if self._should_handle_mouse():

View File

@ -113,20 +113,21 @@ class EventHandler:
def mousePressEventLeft(self, evt):
"""处理鼠标左键按下事件"""
print("\n=== 开始处理鼠标左键事件 ===")
#print(f"当前工具: {self.world.currentTool}")
print("\n=== EventHandler开始处理鼠标左键事件 ===")
print(f"🔧 当前工具: {getattr(self.world, 'currentTool', '未知')}")
if not evt:
print("事件为空")
print("事件为空")
return
if self.world.currentTool == "地形编辑":
print("🔧 地形编辑模式,调用地形编辑处理")
self._handleTerrainEdit(evt,"add")
return
# 获取鼠标点击的位置
x = evt.get('x', 0)
y = evt.get('y', 0)
#print(f"鼠标点击位置: ({x}, {y})")
print(f"📍 EventHandler收到鼠标点击位置: ({x:.1f}, {y:.1f})")
# 获取准确的窗口尺寸
winWidth, winHeight = self.world.getWindowSize()
@ -184,7 +185,7 @@ class EventHandler:
self.showClickRay(worldNearPoint, worldFarPoint, hitPos)
# 处理ImGui鼠标点击
if hasattr(self.world, 'imgui_manager') and self.world.imgui_manager:
if hasattr(self.world, 'processImGuiMouseClick'):
if self.world.processImGuiMouseClick(x, y):
# 如果ImGui处理了点击不再进行其他处理
pickerNP.removeNode()
@ -484,7 +485,7 @@ class EventHandler:
self.world.selection.updateSelection(selectedModel)
# 在树形控件中查找并选中对应的项
if self.world.interface_manager.treeWidget:
if hasattr(self.world, 'interface_manager') and self.world.interface_manager and hasattr(self.world.interface_manager, 'treeWidget') and self.world.interface_manager.treeWidget:
#print("查找树形控件中的对应项...")
root = self.world.interface_manager.treeWidget.invisibleRootItem()
foundItem = None

File diff suppressed because it is too large Load Diff

140
demo.py
View File

@ -122,6 +122,13 @@ class MyWorld(CoreWorld):
self.accept("p",self.onPatrolKeyPressed)
self.accept("P",self.onPatrolKeyPressed)
# 绑定鼠标事件用于3D场景选择
self.accept("mouse1", self.onMouseClick)
self.accept("mouse1-up", self.onMouseRelease)
# 尝试多种鼠标移动事件绑定方式
self.accept("mouse-move", self.onMouseMove)
self.accept("drag", self.onMouseMove)
# 初始化事件处理系统
self.event_handler = EventHandler(self)
@ -480,6 +487,103 @@ class MyWorld(CoreWorld):
except Exception as e:
print(f"处理 F 键事件失败: {e}")
def onMouseClick(self):
"""处理鼠标点击事件"""
print("\n=== 鼠标点击事件触发 ===")
try:
# 检查鼠标是否有效
if not self.mouseWatcherNode.hasMouse():
print("❌ 鼠标无效或不在窗口内")
return
print("✓ 鼠标位置有效")
# 获取鼠标位置
mouse_x = self.mouseWatcherNode.getMouseX()
mouse_y = self.mouseWatcherNode.getMouseY()
print(f"📍 鼠标标准化坐标: ({mouse_x:.3f}, {mouse_y:.3f})")
# 转换为窗口坐标
winWidth, winHeight = self.win.getSize()
window_x = (mouse_x + 1) * 0.5 * winWidth
window_y = (1 - mouse_y) * 0.5 * winHeight
print(f"📍 鼠标窗口坐标: ({window_x:.1f}, {window_y:.1f})")
print(f"📐 窗口尺寸: {winWidth} x {winHeight}")
# 检查ImGui是否捕获了鼠标
imgui_captured = self.processImGuiMouseClick(window_x, window_y)
print(f"🖱️ ImGui捕获状态: {imgui_captured}")
if imgui_captured:
print("❌ ImGui处理了该事件跳过3D场景选择")
return
# 调用事件处理器进行射线检测和选择
if hasattr(self, 'event_handler'):
print("✓ 找到事件处理器,开始处理选择")
self.event_handler.mousePressEventLeft({
'x': window_x,
'y': window_y
})
else:
print("❌ 未找到事件处理器")
except Exception as e:
print(f"❌ 处理鼠标点击事件失败: {e}")
import traceback
traceback.print_exc()
def onMouseRelease(self):
"""处理鼠标释放事件"""
try:
# 检查鼠标是否有效
if not self.mouseWatcherNode.hasMouse():
return
# 获取鼠标位置
mouse_x = self.mouseWatcherNode.getMouseX()
mouse_y = self.mouseWatcherNode.getMouseY()
# 转换为窗口坐标
winWidth, winHeight = self.win.getSize()
window_x = (mouse_x + 1) * 0.5 * winWidth
window_y = (1 - mouse_y) * 0.5 * winHeight
# 调用事件处理器
if hasattr(self, 'event_handler'):
self.event_handler.mouseReleaseEventLeft({
'x': window_x,
'y': window_y
})
except Exception as e:
print(f"处理鼠标释放事件失败: {e}")
def onMouseMove(self):
"""处理鼠标移动事件"""
try:
# 检查鼠标是否有效
if not self.mouseWatcherNode.hasMouse():
return
# 获取鼠标位置
mouse_x = self.mouseWatcherNode.getMouseX()
mouse_y = self.mouseWatcherNode.getMouseY()
# 转换为窗口坐标
winWidth, winHeight = self.win.getSize()
window_x = (mouse_x + 1) * 0.5 * winWidth
window_y = (1 - mouse_y) * 0.5 * winHeight
# 调用事件处理器
if hasattr(self, 'event_handler'):
self.event_handler.mouseMoveEvent({
'x': window_x,
'y': window_y
})
except Exception as e:
print(f"处理鼠标移动事件失败: {e}")
def onPatrolKeyPressed(self):
"""处理 P 键按下事件 - 控制巡检系统"""
try:
@ -904,15 +1008,7 @@ class MyWorld(CoreWorld):
imgui.separator()
imgui.same_line()
# 其他工具按钮
if imgui.button("导入"):
print("导入模型")
imgui.same_line()
if imgui.button("保存"):
print("保存场景")
imgui.same_line()
if imgui.button("播放"):
print("播放动画")
# 工具按钮已移除(导入、保存、播放)
def _draw_scene_tree(self):
"""绘制场景树面板"""
@ -4944,6 +5040,32 @@ class MyWorld(CoreWorld):
print(f"ImGui界面检测失败: {e}")
return False
def processImGuiMouseClick(self, x, y):
"""处理ImGui鼠标点击事件返回是否消费了该事件"""
try:
# ImGui优先策略如果ImGui想要捕获鼠标则由ImGui处理
if hasattr(imgui, 'get_io') and imgui.get_io().want_capture_mouse:
return True
# 检查是否有任何ImGui窗口悬停
try:
if imgui.is_any_window_hovered():
return True
except AttributeError:
# 如果方法不存在,跳过这个检查
pass
# 检查鼠标是否在ImGui界面区域内
if self._is_mouse_over_imgui():
return True
# 如果以上条件都不满足则让3D场景处理该事件
return False
except Exception as e:
print(f"ImGui鼠标点击处理失败: {e}")
return False
# ==================== 消息系统 ====================
def add_message(self, text, color=(1.0, 1.0, 1.0, 1.0)):