145 lines
6.3 KiB
Python
145 lines
6.3 KiB
Python
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
|
||
|
||
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_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 |