#include #include #include #include #include "TestUtils.h" using namespace test; namespace { void testUndoRedoRestoresEdits() { Scene& scene = SceneManager::GetInstance().CreateScene("undo"); GameObject* box = scene.CreateGameObject("box"); box->GetTransform().SetLocalPosition({1.0f, 0.0f, 0.0f}); scene.CommitPendingAdditions(); UndoStack history; history.Reset(scene); check(!history.CanUndo() && !history.Record(scene), "an unchanged scene must not create an undo step"); findByName(scene, "box")->GetTransform().SetLocalPosition({5.0f, 0.0f, 0.0f}); scene.SetSelectedObject(findByName(scene, "box")->GetId()); check(history.Record(scene) && history.CanUndo() && !history.CanRedo(), "an edit must create an undo step"); check(history.Undo(scene), "undo must succeed"); scene.CommitPendingAdditions(); const GameObject* undone = findByName(scene, "box"); check(undone != nullptr && close(undone->GetTransform().GetLocalPosition().x, 1.0f), "undo must restore the earlier state"); check(scene.GetSelectedObject() == undone, "undo must keep the edited object selected"); check(history.CanRedo(), "undo must allow redo"); check(history.Redo(scene), "redo must succeed"); scene.CommitPendingAdditions(); check(close(findByName(scene, "box")->GetTransform().GetLocalPosition().x, 5.0f), "redo must bring the edit back"); check(!history.Record(scene), "reloading the scene for undo must not count as an edit"); scene.CreateGameObject("spawned"); scene.CommitPendingAdditions(); check(history.Record(scene) && !history.CanRedo(), "a new edit must drop the redo steps"); SceneManager::GetInstance().Destroy(); } void testUndoHistoryIsCapped() { Scene& scene = SceneManager::GetInstance().CreateScene("undo cap"); GameObject* box = scene.CreateGameObject("box"); scene.CommitPendingAdditions(); UndoStack history; history.Reset(scene); for (std::size_t i = 0; i < UndoStack::MaxSteps + 10; ++i) { box->GetTransform().SetLocalPosition({static_cast(i + 1), 0.0f, 0.0f}); history.Record(scene); } check(history.UndoCount() == UndoStack::MaxSteps, "the undo history must keep only the newest steps"); SceneManager::GetInstance().Destroy(); } } void RunEditorTests() { testUndoRedoRestoresEdits(); testUndoHistoryIsCapped(); }