Răsfoiți Sursa

Merge branch 'lottie'

Michael Ragazzon 5 ani în urmă
părinte
comite
ff920d6ef0

+ 13 - 3
.appveyor.yml

@@ -20,7 +20,15 @@ install:
     mv freetype_tmp/include include
     mv freetype_tmp/%PLATFORM_NAME% lib
     
-    cd ..
+    git clone --depth 1 --branch v0.2 https://github.com/Samsung/rlottie.git
+    cd rlottie
+    mkdir build
+    cd build
+    cmake -G "%VS_GENERATOR%" -DBUILD_SHARED_LIBS=OFF -DLOTTIE_MODULE=OFF ..
+    cmake --build . --target rlottie --config Debug -- "/clp:ErrorsOnly"
+    cmake --build . --target rlottie --config Release -- "/clp:ErrorsOnly"
+    cd ../../../
+    
     mkdir Build-Dynamic, Build-Static
     
     cd Build-Dynamic
@@ -66,10 +74,12 @@ after_build:
     echo Built using %VS_GENERATOR% on %APPVEYOR_REPO_COMMIT_TIMESTAMP:~0,10% (build %APPVEYOR_BUILD_NUMBER%).>> Readme.txt
     echo Commit id: %APPVEYOR_REPO_COMMIT%.>> Readme.txt
     
-    7z a RmlUi-%PLATFORM_NAME%.zip Bin/ Include/ Readme.txt changelog.md LICENSE Dependencies/freetype-%FREETYPE_VER%/ Samples/
+    7z a RmlUi-%PLATFORM_NAME%.zip Bin/ Include/ Samples/ Readme.txt changelog.md LICENSE Dependencies/freetype-%FREETYPE_VER%/ Dependencies/rlottie/COPYING Dependencies/rlottie/licenses/
     
