Prechádzať zdrojové kódy

Visual tests: Add Ctrl+Q shortcut for comparing test to previous capture

Michael Ragazzon 4 rokov pred
rodič
commit
ef95ca0c86

+ 1 - 0
Tests/Data/visual_tests_help.rml

@@ -64,6 +64,7 @@
 <key>Ctrl+R</key> <value>Reload test</value>
 <key>Ctrl+S</key> <value>View source of test</value>
 <key>Ctrl+Shift+S</key> <value>View source of reference</value>
+<key>Ctrl+Q</key> <value>Show previous capture of test</value>
 <key>Left Mouse Button on Link</key> <value>Copy link to clipboard (on supported platforms)</value>
 <key>F1</key> <value>Show / hide help</value>
 

+ 52 - 0
Tests/Source/VisualTests/CaptureScreen.cpp

@@ -32,6 +32,7 @@
 #include <ShellRenderInterfaceOpenGL.h>
 #include <RmlUi/Core/Log.h>
 #include <RmlUi/Core/StringUtilities.h>
+#include <RmlUi/Core/GeometryUtilities.h>
 #include <cmath>
 
 #define LODEPNG_NO_COMPILE_CPP
@@ -196,6 +197,57 @@ ComparisonResult CompareScreenToPreviousCapture(ShellRenderInterfaceOpenGL* shel
 	return result;
 }
 
+bool LoadPreviousCapture(
+	ShellRenderInterfaceOpenGL* shell_renderer, const Rml::String& filename, TextureGeometry& out_geometry, Rml::String& out_error_msg)
+{
+	RMLUI_ASSERT(!out_geometry.texture_handle);
+
+	const Rml::String input_path = GetCompareInputDirectory() + "/" + filename;
+
+	unsigned char* data_ref = nullptr;
+	unsigned int w_ref = 0, h_ref = 0;
+
+	unsigned int lodepng_result = lodepng_decode32_file(&data_ref, &w_ref, &h_ref, input_path.c_str());
+	DeferFree defer_free{data_ref};
+
+	if (lodepng_result)
+	{
+		out_error_msg =
+			Rml::CreateString(1024, "Could not load captured screenshot from %s: %s", input_path.c_str(), lodepng_error_text(lodepng_result));
+		return false;
+	}
+	RMLUI_ASSERT(w_ref > 0 && h_ref > 0 && data_ref);
+
+	if (!shell_renderer->GenerateTexture(out_geometry.texture_handle, data_ref, Rml::Vector2i((int)w_ref, (int)h_ref)))
+	{
+		out_error_msg = Rml::CreateString(1024, "Could not generate texture from file %s", input_path.c_str());
+		return false;
+	}
+
+	const Rml::Colourb colour = {255, 255, 255, 255};
+	const Rml::Vector2f uv_top_left = {0, 0};
+	const Rml::Vector2f uv_bottom_right = {1, 1};
+
+	Rml::GeometryUtilities::GenerateQuad(out_geometry.vertices, out_geometry.indices, Rml::Vector2f(0, 0), Rml::Vector2f((float)w_ref, (float)h_ref),
+		colour, uv_top_left, uv_bottom_right, 0);
+
+	return true;
+}
+
+void RenderTextureGeometry(ShellRenderInterfaceOpenGL* shell_renderer, TextureGeometry& geometry)
+{
+	if (geometry.texture_handle)
+		shell_renderer->RenderGeometry(geometry.vertices, 4, geometry.indices, 6, geometry.texture_handle, Rml::Vector2f(0, 0));
+}
+
+void ReleaseTextureGeometry(ShellRenderInterfaceOpenGL* shell_renderer, TextureGeometry& geometry)
+{
+	if (geometry.texture_handle)
+	{
+		shell_renderer->ReleaseTexture(geometry.texture_handle);
+		geometry.texture_handle = 0;
+	}
+}
 
 // Suppress warnings emitted by lodepng
 #if defined(RMLUI_PLATFORM_WIN32) && !defined(__MINGW32__)

+ 14 - 0
Tests/Source/VisualTests/CaptureScreen.h

@@ -30,6 +30,7 @@
 #define RMLUI_TESTS_VISUALTESTS_CAPTURESCREEN_H
 
 #include <RmlUi/Core/Types.h>
+#include <RmlUi/Core/Vertex.h>
 
 class ShellRenderInterfaceOpenGL;
 
@@ -46,5 +47,18 @@ bool CaptureScreenshot(ShellRenderInterfaceOpenGL* shell_renderer, const Rml::St
 
 ComparisonResult CompareScreenToPreviousCapture(ShellRenderInterfaceOpenGL* shell_renderer, const Rml::String& filename);
 
+struct TextureGeometry {
+	Rml::TextureHandle texture_handle = 0;
+	Rml::Vertex vertices[4];
+	int indices[6] = {};
+};
+
+bool LoadPreviousCapture(
+	ShellRenderInterfaceOpenGL* shell_renderer, const Rml::String& filename, TextureGeometry& out_geometry, Rml::String& out_error_msg);
+
+void RenderTextureGeometry(ShellRenderInterfaceOpenGL* shell_renderer, TextureGeometry& geometry);
+
+void ReleaseTextureGeometry(ShellRenderInterfaceOpenGL* shell_renderer, TextureGeometry& geometry);
+
 
 #endif

+ 40 - 3
Tests/Source/VisualTests/TestNavigator.cpp

@@ -34,6 +34,7 @@
 #include <RmlUi/Core/Context.h>
 #include <RmlUi/Core/Element.h>
 #include <Shell.h>
+#include <ShellRenderInterfaceOpenGL.h>
 #include <cstdio>
 
 // When capturing frames it seems we need to wait at least an extra frame for the newly submitted
@@ -61,6 +62,7 @@ TestNavigator::~TestNavigator()
 	context->GetRootElement()->RemoveEventListener(Rml::EventId::Keydown, this);
 	context->GetRootElement()->RemoveEventListener(Rml::EventId::Textinput, this);
 	context->GetRootElement()->RemoveEventListener(Rml::EventId::Change, this);
+	ReleaseTextureGeometry(shell_renderer, reference_geometry);
 }
 
 void TestNavigator::Update()
@@ -104,6 +106,15 @@ void TestNavigator::Update()
 	}
 }
 
+void TestNavigator::Render()
+{
+	if (show_reference && reference_geometry.texture_handle)
+	{
+		shell_renderer->RenderGeometry(
+			reference_geometry.vertices, 4, reference_geometry.indices, 6, reference_geometry.texture_handle, Rml::Vector2f(0, 0));
+	}
+}
+
 void TestNavigator::ProcessEvent(Rml::Event& event)
 {
 	// Keydown events in capture phase to override text input
@@ -189,6 +200,11 @@ void TestNavigator::ProcessEvent(Rml::Event& event)
 					source_state = SourceType::None;
 			}
 			viewer->ShowSource(source_state);
+			ShowReference(false);
+		}
+		else if (key_identifier == Rml::Input::KI_Q && key_ctrl)
+		{
+			ShowReference(!show_reference);
 		}
 		else if (key_identifier == Rml::Input::KI_ESCAPE)
 		{
@@ -337,6 +353,7 @@ void TestNavigator::LoadActiveTest()
 	const TestSuite& suite = CurrentSuite();
 	viewer->LoadTest(suite.GetDirectory(), suite.GetFilename(), suite.GetIndex(), suite.GetNumTests(), suite.GetFilterIndex(), suite.GetNumFilteredTests(), suite_index, (int)test_suites.size());
 	viewer->ShowSource(source_state);
+	ShowReference(false);
 	UpdateGoToText();
 }
 
@@ -514,13 +531,13 @@ void TestNavigator::StopTestSuiteIteration()
 			Rml::Log::Message(Rml::Log::LT_ERROR, "Failed writing comparison log output to file %s", log_path.c_str());
 	}
 
-	suite.SetIndex(iteration_initial_index);
-	LoadActiveTest();
-
 	iteration_index = -1;
 	iteration_initial_index = -1;
 	iteration_wait_frames = -1;
 	iteration_state = IterationState::None;
+
+	suite.SetIndex(iteration_initial_index);
+	LoadActiveTest();
 }
 
 void TestNavigator::UpdateGoToText(bool out_of_bounds)
@@ -531,9 +548,29 @@ void TestNavigator::UpdateGoToText(bool out_of_bounds)
 		viewer->SetGoToText(Rml::CreateString(64, "Go To: %d", goto_index));
 	else if(goto_index == 0)
 		viewer->SetGoToText("Go To:");
+	else if (show_reference)
+		viewer->SetGoToText("Showing reference capture '" + GetImageFilenameFromCurrentTest() + "'");
+	else if (iteration_state == IterationState::Capture)
+		viewer->SetGoToText("Capturing all tests");
+	else if (iteration_state == IterationState::Comparison)
+		viewer->SetGoToText("Comparing all tests");
 	else
 		viewer->SetGoToText("Press 'F1' for keyboard shortcuts.");
 }
 
+void TestNavigator::ShowReference(bool in_show_reference)
+{
+	show_reference = in_show_reference;
+	ReleaseTextureGeometry(shell_renderer, reference_geometry);
+
+	Rml::String error_msg;
+	if (show_reference)
+		show_reference = LoadPreviousCapture(shell_renderer, GetImageFilenameFromCurrentTest(), reference_geometry, error_msg);
 
+	viewer->SetAttention(show_reference);
 
+	if (!error_msg.empty())
+		viewer->SetGoToText(error_msg);
+	else
+		UpdateGoToText();
+}

+ 6 - 0
Tests/Source/VisualTests/TestNavigator.h

@@ -44,6 +44,8 @@ public:
 
 	void Update();
 
+	void Render();
+
 protected:
 	void ProcessEvent(Rml::Event& event) override;
 
@@ -63,6 +65,8 @@ private:
 
 	void UpdateGoToText(bool out_of_bounds = false);
 
+	void ShowReference(bool show);
+
 	Rml::String GetImageFilenameFromCurrentTest();
 
 	ShellRenderInterfaceOpenGL* shell_renderer;
@@ -75,6 +79,8 @@ private:
 	int suite_index = 0;
 	int goto_index = -1;
 	SourceType source_state = SourceType::None;
+	bool show_reference = false;
+	TextureGeometry reference_geometry;
 
 	IterationState iteration_state = IterationState::None;
 

+ 8 - 0
Tests/Source/VisualTests/TestViewer.cpp

@@ -332,3 +332,11 @@ void TestViewer::SetGoToText(const Rml::String& rml)
 	RMLUI_ASSERT(description_goto);
 	description_goto->SetInnerRML(rml);
 }
+
+void TestViewer::SetAttention(bool active)
+{
+	if (active)
+		document_description->SetProperty(Rml::PropertyId::BackgroundColor, Rml::Property(Rml::Colourb(100, 100, 30), Rml::Property::COLOUR));
+	else
+		document_description->RemoveProperty(Rml::PropertyId::BackgroundColor);
+}

+ 2 - 0
Tests/Source/VisualTests/TestViewer.h

@@ -51,6 +51,8 @@ public:
 
 	void SetGoToText(const Rml::String& rml);
 
+	void SetAttention(bool active);
+
 private:
 	Rml::Context* context;
 

+ 4 - 2
Tests/Source/VisualTests/main.cpp

@@ -50,12 +50,14 @@ void GameLoop()
 
 	shell_renderer->PrepareRenderBuffer();
 	context->Render();
+
+	if (g_navigator)
+		g_navigator->Render();
+
 	shell_renderer->PresentRenderBuffer();
 
 	if (g_navigator)
-	{
 		g_navigator->Update();
-	}
 }