EG/ui/panels/editor_panels_right_transform.py
2026-03-12 22:07:48 +08:00

148 lines
5.0 KiB
Python

from imgui_bundle import imgui
class EditorPanelsRightTransformMixin:
"""Compact Unity-style transform editor."""
def _draw_transform_properties(self, node):
imgui.push_style_var(imgui.StyleVar_.frame_padding, (6.0, 4.0))
imgui.push_style_var(imgui.StyleVar_.item_spacing, (6.0, 4.0))
try:
position = node.getPos()
rotation = node.getHpr()
scale = node.getScale()
self._draw_transform_row(
"位置",
"position",
(position.x, position.y, position.z),
lambda values: node.setPos(*values),
speed=0.05,
value_format="%.3f",
reset_values=(0.0, 0.0, 0.0),
)
self._draw_transform_row(
"旋转",
"rotation",
(rotation.x, rotation.y, rotation.z),
lambda values: node.setHpr(*values),
speed=0.25,
value_format="%.2f",
reset_values=(0.0, 0.0, 0.0),
)
self._draw_transform_row(
"缩放",
"scale",
(scale.x, scale.y, scale.z),
lambda values: node.setScale(*values),
speed=0.02,
value_format="%.3f",
reset_values=(1.0, 1.0, 1.0),
linked=getattr(self, "_transform_scale_locked", True),
show_lock=True,
)
finally:
imgui.pop_style_var(2)
def _draw_transform_row(
self,
label,
row_id,
values,
apply_callback,
speed,
value_format,
reset_values,
linked=False,
show_lock=False,
):
axis_names = ("X", "Y", "Z")
axis_colors = (
(0.85, 0.32, 0.32, 1.0),
(0.36, 0.78, 0.42, 1.0),
(0.30, 0.55, 0.92, 1.0),
)
current_values = [float(value) for value in values]
original_values = list(current_values)
changed_any = False
table_flags = (
imgui.TableFlags_.sizing_stretch_same.value
| imgui.TableFlags_.no_pad_outer_x.value
| imgui.TableFlags_.no_borders_in_body.value
)
if imgui.begin_table(f"{row_id}_table", 8, table_flags):
imgui.table_setup_column("label", imgui.TableColumnFlags_.width_fixed.value, 52.0)
imgui.table_setup_column("lock", imgui.TableColumnFlags_.width_fixed.value, 22.0)
for axis_name in axis_names:
imgui.table_setup_column(f"{axis_name}_label", imgui.TableColumnFlags_.width_fixed.value, 16.0)
imgui.table_setup_column(f"{axis_name}_value", imgui.TableColumnFlags_.width_stretch.value, 1.0)
imgui.table_next_row()
imgui.table_next_column()
imgui.text_disabled(label)
imgui.table_next_column()
if show_lock:
changed, self._transform_scale_locked = imgui.checkbox(
f"##{row_id}_lock",
getattr(self, "_transform_scale_locked", True),
)
if imgui.is_item_hovered():
imgui.set_tooltip("锁定 XYZ 缩放比例")
else:
imgui.text("")
for axis_index, axis_name in enumerate(axis_names):
imgui.table_next_column()
imgui.text_colored(axis_colors[axis_index], axis_name)
imgui.table_next_column()
imgui.set_next_item_width(-1)
axis_changed, new_value = imgui.drag_float(
f"##{row_id}_{axis_name}",
current_values[axis_index],
speed,
format=value_format,
)
if axis_changed:
current_values = self._apply_vector_value_change(
original_values,
current_values,
axis_index,
float(new_value),
linked,
reset_values,
)
changed_any = True
imgui.end_table()
if changed_any:
apply_callback(tuple(current_values))
def _apply_vector_value_change(
self,
original_values,
current_values,
axis_index,
new_value,
linked,
reset_values,
):
next_values = list(current_values)
if not linked:
next_values[axis_index] = new_value
return next_values
old_value = original_values[axis_index]
if abs(old_value) > 1e-6:
ratio = new_value / old_value
return [value * ratio for value in original_values]
if abs(reset_values[axis_index]) > 1e-6:
ratio = new_value / float(reset_values[axis_index])
return [float(default_value) * ratio for default_value in reset_values]
return [new_value, new_value, new_value]