#include "render_2D/scene/Render_Scene_2D.h" #include #include #include namespace renderive { namespace { std::unique_ptr make_scene( Render_Scene_2D::State state = {}) { auto strategy = std::make_shared(); return Render_Scene_2D::Builder(std::move(strategy)) .configure([&](Render_Scene_2D::Properties& properties) { properties = state; }) .build().value(); } TEST(RenderScene2DFramePipeline, BuilderOwnsConstructionAndState) { Render_Scene_2D::State state; state.viewport = {96, 54}; state.background = Color{8, 16, 24, 255}; auto scene = make_scene(state); ASSERT_TRUE(scene); EXPECT_EQ(scene->root_renderable()->object_name(), "root"); } TEST(RenderScene2DFramePipeline, SceneBuilderOwnsRenderableGroupAndObjectNames) { auto builder = Render_Scene_2D::Builder( std::make_shared()); auto child = detail::make_renderable_group(false, "child"); builder.add_renderable(child); auto built_scene = builder.build(); ASSERT_TRUE(built_scene); ASSERT_TRUE(*built_scene); EXPECT_EQ(child->object_name(), "child"); EXPECT_EQ((*built_scene)->observer().renderable_count, 2U); } TEST(RenderScene2DFramePipeline, SceneBuilderRejectsMissingDependencyEndpoint) { auto builder = Render_Scene_2D::Builder( std::make_shared()); auto external = detail::make_renderable_group(false, "external"); auto child = detail::make_renderable_group(false, "child"); detail::Renderable_Build_Access::add_dependency_parent( *child, external); builder.add_renderable(child); auto built_scene = builder.build(); ASSERT_FALSE(built_scene); EXPECT_EQ(built_scene.error(), Scene_Build_Result::dependency_endpoint_missing); } TEST(RenderScene2DFramePipeline, SceneBuilderRejectsDependencyCycle) { auto builder = Render_Scene_2D::Builder( std::make_shared()); auto first = detail::make_renderable_group(false, "first"); auto second = detail::make_renderable_group(false, "second"); detail::Renderable_Build_Access::add_dependency_parent(*first, second); detail::Renderable_Build_Access::add_dependency_parent(*second, first); builder.add_renderable(first); builder.add_renderable(second); auto built_scene = builder.build(); ASSERT_FALSE(built_scene); EXPECT_EQ(built_scene.error(), Scene_Build_Result::dependency_cycle); } TEST(RenderScene2DFramePipeline, SceneValidityDoesNotGateStrategyProgress) { Render_Scene_2D::State state; state.viewport = {80, 45}; auto scene = make_scene(state); scene->publish_frame_state(); EXPECT_EQ(scene->observer().state, state); EXPECT_EQ(scene->render_frame().value(), Plot_Render_Status::view_inactive); scene->activate_view(); EXPECT_EQ(scene->render_frame().value(), Plot_Render_Status::rendered); EXPECT_EQ(scene->render_frame().value(), Plot_Render_Status::rendered); EXPECT_EQ(scene->wait_for_render(), Scene_Render_Result::none); } TEST(RenderScene2DFramePipeline, ObserverReadsPublishedDoubleBufferedState) { Render_Scene_2D::State state; state.viewport = {32, 24}; auto scene = make_scene(state); scene->activate_view(); ASSERT_EQ(scene->render_frame().value(), Plot_Render_Status::rendered); ASSERT_EQ(scene->wait_for_render(), Scene_Render_Result::none); const auto observation = scene->observer(); EXPECT_EQ(observation.state, state); EXPECT_EQ(observation.renderable_count, 1U); EXPECT_TRUE(observation.view_active); EXPECT_GT(observation.frequency_hz, 0.0); } } // namespace } // namespace renderive