Files
atdunbg beba491bcb 阶段性合并:动画重定向、碎裂共享库、第三人称玩法、编辑器面板与 vendored ufbx
- 动画:HumanoidRig 三层架构(standard 标准槽 / dialects 方言映射 / mapper 配对),
  指/趾统一走世界增量两遍式烘焙;AnimationAttach 拆为纯算法 + facade;修正 HumanoidBasis
  行走基朝向与跨骨架去重、根运动通道
- 物理:CharacterController 角色互碰撞 / shapeOffset / 接触事件;PhysicsWorld 接触合成与
  字符冲量判定
- 渲染与材质:Model 多材质按材质拆子 mesh 与贴图路径解析、DDS 直传、GLB 内嵌纹理落盘、
  不透明通道 alpha 固定 1.0、glTF FlipUVs 对齐;SceneSerializer 支持 meshIndex 与材质覆盖
- 脚本:FractureLib 抽为共享库(HostView 桥接)、WallFracture 参数直绑、新增
  ThirdPersonCamera / Follower / WASDMove 玩法;移除 GameDirector / PlayerController / Target
- 编辑器:新增 GamepadPanel、LogPanel(LogRing),改进 Inspector / 材质 / 统计 / 视口面板
- 依赖:vendored ufbx(FBX 5.x/6.x/7.x 全版本解析,替代 assimp 对 FBX 6.1 的拒读)
2026-10-11 22:22:19 +08:00