-    mkdir Samples\Dependencies\freetype-%FREETYPE_VER%
+    mkdir Samples\Dependencies\freetype-%FREETYPE_VER%, Samples\Dependencies\rlottie, Samples\Dependencies\rlottie\licenses
     cp Dependencies/freetype-%FREETYPE_VER%/*.TXT Samples/Dependencies/freetype-%FREETYPE_VER%
+    cp Dependencies/rlottie/COPYING Samples/Dependencies/rlottie
+    cp Dependencies/rlottie/licenses/* Samples/Dependencies/rlottie/licenses
     IF "%PLATFORM_NAME%"=="win64" 7z a RmlUi-%PLATFORM_NAME%-samples-only.zip LICENSE .\Samples\* -r -xr!src\ -x!shell\ -x!luainvaders\
     
 for:

+ 11 - 0
CMake/SampleFileList.cmake

@@ -103,6 +103,17 @@ set(transform_SRC_FILES
     ${PROJECT_SOURCE_DIR}/Samples/basic/transform/src/main.cpp
 )
 
+set(lottie_HDR_FILES
+    ${PROJECT_SOURCE_DIR}/Samples/basic/lottie/src/ElementLottie.h
+    ${PROJECT_SOURCE_DIR}/Samples/basic/lottie/src/LottiePlugin.h
+)
+
+set(lottie_SRC_FILES
+    ${PROJECT_SOURCE_DIR}/Samples/basic/lottie/src/ElementLottie.cpp
+    ${PROJECT_SOURCE_DIR}/Samples/basic/lottie/src/LottiePlugin.cpp
+    ${PROJECT_SOURCE_DIR}/Samples/basic/lottie/src/main.cpp
+)
+
 set(sdl2_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Samples/basic/sdl2/src/RenderInterfaceSDL2.h
     ${PROJECT_SOURCE_DIR}/Samples/basic/sdl2/src/SystemInterfaceSDL2.h

+ 1 - 1
CMake/gen_samplelists.sh

@@ -8,7 +8,7 @@ srcdir='${PROJECT_SOURCE_DIR}'
 srcpath=Samples
 samples=( 'shell'
 	'basic/animation' 'basic/benchmark' 'basic/bitmapfont' 'basic/customlog' 'basic/databinding' 'basic/demo' 'basic/drag' 'basic/loaddocument' 'basic/treeview' 'basic/transform'
-	'basic/sdl2' 'basic/sfml2'
+	'basic/lottie' 'basic/sdl2' 'basic/sfml2'
 	'tutorial/template' 'tutorial/datagrid' 'tutorial/datagrid_tree' 'tutorial/drag'
 	'invaders' 'luainvaders'
 )

+ 40 - 1
CMakeLists.txt

@@ -120,6 +120,10 @@ if(NOT DEFINED ENV{TRACY_DIR})
 	set(ENV{TRACY_DIR} "${PROJECT_SOURCE_DIR}/Dependencies")
 endif()
 
+if(NOT DEFINED ENV{RLOTTIE_DIR})
+	set(ENV{RLOTTIE_DIR} "${PROJECT_SOURCE_DIR}/Dependencies/rlottie")
+endif()
+
 #===================================
 # Plaform specific global hacks ====
 #===================================
@@ -256,7 +260,6 @@ elseif (ENABLE_PRECOMPILED_HEADERS)
 	set(PRECOMPILED_HEADERS_ENABLED ON)
 endif()
 
-
 option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors." OFF)
 mark_as_advanced(WARNINGS_AS_ERRORS)
 
@@ -675,6 +678,36 @@ endif(NOT BUILD_FRAMEWORK)
 				RUNTIME DESTINATION ${SAMPLES_DIR}/sfml2
 				BUNDLE DESTINATION ${SAMPLES_DIR})
 	endif()
+	
+	# Try to find rlottie for the lottie sample.
+	if(NOT DEFINED rlottie_DIR)
+		set(rlottie_DIR $ENV{RLOTTIE_DIR})
+	endif()
+
+	list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Dependencies/rlottie/build)
+	find_package(rlottie CONFIG)
+	find_path(rlottie_INCLUDE_DIR rlottie.h HINTS ${rlottie_DIR} $ENV{rlottie_DIR} PATH_SUFFIXES inc rlottie/inc )
+	
+	if(rlottie_FOUND AND rlottie_INCLUDE_DIR)
+		message("-- Can lottie sample be built - yes")
+		bl_sample(lottie ${sample_LIBRARIES} rlottie::rlottie)
+		target_include_directories(lottie PRIVATE ${rlottie_INCLUDE_DIR})
+		
+		# The samples always set this as their current working directory
+		install(DIRECTORY DESTINATION ${SAMPLES_DIR}/basic/lottie)
+		install(TARGETS lottie
+			RUNTIME DESTINATION ${SAMPLES_DIR}/lottie
+			BUNDLE DESTINATION ${SAMPLES_DIR}
+		)
+	else()
+		if(rlottie_FOUND)
+			message("-- Can lottie sample be built - no - rlottie library found - rlotty include directory not found")
+		elseif(rlottie_INCLUDE_DIR)
+			message("-- Can lottie sample be built - no - rlottie library not found - rlotty include directory found at ${rlottie_INCLUDE_DIR}")
+		else()
+			message("-- Can lottie sample be built - no - rlottie not found")
+		endif()
+	endif()
 
 	# Build and install the tutorials
 	foreach(tutorial ${tutorials})
@@ -771,6 +804,12 @@ if(BUILD_SAMPLES)
 	install(DIRECTORY ${PROJECT_SOURCE_DIR}/Samples/invaders/data
 			DESTINATION ${SAMPLES_DIR}/invaders
 	)
+	
+	if(TARGET lottie)
+		install(DIRECTORY ${PROJECT_SOURCE_DIR}/Samples/basic/lottie/data
+				DESTINATION ${SAMPLES_DIR}/basic/lottie
+		)
+	endif()
 
 	if(BUILD_LUA_BINDINGS)
 		install(DIRECTORY ${PROJECT_SOURCE_DIR}/Samples/luainvaders/data 

+ 7 - 1
Include/RmlUi/Core/FileInterface.h

@@ -52,7 +52,7 @@ public:
 	virtual ~FileInterface();
 
 	/// Opens a file.
-	/// @param file The file handle to write to.
+	/// @param path The path to the file to open.
 	/// @return A valid file handle, or nullptr on failure
 	virtual FileHandle Open(const String& path) = 0;
 	/// Closes a previously opened file.
@@ -81,6 +81,12 @@ public:
 	/// @param file The handle of the file to be queried.
 	/// @return The length of the file in bytes.
 	virtual size_t Length(FileHandle file);
+
+	/// Load and return a file.
+	/// @param path The path to the file to load.
+	/// @param out_data The string contents of the file.
+	/// @return True on success.
+	virtual bool LoadFile(const String& path, String& out_data);
 };
 
 } // namespace Rml

+ 12 - 0
Samples/basic/lottie/data/LICENSE.txt

@@ -0,0 +1,12 @@
+The file 'a_mountain.json' included in this directory is from the rlottie project [1], licensed under MIT. The license is restated below.
+[1] https://github.com/Samsung/rlottie
+
+----------------------------
+
+Copyright 2020 (see AUTHORS)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
Samples/basic/lottie/data/a_mountain.json


+ 32 - 0
Samples/basic/lottie/data/lottie.rml

@@ -0,0 +1,32 @@
+<rml>
+	<head>
+		<title>Demo</title>
+		<link type="text/template" href="/assets/window.rml" />
+		<style>
+			body
+			{
+				width: 300px;
+				height: 225px;
+				
+				margin: auto;
+			}
+			
+			div#title_bar div#icon
+			{
+				display: none;
+			}
+			
+			div#content
+			{
+				text-align: left;
+			}
+			lottie {
+				width: 100%;
+				max-height: 100%;
+			}
+		</style>
+	</head>
+	<body template="window">
+		<lottie src="a_mountain.json"></lottie>
+	</body>
+</rml>

+ 236 - 0
Samples/basic/lottie/src/ElementLottie.cpp

@@ -0,0 +1,236 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ * Copyright (c) 2019 The RmlUi Team, and contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "ElementLottie.h"
+#include <RmlUi/Core/Core.h>
+#include <RmlUi/Core/PropertyIdSet.h>
+#include <RmlUi/Core/GeometryUtilities.h>
+#include <RmlUi/Core/ElementDocument.h>
+#include <RmlUi/Core/SystemInterface.h>
+#include <RmlUi/Core/FileInterface.h>
+#include <cmath>
+#include <rlottie.h>
+
+namespace Rml {
+
+ElementLottie::ElementLottie(const String& tag) : Element(tag), geometry(this)
+{
+}
+
+ElementLottie::~ElementLottie(void)
+{
+}
+
+bool ElementLottie::GetIntrinsicDimensions(Vector2f& dimensions, float& ratio)
+{
+	if (animation_dirty)
+		LoadAnimation();
+
+	dimensions = intrinsic_dimensions;
+	if (dimensions.y > 0)
+		ratio = dimensions.x / dimensions.y;
+
+	return true;
+}
+
+void ElementLottie::OnRender()
+{
+	if (animation)
+	{
+		if (geometry_dirty)
+			GenerateGeometry();
+
+		UpdateTexture();
+		geometry.Render(GetAbsoluteOffset(Box::CONTENT).Round());
+	}
+}
+
+void ElementLottie::OnResize()
+{
+	geometry_dirty = true;
+}
+
+void ElementLottie::OnAttributeChange(const ElementAttributes& changed_attributes)
+{
+	Element::OnAttributeChange(changed_attributes);
+
+	if (changed_attributes.count("src"))
+	{
+		animation_dirty = true;
+		DirtyLayout();
+	}
+}
+
+void ElementLottie::OnPropertyChange(const PropertyIdSet& changed_properties)
+{
+	Element::OnPropertyChange(changed_properties);
+
+	if (changed_properties.Contains(PropertyId::ImageColor) ||
+		changed_properties.Contains(PropertyId::Opacity)) {
+		geometry_dirty = true;
+	}
+}
+
+void ElementLottie::GenerateGeometry()
+{
+	geometry.Release(true);
+
+	Vector< Vertex >& vertices = geometry.GetVertices();
+	Vector< int >& indices = geometry.GetIndices();
+
+	vertices.resize(4);
+	indices.resize(6);
+
+	Vector2f texcoords[2] = {
+		{0.0f, 0.0f},
+		{1.0f, 1.0f}
+	};
+
+	const ComputedValues& computed = GetComputedValues();
+
+	const float opacity = computed.opacity;
+	Colourb quad_colour = computed.image_color;
+	quad_colour.alpha = (byte)(opacity * (float)quad_colour.alpha);
+
+	const Vector2f render_dimensions_f = GetBox().GetSize(Box::CONTENT).Round();
+	render_dimensions.x = int(render_dimensions_f.x);
+	render_dimensions.y = int(render_dimensions_f.y);
+
+	GeometryUtilities::GenerateQuad(&vertices[0], &indices[0], Vector2f(0, 0), render_dimensions_f, quad_colour, texcoords[0], texcoords[1]);
+
+	geometry_dirty = false;
+}
+
+bool ElementLottie::LoadAnimation()
+{
+	animation_dirty = false;
+	intrinsic_dimensions = Vector2f{};
+	geometry.SetTexture(nullptr);
+	animation.reset();
+	prev_animation_frame = size_t(-1);
+	time_animation_start = -1;
+
+	const String attribute_src = GetAttribute<String>("src", "");
+
+	if (attribute_src.empty())
+		return false;
+
+	String path = attribute_src;
+	String directory;
+
+	if (ElementDocument* document = GetOwnerDocument())
+	{
+		const String document_source_url = StringUtilities::Replace(document->GetSourceURL(), '|', ':');
+		GetSystemInterface()->JoinPath(path, document_source_url, attribute_src);
+		GetSystemInterface()->JoinPath(directory, document_source_url, "");
+	}
+
+	String json_data;
+
+	if (path.empty() || !GetFileInterface()->LoadFile(path, json_data))
+	{
+		Log::Message(Rml::Log::Type::LT_WARNING, "Could not load lottie file %s", path.c_str());
+		return false;
+	}
+
+	animation = rlottie::Animation::loadFromData(std::move(json_data), path, directory);
+
+	if (!animation)
+	{
+		Log::Message(Rml::Log::Type::LT_WARNING, "Could not construct the lottie animation %s", path.c_str());
+		return false;
+	}
+
+	size_t width = 0, height = 0;
+	animation->size(width, height);
+	intrinsic_dimensions.x = float(width);
+	intrinsic_dimensions.y = float(height);
+
+	return true;
+}
+
+void ElementLottie::UpdateTexture()
+{
+	if (!animation)
+		return;
+
+	const double t = GetSystemInterface()->GetElapsedTime();
+
+	if (time_animation_start < 0.0)
+		time_animation_start = t;
+
+	// Find the next animation frame to display.
+	// Here it is possible to add more logic to control playback speed, pause/resume, and more.
+	double _unused;
+	// Find the normalized animation progress [0, 1].
+	const double pos = std::modf((t - time_animation_start) / animation->duration(), &_unused);
+
+	const size_t next_frame = animation->frameAtPos(pos);
+	if (next_frame == prev_animation_frame)
+		return;
+
+	// Callback for generating texture.
+	auto p_callback = [this, next_frame](const String& /*name*/, UniquePtr<const byte[]>& data, Vector2i& dimensions) -> bool {
+		RMLUI_ASSERT(animation);
+
+		const size_t bytes_per_line = 4 * render_dimensions.x;
+		const size_t total_bytes = bytes_per_line * render_dimensions.y;
+
+		byte* p_data = new byte[total_bytes];
+
+		rlottie::Surface surface(reinterpret_cast<std::uint32_t*>(p_data), render_dimensions.x, render_dimensions.y, bytes_per_line);
+		animation->renderSync(next_frame, surface);
+
+		// Swizzle the channel order from rlottie's BGRA to RmlUi's RGBA, and change pre-multiplied to post-multiplied alpha.
+		for (size_t i = 0; i < total_bytes; i += 4)
+		{
+			// Swap the RB order for correct color channels.
+			std::swap(p_data[i], p_data[i + 2]);
+
+			const byte a = p_data[i + 3];
+
+			// The RmlUi samples shell uses post-multiplied alpha, while rlottie serves pre-multiplied alpha.
+			// Here, we un-premultiply the colors.
+			if (a > 0 && a < 255)
+			{
+				for (size_t j = 0; j < 3; j++)
+					p_data[i + j] = (p_data[i + j] * 255) / a;
+			}
+		}
+
+		data.reset(p_data);
+		dimensions = render_dimensions;
+
+		return true;
+	};
+
+	texture.Set("lottie", p_callback);
+	geometry.SetTexture(&texture);
+	prev_animation_frame = next_frame;
+}
+}

