from direct.task.TaskManagerGlobal import taskMgr class CustomMouseController: def __init__(self, showbase): self.showbase = showbase # This is used to store which keys are currently pressed. self.keyMap = { "mouse1": 0, "mouse3": 0, # 右键 "cam-forward": 0, "cam-backward": 0, "cam-left": 0, "cam-right": 0, "cam-up": 0, "cam-down": 0 } # 添加鼠标控制 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]) # 右键释放 self.showbase.accept("w", self.setKey, ["cam-forward", True]) self.showbase.accept("a", self.setKey, ["cam-left", True]) self.showbase.accept("s", self.setKey, ["cam-backward", True]) self.showbase.accept("d", self.setKey, ["cam-right", True]) self.showbase.accept("e", self.setKey, ["cam-up", True]) self.showbase.accept("q", self.setKey, ["cam-down", True]) self.showbase.accept("w-up", self.setKey, ["cam-forward", False]) self.showbase.accept("a-up", self.setKey, ["cam-left", False]) self.showbase.accept("s-up", self.setKey, ["cam-backward", False]) self.showbase.accept("d-up", self.setKey, ["cam-right", False]) self.showbase.accept("e-up", self.setKey, ["cam-up", False]) self.showbase.accept("q-up", self.setKey, ["cam-down", False]) self.last_mouse_x = 0 self.last_mouse_y = 0 self.camera_speed = 25 self.move_speed = 20 def setUp(self, mouse_speed: float = 25, move_speed: float = 20): taskMgr.add(self.move, "moveTask") self.camera_speed = mouse_speed self.move_speed = move_speed def setKey(self, key, value, arg: str = None): self.keyMap[key] = value if (key == "mouse1" or key == "mouse3") and value == True: mouse_pos = self.showbase.mouseWatcherNode.getMouse() if mouse_pos: self.last_mouse_x = mouse_pos.get_x() self.last_mouse_y = mouse_pos.get_y() def move(self, task): dt = self.showbase.clock.dt # 检查ImGui是否捕获了键盘输入 if self._should_handle_keyboard(): if self.keyMap["cam-left"]: self.showbase.camera.setX(self.showbase.camera, -self.move_speed * dt) if self.keyMap["cam-right"]: self.showbase.camera.setX(self.showbase.camera, +self.move_speed * dt) if self.keyMap["cam-backward"]: self.showbase.camera.setY(self.showbase.camera, -self.move_speed * dt) if self.keyMap["cam-forward"]: self.showbase.camera.setY(self.showbase.camera, +self.move_speed * dt) if self.keyMap["cam-up"]: 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"]: # 左键或右键按下 try: # 检查是否应该处理鼠标事件(避免与ImGui冲突) if self._should_handle_mouse(): mouse_pos = self.showbase.mouseWatcherNode.getMouse() if mouse_pos: current_x = mouse_pos.get_x() current_y = mouse_pos.get_y() # 计算鼠标移动差值 dx = current_x - self.last_mouse_x dy = current_y - self.last_mouse_y dy *= -1 # 根据鼠标移动调整摄像机 if abs(dx) > 0.01 or abs(dy) > 0.01: cam_hpr = self.showbase.camera.get_hpr() self.showbase.camera.set_hpr( cam_hpr.x - dx * self.camera_speed, max(-90, min(90, cam_hpr.y - dy * self.camera_speed)), 0 ) # 更新鼠标位置 self.last_mouse_x = current_x self.last_mouse_y = current_y except Exception as e: print(f"旋转相机失败:{e}") return task.cont def _should_handle_keyboard(self): """检查是否应该处理键盘事件(避免与ImGui冲突)""" try: # 检查ImGui是否想要捕获键盘 try: from imgui_bundle import imgui if hasattr(imgui, 'get_io') and imgui.get_io().want_capture_keyboard: return False except ImportError: pass # 如果右键按下,优先处理视角控制(即使ImGui有焦点) if self.keyMap["mouse3"]: return True return True except: return True def _should_handle_mouse(self): """检查是否应该处理鼠标事件(避免与ImGui冲突)""" try: # 如果是右键,优先处理视角控制 if self.keyMap["mouse3"]: return True # 检查ImGui是否想要捕获鼠标 try: from imgui_bundle import imgui if hasattr(imgui, 'get_io') and imgui.get_io().want_capture_mouse: return False except ImportError: pass # 检查鼠标位置是否在ImGui窗口区域内 mouse_pos = self.showbase.mouseWatcherNode.getMouse() if not mouse_pos: return True # 获取显示尺寸 try: from imgui_bundle import imgui display_size = imgui.get_io().display_size mouse_x = mouse_pos.get_x() * display_size.x / 2 + display_size.x / 2 mouse_y = display_size.y - (mouse_pos.get_y() * display_size.y / 2 + display_size.y / 2) # 检查是否在常见的ImGui界面区域内 # 这里可以根据实际的ImGui窗口位置进行更精确的检测 if mouse_x < 300 and mouse_y < 200: # 左上角区域(菜单栏) return False if mouse_x < 300 and mouse_y > display_size.y - 200: # 左下角区域(工具栏) return False if mouse_x > display_size.x - 300 and mouse_y < 200: # 右上角区域 return False except: pass return True except Exception as e: print(f"鼠标事件检测失败: {e}") return True