167 lines
6.6 KiB
C++
Raw Permalink 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.
//
// Editor:docking 编辑器骨架。
//
// 职责:
// - 顶栏菜单(File/View)+ 全屏 DockSpace + 首帧默认布局(DockBuilder)
// - 实体选中状态(entt::entity,Hierarchy 写 / Inspector 读)
// - 退出确认模态框(窗口关闭 → RequestQuit → Yes 时 Close)
//
// 面板窗口名(Outliner/Details/Viewport/Stats/Content Browser)即
// docking 身份,imgui.ini 持久化布局;默认布局只在 dock node 为空时
// 构建一次(旧名 ini 由 Init 一次性迁移删除,见 Editor.cpp)。
//
#ifndef HELLOVULKAN_EDITOR_H
#define HELLOVULKAN_EDITOR_H
#include "EditorContext.h"
#include "panels/ViewportPanel.h" // ViewportInputState(成员按值持有)
#include <Engine/Core/Types.h> // u32(SelectEntity 位模式转换)
#include <Engine/Core/GameFlow.h> // PIE 状态权威(IsPlaying 直查)
#include <entt/entt.hpp>
#include <memory>
#include <optional>
class HierarchyPanel;
class InspectorPanel;
class ViewportPanel;
class StatsPanel;
class LogPanel;
class GamepadPanel;
class AssetBrowserPanel;
class MaterialEditorPanel;
class ControllerEditorPanel;
class Editor {
public:
Editor();
~Editor();
Editor(const Editor&) = delete;
Editor& operator=(const Editor&) = delete;
// 注入上下文(OnInit 阶段,指针必须全部有效)
void Init(const EditorContext& ctx);
// 每帧 UI 构建(OnImGuiRender 唯一入口)
void Draw();
// ---- 输入归属判定(Window 层输入捕获谓词;UE/Unity 的
// "viewport 持焦才拥有输入" 语义,ImGui 侧经自身后端
// 链式回调永远正常收输入)----
// 键盘:编辑器形态 = Viewport 持焦且不在文本输入中;游戏形态
// (Fullscreen)只在文本输入中让位(打字不触发快捷键)
bool BlockingKeyboard() const;
// 鼠标:编辑器形态 = 悬停 Viewport 才放行;Gizmo 拖拽中一律拦截
// (抓杆时相机不能吃鼠标);游戏形态沿用 WantCaptureMouse
bool BlockingMouse() const;
// 请求退出(弹确认框;窗口关闭事件走这里)
void RequestQuit() { m_ShowQuitConfirm = true; }
// ---- PIE(Play-In-Editor,UE 主工具栏语义)----
// 状态权威 = GameFlow(EditorContext::flow);编辑器只是转换的
// 发起者(Request*)与监听器(快照/恢复挂在 →Loading/→Stopped)
bool IsPlaying() const
{
return m_Ctx.flow &&
(m_Ctx.flow->IsIn(Engine::GameFlowState::Running) ||
m_Ctx.flow->IsIn(Engine::GameFlowState::Paused));
}
bool IsPaused() const
{
return m_Ctx.flow &&
m_Ctx.flow->IsIn(Engine::GameFlowState::Paused);
}
// Play:RequestStart → →Loading 监听器做快照 + 切 gameView(Viewport
// 内嵌 primary 相机渲染,UE PIE 语义;不切全屏)→ 同步加载完成
// CompleteLoading → Running 解冻;Stop:RequestStop → →Stopped 监听器
// 快照原子换血恢复 → 回编辑器渲染。编辑器态默认冻结(GameFlow 构造
// 即 timeScale=0),Play 解冻由 GameFlow 权威处理
void TogglePlay();
// PIE 暂停切换(UE Pause 语义):Running ↔ Paused(timeScale 由
// GameFlow 权威处理)。运行态才有意义(编辑器态本来就冻结,
// Pause 按钮不出现)
void TogglePause();
private:
// GameFlow 监听器(Init 注册):编辑器快照/恢复挂在此处——
// GameFlow 不知场景,转换的副作用由消费端自己挂
void OnFlowEnterLoading(); // →Loading:快照 + 切 gameView + 同步完成加载
void OnFlowEnterStopped(); // →Stopped:快照换血恢复 + 回编辑器渲染
// ---- 选中状态 ----
// 同步描边:Renderer 落帧后 SelectionMask/Outline 只画选中实体。
// nullopt = 清选中——实体 0 号(场景首个创建)位模式 = 0,
// 不能拿位值兼作哨兵("第一个模型无描边"的根因)
void SelectEntity(entt::entity e)
{
m_Selected = e;
if (m_Ctx.renderer) {
m_Ctx.renderer->SetSelectedEntity(
e == entt::null
? std::optional<Engine::u32>{}
: std::optional<Engine::u32>(
static_cast<Engine::u32>(entt::to_integral(e))));
}
}
entt::entity GetSelected() const { return m_Selected; }
private:
void DrawMenuBar(); // host 窗口内顶栏(File/View 菜单)
void DrawToolbar(); // 菜单栏下方主工具栏(Play/Pause/Stop 居中)
void DrawDockSpace(); // 全屏 host + dockspace + 默认布局
void DrawQuitModal(); // 退出确认模态框
void DrawSceneModals(); // 保存/加载路径模态框(共用一个路径输入)
void DoSaveScene(); // 模态确认动作:目录创建 + 序列化落盘
void DoLoadScene(); // 模态确认动作:反序列化 + 选中清空 + 环境恢复 + 回调
EditorContext m_Ctx{};
ViewportInputState m_VpInput{}; // Viewport 面板 hover/focus(每帧刷新)
GizmoState m_Gizmo{}; // 视口操纵杆状态(op/拖拽中)
std::unique_ptr<HierarchyPanel> m_Hierarchy;
std::unique_ptr<InspectorPanel> m_Inspector;
std::unique_ptr<ViewportPanel> m_Viewport;
std::unique_ptr<StatsPanel> m_Stats;
std::unique_ptr<LogPanel> m_Log;
std::unique_ptr<GamepadPanel> m_Gamepad;
std::unique_ptr<AssetBrowserPanel> m_AssetBrowser;
std::unique_ptr<MaterialEditorPanel> m_MaterialEditor;
std::unique_ptr<ControllerEditorPanel> m_ControllerEditor;
entt::entity m_Selected{entt::null};
// 面板显隐(View 菜单)
bool m_ShowHierarchy = true;
bool m_ShowInspector = true;
bool m_ShowViewport = true;
bool m_ShowStats = true;
bool m_ShowLog = true;
bool m_ShowAssetBrowser = true;
bool m_ShowMaterialEditor = true;
// 默认布局只建一次(imgui.ini 已有布局则跳过)
bool m_LayoutBuilt = false;
// 退出确认链
bool m_ShowQuitConfirm = false;
bool m_QuitConfirmed = false;
// 场景保存/加载(File 菜单 → 路径模态框;无文件对话框库,InputText 手输)
bool m_ShowSaveModal = false;
bool m_ShowLoadModal = false;
char m_ScenePathBuf[256] = "scenes/sandbox.scene";
// PIE 镜像态(面板只读指针消费;权威 = GameFlow,Draw 开头同步)
bool m_PlayingMirror = false;
bool m_PausedMirror = false;
std::string m_PlaySnapshot;
};
#endif //HELLOVULKAN_EDITOR_H