+ 101 - 0
Samples/basic/lottie/src/ElementLottie.h

@@ -0,0 +1,101 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ * Copyright (c) 2019 The RmlUi Team, and contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef RMLUI_ELEMENT_LOTTIE_H
+#define RMLUI_ELEMENT_LOTTIE_H
+
+#include <RmlUi/Core/Header.h>
+#include <RmlUi/Core/Element.h>
+#include <RmlUi/Core/Geometry.h>
+#include <RmlUi/Core/Texture.h>
+#include <memory>
+
+namespace rlottie { class Animation; }
+
+namespace Rml {
+
+
+class ElementLottie : public Element
+{
+public:
+	RMLUI_RTTI_DefineWithParent(ElementLottie, Element)
+
+	ElementLottie(const String& tag);
+	virtual ~ElementLottie();
+
+	/// Returns the element's inherent size.
+	bool GetIntrinsicDimensions(Vector2f& dimensions, float& ratio) override;
+
+protected:
+	/// Renders the animation.
+	void OnRender() override;
+
+	/// Regenerates the element's geometry.
+	void OnResize() override;
+
+	/// Checks for changes to the image's source or dimensions.
+	/// @param[in] changed_attributes A list of attributes changed on the element.
+	void OnAttributeChange(const ElementAttributes& changed_attributes) override;
+
+	/// Called when properties on the element are changed.
+	/// @param[in] changed_properties The properties changed on the element.
+	void OnPropertyChange(const PropertyIdSet& changed_properties) override;
+
+private:
+	// Generates the element's geometry.
+	void GenerateGeometry();
+	// Loads the element's animation, as specified by the 'src' attribute.
+	bool LoadAnimation();
+	// Update the texture for the next animation frame when necessary.
+	void UpdateTexture();
+
+	bool animation_dirty = false;
+	bool geometry_dirty = false;
+
+	// The texture this element is rendering from.
+	Texture texture;
+
+	// The animation's intrinsic dimensions.
+	Vector2f intrinsic_dimensions;
+	// The element's size for rendering.
+	Vector2i render_dimensions;
+
+	// The geometry used to render this element.
+	Geometry geometry;
+
+	// The absolute time when the current animation was first displayed.
+	double time_animation_start = -1;
+	// The previous animation frame displayed.
+	size_t prev_animation_frame = size_t(-1);
+
+	std::unique_ptr<rlottie::Animation> animation;
+};
+
+}
+
+#endif

