1097 lines
41 KiB
Markdown
1097 lines
41 KiB
Markdown
# XCEngine 蓝图
|
||
|
||
本文按当前工作树整理,快照时间为 `2026-04-04`。如果源码、测试、`CMakeLists.txt` 或项目布局继续演进,这份蓝图也必须同步更新。
|
||
|
||
---
|
||
|
||
# SYSTEM_META
|
||
|
||
```yaml
|
||
name: XCEngine
|
||
version: 0.1.0
|
||
type: editor-first-game-engine-workspace
|
||
description: "Windows 优先、编辑器优先的模块化 C++17 游戏引擎工作区,当前已经形成 RHI、Rendering、AssetDatabase/Library、Mono Scripting 与 Editor Viewport 的可运行闭环。"
|
||
target_runtime: "C++17 + .NET Framework 4.7.2 + Mono"
|
||
snapshot_date: 2026-04-04
|
||
primary_platform: Windows 10/11
|
||
workspace_roots: [engine, editor, managed, project, tests]
|
||
```
|
||
|
||
---
|
||
|
||
# SYSTEM_STRUCTURE
|
||
|
||
```yaml
|
||
root: XCEngineWorkspace
|
||
|
||
subsystems:
|
||
- name: Core
|
||
responsibilities:
|
||
- "提供基础类型、事件、Layer/LayerStack、容器、数学和资源路径等通用基础设施。"
|
||
- "为上层 Memory、Threading、Resources、Rendering、Scene 和 Editor 提供共享工具。"
|
||
provides: [Types, Event, LayerStack, Containers, Math, ResourcePath]
|
||
depends_on: []
|
||
boundary:
|
||
inputs: []
|
||
outputs: [基础类型, 通用容器, 几何与路径工具]
|
||
|
||
- name: Memory
|
||
responsibilities:
|
||
- "提供 Allocator、LinearAllocator、PoolAllocator、ProxyAllocator 和全局 MemoryManager。"
|
||
- "为资源缓存、RHI 资源和长期对象生命周期管理提供分配策略。"
|
||
provides: [Allocator, LinearAllocator, PoolAllocator, ProxyAllocator, MemoryManager]
|
||
depends_on: [Core]
|
||
boundary:
|
||
inputs: [分配请求]
|
||
outputs: [内存块, 内存统计]
|
||
|
||
- name: Threading
|
||
responsibilities:
|
||
- "提供 Thread、Mutex、SpinLock、ReadWriteLock、TaskSystem、TaskGroup。"
|
||
- "支撑资源异步加载、后台导入和部分并行测试场景。"
|
||
provides: [Thread, Mutex, ReadWriteLock, TaskSystem, TaskGroup]
|
||
depends_on: [Core]
|
||
boundary:
|
||
inputs: [任务函数, 同步请求]
|
||
outputs: [调度结果, 同步原语]
|
||
|
||
- name: Debug
|
||
responsibilities:
|
||
- "提供 Logger、ILogSink、Profiler、RenderDocCapture 等诊断能力。"
|
||
- "为 engine、editor 和 tests 提供统一日志与性能分析入口。"
|
||
provides: [Logger, ILogSink, Profiler, RenderDocCapture]
|
||
depends_on: [Core, Threading]
|
||
boundary:
|
||
inputs: [日志消息, profile 样本]
|
||
outputs: [控制台输出, 文件输出, profile 数据]
|
||
|
||
- name: Input
|
||
responsibilities:
|
||
- "维护 InputManager、InputModule、InputEvent、InputAxis 和键鼠状态抽象。"
|
||
- "为 runtime 与 editor viewport 导航提供统一输入层。"
|
||
provides: [InputManager, InputModule, InputEvent, InputAxis]
|
||
depends_on: [Core]
|
||
boundary:
|
||
inputs: [平台输入事件]
|
||
outputs: [输入状态, 输入事件流]
|
||
|
||
- name: Project
|
||
responsibilities:
|
||
- "承载 `Project.xcproject`、`Assets/`、`.meta`、`Library/` 的工程数据布局。"
|
||
- "作为 editor、resources、managed、scripting 共享的项目根目录边界。"
|
||
provides: [ProjectDescriptor, AssetSourceTree, AssetMetaFiles, ProjectLibrary, StartupScene]
|
||
depends_on: []
|
||
boundary:
|
||
inputs: [用户资源, 用户脚本, 编辑器操作, 构建产物]
|
||
outputs: [Project.xcproject, Assets, Library]
|
||
|
||
- name: Resources
|
||
responsibilities:
|
||
- "维护 AssetDatabase、AssetImportService、ProjectAssetIndex、ResourceManager 和 ResourceCache。"
|
||
- "把 `Assets/ + .meta` 导入为 `Library/SourceAssetDB`、`Library/ArtifactDB`、`Library/Artifacts`。"
|
||
- "统一运行时资源查找、Artifact 解析、ResourceHandle 与异步加载。"
|
||
provides: [AssetDatabase, AssetImportService, ProjectAssetIndex, ResourceManager, ResourceHandle, AsyncLoader]
|
||
depends_on: [Core, Memory, Threading, Debug, Project]
|
||
boundary:
|
||
inputs: [projectRoot, assetPath, AssetRef, importer settings]
|
||
outputs: [IResource, ArtifactRecord, AssetRef, import status]
|
||
|
||
- name: RHI
|
||
responsibilities:
|
||
- "提供 RHIDevice、RHICommandList、RHISwapChain、RHITexture、RHIBuffer 等抽象接口。"
|
||
- "维护 D3D12、OpenGL、Vulkan 三后端及 RHIFactory 选择逻辑。"
|
||
- "为 Rendering 和 editor host 提供统一 GPU 资源与提交契约。"
|
||
provides: [RHIFactory, RHIDevice, RHICommandList, RHISwapChain, RHITexture, RHIBuffer]
|
||
depends_on: [Core, Debug]
|
||
boundary:
|
||
inputs: [RHIType, 渲染命令, 资源描述]
|
||
outputs: [后端设备, GPU 资源, 提交结果]
|
||
|
||
- name: Rendering
|
||
responsibilities:
|
||
- "维护 `SceneRenderer -> CameraRenderer -> RenderPipeline` 正式主链。"
|
||
- "提供 RenderSurface、RenderContext、RenderSceneExtractor、RenderResourceCache 和 builtin passes。"
|
||
- "支撑 Scene/Game viewport 离屏渲染、ObjectId picking、Outline、InfiniteGrid 和 overlay passes。"
|
||
provides: [SceneRenderer, CameraRenderer, RenderPipeline, RenderSurface, RenderContext, BuiltinPasses]
|
||
depends_on: [Core, Debug, Resources, RHI, Components, Scene]
|
||
boundary:
|
||
inputs: [Scene, CameraRenderRequest, RenderSurface]
|
||
outputs: [离屏颜色/深度目标, ObjectId, overlay draw results]
|
||
|
||
- name: Components
|
||
responsibilities:
|
||
- "提供 GameObject、Component、ComponentFactoryRegistry 和内建组件集合。"
|
||
- "维护 Transform、Camera、Light、Mesh、Audio 等组件级数据。"
|
||
provides: [GameObject, Component, TransformComponent, CameraComponent, LightComponent, MeshFilterComponent, MeshRendererComponent, AudioComponents]
|
||
depends_on: [Core, Resources, Audio]
|
||
boundary:
|
||
inputs: [场景编辑操作, 资源引用]
|
||
outputs: [组件树, 运行时组件状态]
|
||
|
||
- name: Scene
|
||
responsibilities:
|
||
- "维护 Scene、SceneManager、SceneRuntime、RuntimeLoop 和场景序列化。"
|
||
- "负责 `.xc` 场景文档的读写、运行时更新与层级查询。"
|
||
provides: [Scene, SceneManager, SceneRuntime, RuntimeLoop]
|
||
depends_on: [Core, Components]
|
||
boundary:
|
||
inputs: [场景文件, 编辑器命令, deltaTime]
|
||
outputs: [场景树, 保存后的场景文档, 生命周期事件]
|
||
|
||
- name: Scripting
|
||
responsibilities:
|
||
- "维护 ScriptComponent、ScriptEngine、ScriptFieldStorage、IScriptRuntime 与 MonoScriptRuntime。"
|
||
- "加载 `Library/ScriptAssemblies/` 中的 `XCEngine.ScriptCore.dll`、`GameScripts.dll` 和 `mscorlib.dll`。"
|
||
- "提供脚本类发现、字段元数据、默认值、override 和运行时字段同步。"
|
||
provides: [ScriptComponent, ScriptEngine, ScriptFieldStorage, IScriptRuntime, MonoScriptRuntime]
|
||
depends_on: [Core, Components, Scene, Project]
|
||
boundary:
|
||
inputs: [程序集路径, Scene, ScriptComponent field writes]
|
||
outputs: [脚本实例, 字段快照, 生命周期回调]
|
||
|
||
- name: Audio
|
||
responsibilities:
|
||
- "提供 AudioSystem、AudioMixer、IAudioBackend 和 WindowsAudioBackend。"
|
||
- "为 AudioSource / AudioListener 组件提供基础音频运行时支持。"
|
||
provides: [AudioSystem, AudioMixer, IAudioBackend, WindowsAudioBackend]
|
||
depends_on: [Core]
|
||
boundary:
|
||
inputs: [音频配置, 场景音频源]
|
||
outputs: [混音结果, 平台音频提交]
|
||
|
||
- name: Editor
|
||
responsibilities:
|
||
- "维护 `XCEditor` 桌面宿主、项目根解析、SceneManager、ProjectManager、Undo/Selection 和各类面板。"
|
||
- "通过 `ViewportHostService` 把引擎 Rendering + RHI 离屏结果接入 ImGui。"
|
||
- "当前 Scene View 主链按 `SceneViewportChrome -> SceneViewportInteractionFrame -> SceneViewportNavigation -> SceneViewportTransformGizmoCoordinator -> ViewportHostService` 编排。"
|
||
provides: [XCEditor, EditorContext, SceneManager, ProjectManager, ViewportHostService, SceneViewportHelpers]
|
||
depends_on: [Core, Debug, Input, Project, Resources, Rendering, Scene, Scripting, RHI]
|
||
boundary:
|
||
inputs: [用户交互, 项目路径, viewport host window]
|
||
outputs: [编辑器 UI, 场景编辑命令, project workflow, script build trigger]
|
||
|
||
- name: Managed
|
||
responsibilities:
|
||
- "编译 `managed/XCEngine.ScriptCore/` 与 `managed/GameScripts/`。"
|
||
- "扫描 `project/Assets/**/*.cs`,生成项目脚本程序集。"
|
||
- "把产物复制到 `project/Library/ScriptAssemblies/` 和 tests 专用输出目录。"
|
||
provides: [ScriptCoreAssembly, GameScriptsAssembly, ProjectGameScriptsAssembly, MonoCorlibCopy]
|
||
depends_on: [Project, Scripting]
|
||
boundary:
|
||
inputs: [managed C# source files, project C# source files, Mono corlib]
|
||
outputs: [XCEngine.ScriptCore.dll, GameScripts.dll, mscorlib.dll]
|
||
|
||
- name: Tests
|
||
responsibilities:
|
||
- "维护 `tests/` 下对 Core、Resources、RHI、Rendering、Editor、Scripting 等主线模块的回归覆盖。"
|
||
- "维持 `rhi_all_tests`、`rendering_all_tests`、`editor_tests`、`scripting_tests` 等聚合 target。"
|
||
- "验证资源导入、viewport helper 链、脚本程序集输出和 backend 分层边界。"
|
||
provides: [CTestTargets, RegressionSpecs, IntegrationScenes]
|
||
depends_on: [Core, Memory, Threading, Debug, Input, Project, Resources, RHI, Rendering, Components, Scene, Scripting, Editor, Managed]
|
||
boundary:
|
||
inputs: [build targets, test assets, project fixtures]
|
||
outputs: [测试结果, 回归信号]
|
||
|
||
modules:
|
||
- name: Event
|
||
parent_subsystem: Core
|
||
responsibility: "提供线程安全的订阅、退订和事件广播能力。"
|
||
public_api:
|
||
- fn: Subscribe
|
||
params:
|
||
- name: callback
|
||
type: std::function<void(Args...)>
|
||
returns:
|
||
type: uint32
|
||
- fn: Unsubscribe
|
||
params:
|
||
- name: id
|
||
type: uint32
|
||
returns:
|
||
type: void
|
||
- fn: Invoke
|
||
params:
|
||
- name: args
|
||
type: Args...
|
||
returns:
|
||
type: void
|
||
|
||
- name: AssetDatabase
|
||
parent_subsystem: Resources
|
||
responsibility: "维护源资产记录、artifact 记录、.meta 生成和按需重导入。"
|
||
public_api:
|
||
- fn: Initialize
|
||
params:
|
||
- name: projectRoot
|
||
type: const Containers::String&
|
||
returns:
|
||
type: void
|
||
- fn: Refresh
|
||
params: []
|
||
returns:
|
||
type: MaintenanceStats
|
||
- fn: EnsureArtifact
|
||
params:
|
||
- name: requestPath
|
||
type: const Containers::String&
|
||
- name: requestedType
|
||
type: ResourceType
|
||
- name: outAsset
|
||
type: ResolvedAsset&
|
||
returns:
|
||
type: bool
|
||
- fn: TryGetAssetRef
|
||
params:
|
||
- name: requestPath
|
||
type: const Containers::String&
|
||
- name: resourceType
|
||
type: ResourceType
|
||
- name: outRef
|
||
type: AssetRef&
|
||
returns:
|
||
type: bool
|
||
|
||
- name: ResourceManager
|
||
parent_subsystem: Resources
|
||
responsibility: "负责统一资源加载、缓存、AssetRef 解析、项目资源刷新和 Library 重建入口。"
|
||
public_api:
|
||
- fn: Initialize
|
||
params: []
|
||
returns:
|
||
type: void
|
||
- fn: Load
|
||
params:
|
||
- name: path
|
||
type: const Containers::String&
|
||
- name: settings
|
||
type: ImportSettings*
|
||
returns:
|
||
type: ResourceHandle<T>
|
||
- fn: RefreshProjectAssets
|
||
params: []
|
||
returns:
|
||
type: void
|
||
- fn: RebuildProjectAssetCache
|
||
params: []
|
||
returns:
|
||
type: bool
|
||
- fn: GetProjectAssetImportStatus
|
||
params: []
|
||
returns:
|
||
type: AssetImportService::ImportStatusSnapshot
|
||
|
||
- name: RHIFactory
|
||
parent_subsystem: RHI
|
||
responsibility: "根据后端类型创建 RHIDevice,实现抽象层到具体后端的选择。"
|
||
public_api:
|
||
- fn: CreateRHIDevice
|
||
params:
|
||
- name: type
|
||
type: RHIType
|
||
returns:
|
||
type: RHIDevice*
|
||
- fn: CreateRHIDevice
|
||
params:
|
||
- name: typeName
|
||
type: const std::string&
|
||
returns:
|
||
type: RHIDevice*
|
||
|
||
- name: SceneRenderer
|
||
parent_subsystem: Rendering
|
||
responsibility: "构建 CameraRenderRequest 并驱动 CameraRenderer / RenderPipeline 完成场景渲染。"
|
||
public_api:
|
||
- fn: BuildRenderRequests
|
||
params:
|
||
- name: scene
|
||
type: const Components::Scene&
|
||
- name: overrideCamera
|
||
type: Components::CameraComponent*
|
||
- name: context
|
||
type: const RenderContext&
|
||
- name: surface
|
||
type: const RenderSurface&
|
||
returns:
|
||
type: std::vector<CameraRenderRequest>
|
||
- fn: Render
|
||
params:
|
||
- name: requests
|
||
type: const std::vector<CameraRenderRequest>&
|
||
returns:
|
||
type: bool
|
||
|
||
- name: Scene
|
||
parent_subsystem: Scene
|
||
responsibility: "负责 GameObject 层级管理、场景更新和 `.xc` 文档读写。"
|
||
public_api:
|
||
- fn: CreateGameObject
|
||
params:
|
||
- name: name
|
||
type: const std::string&
|
||
- name: parent
|
||
type: GameObject*
|
||
returns:
|
||
type: GameObject*
|
||
- fn: Update
|
||
params:
|
||
- name: deltaTime
|
||
type: float
|
||
returns:
|
||
type: void
|
||
- fn: Save
|
||
params:
|
||
- name: filePath
|
||
type: const std::string&
|
||
returns:
|
||
type: void
|
||
- fn: Load
|
||
params:
|
||
- name: filePath
|
||
type: const std::string&
|
||
returns:
|
||
type: void
|
||
|
||
- name: ScriptEngine
|
||
parent_subsystem: Scripting
|
||
responsibility: "管理 ScriptComponent 生命周期、程序集类发现、字段读写和运行时同步。"
|
||
public_api:
|
||
- fn: SetRuntime
|
||
params:
|
||
- name: runtime
|
||
type: IScriptRuntime*
|
||
returns:
|
||
type: void
|
||
- fn: OnRuntimeStart
|
||
params:
|
||
- name: scene
|
||
type: Components::Scene*
|
||
returns:
|
||
type: void
|
||
- fn: TryGetAvailableScriptClasses
|
||
params:
|
||
- name: outClasses
|
||
type: std::vector<ScriptClassDescriptor>&
|
||
- name: assemblyName
|
||
type: const std::string&
|
||
returns:
|
||
type: bool
|
||
- fn: ApplyScriptFieldWrites
|
||
params:
|
||
- name: component
|
||
type: ScriptComponent*
|
||
- name: requests
|
||
type: const std::vector<ScriptFieldWriteRequest>&
|
||
- name: outResults
|
||
type: std::vector<ScriptFieldWriteResult>&
|
||
returns:
|
||
type: bool
|
||
- fn: TryGetScriptFieldModel
|
||
params:
|
||
- name: component
|
||
type: const ScriptComponent*
|
||
- name: outModel
|
||
type: ScriptFieldModel&
|
||
returns:
|
||
type: bool
|
||
|
||
- name: ScriptFieldStorage
|
||
parent_subsystem: Scripting
|
||
responsibility: "保存脚本字段 override,并提供字符串序列化 / 反序列化。"
|
||
public_api:
|
||
- fn: SetFieldValue
|
||
params:
|
||
- name: fieldName
|
||
type: const std::string&
|
||
- name: type
|
||
type: ScriptFieldType
|
||
- name: value
|
||
type: const ScriptFieldValue&
|
||
returns:
|
||
type: bool
|
||
- fn: Remove
|
||
params:
|
||
- name: fieldName
|
||
type: const std::string&
|
||
returns:
|
||
type: bool
|
||
- fn: SerializeToString
|
||
params: []
|
||
returns:
|
||
type: std::string
|
||
- fn: DeserializeFromString
|
||
params:
|
||
- name: data
|
||
type: const std::string&
|
||
returns:
|
||
type: void
|
||
|
||
- name: ISceneManager
|
||
parent_subsystem: Editor
|
||
responsibility: "为 editor 提供场景创建、加载、保存、脏标记、复制粘贴与 snapshot 恢复接口。"
|
||
public_api:
|
||
- fn: LoadScene
|
||
params:
|
||
- name: filePath
|
||
type: const std::string&
|
||
returns:
|
||
type: bool
|
||
- fn: SaveSceneAs
|
||
params:
|
||
- name: filePath
|
||
type: const std::string&
|
||
returns:
|
||
type: bool
|
||
- fn: GetScene
|
||
params: []
|
||
returns:
|
||
type: Components::Scene*
|
||
- fn: CaptureSceneSnapshot
|
||
params: []
|
||
returns:
|
||
type: SceneSnapshot
|
||
|
||
- name: SceneViewportChrome
|
||
parent_subsystem: Editor
|
||
responsibility: "负责 Scene View 顶栏工具条、工具切换 overlay 和对应命令构建。"
|
||
public_api:
|
||
- fn: RenderSceneViewportTopBar
|
||
params:
|
||
- name: pivotMode
|
||
type: SceneViewportPivotMode&
|
||
- name: transformSpaceMode
|
||
type: SceneViewportTransformSpaceMode&
|
||
returns:
|
||
type: void
|
||
- fn: RenderSceneViewportToolOverlay
|
||
params:
|
||
- name: content
|
||
type: const ViewportPanelContentResult&
|
||
- name: activeTool
|
||
type: SceneViewportToolMode
|
||
returns:
|
||
type: SceneViewportToolOverlayResult
|
||
- fn: BuildSceneViewportToolCommand
|
||
params:
|
||
- name: overlayResult
|
||
type: const SceneViewportToolOverlayResult&
|
||
- name: shortcutAction
|
||
type: const SceneViewportToolShortcutAction&
|
||
returns:
|
||
type: SceneViewportToolCommand
|
||
|
||
- name: SceneViewportInteractionFrame
|
||
parent_subsystem: Editor
|
||
responsibility: "整合 viewport frame geometry、overlay 数据、gizmo frame 和 presentation 刷新。"
|
||
public_api:
|
||
- fn: BuildSceneViewportToolState
|
||
params:
|
||
- name: toolMode
|
||
type: SceneViewportToolMode
|
||
- name: pivotMode
|
||
type: SceneViewportPivotMode
|
||
- name: transformSpaceMode
|
||
type: SceneViewportTransformSpaceMode
|
||
returns:
|
||
type: SceneViewportToolState
|
||
- fn: BuildSceneViewportFrameGeometry
|
||
params:
|
||
- name: viewportSize
|
||
type: const ImVec2&
|
||
- name: viewportMin
|
||
type: const ImVec2&
|
||
- name: absoluteMousePosition
|
||
type: const ImVec2&
|
||
returns:
|
||
type: SceneViewportFrameGeometry
|
||
- fn: BuildSceneViewportInteractionFrameState
|
||
params:
|
||
- name: context
|
||
type: IEditorContext&
|
||
- name: viewportHostService
|
||
type: IViewportHostService&
|
||
- name: hasInteractiveViewport
|
||
type: bool
|
||
- name: geometry
|
||
type: const SceneViewportFrameGeometry&
|
||
- name: gizmoFrameOptions
|
||
type: const SceneViewportTransformGizmoFrameOptions&
|
||
- name: moveGizmo
|
||
type: SceneViewportMoveGizmo&
|
||
- name: rotateGizmo
|
||
type: SceneViewportRotateGizmo&
|
||
- name: scaleGizmo
|
||
type: SceneViewportScaleGizmo&
|
||
- name: emptyOverlayFrameData
|
||
type: const SceneViewportOverlayFrameData&
|
||
returns:
|
||
type: SceneViewportInteractionFrameState
|
||
|
||
- name: EditorScriptAssemblyBuilder
|
||
parent_subsystem: Editor
|
||
responsibility: "从 editor 侧触发项目脚本程序集重建。"
|
||
public_api:
|
||
- fn: RebuildProjectAssemblies
|
||
params:
|
||
- name: projectPath
|
||
type: const std::string&
|
||
returns:
|
||
type: EditorScriptAssemblyBuildResult
|
||
|
||
- name: ProjectFileUtils
|
||
parent_subsystem: Editor
|
||
responsibility: "读写 `Project.xcproject`,并在 project root 与相对路径之间做转换。"
|
||
public_api:
|
||
- fn: SaveProjectDescriptor
|
||
params:
|
||
- name: projectRoot
|
||
type: const std::string&
|
||
- name: descriptor
|
||
type: const ProjectDescriptor&
|
||
returns:
|
||
type: bool
|
||
- fn: LoadProjectDescriptor
|
||
params:
|
||
- name: projectRoot
|
||
type: const std::string&
|
||
returns:
|
||
type: std::optional<ProjectDescriptor>
|
||
- fn: ResolveProjectPath
|
||
params:
|
||
- name: projectRoot
|
||
type: const std::string&
|
||
- name: pathValue
|
||
type: const std::string&
|
||
returns:
|
||
type: std::string
|
||
```
|
||
|
||
---
|
||
|
||
# EVOLUTION_MODE
|
||
|
||
```yaml
|
||
mode: evolve
|
||
description: "当前工作重点是在已经成型的 editor-first 主链上继续收口,而不是重新设计另一套全新架构。"
|
||
context: |
|
||
XCEngine 已经不再是“若干独立 sample + 早期渲染实验”的状态。
|
||
当前真实主线已经包含:
|
||
- D3D12 / OpenGL / Vulkan 三后端 RHI
|
||
- SceneRenderer -> CameraRenderer -> RenderPipeline 渲染链
|
||
- Assets/ + .meta + Library/ 的项目与资源导入链
|
||
- Mono C# scripting runtime 与 ScriptComponent 字段编辑链
|
||
- 通过 Rendering + RHI 接入 ImGui 的 editor Scene/Game viewport
|
||
|
||
当前演进不是从零构建 build,也不是只做零碎 bugfix maintain,而是:
|
||
- 把旧时期残留入口继续收口到当前正式链路
|
||
- 把 project、managed、editor、tests 的边界写实化
|
||
- 在不破坏现有 workflow 的前提下推进 backend parity、viewport helper 正式化、脚本字段持久化和 Library 生命周期工具化
|
||
|
||
仍需明确的现实约束:
|
||
- editor 目前仍是 D3D12 宿主应用
|
||
- Vulkan SDK 当前是配置阶段硬依赖
|
||
- Mono scripting 需要额外外部依赖,但相关代码与构建链已经落地
|
||
- 部分 builtin render pass 仍存在 D3D12-first 假设,需要逐步跨后端收口
|
||
```
|
||
|
||
---
|
||
|
||
# REQUIREMENTS
|
||
|
||
```yaml
|
||
- id: REQ-001
|
||
title: "Editor 必须能加载工程并打开启动场景"
|
||
description: "桌面编辑器必须能够识别 project root、读取 `Project.xcproject`,并加载 `startup_scene` 指向的 `.xc` 场景。"
|
||
source: user
|
||
type: functional
|
||
acceptance_criteria:
|
||
- "`editor/bin/<Config>/XCEngine.exe` 默认可把仓库内 `project/` 识别为工程根。"
|
||
- "支持通过 `--project <path>` 覆盖工程根。"
|
||
- "`startup_scene=Assets/Scenes/Main.xc` 这类相对路径可被 editor 正确解析并载入。"
|
||
priority: P0
|
||
|
||
- id: REQ-002
|
||
title: "项目资源必须通过 Assets/.meta/Library 闭环管理"
|
||
description: "资源系统必须维护 `.meta`、源资产数据库、artifact 数据库和 artifact 输出目录,而不是只做裸路径加载。"
|
||
source: constraint
|
||
type: functional
|
||
acceptance_criteria:
|
||
- "`AssetDatabase` 能扫描 `Assets/` 并为缺失资源生成 `.meta`。"
|
||
- "工程目录下存在 `Library/SourceAssetDB/assets.db` 与 `Library/ArtifactDB/artifacts.db` 两套持久化记录。"
|
||
- "`ResourceManager` 能通过路径或 `AssetRef` 解析 artifact 并触发必要的重导入。"
|
||
priority: P0
|
||
|
||
- id: REQ-003
|
||
title: "Viewport 渲染必须走引擎 Rendering + RHI 主链"
|
||
description: "Scene/Game viewport 不能退化成 editor 私有渲染器,必须继续使用离屏 RenderSurface、CameraRenderRequest 和 builtin passes。"
|
||
source: constraint
|
||
type: functional
|
||
acceptance_criteria:
|
||
- "Scene/Game viewport 能从引擎离屏颜色目标接入 ImGui。"
|
||
- "`ObjectId` picking、outline、grid 和 overlay pass 仍通过 Rendering 合约接入。"
|
||
- "Scene View helper 链保持 `Chrome -> InteractionFrame -> Navigation -> TransformGizmoCoordinator -> ViewportHostService` 口径。"
|
||
priority: P0
|
||
|
||
- id: REQ-004
|
||
title: "脚本程序集必须能从 project/Library/ScriptAssemblies 被发现和加载"
|
||
description: "脚本系统必须同时支持 ScriptCore、示例 GameScripts 和项目 `Assets/**/*.cs` 编译结果。"
|
||
source: user
|
||
type: functional
|
||
acceptance_criteria:
|
||
- "`xcengine_managed_assemblies` 能生成 `XCEngine.ScriptCore.dll`、`GameScripts.dll` 和 `mscorlib.dll`。"
|
||
- "`xcengine_project_managed_assemblies` 能把项目程序集输出到 `project/Library/ScriptAssemblies/`。"
|
||
- "`ScriptEngine` / `MonoScriptRuntime` 能发现脚本类并让 Inspector 读取字段元数据。"
|
||
priority: P0
|
||
|
||
- id: REQ-005
|
||
title: "场景与组件必须可编辑、可保存、可恢复"
|
||
description: "Scene、GameObject 和内建组件必须支持编辑器中的创建、层级调整、复制粘贴、保存与重新加载。"
|
||
source: user
|
||
type: functional
|
||
acceptance_criteria:
|
||
- "`ISceneManager` 提供 New/Load/Save/SaveAs、Copy/Paste/Duplicate、snapshot 恢复。"
|
||
- "`.xc` 场景文件能保留 GameObject 层级、Transform、Mesh、Light、ScriptComponent 等数据。"
|
||
- "重新载入场景后,Inspector 与 viewport 仍能解析对应实体和组件。"
|
||
priority: P0
|
||
|
||
- id: REQ-006
|
||
title: "RHI 抽象层必须维持三后端并保持测试分层"
|
||
description: "公共 RHI 抽象与 D3D12/OpenGL/Vulkan 后端必须继续分层,不能通过测试反向污染抽象层。"
|
||
source: constraint
|
||
type: non-functional
|
||
acceptance_criteria:
|
||
- "`RHIFactory` 继续支持 D3D12、OpenGL、Vulkan 三后端创建。"
|
||
- "`tests/RHI/unit/` 与 `tests/RHI/integration/` 不直接依赖后端私有实现。"
|
||
- "`rhi_all_tests` 仍可作为统一聚合入口。"
|
||
priority: P1
|
||
|
||
- id: REQ-007
|
||
title: "主线测试 target 必须持续可用"
|
||
description: "工程需要保留跨模块聚合 target,用于快速验证 Rendering、Editor、Scripting 和 RHI 主线。"
|
||
source: constraint
|
||
type: non-functional
|
||
acceptance_criteria:
|
||
- "`rendering_all_tests`、`rendering_phase_regression`、`editor_tests`、`scripting_tests`、`rhi_all_tests` 仍存在。"
|
||
- "`tests/Editor/` 覆盖 Scene View helper 新链路。"
|
||
- "资源导入和项目脚本程序集输出存在对应 tests。"
|
||
priority: P1
|
||
|
||
- id: REQ-008
|
||
title: "构建入口必须真实反映当前外部依赖门槛"
|
||
description: "文档和蓝图必须明确 Vulkan、Mono、ImGui、googletest 等依赖的实际门槛,不能继续保留旧时期的过时描述。"
|
||
source: constraint
|
||
type: non-functional
|
||
acceptance_criteria:
|
||
- "配置阶段明确 Vulkan SDK 是当前硬依赖。"
|
||
- "Mono scripting 可通过 `XCENGINE_ENABLE_MONO_SCRIPTING=OFF` 关闭。"
|
||
- "首次配置 editor/tests 时需要考虑 `FetchContent` 的 ImGui 与 googletest。"
|
||
priority: P1
|
||
```
|
||
|
||
---
|
||
|
||
# MVS_DEFINITION
|
||
|
||
```yaml
|
||
mvs_solutions:
|
||
- id: MVS-001
|
||
name: "Editor 宿主与 Scene View 渲染闭环"
|
||
goal: "确保 editor 能以 D3D12 宿主身份启动,并通过 Rendering + RHI 离屏结果驱动 Scene/Game viewport。"
|
||
verification_criteria:
|
||
- "构建 `XCEditor` 后可打开 `project/Assets/Scenes/Main.xc`。"
|
||
- "Scene/Game viewport 能显示离屏渲染结果,而不是空白宿主窗口。"
|
||
- "`tests/Editor/` 中与 viewport helper 链相关的测试保持通过。"
|
||
scope:
|
||
- subsystem: Editor
|
||
components: [Application, ViewportHostService, SceneViewPanel, SceneViewportChrome, SceneViewportInteractionFrame]
|
||
- subsystem: Rendering
|
||
components: [SceneRenderer, CameraRenderer, RenderPipeline, RenderSurface]
|
||
- subsystem: RHI
|
||
components: [RHIFactory, RHIDevice, RHITexture]
|
||
- external: [Win32, ImGui, D3D12]
|
||
code_structure:
|
||
- file: editor/src/Application.cpp
|
||
purpose: "初始化 editor 宿主、project root、script runtime status 和 application 生命周期。"
|
||
contains:
|
||
- "project root 解析"
|
||
- "Library/ScriptAssemblies wiring"
|
||
- "editor runtime lifecycle"
|
||
standalone: false
|
||
- file: editor/src/Viewport/ViewportHostService.h
|
||
purpose: "把 Scene View 与引擎 Rendering/RHI 输出连接起来。"
|
||
contains:
|
||
- "offscreen render target ownership"
|
||
- "overlay data access"
|
||
- "viewport render flow"
|
||
standalone: false
|
||
- file: engine/include/XCEngine/Rendering/SceneRenderer.h
|
||
purpose: "构建并执行场景渲染请求。"
|
||
contains:
|
||
- "CameraRenderRequest build"
|
||
- "render dispatch"
|
||
standalone: false
|
||
integration_plan:
|
||
- step: "由 editor 解析工程根并创建 viewport host。"
|
||
- step: "由 Rendering 根据当前 scene 与 camera 构建 render requests。"
|
||
- step: "把离屏颜色目标交回 editor,并由 ImGui 面板展示。"
|
||
status: completed
|
||
|
||
- id: MVS-002
|
||
name: "Assets/.meta/Library 资源导入与运行时加载闭环"
|
||
goal: "确保工程资源从 `Assets/` 到 `Library/Artifacts/` 的导入、记录和运行时解析已经形成统一链路。"
|
||
verification_criteria:
|
||
- "首次扫描工程时能补 `.meta` 并建立 `assets.db` / `artifacts.db`。"
|
||
- "`ResourceManager` 能按路径和 `AssetRef` 成功定位 artifact。"
|
||
- "材质、网格、shader 等资源的 artifact 重导入路径保持一致。"
|
||
scope:
|
||
- subsystem: Project
|
||
components: [Assets, AssetMetaFiles, ProjectLibrary]
|
||
- subsystem: Resources
|
||
components: [AssetDatabase, AssetImportService, ProjectAssetIndex, ResourceManager]
|
||
- subsystem: Tests
|
||
components: [asset_tests, material_tests, mesh_tests, shader_tests, texture_tests]
|
||
code_structure:
|
||
- file: engine/include/XCEngine/Core/Asset/AssetDatabase.h
|
||
purpose: "定义源资产记录、artifact 记录和导入维护接口。"
|
||
contains:
|
||
- "SourceAssetRecord"
|
||
- "ArtifactRecord"
|
||
- "EnsureArtifact / Refresh"
|
||
standalone: false
|
||
- file: engine/include/XCEngine/Core/Asset/ResourceManager.h
|
||
purpose: "统一运行时加载、项目资源刷新和 Library 重建入口。"
|
||
contains:
|
||
- "Load / LoadAsync"
|
||
- "RefreshProjectAssets"
|
||
- "RebuildProjectAssetCache"
|
||
standalone: false
|
||
- file: project/Library/
|
||
purpose: "承载 SourceAssetDB、ArtifactDB、Artifacts、ScriptAssemblies 等工程级缓存。"
|
||
contains:
|
||
- "SourceAssetDB/assets.db"
|
||
- "ArtifactDB/artifacts.db"
|
||
- "Artifacts/<shard>/<artifactKey>"
|
||
standalone: false
|
||
integration_plan:
|
||
- step: "扫描 `Assets/` 并生成缺失 `.meta`。"
|
||
- step: "写入源资产与 artifact 数据库。"
|
||
- step: "通过 `ResourceManager` 暴露统一的运行时解析入口。"
|
||
status: completed
|
||
|
||
- id: MVS-003
|
||
name: "Mono 脚本程序集与 ScriptComponent 闭环"
|
||
goal: "确保 C# API、示例脚本和项目脚本可构建、可发现、可在 Inspector 与运行时之间同步字段。"
|
||
verification_criteria:
|
||
- "`xcengine_managed_assemblies` 与 `xcengine_project_managed_assemblies` 产物齐全。"
|
||
- "`ScriptEngine` 能发现可用脚本类并生成字段模型。"
|
||
- "Inspector 中对 ScriptComponent 字段的编辑能写回存储并在运行时同步。"
|
||
scope:
|
||
- subsystem: Managed
|
||
components: [XCEngine.ScriptCore, GameScripts, project asset assemblies]
|
||
- subsystem: Scripting
|
||
components: [ScriptEngine, ScriptFieldStorage, MonoScriptRuntime, ScriptComponent]
|
||
- subsystem: Editor
|
||
components: [EditorScriptAssemblyBuilder, ScriptComponentEditor]
|
||
- external: [dotnet, Mono]
|
||
code_structure:
|
||
- file: managed/CMakeLists.txt
|
||
purpose: "定义 ScriptCore、示例脚本、项目脚本与 tests 专用程序集输出。"
|
||
contains:
|
||
- "xcengine_managed_assemblies"
|
||
- "xcengine_project_managed_assemblies"
|
||
- "xcengine_test_project_managed_assemblies"
|
||
standalone: false
|
||
- file: engine/include/XCEngine/Scripting/ScriptEngine.h
|
||
purpose: "管理脚本生命周期、脚本类发现和字段同步。"
|
||
contains:
|
||
- "TryGetAvailableScriptClasses"
|
||
- "ApplyScriptFieldWrites"
|
||
- "TryGetScriptFieldModel"
|
||
standalone: false
|
||
- file: editor/src/Scripting/EditorScriptAssemblyBuilder.h
|
||
purpose: "从 editor 触发项目脚本程序集重建。"
|
||
contains:
|
||
- "RebuildProjectAssemblies"
|
||
standalone: false
|
||
- file: project/Library/ScriptAssemblies/
|
||
purpose: "承载 editor 与 runtime 实际加载的程序集目录。"
|
||
contains:
|
||
- "XCEngine.ScriptCore.dll"
|
||
- "GameScripts.dll"
|
||
- "mscorlib.dll"
|
||
standalone: false
|
||
integration_plan:
|
||
- step: "先构建 ScriptCore 与示例脚本程序集。"
|
||
- step: "扫描 `project/Assets/**/*.cs` 并生成项目脚本程序集。"
|
||
- step: "由 editor/runtime 从 `Library/ScriptAssemblies/` 装载程序集并驱动 ScriptComponent。"
|
||
status: completed
|
||
```
|
||
|
||
---
|
||
|
||
# DATA_MODELS
|
||
|
||
```yaml
|
||
- name: ProjectDescriptor
|
||
description: "`Project.xcproject` 的键值对格式工程描述。"
|
||
fields:
|
||
- name: version
|
||
type: int
|
||
default: 1
|
||
constraints: required
|
||
- name: name
|
||
type: string
|
||
default: project root folder name
|
||
constraints: required
|
||
- name: startup_scene
|
||
type: string
|
||
default: Assets/Scenes/Main.xc
|
||
constraints: required
|
||
|
||
- name: SceneDocument
|
||
description: "`.xc` 场景文件;文件头记录 scene 名称和 active 状态,随后以 `gameobject_begin/end` 块序列化实体及组件。"
|
||
fields:
|
||
- name: scene
|
||
type: string
|
||
default: Untitled Scene
|
||
constraints: required
|
||
- name: active
|
||
type: bool
|
||
default: true
|
||
constraints: required
|
||
- name: gameObjects
|
||
type: list<GameObjectRecord>
|
||
default: []
|
||
constraints: required
|
||
|
||
- name: AssetMetaFile
|
||
description: "与每个工程资源并存的 `.meta` 文件,保存 guid 与 importer 信息。"
|
||
fields:
|
||
- name: fileFormatVersion
|
||
type: int
|
||
default: 1
|
||
constraints: required
|
||
- name: guid
|
||
type: AssetGUID
|
||
default: generated
|
||
constraints: required
|
||
- name: folderAsset
|
||
type: bool
|
||
default: false
|
||
constraints: required
|
||
- name: importer
|
||
type: string
|
||
default: DefaultImporter
|
||
constraints: required
|
||
- name: importerVersion
|
||
type: int
|
||
default: 5
|
||
constraints: required
|
||
|
||
- name: SourceAssetRecord
|
||
description: "`AssetDatabase` 中对源资产的持久化记录,对应 `Library/SourceAssetDB/assets.db`。"
|
||
fields:
|
||
- name: guid
|
||
type: AssetGUID
|
||
default: generated
|
||
constraints: required
|
||
- name: relativePath
|
||
type: string
|
||
default: ""
|
||
constraints: required
|
||
- name: metaPath
|
||
type: string
|
||
default: ""
|
||
constraints: required
|
||
- name: isFolder
|
||
type: bool
|
||
default: false
|
||
constraints: required
|
||
- name: importerName
|
||
type: string
|
||
default: DefaultImporter
|
||
constraints: required
|
||
- name: importerVersion
|
||
type: uint32
|
||
default: 5
|
||
constraints: required
|
||
- name: metaHash
|
||
type: string
|
||
default: ""
|
||
constraints: required
|
||
- name: sourceHash
|
||
type: string
|
||
default: ""
|
||
constraints: required
|
||
- name: lastKnownArtifactKey
|
||
type: string
|
||
default: ""
|
||
constraints: optional
|
||
|
||
- name: ArtifactRecord
|
||
description: "`AssetDatabase` 对 artifact 的持久化记录,对应 `Library/ArtifactDB/artifacts.db`。"
|
||
fields:
|
||
- name: artifactKey
|
||
type: string
|
||
default: ""
|
||
constraints: required
|
||
- name: assetGuid
|
||
type: AssetGUID
|
||
default: generated
|
||
constraints: required
|
||
- name: importerName
|
||
type: string
|
||
default: ""
|
||
constraints: required
|
||
- name: importerVersion
|
||
type: uint32
|
||
default: 0
|
||
constraints: required
|
||
- name: resourceType
|
||
type: ResourceType
|
||
default: Unknown
|
||
constraints: required
|
||
- name: artifactDirectory
|
||
type: string
|
||
default: ""
|
||
constraints: required
|
||
- name: mainArtifactPath
|
||
type: string
|
||
default: ""
|
||
constraints: required
|
||
- name: dependencies
|
||
type: list<ArtifactDependencyRecord>
|
||
default: []
|
||
constraints: optional
|
||
|
||
- name: ScriptFieldStorageModel
|
||
description: "`ScriptFieldStorage` 的字段 override 存储模型,可序列化为字符串并挂在 ScriptComponent 上。"
|
||
fields:
|
||
- name: fields
|
||
type: map<string, StoredScriptField>
|
||
default: {}
|
||
constraints: required
|
||
- name: StoredScriptField.type
|
||
type: ScriptFieldType
|
||
default: None
|
||
constraints: required
|
||
- name: StoredScriptField.value
|
||
type: ScriptFieldValue
|
||
default: null
|
||
constraints: required
|
||
|
||
- name: ScriptAssemblySet
|
||
description: "`project/Library/ScriptAssemblies/` 中 editor/runtime 解析的一组程序集。"
|
||
fields:
|
||
- name: outputDirectory
|
||
type: path
|
||
default: project/Library/ScriptAssemblies
|
||
constraints: required
|
||
- name: coreAssembly
|
||
type: path
|
||
default: XCEngine.ScriptCore.dll
|
||
constraints: required
|
||
- name: gameAssembly
|
||
type: path
|
||
default: GameScripts.dll
|
||
constraints: required
|
||
- name: corlib
|
||
type: path
|
||
default: mscorlib.dll
|
||
constraints: required
|
||
|
||
- name: MaterialArtifactHeader
|
||
description: "材质 artifact 文件头,对应 `XCMAT02` 和 schema v2。"
|
||
fields:
|
||
- name: magic
|
||
type: char[8]
|
||
default: XCMAT02
|
||
constraints: required
|
||
- name: schemaVersion
|
||
type: uint32
|
||
default: 2
|
||
constraints: required
|
||
- name: renderQueue
|
||
type: int32
|
||
default: Geometry
|
||
constraints: required
|
||
- name: textureBindingCount
|
||
type: uint32
|
||
default: 0
|
||
constraints: required
|
||
```
|
||
|
||
---
|
||
|
||
# EVOLUTION_PLAN
|
||
|
||
```yaml
|
||
fix_plan:
|
||
- issue_id: BUG-001
|
||
description: "工作树中的 `project/Library/ScriptAssemblies/` 快照可能落后于目标构建产物,容易让 editor 脚本类发现与真实构建状态脱节。"
|
||
root_cause: "脚本程序集同时存在 managed 输出、project 输出和 tests 专用输出三处目录,单看仓库快照容易误判。"
|
||
minimal_change:
|
||
- file: managed/CMakeLists.txt
|
||
- file: editor/src/Scripting/EditorScriptAssemblyBuilder.cpp
|
||
- file: tests/Scripting/test_project_script_assembly.cpp
|
||
verification: "执行 `cmake --build build --config Debug --target xcengine_project_managed_assemblies scripting_tests`,确认 editor 与 tests 都从正确输出目录装载程序集。"
|
||
|
||
- issue_id: BUG-002
|
||
description: "Scene View 新交互如果绕过 helper 链直接写回旧 world overlay 路径,会导致实现和 `tests/Editor/` 的行为漂移。"
|
||
root_cause: "旧入口仍可访问,容易跳过 `SceneViewportChrome -> SceneViewportInteractionFrame -> SceneViewportNavigation -> SceneViewportTransformGizmoCoordinator` 的新编排。"
|
||
minimal_change:
|
||
- file: editor/src/Viewport/SceneViewportChrome.h
|
||
- file: editor/src/Viewport/SceneViewportInteractionFrame.h
|
||
- file: editor/src/panels/SceneViewPanel.cpp
|
||
- file: tests/Editor/test_scene_viewport_chrome.cpp
|
||
verification: "执行 `cmake --build build --config Debug --target editor_tests`,确认 helper 链相关测试继续通过。"
|
||
|
||
refactor_plan:
|
||
- target: "继续把 editor 侧 viewport 行为收口到 Rendering overlay pass 与 helper 链"
|
||
constraints:
|
||
- "不要把新逻辑重新堆回 `SceneViewPanel.cpp` 或 panel 层临时拼的 immediate draw 路径。"
|
||
- "保持 `tests/Editor/` 对 helper 的独立覆盖。"
|
||
- "Editor 仍然是宿主层,渲染问题优先回到 Rendering / RHI contract 排查。"
|
||
steps:
|
||
- "优先扩展 `SceneViewportInteractionFrame`、`SceneViewportNavigation`、`SceneViewportTransformGizmoCoordinator`。"
|
||
- "世界空间 overlay 优先经 `CameraRenderRequest::overlayPasses` 和 `SceneViewportEditorOverlayPass` 接入。"
|
||
- "helper 链变化时同步维护 editor README、AGENT 和 API 页面。"
|
||
|
||
- target: "统一 `Assets/.meta/Library` 导入链与运行时解析链的契约"
|
||
constraints:
|
||
- "不要把 `project/Library/` 当作无关垃圾目录。"
|
||
- "不要在局部代码路径里绕开 `AssetDatabase` / `ProjectAssetIndex` / `ResourceManager`。"
|
||
- "artifact schema 变更必须同步 tests 与文档。"
|
||
steps:
|
||
- "继续把资产定位、artifact 生成、AssetRef 解析集中在 `AssetDatabase`、`ProjectAssetIndex`、`ResourceManager`。"
|
||
- "保持 `Project.xcproject`、`.meta`、`assets.db`、`artifacts.db` 和 `Artifacts/` 之间的一致性。"
|
||
- "对材质、网格、shader artifact 的契约修改补齐 `tests/Resources/`。"
|
||
|
||
feature_plan:
|
||
- feature_id: FEAT-001
|
||
name: "Builtin pass 跨后端收口"
|
||
addition: "逐步降低 Rendering 内置 pass 对 D3D12 的硬编码假设,使离屏渲染、ObjectId 和 outline contract 更接近真正的 backend-agnostic。"
|
||
integration_point: "engine/src/Rendering/Passes/, engine/src/RHI/, tests/Rendering/, tests/RHI/"
|
||
steps:
|
||
- "梳理 `BuiltinInfiniteGridPass`、`BuiltinObjectIdPass`、`BuiltinObjectIdOutlinePass` 的 backend gating。"
|
||
- "把必须留在 D3D12-host 层的逻辑与真正属于 Rendering 的逻辑继续拆开。"
|
||
- "为跨后端 contract 补齐单测和场景回归。"
|
||
|
||
- feature_id: FEAT-002
|
||
name: "脚本字段持久化与编辑器回写深化"
|
||
addition: "继续增强 `ScriptFieldStorage`、Inspector 字段编辑与运行时字段同步的一致性。"
|
||
integration_point: "engine/src/Scripting/, editor/src/ComponentEditors/, project/Assets/Scripts/, tests/Scripting/, tests/Editor/"
|
||
steps:
|
||
- "扩展字段类型覆盖与默认值解析。"
|
||
- "校验默认值、stored override 与 runtime 值三态同步。"
|
||
- "保持 scene 保存、重新载入和 play mode 之间的字段一致性。"
|
||
|
||
- feature_id: FEAT-003
|
||
name: "Project Library 生命周期工具化"
|
||
addition: "在不破坏现有 workflow 的前提下增强 Library 清理、重建与状态可视化。"
|
||
integration_point: "engine/include/XCEngine/Core/Asset/ResourceManager.h, editor/src/Managers/ProjectManager.cpp, editor/src/Application.cpp"
|
||
steps:
|
||
- "把清理与重建入口继续收束到 `ResourceManager` 和 editor commands。"
|
||
- "为 `SourceAssetDB`、`ArtifactDB`、`Artifacts`、`ScriptAssemblies` 提供更明确的状态反馈。"
|
||
- "补对应 tests 和用户文档,避免再次把 `Library/` 误写成可忽略目录。"
|
||
```
|