Files
HelloVulkan/App/editor/ViewportPanel.h
T
atdunbg c9d4eed043 editor: scale gizmo fully self-drawn (screen-space, view-independent)
ImGuizmo scale hover/drag relies on ray-plane intersection with the
axis as plane normal; in front views (axis ⟂ camera-to-object) the
intersection numerator is identically zero, so handles can't be
grabbed and values jump randomly; axes parallel to the view have zero
screen displacement. Submodule is read-only and AxisMask can only hide
degenerate axes, not replace them.

Replace the library scale path entirely with a screen-space gizmo:
- three axis rods (line + end square) + center uniform-scale square,
  constant screen size in any view
- axis drag: mouse delta projected onto the axis' screen direction
- axis pointing at camera: radial mapping (drag away = grow)
- center square: uniform scale (library MT_SCALE_XYZ semantics)
- Ctrl snapping quantizes the result; scale clamped >= 0.01
- pick suppressed while hovering/dragging the self-drawn handles
2026-10-03 12:23:00 +08:00

74 lines
3.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// ViewportPanel:场景渲染输出面板。
//
// tonemap 输出经 ImGui::Image 显示(Editor 模式),并提供
// Editor Viewport / Fullscreen 显示模式切换。面板可用区域
// (物理像素)上报为渲染分辨率 → 画面精确填满面板。
//
// 点击拾取(UE 式 GPU HitProxy):单击 → NDC 请求 id 渲染;结果
// 由 Draw 每帧轮询取走(像素级,与视觉画面一致)。
//
#ifndef HELLOVULKAN_VIEWPORTPANEL_H
#define HELLOVULKAN_VIEWPORTPANEL_H
#include "EditorContext.h"
#include <imgui.h> // ImVec2(RequestPickAt 签名)
#include <entt/entt.hpp>
#include <optional>
// Viewport 面板每帧上报的输入焦点状态(Hazel 模式:编辑器据此决定
// 游戏侧输入是否放行——悬停/持焦 Viewport 才拥有 WASD/鼠标)
struct ViewportInputState {
bool hovered = false; // 鼠标悬停在 Viewport 面板上
bool focused = false; // Viewport 面板持有键盘焦点
};
// Gizmo 交互状态(Editor 持有、ViewportPanel 写):
// op 取 ImGuizmo::OPERATION 位掩码(TRANSLATE=7=三轴位或运算,非 0
// 起始枚举;0 = 无任何轴位 → Gizmo 完全不绘制),int 存储避免本
// 头文件 include ImGuizmo.h(拖入 imgui 宏依赖顺序)
// W/E/R 切换 op、T 切换 local/world 空间(UE 语义);dragging 拉起
// Editor::BlockingMouse 门控
struct GizmoState {
int op = 7; // ImGuizmo::TRANSLATE(TRANSLATE_X|Y|Z)
bool localSpace = true; // 操纵空间:true=模型轴(旋转/缩放语义),
// T 键切 world
bool dragging = false; // 拖拽中(IsUsing 或自绘缩放拖拽)→ 鼠标归
// Gizmo 不给游戏侧(Editor::BlockingMouse)
// ---- 自绘缩放 gizmo(op==SCALE 整体不走 ImGuizmo)----
// 库内缩放的 hover/拖拽依赖"法线=轴"平面求交:正对视角(轴⊥
// 相机连线)时求交分子恒 0 → 杆抓不到、数值随机猛变;轴∥视线
// 时又无屏幕位移。submodule 禁改,AxisMask 只能"藏"不能"补"
// → 调用层整体自绘三轴杆 + 中心等比方块(纯屏幕空间数学,任意
// 视角良构),实现见 ViewportPanel.cpp ScaleGizmoSelf
bool scaleDragActive = false; // 自绘缩放拖拽中
int scaleDragAxis = -1; // 拖拽目标:0/1/2 轴;-2 = 中心等比
bool scaleHover = false; // 本帧悬停/拖拽自绘手柄 → 抑制 pick
float scaleStartMouse[2] = {0.0f, 0.0f}; // 拖拽起始鼠标(屏幕系)
float scaleStartDist = 0.0f; // 起始鼠标到杆心距离(径向映射用)
float scaleStartScale[3] = {1.0f, 1.0f, 1.0f}; // 拖拽起始 scale
};
class ViewportPanel {
public:
// 返回值:本帧拾取命中的实体(无点击/未命中 = nullopt 或 null);
// Editor 据此 SelectEntity(面板不持有选中状态)
std::optional<entt::entity> Draw(const EditorContext& ctx,
ViewportInputState& out,
GizmoState& gizmo,
entt::entity selected) const;
private:
// Image 区域内的鼠标位置 → NDC → Renderer::RequestPick
//(结果下一帧由 Draw 轮询 TakePickResult 取走)
void RequestPickAt(const EditorContext& ctx, const ImVec2& size) const;
// 命中打印:实体名 + collider 参数对照(诊断物理盒 ≠ 视觉用)
static void LogPick(const EditorContext& ctx, entt::entity e);
};
#endif //HELLOVULKAN_VIEWPORTPANEL_H