+ 68 - 0
Samples/basic/lottie/src/LottiePlugin.cpp

@@ -0,0 +1,68 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ * Copyright (c) 2019 The RmlUi Team, and contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+
+#include "ElementLottie.h"
+#include <RmlUi/Core/ElementInstancer.h>
+#include <RmlUi/Core/Factory.h>
+#include <RmlUi/Core/Plugin.h>
+#include <RmlUi/Core/Core.h>
+
+namespace Rml {
+namespace Lottie {
+
+static UniquePtr<ElementInstancerGeneric<ElementLottie>> instancer;
+
+class LottiePlugin : public Plugin {
+public:
+	void OnShutdown() override
+	{
+		instancer.reset();
+		delete this;
+	}
+
+	int GetEventClasses() override
+	{
+		return Plugin::EVT_BASIC;
+	}
+};
+
+void Initialise()
+{
+	if (!instancer)
+	{
+		instancer = MakeUnique<ElementInstancerGeneric<ElementLottie> >();
+
+		Factory::RegisterElementInstancer("lottie", instancer.get());
+
+		RegisterPlugin(new LottiePlugin());
+	}
+}
+
+}
+}

+ 41 - 0
Samples/basic/lottie/src/LottiePlugin.h

@@ -0,0 +1,41 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ * Copyright (c) 2019 The RmlUi Team, and contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef RMLUI_LOTTIE_PLUGIN_H
+#define RMLUI_LOTTIE_PLUGIN_H
+
+
+namespace Rml {
+namespace Lottie {
+
+void Initialise();
+
+}
+}
+
+#endif

