MetaCore/docs/designs/metacore-model-workflow-p0-implementation-plan.md

11 KiB
Raw Blame History

MetaCore 模型工作流 P0 实施计划

生成时间2026-04-11
状态:执行稿
范围Task 06 / 01 / 03 / 02 / 04 / 05

目的

这份文档把 metacore-model-workflow-p0-task-cards.md 再往下压一层,直接落到:

  • 要改哪些状态
  • 要加哪些接口
  • 哪些面板负责什么
  • 每一步怎么验收

目标是让后续实现阶段尽量少临场改设计。

推荐实施顺序

建议严格按下面顺序推进:

  1. Task 06资源选择状态统一
  2. Task 01Project 面板最小版
  3. Task 03模型资源 Inspector 最小版
  4. Task 02模型 / Prefab 拖拽到 Scene / Hierarchy
  5. Task 04对象材质槽编辑
  6. Task 05材质资源 Inspector 最小版

原因:

  • 没有独立资源选择状态Project 面板和 Inspector 没法稳
  • 没有 Project 面板,后面的资源拖拽和资源 Inspector 都无从谈起
  • 没有模型资源 Inspector资源选中就没有价值
  • 材质槽编辑和材质资源编辑必须等资源选择主链稳定后再上

Step 1资源选择状态统一

目标

让编辑器同时理解两套不同的选择:

  • 场景对象选择
  • 资源选择

并明确 Inspector 当前展示哪一种。

当前问题

目前编辑器核心状态明显偏向对象选择:

  • Hierarchy
  • Scene View
  • Inspector

基本都围绕 GameObject 选中展开。

但一旦引入 Project 面板,编辑器必须明确:

  • 选中资源时Inspector 显示资源
  • 选中对象时Inspector 显示对象

建议改动

A. 在 MetaCoreEditorContext 中新增资源选择状态

建议新增最小状态:

  • std::optional<MetaCoreAssetGuid> SelectedAssetGuid
  • std::filesystem::path SelectedAssetPath
  • std::string SelectedAssetType

也可以封成:

struct MetaCoreSelectedAssetState {
    MetaCoreAssetGuid AssetGuid{};
    std::filesystem::path RelativePath{};
    std::string AssetType{};
    bool Valid = false;
};

B. 新增最小 API

建议在 MetaCoreEditorContext.h 增加:

  • void ClearSelectedAsset();
  • void SelectAsset(const MetaCoreAssetRecord& record);
  • bool HasSelectedAsset() const;
  • const MetaCoreSelectedAssetState& GetSelectedAsset() const;

C. 明确 Inspector 模式

建议增加一个轻量枚举:

enum class MetaCoreInspectorTargetKind {
    None = 0,
    SceneObject,
    Asset
};

EditorContext 决定当前 Inspector 看谁。

D. 事件广播

当前已有 MetaCoreEditorEventBus,建议增加:

  • 复用 SelectionChanged
  • 或新增 AssetSelectionChanged

如果不想扩事件类型,SelectionChanged 也能先扛住,但消息体里最好补一位,区分对象/资源选择。

落点

完成标准

  • 选中对象时 Inspector 仍按对象逻辑显示
  • 选中资源时 Inspector 切到资源模式
  • 二者切换时状态不互相污染

Step 2Project 面板最小版

目标

做出最小可用的资源工作台。

推荐 UI 结构

左栏:目录树

首批固定展示:

  • Assets
  • Scenes
  • Runtime

Library 不作为主工作目录。

右栏:资源列表

当前目录下显示:

  • 文件夹
  • 资源项

建议首批字段:

  • 名称
  • 类型
  • 来源类型(可选)

交互设计

单击目录

  • 更新当前浏览目录

单击资源

  • 写入 EditorContext 的资源选择状态
  • Inspector 联动

双击资源

首批建议:

  • 场景:加载 Scene
  • Prefab先不做独立打开可先选中并允许实例化
  • 模型/材质/纹理:先只选中,不双开

最小动作

建议面板工具栏有:

  • Refresh
  • New Folder

资源项右键菜单首批支持:

  • Reimport
  • Copy Relative Path

数据来源

依赖:

  • GetDirectoriesUnder(relativeDirectory)
  • GetAssetsUnder(relativeDirectory)

落点

完成标准

  • 用户可以浏览项目目录
  • 用户可以选中资源
  • 用户可以执行刷新
  • 用户可以对单资源执行重导入

Step 3模型资源 Inspector 最小版

目标

让选中模型资源这件事有足够信息密度。

建议 Inspector 结构

基础信息区

  • 名称
  • 相对路径
  • ImporterId
  • SourceFormat
  • SourceHash

统计区

  • Mesh Count
  • Material Count
  • Texture Count
  • Node Count

摘要区

  • Mesh 列表
    • 名称
    • PrimitiveCount
  • Material 列表
    • 名称
  • Texture 列表
    • 相对路径

数据读取方式

建议流程:

  1. SelectedAssetGuidMetaCoreAssetRecord
  2. PackagePath
  3. 反序列化 MetaCoreModelAssetDocument
  4. 在 Inspector 渲染

最小动作

  • Reimport
  • Copy Relative Path

落点

完成标准

  • 选中模型资源时能显示完整最小摘要
  • glTF / glb / generic model 都能显示

Step 4模型 / Prefab 拖拽到 Scene / Hierarchy

目标

把现有实例化服务接到编辑器交互里。

