feat: parent-child transform hierarchy (UE Actor attach semantics)
- TransformComponent TRS = local (relative to parent); cached world SRT composed hierarchically (parent pos/rot/scale, no matrix decomposition shear under non-uniform parent scale) - HierarchyComponent (parent + children, lazily attached); Scene:: SetParent (keepWorld, cycle-safe) / GetParent / IsDescendantOf / SetWorldPose (world->local inverse, used by physics writeback & gizmo) - UpdateTransforms: DFS from roots, recompose only dirty-or-dirty- ancestor subtrees (parents before children) - DestroyEntity: descendants buried with parent (UE cascade) - Serialization v2: optional Parent uuid key, two-pass relink on load - Hierarchy panel: tree view, drag-drop reparent / drop-to-root detach, Create Child / Detach context menu; Inspector shows parent name - Consumers moved to world-space reads: lights, camera pos, physics bodies/characters/joints/collider baking, gizmo, F-focus, AlignTo
This commit is contained in:
@@ -164,14 +164,15 @@ std::optional<entt::entity> ViewportPanel::Draw(const EditorContext &ctx,
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_F) && tr != nullptr) {
|
||||
// F = 焦点选中实体(frame-selection):编辑器相机
|
||||
// 环绕 pivot 设为选中实体位置,沿视线平移对准(环
|
||||
// 绕距离沿用当前值,滚轮可调)
|
||||
ctx.editorCamera->FocusOn(tr->GetPosition());
|
||||
// 绕距离沿用当前值,滚轮可调)。世界位姿(层级
|
||||
// 实体 = 父链组合结果)
|
||||
ctx.editorCamera->FocusOn(tr->GetWorldPosition());
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Gizmo 操纵杆(ImGui drawlist 叠加,无 GPU pass)----
|
||||
// 选中实体 + 有 Transform 才出杆;矩阵分解直接写回
|
||||
// TransformComponent(与 Inspector 同源,下一帧数值自动跟随)
|
||||
// 选中实体 + 有 Transform 才出杆;分解 world 矩阵经
|
||||
// SetWorldPose 写回(与 Inspector 同源,下一帧数值自动跟随)
|
||||
// PIE 运行态不出杆(编辑操作冻结)
|
||||
if (tr != nullptr && !playing) {
|
||||
// 相机矩阵:跟随渲染源(编辑器形态 = EditorCamera,游戏
|
||||
@@ -263,8 +264,8 @@ std::optional<entt::entity> ViewportPanel::Draw(const EditorContext &ctx,
|
||||
snapping ? snap : nullptr);
|
||||
gizmo.dragging = ImGuizmo::IsUsing();
|
||||
|
||||
// 拖拽生效:分解 world 矩阵写回 SRT(Set* 标脏 →
|
||||
// UpdateTransforms 重算 → 渲染下帧生效)。旋转用
|
||||
// 拖拽生效:分解 world 矩阵 → world SRT → 沿父链反解
|
||||
// local 写回(SetWorldPose;根实体 = 直写)。旋转用
|
||||
// decompose 出的 quat 直写(UE FTransform 语义)——
|
||||
// 不经欧拉往返,拖拽零漂移、无万向锁
|
||||
if (ImGuizmo::IsUsing()) {
|
||||
@@ -272,9 +273,8 @@ std::optional<entt::entity> ViewportPanel::Draw(const EditorContext &ctx,
|
||||
glm::quat rot;
|
||||
glm::vec4 persp;
|
||||
if (glm::decompose(m, scale, rot, transl, skew, persp)) {
|
||||
tr->SetPosition(transl)
|
||||
.SetRotationQuat(rot)
|
||||
.SetScale(scale);
|
||||
ctx.scene->SetWorldPose(selected, transl, rot,
|
||||
scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -382,7 +382,7 @@ void ViewportPanel::LogPick(const EditorContext &ctx, entt::entity e) {
|
||||
? "static" : "dynamic",
|
||||
rb->boxHalfExtents.x, rb->boxHalfExtents.y,
|
||||
rb->boxHalfExtents.z, rb->sphereRadius,
|
||||
tr.GetPosition().x, tr.GetPosition().y, tr.GetPosition().z);
|
||||
tr.GetWorldPosition().x, tr.GetWorldPosition().y, tr.GetWorldPosition().z);
|
||||
} else {
|
||||
ENGINE_INFO("[pick] '{}' (hitproxy) | (no collider)", name);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user