+ 121 - 0
Samples/basic/lottie/src/main.cpp

@@ -0,0 +1,121 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ * Copyright (c) 2019 The RmlUi Team, and contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include <RmlUi/Core.h>
+#include <RmlUi/Debugger.h>
+#include <Input.h>
+#include <Shell.h>
+#include <ShellRenderInterfaceOpenGL.h>
+#include "LottiePlugin.h"
+
+Rml::Context* context = nullptr;
+
+ShellRenderInterfaceExtensions* shell_renderer;
+
+void GameLoop()
+{
+	context->Update();
+
+	shell_renderer->PrepareRenderBuffer();
+	context->Render();
+	shell_renderer->PresentRenderBuffer();
+}
+
+#if defined RMLUI_PLATFORM_WIN32
+#include <windows.h>
+int APIENTRY WinMain(HINSTANCE RMLUI_UNUSED_PARAMETER(instance_handle), HINSTANCE RMLUI_UNUSED_PARAMETER(previous_instance_handle), char* RMLUI_UNUSED_PARAMETER(command_line), int RMLUI_UNUSED_PARAMETER(command_show))
+#else
+int main(int RMLUI_UNUSED_PARAMETER(argc), char** RMLUI_UNUSED_PARAMETER(argv))
+#endif
+{
+#ifdef RMLUI_PLATFORM_WIN32
+	RMLUI_UNUSED(instance_handle);
+	RMLUI_UNUSED(previous_instance_handle);
+	RMLUI_UNUSED(command_line);
+	RMLUI_UNUSED(command_show);
+#else
+	RMLUI_UNUSED(argc);
+	RMLUI_UNUSED(argv);
+#endif
+
+	int window_width = 1024;
+	int window_height = 768;
+
+	ShellRenderInterfaceOpenGL opengl_renderer;
+	shell_renderer = &opengl_renderer;
+
+	// Generic OS initialisation, creates a window and attaches OpenGL.
+	if (!Shell::Initialise() ||
+		!Shell::OpenWindow("Lottie sample", shell_renderer, window_width, window_height, true))
+	{
+		Shell::Shutdown();
+		return -1;
+	}
+
+	// RmlUi initialisation.
+	Rml::SetRenderInterface(&opengl_renderer);
+	shell_renderer->SetViewport(window_width, window_height);
+
+	ShellSystemInterface system_interface;
+	Rml::SetSystemInterface(&system_interface);
+
+	Rml::Initialise();
+
+	// Create the main RmlUi context and set it on the shell's input layer.
+	context = Rml::CreateContext("main", Rml::Vector2i(window_width, window_height));
+	if (context == nullptr)
+	{
+		Rml::Shutdown();
+		Shell::Shutdown();
+		return -1;
+	}
+
+	Rml::Lottie::Initialise();
+	Rml::Debugger::Initialise(context);
+	Input::SetContext(context);
+	shell_renderer->SetContext(context);
+
+	Shell::LoadFonts("assets/");
+
+	// Load and show the demo document.
+	if (Rml::ElementDocument* document = context->LoadDocument("basic/lottie/data/lottie.rml"))
+	{
+		document->Show();
+		document->GetElementById("title")->SetInnerRML("Lottie");
+	}
+
+	Shell::EventLoop(GameLoop);
+
+	// Shutdown RmlUi.
+	Rml::Shutdown();
+
+	Shell::CloseWindow();
+	Shell::Shutdown();
+
+	return 0;
+}

