MetaCore/tests/MetaCoreSmokeTests.cpp

160 lines
6.9 KiB
C++

#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 <cstdlib>
#include <iostream>
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<MetaCore::MetaCoreId> 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<MetaCore::MetaCoreId> 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<MetaCoreDummyPanelProvider>());
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;
}