camera: UE Scene-view semantics — RMB fly, MMB focus-orbit, wheel dolly, F focus
Key conflict fix (UE semantics): while RMB is held the keyboard belongs to the camera, so WASD no longer collides with the gizmo W/E/R tool hotkeys. Editor mode gates fly movement behind RMB; game mode keeps always-on WASD. Viewport tool hotkeys (W/E/R/T/F) are suppressed while RMB is held. Focus orbit (pivot): MMB drag rotates the camera around a pivot keeping distance; first orbit picks a pivot 5m ahead on the view ray. Shift+MMB pans in screen plane (camera and pivot move together). Mouse wheel dollies toward/away from the pivot with exponential steps (no pivot: move along view ray). F focuses the selected entity (frame-selection): pivot set to its position, camera slides along the view ray; orbit distance persists. Window gains a polled scroll-delta channel (ConsumeScrollDelta) that respects ImGui mouse capture; Camera::Update mutates orbit state (no longer const).
This commit is contained in:
@@ -125,26 +125,38 @@ std::optional<entt::entity> ViewportPanel::Draw(const EditorContext &ctx,
|
||||
else size.y = avail.x / aspect;
|
||||
ImGui::Image((ImTextureID) (intptr_t) sceneTex, size);
|
||||
|
||||
// ---- W/E/R 切换 Gizmo 模式(UE 语义:W 平移 / E 旋转 /
|
||||
// R 缩放),T 切换 local/world 操纵空间。仅 Viewport 持焦时
|
||||
// 生效——输入框打字(WantTextInput)由 BlockingKeyboard 拦
|
||||
// 游戏侧,但 ImGui 自身仍收键,故必须限定持焦面板,避免在
|
||||
// Inspector 拖数值时误切 ----
|
||||
if (out.focused && !ImGui::GetIO().WantTextInput) {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_W)) gizmo.op = ImGuizmo::TRANSLATE;
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_E)) gizmo.op = ImGuizmo::ROTATE;
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_R)) gizmo.op = ImGuizmo::SCALE;
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_T)) gizmo.localSpace = !gizmo.localSpace;
|
||||
}
|
||||
|
||||
// ---- Gizmo 操纵杆(ImGui drawlist 叠加,无 GPU pass)----
|
||||
// 选中实体 + 有 Transform 才出杆;矩阵分解直接写回
|
||||
// TransformComponent(与 Inspector 同源,下一帧数值自动跟随)
|
||||
// ---- 工具热键(UE 语义):W/E/R 切 Gizmo 模式、T 切
|
||||
// local/world、F 焦点选中实体。仅 Viewport 持焦时生效——
|
||||
// 输入框打字(WantTextInput)由 BlockingKeyboard 拦游戏侧,
|
||||
// 但 ImGui 自身仍收键,故必须限定持焦面板。RMB 按住 = 相机
|
||||
// 飞行模式(键盘归相机),工具热键全部抑制——W 前进与
|
||||
// W 平移 Gizmo 的键位冲突就此解耦 ----
|
||||
auto ® = ctx.scene->GetRegistry();
|
||||
ECS::TransformComponent *tr =
|
||||
selected != entt::null
|
||||
? reg.try_get<ECS::TransformComponent>(selected)
|
||||
: nullptr;
|
||||
if (out.focused && !ImGui::GetIO().WantTextInput &&
|
||||
!ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_W)) gizmo.op = ImGuizmo::TRANSLATE;
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_E)) gizmo.op = ImGuizmo::ROTATE;
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_R)) gizmo.op = ImGuizmo::SCALE;
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_T)) gizmo.localSpace = !gizmo.localSpace;
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_F) && tr != nullptr) {
|
||||
// F = 焦点选中实体(frame-selection):环绕 pivot 设
|
||||
// 为选中实体位置,相机沿视线平移对准(环绕距离沿用
|
||||
// 当前值,滚轮可调)
|
||||
ECS::TransformComponent *camT = nullptr;
|
||||
if (auto *camComp = ctx.scene->GetPrimaryCamera(&camT);
|
||||
camComp != nullptr && camT != nullptr) {
|
||||
camComp->camera.FocusOn(*camT, tr->GetPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Gizmo 操纵杆(ImGui drawlist 叠加,无 GPU pass)----
|
||||
// 选中实体 + 有 Transform 才出杆;矩阵分解直接写回
|
||||
// TransformComponent(与 Inspector 同源,下一帧数值自动跟随)
|
||||
if (tr != nullptr) {
|
||||
// 相机矩阵:primary 相机 view + Vulkan proj(转 GL 形式),
|
||||
// 参数与渲染侧一致(aspect = 渲染分辨率、near/far 0.1/100)
|
||||
|
||||
Reference in New Issue
Block a user