修复世界位置更新,节点拖动逻辑改进,所有节点不受父级缩放影响
This commit is contained in:
parent
0cce93b05a
commit
ad59e573be
File diff suppressed because one or more lines are too long
@ -1282,33 +1282,23 @@ class SelectionSystem:
|
|||||||
|
|
||||||
# 确定轴向量的变换上下文
|
# 确定轴向量的变换上下文
|
||||||
if parent_node and parent_node != self.world.render:
|
if parent_node and parent_node != self.world.render:
|
||||||
# 子节点:使用父节点的局部坐标系
|
|
||||||
# print(f"子节点拖拽 - 父节点: {parent_node.getName()}, 父节点旋转: {parent_node.getHpr()}")
|
|
||||||
# transform_context = parent_node
|
|
||||||
transform_mat = parent_node.getMat(self.world.render)
|
transform_mat = parent_node.getMat(self.world.render)
|
||||||
world_axis_vector = transform_mat.xformVec(local_axis_vector)
|
world_axis_vector = transform_mat.xformVec(local_axis_vector)
|
||||||
else:
|
else:
|
||||||
world_axis_vector = local_axis_vector
|
world_axis_vector = local_axis_vector
|
||||||
# 顶级模型:使用世界坐标系
|
|
||||||
# print(f"顶级模型拖拽 - 使用世界坐标系")
|
#axis_end = gizmo_world_pos + world_axis_vector
|
||||||
# transform_context = self.world.render
|
|
||||||
axis_end = gizmo_world_pos + world_axis_vector
|
|
||||||
|
|
||||||
# 投影到屏幕空间
|
# 投影到屏幕空间
|
||||||
def worldToScreen(worldPos):
|
def worldToScreen(worldPos):
|
||||||
try:
|
try:
|
||||||
# 先转换为相机坐标系
|
|
||||||
camPos = self.world.cam.getRelativePoint(self.world.render, worldPos)
|
camPos = self.world.cam.getRelativePoint(self.world.render, worldPos)
|
||||||
|
|
||||||
# 检查是否在相机前方
|
|
||||||
if camPos.getY() <= 0:
|
if camPos.getY() <= 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
screenPos = Point2()
|
screenPos = Point2()
|
||||||
if self.world.cam.node().getLens().project(camPos, screenPos):
|
if self.world.cam.node().getLens().project(camPos, screenPos):
|
||||||
# 获取准确的窗口尺寸
|
|
||||||
winWidth, winHeight = self.world.getWindowSize()
|
winWidth, winHeight = self.world.getWindowSize()
|
||||||
|
|
||||||
winX = (screenPos.x + 1) * 0.5 * winWidth
|
winX = (screenPos.x + 1) * 0.5 * winWidth
|
||||||
winY = (1 - screenPos.y) * 0.5 * winHeight
|
winY = (1 - screenPos.y) * 0.5 * winHeight
|
||||||
return (winX, winY)
|
return (winX, winY)
|
||||||
@ -1316,28 +1306,45 @@ class SelectionSystem:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"世界坐标转屏幕坐标失败: {e}")
|
print(f"世界坐标转屏幕坐标失败: {e}")
|
||||||
return None
|
return None
|
||||||
|
axis_start_screen = worldToScreen(gizmo_world_pos)
|
||||||
|
axis_end_world = gizmo_world_pos + world_axis_vector
|
||||||
|
axis_end_screen = worldToScreen(axis_end_world)
|
||||||
|
#gizmo_screen = worldToScreen(gizmo_world_pos)
|
||||||
|
#axis_screen = worldToScreen(axis_end)
|
||||||
|
|
||||||
gizmo_screen = worldToScreen(gizmo_world_pos)
|
# if not gizmo_screen:
|
||||||
axis_screen = worldToScreen(axis_end)
|
# print("拖拽更新失败: 坐标轴中心不在屏幕内")
|
||||||
|
# return
|
||||||
|
# if not axis_screen:
|
||||||
|
# print("拖拽更新失败: 坐标轴端点不在屏幕内")
|
||||||
|
# return
|
||||||
|
#
|
||||||
|
# # 计算轴在屏幕空间的方向向量
|
||||||
|
# screen_axis_dir = (
|
||||||
|
# axis_screen[0] - gizmo_screen[0],
|
||||||
|
# axis_screen[1] - gizmo_screen[1]
|
||||||
|
# )
|
||||||
|
|
||||||
if not gizmo_screen:
|
if not axis_start_screen or not axis_end_screen:
|
||||||
print("拖拽更新失败: 坐标轴中心不在屏幕内")
|
print("拖拽更新失败: 无法获取轴线屏幕坐标")
|
||||||
return
|
|
||||||
if not axis_screen:
|
|
||||||
print("拖拽更新失败: 坐标轴端点不在屏幕内")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# 计算轴在屏幕空间的方向向量
|
|
||||||
screen_axis_dir = (
|
screen_axis_dir = (
|
||||||
axis_screen[0] - gizmo_screen[0],
|
axis_end_screen[0] - axis_start_screen[0],
|
||||||
axis_screen[1] - gizmo_screen[1]
|
axis_end_screen[1] - axis_start_screen[1]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# 归一化屏幕轴方向
|
# 归一化屏幕轴方向
|
||||||
import math
|
import math
|
||||||
length = math.sqrt(screen_axis_dir[0]**2 + screen_axis_dir[1]**2)
|
length = math.sqrt(screen_axis_dir[0]**2 + screen_axis_dir[1]**2)
|
||||||
if length > 0:
|
if length > 0:
|
||||||
screen_axis_dir = (screen_axis_dir[0] / length, screen_axis_dir[1] / length)
|
#screen_axis_dir = (screen_axis_dir[0] / length, screen_axis_dir[1] / length)
|
||||||
|
screen_axis_dir = (
|
||||||
|
screen_axis_dir[0] / length,
|
||||||
|
screen_axis_dir[1] / length
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("拖拽更新失败: 屏幕轴方向长度为0")
|
print("拖拽更新失败: 屏幕轴方向长度为0")
|
||||||
return
|
return
|
||||||
@ -1346,30 +1353,55 @@ class SelectionSystem:
|
|||||||
projected_distance = (mouseDeltaX * screen_axis_dir[0] +
|
projected_distance = (mouseDeltaX * screen_axis_dir[0] +
|
||||||
mouseDeltaY * screen_axis_dir[1])
|
mouseDeltaY * screen_axis_dir[1])
|
||||||
|
|
||||||
scale_adjustment = 1.0
|
cam_pos = self.world.cam.getPos(self.world.render)
|
||||||
if parent_node and parent_node!= self.world.render:
|
distance_to_object = (cam_pos - gizmo_world_pos).length()
|
||||||
current_node = parent_node
|
|
||||||
total_scale = 1.0
|
|
||||||
while current_node and current_node != self.world.render:
|
|
||||||
node_scale = current_node.getScale()
|
|
||||||
avg_scale = (node_scale.x+node_scale.y + node_scale.z)/3.0
|
|
||||||
total_scale *= avg_scale
|
|
||||||
current_node = current_node.getParent()
|
|
||||||
if total_scale>0:
|
|
||||||
scale_adjustment = 1.0 / total_scale
|
|
||||||
# parent_scale = parent_node.getScale()
|
|
||||||
# avg_scale = (parent_scale.x+parent_scale.y+parent_scale.z)/3.0
|
|
||||||
# if avg_scale>0:
|
|
||||||
# scale_adjustment = 1.0 / avg_scale
|
|
||||||
|
|
||||||
|
lens = self.world.cam.node().getLens()
|
||||||
|
fov = lens.getFov()[0]
|
||||||
|
winWidth,winHeight = self.world.getWindowSize()
|
||||||
|
|
||||||
fixed_pixel_to_world_ratio = 0.01 # 1像素 = 0.01世界单位
|
pixels_to_world_units = (2*distance_to_object*math.tan(math.radians(fov/2)))/winWidth
|
||||||
scale_factor = fixed_pixel_to_world_ratio * scale_adjustment
|
|
||||||
|
movement_distance = projected_distance * pixels_to_world_units
|
||||||
|
|
||||||
|
total_scale_factor = 1.0
|
||||||
|
current_node = self.gizmoTarget.getParent()
|
||||||
|
|
||||||
|
while current_node and current_node != self.world.render:
|
||||||
|
node_scale = current_node.getScale()
|
||||||
|
avg_scale = (node_scale.x+node_scale.y + node_scale.z) / 3.0
|
||||||
|
total_scale_factor *= avg_scale
|
||||||
|
current_node = current_node.getParent()
|
||||||
|
|
||||||
|
if total_scale_factor > 0:
|
||||||
|
movement_distance = movement_distance / total_scale_factor
|
||||||
|
|
||||||
movement_distance = projected_distance * scale_factor
|
|
||||||
# 获取当前位置并只修改选中轴的坐标
|
|
||||||
currentPos = self.gizmoTargetStartPos
|
currentPos = self.gizmoTargetStartPos
|
||||||
|
|
||||||
|
# scale_adjustment = 1.0
|
||||||
|
# if parent_node and parent_node!= self.world.render:
|
||||||
|
# current_node = parent_node
|
||||||
|
# total_scale = 1.0
|
||||||
|
# while current_node and current_node != self.world.render:
|
||||||
|
# node_scale = current_node.getScale()
|
||||||
|
# avg_scale = (node_scale.x+node_scale.y + node_scale.z)/3.0
|
||||||
|
# total_scale *= avg_scale
|
||||||
|
# current_node = current_node.getParent()
|
||||||
|
# if total_scale>0:
|
||||||
|
# scale_adjustment = 1.0 / total_scale
|
||||||
|
# # parent_scale = parent_node.getScale()
|
||||||
|
# # avg_scale = (parent_scale.x+parent_scale.y+parent_scale.z)/3.0
|
||||||
|
# # if avg_scale>0:
|
||||||
|
# # scale_adjustment = 1.0 / avg_scale
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# fixed_pixel_to_world_ratio = 0.01 # 1像素 = 0.01世界单位
|
||||||
|
# scale_factor = fixed_pixel_to_world_ratio * scale_adjustment
|
||||||
|
#
|
||||||
|
# movement_distance = projected_distance * scale_factor
|
||||||
|
# # 获取当前位置并只修改选中轴的坐标
|
||||||
|
# currentPos = self.gizmoTargetStartPos
|
||||||
|
|
||||||
# 根据拖拽的轴,只修改对应的坐标分量
|
# 根据拖拽的轴,只修改对应的坐标分量
|
||||||
if self.dragGizmoAxis == "x":
|
if self.dragGizmoAxis == "x":
|
||||||
newPos = Vec3(currentPos.x + movement_distance, currentPos.y, currentPos.z)
|
newPos = Vec3(currentPos.x + movement_distance, currentPos.y, currentPos.z)
|
||||||
@ -1411,7 +1443,7 @@ class SelectionSystem:
|
|||||||
import time
|
import time
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if current_time - self._last_drag_debug_time > 0.1: # 每0.1秒最多输出一次
|
if current_time - self._last_drag_debug_time > 0.1: # 每0.1秒最多输出一次
|
||||||
print(f"拖拽更新成功 - 轴:{self.dragGizmoAxis}, 比例:{scale_factor:.6f}, 投影:{projected_distance:.2f}")
|
#print(f"拖拽更新成功 - 轴:{self.dragGizmoAxis}, 比例:{scale_factor:.6f}, 投影:{projected_distance:.2f}")
|
||||||
self._last_drag_debug_time = current_time
|
self._last_drag_debug_time = current_time
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@ -192,9 +192,24 @@ class PropertyPanelManager:
|
|||||||
self.pos_z.setValue(relativePos.getZ())
|
self.pos_z.setValue(relativePos.getZ())
|
||||||
|
|
||||||
# 连接位置变化事件
|
# 连接位置变化事件
|
||||||
self.pos_x.valueChanged.connect(lambda v: model.setX(parent, v) if parent else model.setX(v))
|
# self.pos_x.valueChanged.connect(lambda v: model.setX(parent, v) if parent else model.setX(v))
|
||||||
self.pos_y.valueChanged.connect(lambda v: model.setY(parent, v) if parent else model.setY(v))
|
# self.pos_y.valueChanged.connect(lambda v: model.setY(parent, v) if parent else model.setY(v))
|
||||||
self.pos_z.valueChanged.connect(lambda v: model.setZ(parent, v) if parent else model.setZ(v))
|
# self.pos_z.valueChanged.connect(lambda v: model.setZ(parent, v) if parent else model.setZ(v))
|
||||||
|
|
||||||
|
def updateXPosition(value):
|
||||||
|
model.setX(value)
|
||||||
|
self.refreshModelValues(model)
|
||||||
|
self.pos_x.valueChanged.connect(updateXPosition)
|
||||||
|
|
||||||
|
def updateYPosition(value):
|
||||||
|
model.setY(value)
|
||||||
|
self.refreshModelValues(model)
|
||||||
|
self.pos_y.valueChanged.connect(updateYPosition)
|
||||||
|
|
||||||
|
def updateZPosition(value):
|
||||||
|
model.setZ(value)
|
||||||
|
self.refreshModelValues(model)
|
||||||
|
self.pos_z.valueChanged.connect(updateZPosition)
|
||||||
|
|
||||||
# 创建并设置 X, Y, Z 标签居中
|
# 创建并设置 X, Y, Z 标签居中
|
||||||
x_label1 = QLabel("X")
|
x_label1 = QLabel("X")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user