#include "MetaCoreEditor/MetaCoreEditorContext.h" #include "MetaCoreEditor/MetaCoreEditorModule.h" #include "MetaCoreFoundation/MetaCoreLogService.h" #include "MetaCorePlatform/MetaCoreWindow.h" #include "MetaCoreRender/MetaCoreEditorViewportRenderer.h" #include "MetaCoreRender/MetaCoreRenderDevice.h" #include "MetaCoreScene/MetaCoreScene.h" #include #include namespace { void MetaCoreExpect(bool condition, const char* message) { if (!condition) { std::cerr << "MetaCoreSmokeTests failed: " << message << '\n'; std::exit(1); } } class MetaCoreDummyPanelProvider final : public MetaCore::MetaCoreIEditorPanelProvider { public: std::string GetPanelId() const override { return "Dummy"; } std::string GetPanelTitle() const override { return "Dummy"; } bool IsOpenByDefault() const override { return false; } void DrawPanel(MetaCore::MetaCoreEditorContext&) override {} }; void MetaCoreTestSceneEditApi() { MetaCore::MetaCoreScene scene = MetaCore::MetaCoreCreateDefaultScene(); const std::size_t originalCount = scene.GetGameObjects().size(); const auto roots = scene.GetRootObjectIds(); MetaCoreExpect(!roots.empty(), "默认场景应有根对象"); const std::vector duplicateRoots = scene.DuplicateGameObjects({roots.front()}); MetaCoreExpect(!duplicateRoots.empty(), "复制应返回新根对象"); MetaCoreExpect(scene.GetGameObjects().size() > originalCount, "复制后对象数量应增加"); const MetaCore::MetaCoreId duplicatedRootId = duplicateRoots.front(); MetaCoreExpect(scene.FindGameObject(duplicatedRootId) != nullptr, "复制后的对象应可被查找到"); const bool reparented = scene.ReparentGameObjects({duplicatedRootId}, 0, true); MetaCoreExpect(reparented, "重挂接操作应成功"); const std::vector deletedIds = scene.DeleteGameObjects({duplicatedRootId}); MetaCoreExpect(!deletedIds.empty(), "删除应返回被删除对象"); MetaCoreExpect(scene.FindGameObject(duplicatedRootId) == nullptr, "删除后对象不应存在"); } void MetaCoreTestSelectionStateMachine() { MetaCore::MetaCoreWindow window; MetaCore::MetaCoreRenderDevice renderDevice; MetaCore::MetaCoreEditorViewportRenderer viewportRenderer; MetaCore::MetaCoreScene scene; MetaCore::MetaCoreLogService logService; MetaCore::MetaCoreEditorModuleRegistry moduleRegistry; const MetaCore::MetaCoreId objectAId = scene.CreateGameObject("A").Id; const MetaCore::MetaCoreId objectBId = scene.CreateGameObject("B").Id; const MetaCore::MetaCoreId objectCId = scene.CreateGameObject("C").Id; MetaCore::MetaCoreEditorContext editorContext( window, renderDevice, viewportRenderer, scene, logService, moduleRegistry ); editorContext.SelectOnly(objectAId); MetaCoreExpect(editorContext.GetActiveObjectId() == objectAId, "单选后 Active 应为 A"); MetaCoreExpect(editorContext.GetSelectedObjectIds().size() == 1, "单选后应仅包含一个对象"); editorContext.ToggleSelection(objectBId); MetaCoreExpect(editorContext.IsObjectSelected(objectAId), "Toggle 后应保留已选对象 A"); MetaCoreExpect(editorContext.IsObjectSelected(objectBId), "Toggle 后应包含对象 B"); MetaCoreExpect(editorContext.GetActiveObjectId() == objectBId, "Toggle 新增对象后 Active 应为 B"); editorContext.SetSelectionAnchorId(objectAId); editorContext.SelectRangeByOrderedIds(scene.BuildHierarchyPreorder(), objectCId, false); MetaCoreExpect(editorContext.IsObjectSelected(objectAId), "范围选择应包含起点 A"); MetaCoreExpect(editorContext.IsObjectSelected(objectBId), "范围选择应包含中间对象 B"); MetaCoreExpect(editorContext.IsObjectSelected(objectCId), "范围选择应包含终点 C"); MetaCoreExpect(editorContext.GetActiveObjectId() == objectCId, "范围选择后 Active 应为终点 C"); } void MetaCoreTestUndoRedo() { MetaCore::MetaCoreWindow window; MetaCore::MetaCoreRenderDevice renderDevice; MetaCore::MetaCoreEditorViewportRenderer viewportRenderer; MetaCore::MetaCoreScene scene = MetaCore::MetaCoreCreateDefaultScene(); MetaCore::MetaCoreLogService logService; MetaCore::MetaCoreEditorModuleRegistry moduleRegistry; MetaCore::MetaCoreEditorContext editorContext( window, renderDevice, viewportRenderer, scene, logService, moduleRegistry ); const std::size_t beforeCreateCount = scene.GetGameObjects().size(); const bool created = editorContext.ExecuteSnapshotCommand("创建对象", [&]() { MetaCore::MetaCoreGameObject& object = scene.CreateGameObject("UndoRedoObject"); editorContext.SelectOnly(object.Id); return true; }); MetaCoreExpect(created, "创建快照命令应执行成功"); MetaCoreExpect(scene.GetGameObjects().size() == beforeCreateCount + 1, "执行命令后对象数量应增加"); MetaCoreExpect(editorContext.GetCommandService().CanUndo(), "执行命令后应可撤销"); const bool undoSucceeded = editorContext.UndoCommand(); MetaCoreExpect(undoSucceeded, "Undo 应成功"); MetaCoreExpect(scene.GetGameObjects().size() == beforeCreateCount, "Undo 后对象数量应恢复"); MetaCoreExpect(editorContext.GetCommandService().CanRedo(), "Undo 后应可重做"); const bool redoSucceeded = editorContext.RedoCommand(); MetaCoreExpect(redoSucceeded, "Redo 应成功"); MetaCoreExpect(scene.GetGameObjects().size() == beforeCreateCount + 1, "Redo 后对象数量应再次增加"); } } // namespace int main() { MetaCore::MetaCoreScene scene = MetaCore::MetaCoreCreateDefaultScene(); MetaCoreExpect(scene.GetGameObjects().size() == 3, "默认场景应包含三个对象"); bool hasCamera = false; bool hasLight = false; bool hasCube = false; for (const MetaCore::MetaCoreGameObject& object : scene.GetGameObjects()) { hasCamera = hasCamera || object.Camera.has_value(); hasLight = hasLight || object.Light.has_value(); hasCube = hasCube || object.MeshRenderer.has_value(); } MetaCoreExpect(hasCamera, "默认场景应包含摄像机"); MetaCoreExpect(hasLight, "默认场景应包含光源"); MetaCoreExpect(hasCube, "默认场景应包含立方体"); MetaCore::MetaCoreEditorModuleRegistry moduleRegistry; moduleRegistry.RegisterPanelProvider(std::make_unique()); MetaCoreExpect(!moduleRegistry.AccessPanelOpenState("Dummy"), "面板默认状态应为关闭"); MetaCore::MetaCoreLogService logService; logService.AddEntry(MetaCore::MetaCoreLogLevel::Info, "Test", "Smoke"); MetaCoreExpect(logService.GetEntries().size() == 1, "日志服务应记录一条日志"); MetaCoreTestSceneEditApi(); MetaCoreTestSelectionStateMachine(); MetaCoreTestUndoRedo(); std::cout << "MetaCoreSmokeTests passed\n"; return 0; }