回补G任务:拆分LUI _update_drag
This commit is contained in:
parent
c006b69613
commit
22a9b5b64a
@ -310,258 +310,242 @@ class LUIManagerInteractionMixin:
|
||||
print(f"[_get_component_accumulated_pos] Component #{comp_index} (root): local=({left:.1f}, {top:.1f})")
|
||||
return left, top
|
||||
|
||||
def _update_drag(self, task):
|
||||
"""每帧更新拖动状态 - 支持Canvas边界约束和局部坐标"""
|
||||
if getattr(self, 'play_mode', False):
|
||||
# Disable editor drag logic while in play mode
|
||||
return task.cont
|
||||
def _clear_pending_drag_state(self):
|
||||
"""清空 pending 拖拽状态。"""
|
||||
self.pending_drag_comp = None
|
||||
self.pending_drag_index = -1
|
||||
self.pending_drag_start_mouse = None
|
||||
self.pending_drag_start_abs = None
|
||||
self.pending_drag_start_parent = None
|
||||
|
||||
# 1. 处理Canvas拖动
|
||||
if hasattr(self, 'dragging_canvas') and self.dragging_canvas:
|
||||
# 查找对应的Canvas数据
|
||||
canvas_data = None
|
||||
for c in self.canvases:
|
||||
if c['panel'] == self.dragging_canvas:
|
||||
canvas_data = c
|
||||
break
|
||||
|
||||
# 检查Canvas是否锁定
|
||||
if canvas_data and canvas_data.get('fixed', False):
|
||||
return task.cont
|
||||
def _has_mouse_for_drag(self):
|
||||
"""检查是否存在可用鼠标输入。"""
|
||||
return hasattr(self.world, 'mouseWatcherNode') and self.world.mouseWatcherNode.hasMouse()
|
||||
|
||||
if not hasattr(self.world, 'mouseWatcherNode') or not self.world.mouseWatcherNode.hasMouse():
|
||||
return task.cont
|
||||
|
||||
import panda3d.core as p3d
|
||||
if not self.world.mouseWatcherNode.is_button_down(p3d.MouseButton.one()):
|
||||
self.dragging_canvas = None
|
||||
return task.cont
|
||||
|
||||
mouse_x = self.world.mouseWatcherNode.getMouseX()
|
||||
mouse_y = self.world.mouseWatcherNode.getMouseY()
|
||||
|
||||
win_x = self.world.win.getXSize()
|
||||
win_y = self.world.win.getYSize()
|
||||
pixel_x = (mouse_x + 1) * win_x / 2
|
||||
pixel_y = (1 - mouse_y) * win_y / 2
|
||||
|
||||
new_x = pixel_x - self.canvas_drag_offset[0]
|
||||
new_y = pixel_y - self.canvas_drag_offset[1]
|
||||
|
||||
self.dragging_canvas.set_pos(new_x, new_y)
|
||||
return task.cont
|
||||
|
||||
# 2. 处理组件拖动
|
||||
if self.dragging_comp is None:
|
||||
# Pending drag: only start after threshold
|
||||
if self.pending_drag_comp is None:
|
||||
return task.cont
|
||||
|
||||
if not hasattr(self.world, 'mouseWatcherNode') or not self.world.mouseWatcherNode.hasMouse():
|
||||
return task.cont
|
||||
|
||||
import panda3d.core as p3d
|
||||
if not self.world.mouseWatcherNode.is_button_down(p3d.MouseButton.one()):
|
||||
# click without drag
|
||||
self.pending_drag_comp = None
|
||||
self.pending_drag_index = -1
|
||||
self.pending_drag_start_mouse = None
|
||||
self.pending_drag_start_abs = None
|
||||
self.pending_drag_start_parent = None
|
||||
return task.cont
|
||||
|
||||
mouse_x = self.world.mouseWatcherNode.getMouseX()
|
||||
mouse_y = self.world.mouseWatcherNode.getMouseY()
|
||||
win_x = self.world.win.getXSize()
|
||||
win_y = self.world.win.getYSize()
|
||||
pixel_x = (mouse_x + 1) * win_x / 2
|
||||
pixel_y = (1 - mouse_y) * win_y / 2
|
||||
|
||||
if self.pending_drag_start_mouse is None:
|
||||
self.pending_drag_start_mouse = (pixel_x, pixel_y)
|
||||
return task.cont
|
||||
|
||||
dx = pixel_x - self.pending_drag_start_mouse[0]
|
||||
dy = pixel_y - self.pending_drag_start_mouse[1]
|
||||
if (dx * dx + dy * dy) < (self.drag_start_threshold * self.drag_start_threshold):
|
||||
return task.cont
|
||||
|
||||
# Start drag now
|
||||
comp_data = self.pending_drag_comp
|
||||
self.dragging_comp = comp_data
|
||||
self.dragging_index = self.pending_drag_index
|
||||
self._original_parent_obj = self.pending_drag_start_parent
|
||||
self._is_drag_reparented = False
|
||||
|
||||
acc_left, acc_top = self.pending_drag_start_abs
|
||||
if acc_left is None or acc_top is None:
|
||||
acc_left, acc_top = self._get_component_accumulated_pos(self.pending_drag_index)
|
||||
|
||||
# If child, reparent to canvas for free drag
|
||||
p_idx = comp_data.get('parent_index')
|
||||
if p_idx is not None and p_idx >= 0 and self.current_canvas_index >= 0:
|
||||
canvas_panel = self.canvases[self.current_canvas_index]['panel']
|
||||
comp_obj = comp_data['object']
|
||||
if not comp_data.get('visual_parent_canvas'):
|
||||
try:
|
||||
if getattr(comp_obj, 'parent', None) == canvas_panel:
|
||||
pass
|
||||
elif hasattr(comp_obj, 'reparent_to'):
|
||||
comp_obj.reparent_to(canvas_panel)
|
||||
if hasattr(comp_obj, 'set_pos'):
|
||||
comp_obj.set_pos(acc_left, acc_top)
|
||||
else:
|
||||
comp_obj.left = acc_left
|
||||
comp_obj.top = acc_top
|
||||
self._is_drag_reparented = True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Compute drag offset
|
||||
canvas_abs_left = 0
|
||||
canvas_abs_top = 0
|
||||
if self.current_canvas_index >= 0 and self.current_canvas_index < len(self.canvases):
|
||||
canvas_panel = self.canvases[self.current_canvas_index]['panel']
|
||||
canvas_abs_left = getattr(canvas_panel, 'left', 0)
|
||||
canvas_abs_top = getattr(canvas_panel, 'top', 0)
|
||||
if canvas_abs_left == 0 and canvas_abs_top == 0:
|
||||
try:
|
||||
canvas_pos = canvas_panel.get_pos()
|
||||
canvas_abs_left = canvas_pos.x
|
||||
canvas_abs_top = canvas_pos.y
|
||||
except:
|
||||
canvas_abs_left = 300
|
||||
canvas_abs_top = 100
|
||||
|
||||
comp_abs_left = canvas_abs_left + acc_left
|
||||
comp_abs_top = canvas_abs_top + acc_top
|
||||
self.drag_offset = (pixel_x - comp_abs_left, pixel_y - comp_abs_top)
|
||||
|
||||
# Clear pending state
|
||||
self.pending_drag_comp = None
|
||||
self.pending_drag_index = -1
|
||||
self.pending_drag_start_mouse = None
|
||||
self.pending_drag_start_abs = None
|
||||
self.pending_drag_start_parent = None
|
||||
|
||||
# Continue with drag in same frame
|
||||
|
||||
|
||||
# 检查鼠标状态
|
||||
if not hasattr(self.world, 'mouseWatcherNode') or not self.world.mouseWatcherNode.hasMouse():
|
||||
return task.cont
|
||||
|
||||
# 检查鼠标左键是否释放
|
||||
def _is_left_mouse_down(self):
|
||||
"""检查鼠标左键是否按下。"""
|
||||
import panda3d.core as p3d
|
||||
if not self.world.mouseWatcherNode.is_button_down(p3d.MouseButton.one()):
|
||||
if self.dragging_comp:
|
||||
comp_data = self.dragging_comp
|
||||
print(f"组件移动到: left={comp_data.get('left', 0):.1f}, top={comp_data.get('top', 0):.1f} (局部坐标)")
|
||||
|
||||
# 拖动结束:检查是否需要接触父子关系 (Auto-unparent)
|
||||
should_unparent = False
|
||||
if getattr(self, '_is_drag_reparented', False):
|
||||
comp_obj = comp_data['object']
|
||||
|
||||
# Check if center of component is outside parent bounds
|
||||
p_idx = comp_data.get('parent_index')
|
||||
if p_idx is not None and p_idx >= 0:
|
||||
parent_data = self.components[p_idx]
|
||||
p_w = parent_data.get('width', 100)
|
||||
p_h = parent_data.get('height', 100)
|
||||
|
||||
c_w = comp_data.get('width', 0)
|
||||
c_h = comp_data.get('height', 0)
|
||||
|
||||
# Current comp_data['left'] is LOCAL to parent
|
||||
local_l = comp_data.get('left', 0)
|
||||
local_t = comp_data.get('top', 0)
|
||||
|
||||
center_x = local_l + c_w / 2
|
||||
center_y = local_t + c_h / 2
|
||||
|
||||
# Check bounds: center must be in 0..p_w, 0..p_h
|
||||
# Allow some leniency or strict? Let's say if center is outside, unparent.
|
||||
if center_x < 0 or center_x > p_w or center_y < 0 or center_y > p_h:
|
||||
should_unparent = True
|
||||
return self.world.mouseWatcherNode.is_button_down(p3d.MouseButton.one())
|
||||
|
||||
if should_unparent:
|
||||
# Unparent!
|
||||
# The component is currently visually attached to Canvas (from drag start)
|
||||
# We just need to update the data to reflect this permanent change.
|
||||
|
||||
# Calculate the new global (canvas-relative) position
|
||||
# current local + parent offset
|
||||
p_off_x, p_off_y = self._get_component_accumulated_pos(p_idx)
|
||||
new_canvas_left = local_l + p_off_x
|
||||
new_canvas_top = local_t + p_off_y
|
||||
|
||||
comp_data['left'] = new_canvas_left
|
||||
comp_data['top'] = new_canvas_top
|
||||
|
||||
# Remove parent linkage
|
||||
if 'parent_index' in comp_data:
|
||||
del comp_data['parent_index']
|
||||
if 'anchored_to_parent' in comp_data:
|
||||
del comp_data['anchored_to_parent']
|
||||
|
||||
print(f"✓ Auto-unparented component from #{p_idx} (Dragged out)")
|
||||
|
||||
elif hasattr(comp_obj, 'reparent_to') and hasattr(self, '_original_parent_obj'):
|
||||
comp_obj.reparent_to(self._original_parent_obj)
|
||||
# 重新应用计算出的局部坐标
|
||||
comp_obj.left = comp_data.get('left', 0)
|
||||
comp_obj.top = comp_data.get('top', 0)
|
||||
print(f"✓ 组件归位到逻辑父级")
|
||||
|
||||
self.dragging_comp = None
|
||||
return task.cont
|
||||
|
||||
# 获取鼠标位置
|
||||
def _get_mouse_pixel_data(self):
|
||||
"""获取鼠标像素坐标及窗口尺寸。"""
|
||||
mouse_x = self.world.mouseWatcherNode.getMouseX()
|
||||
mouse_y = self.world.mouseWatcherNode.getMouseY()
|
||||
|
||||
# 转换为像素坐标
|
||||
win_x = self.world.win.getXSize()
|
||||
win_y = self.world.win.getYSize()
|
||||
pixel_x = (mouse_x + 1) * win_x / 2
|
||||
pixel_y = (1 - mouse_y) * win_y / 2
|
||||
|
||||
# 计算新的绝对位置(减去偏移量)
|
||||
new_abs_left = pixel_x - self.drag_offset[0]
|
||||
new_abs_top = pixel_y - self.drag_offset[1]
|
||||
|
||||
# 获取Canvas信息
|
||||
return pixel_x, pixel_y, win_x, win_y
|
||||
|
||||
def _find_canvas_data_by_panel(self, canvas_panel):
|
||||
"""按 panel 对象查找 canvas 配置。"""
|
||||
for c in self.canvases:
|
||||
if c['panel'] == canvas_panel:
|
||||
return c
|
||||
return None
|
||||
|
||||
def _process_canvas_drag(self):
|
||||
"""处理 Canvas 拖动,返回是否已处理该帧。"""
|
||||
if not (hasattr(self, 'dragging_canvas') and self.dragging_canvas):
|
||||
return False
|
||||
|
||||
canvas_data = self._find_canvas_data_by_panel(self.dragging_canvas)
|
||||
if canvas_data and canvas_data.get('fixed', False):
|
||||
return True
|
||||
|
||||
if not self._has_mouse_for_drag():
|
||||
return True
|
||||
|
||||
if not self._is_left_mouse_down():
|
||||
self.dragging_canvas = None
|
||||
return True
|
||||
|
||||
pixel_x, pixel_y, _, _ = self._get_mouse_pixel_data()
|
||||
new_x = pixel_x - self.canvas_drag_offset[0]
|
||||
new_y = pixel_y - self.canvas_drag_offset[1]
|
||||
self.dragging_canvas.set_pos(new_x, new_y)
|
||||
return True
|
||||
|
||||
def _try_start_pending_component_drag(self):
|
||||
"""处理 pending 拖拽转正,返回是否需要本帧提前结束。"""
|
||||
if self.dragging_comp is not None:
|
||||
return False
|
||||
|
||||
if self.pending_drag_comp is None:
|
||||
return True
|
||||
|
||||
if not self._has_mouse_for_drag():
|
||||
return True
|
||||
|
||||
if not self._is_left_mouse_down():
|
||||
# click without drag
|
||||
self._clear_pending_drag_state()
|
||||
return True
|
||||
|
||||
pixel_x, pixel_y, _, _ = self._get_mouse_pixel_data()
|
||||
|
||||
if self.pending_drag_start_mouse is None:
|
||||
self.pending_drag_start_mouse = (pixel_x, pixel_y)
|
||||
return True
|
||||
|
||||
dx = pixel_x - self.pending_drag_start_mouse[0]
|
||||
dy = pixel_y - self.pending_drag_start_mouse[1]
|
||||
if (dx * dx + dy * dy) < (self.drag_start_threshold * self.drag_start_threshold):
|
||||
return True
|
||||
|
||||
# Start drag now
|
||||
comp_data = self.pending_drag_comp
|
||||
self.dragging_comp = comp_data
|
||||
self.dragging_index = self.pending_drag_index
|
||||
self._original_parent_obj = self.pending_drag_start_parent
|
||||
self._is_drag_reparented = False
|
||||
|
||||
acc_left, acc_top = self.pending_drag_start_abs
|
||||
if acc_left is None or acc_top is None:
|
||||
acc_left, acc_top = self._get_component_accumulated_pos(self.pending_drag_index)
|
||||
|
||||
# If child, reparent to canvas for free drag
|
||||
p_idx = comp_data.get('parent_index')
|
||||
if p_idx is not None and p_idx >= 0 and self.current_canvas_index >= 0:
|
||||
canvas_panel = self.canvases[self.current_canvas_index]['panel']
|
||||
comp_obj = comp_data['object']
|
||||
if not comp_data.get('visual_parent_canvas'):
|
||||
try:
|
||||
if getattr(comp_obj, 'parent', None) == canvas_panel:
|
||||
pass
|
||||
elif hasattr(comp_obj, 'reparent_to'):
|
||||
comp_obj.reparent_to(canvas_panel)
|
||||
if hasattr(comp_obj, 'set_pos'):
|
||||
comp_obj.set_pos(acc_left, acc_top)
|
||||
else:
|
||||
comp_obj.left = acc_left
|
||||
comp_obj.top = acc_top
|
||||
self._is_drag_reparented = True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Compute drag offset
|
||||
canvas_abs_left = 0
|
||||
canvas_abs_top = 0
|
||||
if self.current_canvas_index >= 0 and self.current_canvas_index < len(self.canvases):
|
||||
canvas_panel = self.canvases[self.current_canvas_index]['panel']
|
||||
canvas_abs_left = getattr(canvas_panel, 'left', 0)
|
||||
canvas_abs_top = getattr(canvas_panel, 'top', 0)
|
||||
if canvas_abs_left == 0 and canvas_abs_top == 0:
|
||||
try:
|
||||
canvas_pos = canvas_panel.get_pos()
|
||||
canvas_abs_left = canvas_pos.x
|
||||
canvas_abs_top = canvas_pos.y
|
||||
except Exception:
|
||||
canvas_abs_left = 300
|
||||
canvas_abs_top = 100
|
||||
|
||||
comp_abs_left = canvas_abs_left + acc_left
|
||||
comp_abs_top = canvas_abs_top + acc_top
|
||||
self.drag_offset = (pixel_x - comp_abs_left, pixel_y - comp_abs_top)
|
||||
|
||||
self._clear_pending_drag_state()
|
||||
return False
|
||||
|
||||
def _finish_component_drag_if_released(self):
|
||||
"""在鼠标释放时完成拖拽收尾,返回是否已处理该帧。"""
|
||||
if not self._is_left_mouse_down():
|
||||
if self.dragging_comp:
|
||||
comp_data = self.dragging_comp
|
||||
print(f"组件移动到: left={comp_data.get('left', 0):.1f}, top={comp_data.get('top', 0):.1f} (局部坐标)")
|
||||
|
||||
# 拖动结束:检查是否需要接触父子关系 (Auto-unparent)
|
||||
should_unparent = False
|
||||
if getattr(self, '_is_drag_reparented', False):
|
||||
comp_obj = comp_data['object']
|
||||
|
||||
# Check if center of component is outside parent bounds
|
||||
p_idx = comp_data.get('parent_index')
|
||||
if p_idx is not None and p_idx >= 0:
|
||||
parent_data = self.components[p_idx]
|
||||
p_w = parent_data.get('width', 100)
|
||||
p_h = parent_data.get('height', 100)
|
||||
|
||||
c_w = comp_data.get('width', 0)
|
||||
c_h = comp_data.get('height', 0)
|
||||
|
||||
# Current comp_data['left'] is LOCAL to parent
|
||||
local_l = comp_data.get('left', 0)
|
||||
local_t = comp_data.get('top', 0)
|
||||
|
||||
center_x = local_l + c_w / 2
|
||||
center_y = local_t + c_h / 2
|
||||
|
||||
# Check bounds: center must be in 0..p_w, 0..p_h
|
||||
# Allow some leniency or strict? Let's say if center is outside, unparent.
|
||||
if center_x < 0 or center_x > p_w or center_y < 0 or center_y > p_h:
|
||||
should_unparent = True
|
||||
|
||||
if should_unparent:
|
||||
# Unparent!
|
||||
# The component is currently visually attached to Canvas (from drag start)
|
||||
# We just need to update the data to reflect this permanent change.
|
||||
|
||||
# Calculate the new global (canvas-relative) position
|
||||
# current local + parent offset
|
||||
p_off_x, p_off_y = self._get_component_accumulated_pos(p_idx)
|
||||
new_canvas_left = local_l + p_off_x
|
||||
new_canvas_top = local_t + p_off_y
|
||||
|
||||
comp_data['left'] = new_canvas_left
|
||||
comp_data['top'] = new_canvas_top
|
||||
|
||||
# Remove parent linkage
|
||||
if 'parent_index' in comp_data:
|
||||
del comp_data['parent_index']
|
||||
if 'anchored_to_parent' in comp_data:
|
||||
del comp_data['anchored_to_parent']
|
||||
|
||||
print(f"✓ Auto-unparented component from #{p_idx} (Dragged out)")
|
||||
|
||||
elif hasattr(comp_obj, 'reparent_to') and hasattr(self, '_original_parent_obj'):
|
||||
comp_obj.reparent_to(self._original_parent_obj)
|
||||
# 重新应用计算出的局部坐标
|
||||
comp_obj.left = comp_data.get('left', 0)
|
||||
comp_obj.top = comp_data.get('top', 0)
|
||||
print(f"✓ 组件归位到逻辑父级")
|
||||
|
||||
self.dragging_comp = None
|
||||
return True
|
||||
return False
|
||||
|
||||
def _resolve_canvas_metrics_for_drag(self, win_x, win_y):
|
||||
"""获取当前 Canvas 的绝对位置与尺寸。"""
|
||||
canvas_abs_left = 0
|
||||
canvas_abs_top = 0
|
||||
canvas_width = 800
|
||||
canvas_height = 600
|
||||
|
||||
|
||||
if self.current_canvas_index >= 0 and self.current_canvas_index < len(self.canvases):
|
||||
canvas_data = self.canvases[self.current_canvas_index]
|
||||
canvas_panel = canvas_data['panel']
|
||||
|
||||
|
||||
# 获取Canvas的绝对位置
|
||||
canvas_abs_left = getattr(canvas_panel, 'left', 0)
|
||||
canvas_abs_top = getattr(canvas_panel, 'top', 0)
|
||||
|
||||
|
||||
if canvas_abs_left == 0 and canvas_abs_top == 0:
|
||||
try:
|
||||
pos = canvas_panel.get_pos()
|
||||
canvas_abs_left = pos.x
|
||||
canvas_abs_top = pos.y
|
||||
except:
|
||||
except Exception:
|
||||
# 如果获取失败,使用默认值
|
||||
canvas_abs_left = canvas_data.get('margins', {}).get('left', 240)
|
||||
canvas_abs_top = canvas_data.get('margins', {}).get('top', 89)
|
||||
|
||||
|
||||
# 获取Canvas的实际尺寸
|
||||
try:
|
||||
if hasattr(canvas_panel, 'width') and canvas_panel.width is not None:
|
||||
canvas_width = float(canvas_panel.width)
|
||||
elif hasattr(canvas_panel, 'get_width'):
|
||||
canvas_width = float(canvas_panel.get_width())
|
||||
|
||||
|
||||
if hasattr(canvas_panel, 'height') and canvas_panel.height is not None:
|
||||
canvas_height = float(canvas_panel.height)
|
||||
elif hasattr(canvas_panel, 'get_height'):
|
||||
@ -572,7 +556,18 @@ class LUIManagerInteractionMixin:
|
||||
margins = canvas_data.get('margins', {'left': 240, 'right': 480, 'top': 89, 'bottom': 220})
|
||||
canvas_width = win_x - margins.get('left', 0) - margins.get('right', 0)
|
||||
canvas_height = win_y - margins.get('top', 0) - margins.get('bottom', 0)
|
||||
|
||||
|
||||
return canvas_abs_left, canvas_abs_top, canvas_width, canvas_height
|
||||
|
||||
def _update_active_component_drag(self, pixel_x, pixel_y, win_x, win_y):
|
||||
"""更新已开始拖拽的组件位置。"""
|
||||
# 计算新的绝对位置(减去偏移量)
|
||||
new_abs_left = pixel_x - self.drag_offset[0]
|
||||
new_abs_top = pixel_y - self.drag_offset[1]
|
||||
|
||||
# 获取Canvas信息
|
||||
canvas_abs_left, canvas_abs_top, canvas_width, canvas_height = self._resolve_canvas_metrics_for_drag(win_x, win_y)
|
||||
|
||||
# 转换为Canvas相对坐标 (Global Canvas Pos)
|
||||
canvas_relative_left = new_abs_left - canvas_abs_left
|
||||
canvas_relative_top = new_abs_top - canvas_abs_top
|
||||
@ -584,7 +579,7 @@ class LUIManagerInteractionMixin:
|
||||
# 获取组件宽高 (用于边界限制)
|
||||
comp_width = comp_data.get('width', 0)
|
||||
comp_height = comp_data.get('height', 0)
|
||||
|
||||
|
||||
# 尝试从对象获取更准确的宽高
|
||||
if hasattr(comp_obj, 'width') and comp_obj.width is not None and comp_obj.width > 0:
|
||||
comp_width = comp_obj.width
|
||||
@ -595,35 +590,33 @@ class LUIManagerInteractionMixin:
|
||||
# 确保左边界不小于0
|
||||
if canvas_relative_left < 0:
|
||||
canvas_relative_left = 0
|
||||
|
||||
# 确保上边界不小于0
|
||||
|
||||
# 确保上边界不小于0
|
||||
if canvas_relative_top < 0:
|
||||
canvas_relative_top = 0
|
||||
|
||||
|
||||
# 确保右边界不超出Canvas宽度
|
||||
if canvas_relative_left + comp_width > canvas_width:
|
||||
canvas_relative_left = max(0, canvas_width - comp_width)
|
||||
|
||||
|
||||
# 确保下边界不超出Canvas高度
|
||||
if canvas_relative_top + comp_height > canvas_height:
|
||||
canvas_relative_top = max(0, canvas_height - comp_height)
|
||||
|
||||
|
||||
# 如果有父组件,需要转换为相对于父组件的局部坐标
|
||||
comp_data = self.dragging_comp
|
||||
parent_index = comp_data.get('parent_index')
|
||||
parent_offset_x = 0
|
||||
parent_offset_y = 0
|
||||
|
||||
|
||||
if parent_index is not None and parent_index >= 0:
|
||||
# 获取父组件相对于Canvas的累积位置
|
||||
parent_offset_x, parent_offset_y = self._get_component_accumulated_pos(parent_index)
|
||||
|
||||
|
||||
# 计算新的局部坐标
|
||||
new_local_left = canvas_relative_left - parent_offset_x
|
||||
new_local_top = canvas_relative_top - parent_offset_y
|
||||
|
||||
|
||||
# 如果物理上已脱离父级(挂在Canvas上),则物理坐标就是Canvas相对坐标
|
||||
comp_obj = comp_data['object']
|
||||
if getattr(self, '_is_drag_reparented', False):
|
||||
# 子组件被重定向到Canvas,使其可以移动到负数局部坐标(即父组件外侧)
|
||||
if hasattr(comp_obj, 'set_pos'):
|
||||
@ -648,7 +641,7 @@ class LUIManagerInteractionMixin:
|
||||
else:
|
||||
comp_obj.left = new_local_left
|
||||
comp_obj.top = new_local_top
|
||||
|
||||
|
||||
# 更新存储的逻辑坐标数据 (保持始终相对于逻辑父级)
|
||||
comp_data['left'] = new_local_left
|
||||
comp_data['top'] = new_local_top
|
||||
@ -656,7 +649,27 @@ class LUIManagerInteractionMixin:
|
||||
# Sync visually-canvas children for non-container parents
|
||||
if self.dragging_index is not None and self.dragging_index >= 0:
|
||||
self._sync_canvas_children(self.dragging_index)
|
||||
|
||||
|
||||
def _update_drag(self, task):
|
||||
"""每帧更新拖动状态 - 支持Canvas边界约束和局部坐标"""
|
||||
if getattr(self, 'play_mode', False):
|
||||
# Disable editor drag logic while in play mode
|
||||
return task.cont
|
||||
|
||||
if self._process_canvas_drag():
|
||||
return task.cont
|
||||
|
||||
if self._try_start_pending_component_drag():
|
||||
return task.cont
|
||||
|
||||
if not self._has_mouse_for_drag():
|
||||
return task.cont
|
||||
|
||||
if self._finish_component_drag_if_released():
|
||||
return task.cont
|
||||
|
||||
pixel_x, pixel_y, win_x, win_y = self._get_mouse_pixel_data()
|
||||
self._update_active_component_drag(pixel_x, pixel_y, win_x, win_y)
|
||||
return task.cont
|
||||
|
||||
def _create_resize_handles(self):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user