+ 21 - 0
Source/Core/FileInterface.cpp

@@ -27,6 +27,7 @@
  */
 
 #include "../../Include/RmlUi/Core/FileInterface.h"
+#include "../../Include/RmlUi/Core/Log.h"
 
 namespace Rml {
 
@@ -48,4 +49,24 @@ size_t FileInterface::Length(FileHandle file)
     return length;
 }
 
+bool FileInterface::LoadFile(const String& path, String& out_data)
+{
+	FileHandle handle = Open(path);
+	if (!handle)
+		return false;
+
+	const size_t length = Length(handle);
+
+	out_data = String(length, 0);
+
+	const size_t read_length = Read(&out_data[0], length, handle);
+	
+	if (length != read_length)
+	{
+		Log::Message(Log::LT_WARNING, "Could only read %zu of %zu bytes from file %s", read_length, length, path.c_str());
+	}
+
+	return true;
+}
+
 } // namespace Rml

+ 5 - 19
Tests/Source/VisualTests/TestViewer.cpp

@@ -140,23 +140,9 @@ TestViewer::~TestViewer()
 
 static Rml::String LoadFile(const String& file_path)
 {
-	FileInterface* file = Rml::GetFileInterface();
-	FileHandle handle = file->Open(file_path);
-	if (!handle)
-	{
-		return Rml::String();
-	}
-
-	const size_t length = file->Length(handle);
-	UniquePtr<char[]> buf = UniquePtr<char[]>(new char[length + 1]);
-
-	const size_t read_length = file->Read(buf.get(), length, handle);
-	file->Close(handle);
-	RMLUI_ASSERT(read_length > 0);
-	RMLUI_ASSERT(read_length <= length);
-	buf[read_length] = '\0';
-
-	return String(buf.get());
+	String result;
+	Rml::GetFileInterface()->LoadFile(file_path, result);
+	return result;
 }
 
 void TestViewer::ShowSource(SourceType type)
