"""RectTransform - 一个轻量级的 Unity-like RectTransform 实现(Python 层 MVP) 提供 anchors/pivot/anchored_position/size_delta 的数据结构和 把相对锚点映射到像素矩形的计算方法。 此实现不修改底层 C++ LUI,而是在 Python 层计算并把结果应用到 `LUIObject` 的 `left/top/width/height` 属性上。 """ from typing import Tuple class RectTransform(object): def __init__(self, anchor_min=(0.5, 0.5), anchor_max=(0.5, 0.5), pivot=(0.5, 0.5), anchored_position=(0.0, 0.0), size_delta=(100.0, 30.0)): # 值域: anchor/pivot 为 0..1,anchored_position/size_delta 为像素 self.anchor_min = tuple(anchor_min) self.anchor_max = tuple(anchor_max) self.pivot = tuple(pivot) self.anchored_position = tuple(anchored_position) self.size_delta = tuple(size_delta) def compute_pixel_rect(self, parent_rect: Tuple[float, float, float, float]): """ 将 RectTransform 转换为相对于父节点的像素矩形 (left, top, width, height) parent_rect: (parent_left, parent_top, parent_width, parent_height) """ p_left, p_top, p_w, p_h = parent_rect a_min_x = self.anchor_min[0] a_min_y = self.anchor_min[1] a_max_x = self.anchor_max[0] a_max_y = self.anchor_max[1] # 计算锚框的像素坐标(left/top 和 right/bottom) anchor_left = p_left + a_min_x * p_w anchor_right = p_left + a_max_x * p_w anchor_top = p_top + a_min_y * p_h anchor_bottom = p_top + a_max_y * p_h # 宽高 if abs(a_max_x - a_min_x) < 1e-6: # 固定锚点 -> 使用 size_delta.x width = float(self.size_delta[0]) # anchored_position.x 表示相对于锚点框的位置(像素) left = anchor_left + float(self.anchored_position[0]) - self.pivot[0] * width else: # 拉伸到锚框再加上 size_delta.x width = (anchor_right - anchor_left) + float(self.size_delta[0]) # anchored_position.x 表示锚框内的像素偏移 left = anchor_left + float(self.anchored_position[0]) if abs(a_max_y - a_min_y) < 1e-6: height = float(self.size_delta[1]) # 注意:engine 中 top 增大表示向下,所以 anchored_position.y 保持像素系 top = anchor_top + float(self.anchored_position[1]) - self.pivot[1] * height else: height = (anchor_bottom - anchor_top) + float(self.size_delta[1]) top = anchor_top + float(self.anchored_position[1]) return (left, top, width, height) def apply_to_lui(self, lui_obj, parent_rect: Tuple[float, float, float, float]): """计算并应用到给定的 LUIObject(设置 left/top/width/height)""" left, top, width, height = self.compute_pixel_rect(parent_rect) try: lui_obj.left = left lui_obj.top = top lui_obj.width = width lui_obj.height = height except Exception: # 忽略不能设置的属性,调用者应保证对象支持这些属性 pass def to_dict(self): return { 'anchor_min': tuple(self.anchor_min), 'anchor_max': tuple(self.anchor_max), 'pivot': tuple(self.pivot), 'anchored_position': tuple(self.anchored_position), 'size_delta': tuple(self.size_delta), }