拖拽载荷建议

建议定义一个最小内部拖拽 payload

struct MetaCoreAssetDragPayload {
    MetaCoreAssetGuid AssetGuid{};
    std::string AssetType{};
    std::filesystem::path RelativePath{};
};

首批只要支持:

  • model
  • prefab
  • material

Scene 接收规则

模型

  • InstantiateModelAsset(...)

Prefab

  • InstantiatePrefab(...)

Hierarchy 接收规则

模型

  • drop 到某对象时,将该对象作为 forcedParentId

Prefab

  • 同理

首批先不做

  • 3D 光标落点
  • 基于鼠标位置自动设置世界坐标
  • 材质拖到 Scene 视口

落点

  • Project 面板的资源项开始拖拽
  • Scene View 面板接收
  • Hierarchy 面板节点接收

推测落点主要仍是:

完成标准

  • 模型可拖到 Scene
  • 模型可拖到 Hierarchy 节点
  • Prefab 可拖到 Scene / Hierarchy
  • drop 后自动选中新建根对象

Step 5对象 Inspector 中的材质槽编辑

目标

让模型实例不只是“摆进去”,而是真的能改材质引用。

当前基础

MetaCoreComponents.h 中已经有:

  • MeshAssetGuid
  • MaterialAssetGuids

这说明对象级引用结构已经具备。

首批实现建议

A. 在 MeshRenderer Inspector 中列出材质槽

至少显示:

  • 槽位索引
  • 当前材质名

B. 用下拉框替换材质

候选来源:

  • 资产数据库中 Type == "material" 的资源

C. 支持从 Project 面板拖入

拖一个材质资源到对应槽位时:

  • 更新 MaterialAssetGuids[slot]

最小约束

  • 如果对象当前没有足够槽位,首批可只支持已有槽位替换
  • 不在 P0 里做 submesh 级复杂编辑器

落点

完成标准

  • 用户能替换对象材质槽
  • 修改后重新选择对象仍能看到结果
  • Scene 保存重开后引用仍保留

Step 6材质资源 Inspector 最小版

目标

MetaCoreMaterialAssetDocument 变成真正能编辑的资源。

建议显示字段

  • 名称
  • ShaderModel
  • BaseColor
  • BaseColorTexture
  • NormalTexture
  • Metallic
  • Roughness
  • MetallicRoughnessTexture
  • EmissiveColor
  • EmissiveTexture
  • AlphaMode
  • AlphaCutoff
  • DoubleSided

建议编辑方式

标量 / 开关

  • DragFloat
  • Checkbox
  • Combo

资源引用

  • 下拉选择
  • 后续支持从 Project 面板拖入

保存策略

首批建议直接:

  1. 读材质资源包
  2. 反序列化 MetaCoreMaterialAssetDocument
  3. 修改字段
  4. 写回 package

运行时联动

P0 阶段至少要求:

  • 编辑后重新渲染当前对象时能读到更新值

如果实时联动太复杂,也应保证:

  • 再次选中对象 / 刷新场景时能反映资源修改

落点

完成标准

  • 选中材质资源能显示参数
  • 能修改并写回资源
  • 引用该材质的对象能反映修改结果

建议接口补充

为了减少 EditorModule 直接拼太多读写逻辑,建议补一层轻量资源编辑服务,至少先支持模型和材质:

class MetaCoreIAssetEditingService : public MetaCoreIEditorService {
public:
    [[nodiscard]] virtual std::optional<MetaCoreModelAssetDocument> LoadModelAsset(const MetaCoreAssetGuid& assetGuid) const = 0;
    [[nodiscard]] virtual std::optional<MetaCoreMaterialAssetDocument> LoadMaterialAsset(const MetaCoreAssetGuid& assetGuid) const = 0;
    [[nodiscard]] virtual bool SaveMaterialAsset(const MetaCoreAssetGuid& assetGuid, const MetaCoreMaterialAssetDocument& document) = 0;
};

这不是 P0 必须,但非常建议。

否则:

  • Project 面板
  • 资源 Inspector
  • 材质编辑器

都会在 UI 层重复拼 package 读写逻辑。


每步验收命令建议

每完成一个步骤后,至少做下面验证:

cmake --build --preset build-debug
ctest --preset test-debug

同时建议补对应 smoke test

  • 资源选择状态切换
  • Project 面板基础交互
  • 模型资源 Inspector 读取
  • 拖拽实例化
  • 材质槽替换
  • 材质资源写回

风险点

1. 资源选择状态与对象选择状态互相覆盖

这是最容易出现的 UI 脏状态问题。

应优先解。

2. Inspector 读写逻辑散落

如果不抽轻量资源编辑服务,后面会重复实现 package 读写。

3. 对象材质参数和材质资源参数边界混乱

当前 MeshRenderer 仍带着一部分材质字段。

P0 阶段先容忍,但实现时必须有意识:

  • 资源 Inspector 编辑的是资源
  • 对象 Inspector 编辑的是引用

4. 拖拽协议分散

建议早一点统一 asset drag payload避免

  • Project 一套
  • Hierarchy 一套
  • Scene 一套

后面难收。


最终建议

P0 实施时最重要的不是功能总数,而是:

每一步都要让“资源 -> Inspector -> Scene/Hierarchy”这条链更顺而不是再加新的孤立能力。

这条链一旦立住MetaCore 的观感会马上从“会导模型的工具”变成“开始像编辑器的引擎”。