@@ -230,7 +216,7 @@ bool TestViewer::LoadTest(const Rml::String& directory, const Rml::String& filen
 		if (source_test.empty())
 			return false;
 
-		document_test = context->LoadDocumentFromMemory(source_test);
+		document_test = context->LoadDocumentFromMemory(source_test, filename);
 		if (!document_test)
 			return false;
 
@@ -253,7 +239,7 @@ bool TestViewer::LoadTest(const Rml::String& directory, const Rml::String& filen
 
 			if (!source_reference.empty())
 			{
-				document_reference = context->LoadDocumentFromMemory(source_reference);
+				document_reference = context->LoadDocumentFromMemory(source_reference, reference_filename);
 				if (document_reference)
 				{
 					document_reference->SetProperty(PropertyId::Left, Property(510.f, Property::PX));

+ 1 - 0
changelog.md

@@ -118,6 +118,7 @@ Use the RCSS `display` property to enable table formatting. See the stylesheet r
 - Fixed several compilation issues and warnings. [#118](https://github.com/mikke89/RmlUi/issues/118) [#97](https://github.com/mikke89/RmlUi/pull/97) (thanks @SpaceCat-Chan).
 - Debugger improvements: Sort property names alphabetically. Fix a bug where the outlines would draw underneath the document.
 - Tabs and panels in tab sets will no longer set the `display` property to `inline-block`, thus it is now possible to customize the display property.
+- [Lottie plugin](https://mikke89.github.io/RmlUiDoc/pages/cpp_manual/lottie.html) added for displaying vector animations [#134](https://github.com/mikke89/RmlUi/pull/134) (thanks @diamondhat).
 
 ### Bug fixes
 

+ 3 - 0
readme.md

@@ -162,6 +162,9 @@ body
 ![Transform](https://github.com/mikke89/RmlUiDoc/blob/3f319d8464e73b821179ff8d20537013af5b9810/assets/gallery/transform.gif)  
 **Animated transforms (entirely in RCSS)**
 
+![Lottie animation](https://github.com/mikke89/RmlUiDoc/blob/086385e119f0fc6e196229b785e91ee0252fe4b4/assets/gallery/lottie.gif)  
+**Vector animations with the [Lottie plugin](https://mikke89.github.io/RmlUiDoc/pages/cpp_manual/lottie.html)**
+
 To see more examples of animations and transitions in action, have a look at the videos in the [animations documentation](https://mikke89.github.io/RmlUiDoc/pages/rcss/animations_transitions_transforms.html).
 
 

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff