Files
EVEngine/test/editor_camera_target.cpp
T

70 lines
3.8 KiB
C++

#include "camera_editing/CameraTarget.h"
#include "zeroerr/assert.h"
#include "zeroerr/unittest.h"
using namespace eve::camera_editing;
using namespace eve::editing;
namespace {
void apply(CameraDocumentTarget& target, EditorResult<DomainOperation> operation) {
REQUIRE(operation.ok());
REQUIRE(target.applyDomainOperation(operation.value()).ok());
}
SelectionSnapshot select(const CameraDocumentTarget& target, const char* id) {
SelectionSnapshot selection;
selection.channel = "camera";
selection.items.push_back({SelectionDomain::Asset, TargetId(target.targetId()), StableId(id), "camera.rig"});
return selection;
}
CameraRigValue rig(const char* id, const char* mode = "follow") {
CameraRigValue value;
value.id = ObjectId(id); value.name = id; value.mode = mode;
return value;
}
}
TEST_CASE("editor.camera.rigs_are_property_editable_reversible_and_persistent") {
CameraDocumentTarget target("shot");
apply(target, target.makeCreateRig(rig("hero", "orbit")));
const auto selection = select(target, "hero");
auto edit = target.makeSet(selection, PropertyPath("rig.fov"), 72.0, PropertySetMode::Absolute);
REQUIRE(edit.ok()); REQUIRE(target.applyDomainOperation(edit.value()).ok());
CHECK_EQ(*target.read(selection, PropertyPath("rig.fov")).value.getIf<double>(), 72.0);
DomainOperation undo = edit.value(); undo.payload = edit.value().inverse;
REQUIRE(target.applyDomainOperation(undo).ok());
CHECK_EQ(*target.read(selection, PropertyPath("rig.fov")).value.getIf<double>(), 60.0);
CameraDocumentTarget restored("copy");
REQUIRE(restored.loadSnapshot(target.snapshotValue()).ok());
CHECK_EQ(restored.rigs().front().id.value(), std::string("hero"));
}
TEST_CASE("editor.camera.timeline_has_stable_keys_reference_safety_and_scrub") {
CameraDocumentTarget target("shot");
auto hero = rig("hero", "follow"); hero.offset = {0, 3, 8};
apply(target, target.makeCreateRig(hero));
CameraTimelineKeyValue cut; cut.id=ObjectId("cut-1"); cut.kind="cut"; cut.time=1; cut.rig=ObjectId("hero"); cut.blend=.5f;
apply(target, target.makeCreateKey(cut));
CameraTimelineKeyValue fov0; fov0.id=ObjectId("fov-0"); fov0.kind="float"; fov0.time=1; fov0.property="fov"; fov0.value=60;
apply(target, target.makeCreateKey(fov0));
CameraTimelineKeyValue fov; fov.id=ObjectId("fov-1"); fov.kind="float"; fov.time=3; fov.property="fov"; fov.value=80;
apply(target, target.makeCreateKey(fov));
CHECK_EQ(static_cast<int>(target.makeDeleteRig(ObjectId("hero")).code()), static_cast<int>(EditorStatus::Conflict));
CameraPreview preview; auto pose=preview.evaluate(target,2); REQUIRE(pose.ok());
CHECK_EQ(pose.value().rig.value(),std::string("hero")); CHECK_EQ(pose.value().fov,70.f);
auto overlay=preview.gizmo(target,2); REQUIRE(overlay.ok()); CHECK_EQ(overlay.value().primitives.size(),static_cast<std::size_t>(3));
}
TEST_CASE("editor.camera.invalid_snapshot_and_runtime_generation_are_atomic") {
CameraDocumentTarget target("shot"); apply(target,target.makeCreateRig(rig("hero")));
const auto before=target.snapshotValue(); EditorValue invalid=before;
auto* root=invalid.getIf<EditorValue::Object>(); auto* content=(*root)["content"].getIf<EditorValue::Object>();
auto* rigs=(*content)["rigs"].getIf<EditorValue::Array>(); auto* first=(*rigs)[0].getIf<EditorValue::Object>(); (*first)["fov"]=200.0;
CHECK_EQ(static_cast<int>(target.loadSnapshot(invalid).code()),static_cast<int>(EditorStatus::Rejected));
CHECK_EQ(target.snapshotValue(),before);
CameraDocumentRuntime runtime; REQUIRE(runtime.publish(target,nullptr).ok());
auto* generation=runtime.controller(); const auto revision=runtime.revision();
CameraDocumentTarget empty("empty"); REQUIRE(runtime.publish(empty,nullptr).ok());
CHECK(runtime.controller()!=generation); CHECK(runtime.revision()!=revision);
}