addRender #2
File diff suppressed because one or more lines are too long
@ -308,6 +308,13 @@ class SelectionSystem:
|
||||
self.setGizmoAxisColor("y", self.gizmo_colors["y"])
|
||||
self.setGizmoAxisColor("z", self.gizmo_colors["z"])
|
||||
|
||||
self._updateGizmoScreenSize()
|
||||
|
||||
self._setupGizmoRendering()
|
||||
|
||||
# 现在才显示坐标轴
|
||||
self.gizmo.show()
|
||||
|
||||
# 只启动一次更新任务
|
||||
taskMgr.add(self.updateGizmoTask, "updateGizmo")
|
||||
|
||||
@ -363,38 +370,59 @@ class SelectionSystem:
|
||||
self.setGizmoAxisColor("y", self.gizmo_colors["y"])
|
||||
self.setGizmoAxisColor("z", self.gizmo_colors["z"])
|
||||
|
||||
# 使用最强的渲染设置,确保坐标轴绝对不会被遮挡
|
||||
# self.gizmo.setBin("default", 0) # 使用最高的GUI渲染层
|
||||
# self.gizmo.setDepthTest(True) # 完全禁用深度测试
|
||||
# self.gizmo.setDepthWrite(True) # 禁用深度写入
|
||||
# self.gizmo.setTwoSided(True) # 双面渲染
|
||||
|
||||
|
||||
#设置渲染属性,解决模型遮挡和阴影问题
|
||||
self._setupGizmoRendering()
|
||||
|
||||
except Exception as e:
|
||||
print(f"创建坐标轴几何体失败: {str(e)}")
|
||||
|
||||
def _applyAxisMaterial(self, node, color):
|
||||
from panda3d.core import Material, Vec4, ColorWriteAttrib, DepthWriteAttrib
|
||||
# 构造一个“自发光”的材质,让颜色不依赖灯光/法线
|
||||
m = Material()
|
||||
col = Vec4(*color)
|
||||
m.setBaseColor(col) # 记录用
|
||||
m.setDiffuse(col) # 记录用(RP标准材质可能不读取)
|
||||
m.setEmission(Vec4(col.x, col.y, col.z, 1.0)) # 关键:用发光通道显示颜色
|
||||
node.setMaterial(m, 1)
|
||||
def _setupGizmoRendering(self):
|
||||
try:
|
||||
axis_nodes = [self.gizmoXAxis,self.gizmoYAxis,self.gizmoZAxis]
|
||||
|
||||
# 走能直接写到最终画面的阶段(两种方式二选一):
|
||||
# 方式1:完全绕过管线(最稳)
|
||||
node.setTag("pipeline-disable", "1")
|
||||
# 方式2:留在管线内但走最终阶段(若不想禁用管线,可改用下面这一行,并去掉上一行)
|
||||
# node.setTag("pipeline-stage", "final")
|
||||
for axis_node in axis_nodes:
|
||||
if axis_node:
|
||||
#禁用光照和阴影
|
||||
axis_node.setLightOff()
|
||||
axis_node.setShaderOff()
|
||||
axis_node.setFogOff()
|
||||
#设置渲染层级,确保大多数对象之前渲染
|
||||
axis_node.setBin("fixed",30)
|
||||
axis_node.setDepthWrite(False)
|
||||
axis_node.setDepthTest(False)
|
||||
arrow_nodes = []
|
||||
if self.gizmoXAxis:
|
||||
x_arrow = self.gizmoXAxis.find("x_arrow")
|
||||
if x_arrow:
|
||||
arrow_nodes.append(x_arrow)
|
||||
if self.gizmoYAxis:
|
||||
y_arrow = self.gizmoYAxis.find("y_arrow")
|
||||
if y_arrow:
|
||||
arrow_nodes.append(y_arrow)
|
||||
if self.gizmoZAxis:
|
||||
z_arrow = self.gizmoZAxis.find("z_arrow")
|
||||
if z_arrow:
|
||||
arrow_nodes.append(z_arrow)
|
||||
|
||||
# 可见性状态:允许颜色写入,不写深度,双面可见,禁用雾
|
||||
node.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.C_all))
|
||||
node.setAttrib(DepthWriteAttrib.make(False))
|
||||
node.setTwoSided(True)
|
||||
node.setFogOff()
|
||||
for arrow_node in arrow_nodes:
|
||||
if arrow_node:
|
||||
arrow_node.setLightOff()
|
||||
arrow_node.setShaderOff()
|
||||
arrow_node.setFogOff()
|
||||
arrow_node.setBin("fixed",31)
|
||||
arrow_node.setDepthWrite(False)
|
||||
arrow_node.setDepthTest(False)
|
||||
#启用透明度S
|
||||
arrow_node.setTransparency(TransparencyAttrib.MAlpha)
|
||||
if self.gizmo:
|
||||
self.gizmo.setLightOff()
|
||||
self.gizmo.setShaderOff()
|
||||
self.gizmo.setFogOff()
|
||||
self.gizmo.setBin("fixed",29)
|
||||
self.gizmo.setDepthWrite(False)
|
||||
self.gizmo.setDepthTest(False)
|
||||
except Exception as e:
|
||||
print(f"设置坐标轴渲染属性失败: {str(e)}")
|
||||
|
||||
def updateGizmoTask(self, task):
|
||||
"""坐标轴更新任务 - 包含固定大小功能"""
|
||||
@ -429,25 +457,6 @@ class SelectionSystem:
|
||||
else:
|
||||
# 只在必要时更新位置和朝向
|
||||
self._updateGizmoPositionAndOrientation()
|
||||
# # 更新坐标轴位置,始终在目标节点中心
|
||||
# minPoint = Point3()
|
||||
# maxPoint = Point3()
|
||||
# if self.gizmoTarget.calcTightBounds(minPoint, maxPoint, self.world.render):
|
||||
# # 计算中心点
|
||||
# center = Point3((minPoint.x + maxPoint.x) * 0.5,
|
||||
# (minPoint.y + maxPoint.y) * 0.5,
|
||||
# (minPoint.z + maxPoint.z) * 0.5)
|
||||
# self.gizmo.setPos(center)
|
||||
#
|
||||
# # 【关键修复】:更新坐标轴朝向以跟踪父节点的变化
|
||||
# parent_node = self.gizmoTarget.getParent()
|
||||
# if parent_node and parent_node != self.world.render:
|
||||
# # 子节点:坐标轴朝向跟随父节点
|
||||
# parent_hpr = parent_node.getHpr()
|
||||
# self.gizmo.setHpr(parent_hpr)
|
||||
# else:
|
||||
# # 顶级模型:使用世界坐标系朝向
|
||||
# self.gizmo.setHpr(0, 0, 0)
|
||||
|
||||
# 【新功能】:动态调整坐标轴大小,保持固定的屏幕大小
|
||||
self._updateGizmoScreenSize()
|
||||
@ -517,8 +526,8 @@ class SelectionSystem:
|
||||
self.gizmo.setScale(scale_factor)
|
||||
|
||||
# 限制缩放范围,避免过大或过小
|
||||
min_scale = 0.1
|
||||
max_scale = 10.0
|
||||
min_scale = 0.08
|
||||
max_scale = 100.0
|
||||
final_scale = max(min_scale, min(max_scale, scale_factor))
|
||||
|
||||
if final_scale != scale_factor:
|
||||
@ -630,19 +639,13 @@ class SelectionSystem:
|
||||
else:
|
||||
arrow_node.setTransparency(TransparencyAttrib.MNone)
|
||||
|
||||
# 创建自定义渲染状态 - 确保始终在最前方
|
||||
# state = RenderState.make(
|
||||
# ColorWriteAttrib.make(ColorWriteAttrib.CAll), # 允许颜色写入
|
||||
# DepthTestAttrib.make(DepthTestAttrib.MAlways), # 始终通过深度测试
|
||||
# DepthWriteAttrib.make(DepthWriteAttrib.MOff) # 不写入深度缓冲区
|
||||
# )
|
||||
# # 应用渲染状态
|
||||
# arrow_node.set_state(state)
|
||||
|
||||
arrow_node.setLightOff() # 禁用光照影响
|
||||
arrow_node.setShaderOff() # 禁用着色器
|
||||
arrow_node.setFogOff() # 禁用雾效果
|
||||
arrow_node.setBin("fixed", 10) # 使用固定渲染顺序,确保在最前
|
||||
|
||||
arrow_node.setBin("fixed",31)
|
||||
#arrow_node.setDepthWrite(False)
|
||||
#arrow_node.setDepthTest(True)
|
||||
|
||||
# 保存材质引用以便后续修改
|
||||
if axis == "x":
|
||||
@ -655,8 +658,9 @@ class SelectionSystem:
|
||||
axis_node.setLightOff()
|
||||
axis_node.setShaderOff()
|
||||
axis_node.setFogOff()
|
||||
#axis_node.set_state(state)
|
||||
axis_node.setBin("fixed", 9) # 确保轴节点在箭头模型之前渲染
|
||||
axis_node.setBin("fixed", 30)
|
||||
#axis_node.setDepthWrite(False)
|
||||
#axis_node.setDepthTest(True)
|
||||
|
||||
except Exception as e:
|
||||
print(f"设置坐标轴颜色失败: {str(e)}")
|
||||
@ -907,38 +911,10 @@ class SelectionSystem:
|
||||
|
||||
# ==================== 高亮和交互 ====================
|
||||
|
||||
def updateGizmoHighlight(self, mouseX, mouseY):
|
||||
"""更新坐标轴高亮状态"""
|
||||
if not self.gizmo or self.isDraggingGizmo:
|
||||
return
|
||||
|
||||
import time
|
||||
current_time = time.time()
|
||||
if not hasattr(self,'_last_highlight_time'):
|
||||
self._last_highlight_time = 0
|
||||
|
||||
if current_time - self._last_highlight_time<0.05:
|
||||
return
|
||||
self._last_highlight_time = current_time
|
||||
|
||||
hoveredAxis = self._detectHoveredAxis(mouseX, mouseY)
|
||||
|
||||
if not hasattr(self,'_hover_stability_counter'):
|
||||
self._hover_stability_counter = {}
|
||||
self._last_detected_axis = None
|
||||
|
||||
if hoveredAxis !=self._last_detected_axis:
|
||||
self._hover_stability_counter[hoveredAxis]=1
|
||||
self._last_detected_axis = hoveredAxis
|
||||
else:
|
||||
self._hover_stability_counter[hoveredAxis] = self._hover_stability_counter.get(hoveredAxis,0)+1
|
||||
|
||||
if self._hover_stability_counter.get(hoveredAxis,0)>=2:
|
||||
if hoveredAxis != self.gizmoHighlightAxis:
|
||||
self._updateAxisHighlight(hoveredAxis)
|
||||
|
||||
# 检测鼠标悬停的轴(使用相同的检测逻辑但不输出调试信息)
|
||||
hoveredAxis = None
|
||||
def detectGizmoAxisAtMouse(self, mouseX, mouseY):
|
||||
"""统一的坐标轴检测方法 - 同时用于高亮和点击检测"""
|
||||
if not self.gizmo or not self.gizmoTarget:
|
||||
return None
|
||||
|
||||
try:
|
||||
# 获取坐标轴中心的世界坐标
|
||||
@ -951,29 +927,29 @@ class SelectionSystem:
|
||||
|
||||
# 将3D坐标投影到屏幕坐标
|
||||
def worldToScreen(worldPos):
|
||||
try:
|
||||
# 转换为相机坐标系
|
||||
camPos = self.world.cam.getRelativePoint(self.world.render, worldPos)
|
||||
try:
|
||||
# 转换为相机坐标系
|
||||
camPos = self.world.cam.getRelativePoint(self.world.render, worldPos)
|
||||
|
||||
# 检查点是否在相机前方
|
||||
if camPos.getY() <= 0:
|
||||
return None
|
||||
# 检查点是否在相机前方
|
||||
if camPos.getY() <= 0:
|
||||
return None
|
||||
|
||||
# 使用相机lens进行投影
|
||||
screenPos = Point2()
|
||||
lens = self.world.cam.node().getLens()
|
||||
# 使用相机lens进行投影
|
||||
screenPos = Point2()
|
||||
lens = self.world.cam.node().getLens()
|
||||
|
||||
if lens.project(camPos, screenPos):
|
||||
# 获取准确的窗口尺寸
|
||||
winWidth, winHeight = self.world.getWindowSize()
|
||||
if lens.project(camPos, screenPos):
|
||||
# 获取准确的窗口尺寸
|
||||
winWidth, winHeight = self.world.getWindowSize()
|
||||
|
||||
# 转换为像素坐标
|
||||
winX = (screenPos.x + 1) * 0.5 * winWidth
|
||||
winY = (1 - screenPos.y) * 0.5 * winHeight
|
||||
return (winX, winY)
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
# 转换为像素坐标
|
||||
winX = (screenPos.x + 1) * 0.5 * winWidth
|
||||
winY = (1 - screenPos.y) * 0.5 * winHeight
|
||||
return (winX, winY)
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
||||
# 获取各坐标轴的屏幕投影
|
||||
gizmo_screen = worldToScreen(gizmo_world_pos)
|
||||
@ -981,70 +957,90 @@ class SelectionSystem:
|
||||
y_screen = worldToScreen(y_end)
|
||||
z_screen = worldToScreen(z_end)
|
||||
|
||||
# 只要坐标轴中心在屏幕内,就进行检测
|
||||
if gizmo_screen:
|
||||
click_threshold = 25
|
||||
# 如果坐标轴中心不在屏幕内,返回None
|
||||
if not gizmo_screen:
|
||||
return None
|
||||
|
||||
def isNearLine(mousePos, start, end, threshold):
|
||||
import math
|
||||
A = mousePos[1] - start[1]
|
||||
B = start[0] - mousePos[0]
|
||||
C = (end[1] - start[1]) * mousePos[0] + (start[0] - end[0]) * mousePos[1] + end[0] * start[1] - start[0] * end[1]
|
||||
# 设置检测阈值
|
||||
click_threshold = 35 # 统一使用25像素的检测阈值
|
||||
|
||||
length = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2)
|
||||
if length == 0:
|
||||
return False
|
||||
# 更准确的点到线段距离计算方法
|
||||
def distanceToLineSegment(mousePos, start, end):
|
||||
import math
|
||||
mx, my = mousePos
|
||||
x1, y1 = start
|
||||
x2, y2 = end
|
||||
|
||||
distance = abs(C) / length
|
||||
t = ((mousePos[0] - start[0]) * (end[0] - start[0]) +
|
||||
(mousePos[1] - start[1]) * (end[1] - start[1])) / (length * length)
|
||||
# 线段向量
|
||||
dx = x2 - x1
|
||||
dy = y2 - y1
|
||||
|
||||
return distance < threshold and 0 <= t <= 1
|
||||
# 线段长度平方
|
||||
length_sq = dx * dx + dy * dy
|
||||
|
||||
mouse_pos = (mouseX, mouseY)
|
||||
if length_sq == 0:
|
||||
# 线段退化为点
|
||||
return math.sqrt((mx - x1) ** 2 + (my - y1) ** 2)
|
||||
|
||||
# 分别检测每个轴,为在屏幕外的轴端点提供替代方案
|
||||
# 按优先级检测轴(Z > X > Y)
|
||||
# 投影参数
|
||||
t = max(0, min(1, ((mx - x1) * dx + (my - y1) * dy) / length_sq))
|
||||
|
||||
# 对于轴端点在屏幕外的情况,使用较短的轴段进行检测
|
||||
def getAxisScreenPoint(axis_name, axis_screen_end):
|
||||
if axis_screen_end:
|
||||
return axis_screen_end
|
||||
# 如果端点在屏幕外,使用轴长度的一半作为检测点
|
||||
if axis_name == "x":
|
||||
half_end = gizmo_world_pos + Vec3(self.axis_length * 0.5, 0, 0)
|
||||
elif axis_name == "y":
|
||||
half_end = gizmo_world_pos + Vec3(0, self.axis_length * 0.5, 0)
|
||||
elif axis_name == "z":
|
||||
half_end = gizmo_world_pos + Vec3(0, 0, self.axis_length * 0.5)
|
||||
return worldToScreen(half_end)
|
||||
# 投影点坐标
|
||||
proj_x = x1 + t * dx
|
||||
proj_y = y1 + t * dy
|
||||
|
||||
# 获取有效的检测点(优先使用完整轴,备用使用半轴)
|
||||
z_detect_point = getAxisScreenPoint("z", z_screen)
|
||||
x_detect_point = getAxisScreenPoint("x", x_screen)
|
||||
y_detect_point = getAxisScreenPoint("y", y_screen)
|
||||
# 返回点到投影点的距离
|
||||
return math.sqrt((mx - proj_x) ** 2 + (my - proj_y) ** 2)
|
||||
|
||||
if z_detect_point and isNearLine(mouse_pos, gizmo_screen, z_detect_point, click_threshold):
|
||||
hoveredAxis = "z"
|
||||
elif x_detect_point and isNearLine(mouse_pos, gizmo_screen, x_detect_point, click_threshold):
|
||||
hoveredAxis = "x"
|
||||
elif y_detect_point and isNearLine(mouse_pos, gizmo_screen, y_detect_point, click_threshold):
|
||||
hoveredAxis = "y"
|
||||
mouse_pos = (mouseX, mouseY)
|
||||
|
||||
# 检测各个轴 - 按优先级检测(Z > X > Y)
|
||||
axes_to_check = [
|
||||
("z", z_screen),
|
||||
("x", x_screen),
|
||||
("y", y_screen)
|
||||
]
|
||||
|
||||
for axis_name, axis_end in axes_to_check:
|
||||
if axis_end:
|
||||
distance = distanceToLineSegment(mouse_pos, gizmo_screen, axis_end)
|
||||
if distance < click_threshold:
|
||||
return axis_name
|
||||
|
||||
# 如果没有检测到,返回None
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
pass # 静默处理错误,避免频繁输出
|
||||
# 静默处理错误,避免频繁输出
|
||||
return None
|
||||
|
||||
# 如果高亮状态发生变化
|
||||
if hoveredAxis != self.gizmoHighlightAxis:
|
||||
# 恢复之前高亮的轴
|
||||
if self.gizmoHighlightAxis:
|
||||
self.setGizmoAxisColor(self.gizmoHighlightAxis, self.gizmo_colors[self.gizmoHighlightAxis])
|
||||
def updateGizmoHighlight(self, mouseX, mouseY):
|
||||
"""更新坐标轴高亮状态"""
|
||||
if not self.gizmo or self.isDraggingGizmo:
|
||||
return
|
||||
|
||||
# 高亮新的轴
|
||||
if hoveredAxis:
|
||||
self.setGizmoAxisColor(hoveredAxis, self.gizmo_highlight_colors[hoveredAxis])
|
||||
# 使用统一的检测方法
|
||||
hoveredAxis = self.detectGizmoAxisAtMouse(mouseX, mouseY)
|
||||
|
||||
self.gizmoHighlightAxis = hoveredAxis
|
||||
# 简化稳定性检测逻辑
|
||||
if not hasattr(self, '_last_detected_axis'):
|
||||
self._last_detected_axis = None
|
||||
|
||||
# 如果检测结果发生变化,立即更新高亮
|
||||
if hoveredAxis != self._last_detected_axis:
|
||||
# 更新轴的高亮状态
|
||||
if hoveredAxis != self.gizmoHighlightAxis:
|
||||
# 恢复之前高亮的轴
|
||||
if self.gizmoHighlightAxis:
|
||||
self.setGizmoAxisColor(self.gizmoHighlightAxis, self.gizmo_colors[self.gizmoHighlightAxis])
|
||||
|
||||
# 高亮新的轴
|
||||
if hoveredAxis:
|
||||
self.setGizmoAxisColor(hoveredAxis, self.gizmo_highlight_colors[hoveredAxis])
|
||||
|
||||
self.gizmoHighlightAxis = hoveredAxis
|
||||
|
||||
self._last_detected_axis = hoveredAxis
|
||||
|
||||
def _detectHoveredAxis(self, mouseX, mouseY):
|
||||
"""检测鼠标悬停的轴 - 提取为独立方法"""
|
||||
@ -1078,14 +1074,36 @@ class SelectionSystem:
|
||||
return
|
||||
|
||||
self.isDraggingGizmo = True
|
||||
self.dragGizmoAxis = axis
|
||||
# 使用当前高亮的轴,如果有的话
|
||||
if self.gizmoHighlightAxis:
|
||||
self.dragGizmoAxis = self.gizmoHighlightAxis
|
||||
else:
|
||||
self.dragGizmoAxis = axis
|
||||
self.dragStartMousePos = (mouseX, mouseY)
|
||||
|
||||
# 保存开始拖拽时目标节点的位置和坐标轴的位置
|
||||
self.gizmoTargetStartPos = self.gizmoTarget.getPos()
|
||||
self.gizmoStartPos = self.gizmo.getPos(self.world.render) # 坐标轴的世界位置
|
||||
|
||||
print(f"开始拖拽 {axis} 轴 - 目标起始位置: {self.gizmoTargetStartPos}, 坐标轴位置: {self.gizmoStartPos}, 鼠标: ({mouseX}, {mouseY})")
|
||||
# 确保正在拖动的轴保持高亮状态
|
||||
if self.dragGizmoAxis and self.dragGizmoAxis in self.gizmo_colors:
|
||||
# 先将所有轴恢复为正常颜色
|
||||
for axis_name in self.gizmo_colors.keys():
|
||||
if axis_name != self.dragGizmoAxis:
|
||||
self.setGizmoAxisColor(axis_name, self.gizmo_colors[axis_name])
|
||||
|
||||
# 然后将当前拖动的轴设置为高亮颜色
|
||||
self.setGizmoAxisColor(self.dragGizmoAxis, self.gizmo_highlight_colors[self.dragGizmoAxis])
|
||||
self.gizmoHighlightAxis = self.dragGizmoAxis
|
||||
elif axis and axis in self.gizmo_colors:
|
||||
for axis_name in self.gizmo_colors.keys():
|
||||
self.setGizmoAxisColor(axis_name, self.gizmo_colors[axis_name])
|
||||
|
||||
self.setGizmoAxisColor(axis, self.gizmo_highlight_colors[axis])
|
||||
self.gizmoHighlightAxis = axis
|
||||
|
||||
print(
|
||||
f"开始拖拽 {self.dragGizmoAxis} 轴 - 目标起始位置: {self.gizmoTargetStartPos}, 坐标轴位置: {self.gizmoStartPos}, 鼠标: ({mouseX}, {mouseY})")
|
||||
|
||||
except Exception as e:
|
||||
print(f"开始坐标轴拖拽失败: {str(e)}")
|
||||
@ -1311,6 +1329,10 @@ class SelectionSystem:
|
||||
def stopGizmoDrag(self):
|
||||
"""停止坐标轴拖拽"""
|
||||
print(f"停止坐标轴拖拽 - 轴: {self.dragGizmoAxis}")
|
||||
if self.dragGizmoAxis and self.dragGizmoAxis in self.gizmo_colors:
|
||||
self.setGizmoAxisColor(self.dragGizmoAxis, self.gizmo_colors[self.dragGizmoAxis])
|
||||
# 不要将 gizmoHighlightAxis 设置为 None,保持当前高亮轴的状态
|
||||
# self.gizmoHighlightAxis = None
|
||||
|
||||
self.isDraggingGizmo = False
|
||||
self.dragGizmoAxis = None
|
||||
|
||||
6
main.py
6
main.py
@ -369,9 +369,6 @@ class MyWorld(CoreWorld):
|
||||
def updatePropertyPanel(self, item):
|
||||
"""更新属性面板显示 - 代理到property_panel"""
|
||||
return self.property_panel.updatePropertyPanel(item)
|
||||
|
||||
# def addAnimationPanel(self,originmodel,filepath):
|
||||
# return self.property_panel._addAnimationPanel(originmodel,filepath)
|
||||
|
||||
def updateGUIPropertyPanel(self, gui_element):
|
||||
"""更新GUI元素属性面板 - 代理到property_panel"""
|
||||
@ -380,6 +377,9 @@ class MyWorld(CoreWorld):
|
||||
def removeActorForModel(self,model):
|
||||
return self.property_panel.removeActorForModel( model)
|
||||
|
||||
def updateNodeVisibilityAfterDrag(self,item):
|
||||
return self.property_panel.updateNodeVisibilityAfterDrag(item)
|
||||
|
||||
# ==================== 工具管理代理 ====================
|
||||
|
||||
def setCurrentTool(self, tool):
|
||||
|
||||
@ -51,6 +51,16 @@ class PropertyPanelManager:
|
||||
if item.widget():
|
||||
item.widget().deleteLater()
|
||||
|
||||
def updateNodeVisibilityAfterDrag(self, item):
|
||||
"""拖拽结束后更新节点的可见性状态"""
|
||||
node = item.data(0, Qt.UserRole)
|
||||
if not node:
|
||||
return
|
||||
|
||||
# 当节点被拖拽后,需要根据新父节点的状态来更新可见性
|
||||
self._syncEffectiveVisibility(node)
|
||||
|
||||
|
||||
def updatePropertyPanel(self, item):
|
||||
"""更新属性面板显示"""
|
||||
if not self._propertyLayout or not self._propertyLayout.parent():
|
||||
@ -133,7 +143,17 @@ class PropertyPanelManager:
|
||||
|
||||
def _syncEffectiveVisibility(self, start_node):
|
||||
"""广度优先,确保父隐藏则子一定隐藏"""
|
||||
q = deque([(start_node, True)]) # (node, parent_effective_visible)
|
||||
# 获取起始节点的父节点
|
||||
parent_node = start_node.getParent()
|
||||
|
||||
# 确定父节点的有效可见性
|
||||
parent_effective_visible = True
|
||||
if parent_node:
|
||||
parent_effective_visible = parent_node.getPythonTag("effective_visible")
|
||||
if parent_effective_visible is None:
|
||||
parent_effective_visible = True
|
||||
|
||||
q = deque([(start_node, parent_effective_visible)]) # (node, parent_effective_visible)
|
||||
|
||||
while q:
|
||||
node, parent_eff = q.popleft()
|
||||
@ -143,7 +163,7 @@ class PropertyPanelManager:
|
||||
eff = parent_eff and user
|
||||
node.setPythonTag("effective_visible", eff)
|
||||
|
||||
#特殊处理:检查是否为碰撞体节点
|
||||
# 特殊处理:检查是否为碰撞体节点
|
||||
|
||||
if node.getName().startswith("modelCollision_"):
|
||||
node.hide()
|
||||
|
||||
@ -339,6 +339,7 @@ class CustomTreeWidget(QTreeWidget):
|
||||
|
||||
# 获取节点引用
|
||||
dragged_node = dragged_item.data(0, Qt.UserRole)
|
||||
amtarget_node = target_item.data(0, Qt.UserRole)
|
||||
|
||||
# 如果目标是模型根节点,使用 render 作为新父节点
|
||||
if target_item.text(0) == "模型":
|
||||
@ -360,13 +361,17 @@ class CustomTreeWidget(QTreeWidget):
|
||||
|
||||
# 接受拖放事件,更新树形控件
|
||||
super().dropEvent(event)
|
||||
|
||||
|
||||
#self.world.property_panel.updateNodeVisibilityAfterDrag(dragged_item)
|
||||
# 更新属性面板
|
||||
self.world.updatePropertyPanel(dragged_item)
|
||||
self.world.property_panel._syncEffectiveVisibility(dragged_node)
|
||||
|
||||
|
||||
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
|
||||
def isValidParentChild(self, dragged_item, target_item):
|
||||
"""检查是否是有效的父子关系"""
|
||||
# 不能拖放到自己上
|
||||
|
||||
Loading…
Reference in New Issue
Block a user