Explorar o código

Initial support for C++11.

Michael Ragazzon %!s(int64=6) %!d(string=hai) anos
pai
achega
42309c4c7e

+ 6 - 6
Build/CMakeLists.txt

@@ -269,7 +269,7 @@ foreach(library ${LIBRARIES})
 		target_compile_options(${NAME} PUBLIC "/MP")
 	endif(MSVC)
 	
-	set_property(TARGET ${NAME} PROPERTY CXX_STANDARD 17)
+	set_property(TARGET ${NAME} PROPERTY CXX_STANDARD 11)
 	set_property(TARGET ${NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
     
     install(TARGETS ${NAME}
@@ -586,7 +586,7 @@ endif(NOT BUILD_FRAMEWORK)
 
     # Build and install sample shell library
     add_library(shell STATIC ${shell_SRC_FILES} ${shell_HDR_FILES})
-	set_property(TARGET shell PROPERTY CXX_STANDARD 17)
+	set_property(TARGET shell PROPERTY CXX_STANDARD 11)
 	set_property(TARGET shell PROPERTY CXX_STANDARD_REQUIRED ON)
     if (APPLE)
     	# We only support i386 for the samples as it still uses Carbon
@@ -597,7 +597,7 @@ endif(NOT BUILD_FRAMEWORK)
     foreach(sample ${samples})
         bl_sample(${sample} ${sample_LIBRARIES})
 		
-		set_property(TARGET ${sample} PROPERTY CXX_STANDARD 17)
+		set_property(TARGET ${sample} PROPERTY CXX_STANDARD 11)
 		set_property(TARGET ${sample} PROPERTY CXX_STANDARD_REQUIRED ON)
 
         # The samples always set this as their current working directory
@@ -716,7 +716,7 @@ endif(NOT BUILD_FRAMEWORK)
 
     # Build and install invaders sample
     bl_sample(invaders ${sample_LIBRARIES})
-	set_property(TARGET invaders PROPERTY CXX_STANDARD 17)
+	set_property(TARGET invaders PROPERTY CXX_STANDARD 11)
 	set_property(TARGET invaders PROPERTY CXX_STANDARD_REQUIRED ON)
     install(DIRECTORY DESTINATION ${SAMPLES_DIR}/invaders)
     install(TARGETS invaders 
@@ -726,7 +726,7 @@ endif(NOT BUILD_FRAMEWORK)
 	if(BUILD_PYTHON_BINDINGS)
 	    # Build and install pyinvaders sample
 	    bl_sample(pyinvaders ${sample_LIBRARIES} ${PYTHON_LIBRARIES} ${PY_BINDINGS_LINK_LIBS})
-		set_property(TARGET pyinvaders PROPERTY CXX_STANDARD 17)
+		set_property(TARGET pyinvaders PROPERTY CXX_STANDARD 11)
 		set_property(TARGET pyinvaders PROPERTY CXX_STANDARD_REQUIRED ON)
 	    install(DIRECTORY DESTINATION ${SAMPLES_DIR}/pyinvaders)
 	    install(TARGETS pyinvaders
@@ -736,7 +736,7 @@ endif(NOT BUILD_FRAMEWORK)
     
     if(BUILD_LUA_BINDINGS)
         bl_sample(luainvaders RocketCoreLua RocketControlsLua ${sample_LIBRARIES} ${LUA_BINDINGS_LINK_LIBS})
-		set_property(TARGET luainvaders PROPERTY CXX_STANDARD 17)
+		set_property(TARGET luainvaders PROPERTY CXX_STANDARD 11)
 		set_property(TARGET luainvaders PROPERTY CXX_STANDARD_REQUIRED ON)
         install(DIRECTORY DESTINATION ${SAMPLES_DIR}/luainvaders)
         install(TARGETS luainvaders 

+ 62 - 10
Include/Rocket/Core/TransformPrimitive.h

@@ -31,7 +31,6 @@
 #include "Header.h"
 #include "Types.h"
 #include "Property.h"
-#include <variant>
 #include <array>
 
 namespace Rocket {
@@ -277,13 +276,46 @@ struct DecomposedMatrix4
 };
 
 
-using PrimitiveVariant = std::variant<
-	Matrix2D, Matrix3D,
-	TranslateX, TranslateY, TranslateZ, Translate2D, Translate3D,
-	ScaleX, ScaleY, ScaleZ, Scale2D, Scale3D,
-	RotateX, RotateY, RotateZ, Rotate2D, Rotate3D,
-	SkewX, SkewY, Skew2D,
-	Perspective, DecomposedMatrix4>;
+struct PrimitiveVariant {
+
+	enum Type {
+		MATRIX2D, MATRIX3D,
+		TRANSLATEX, TRANSLATEY, TRANSLATEZ, TRANSLATE2D, TRANSLATE3D,
+		SCALEX, SCALEY, SCALEZ, SCALE2D, SCALE3D,
+		ROTATEX, ROTATEY, ROTATEZ, ROTATE2D, ROTATE3D,
+		SKEWX, SKEWY, SKEW2D,
+		PERSPECTIVE, DECOMPOSEDMATRIX4
+	};
+
+	PrimitiveVariant(Type type) : type(type) {}
+
+	Type type;
+
+	union {
+		Matrix2D matrix_2d;
+		Matrix3D matrix_3d;
+		TranslateX translate_x;
+		TranslateY translate_y;
+		TranslateZ translate_z;
+		Translate2D translate_2d;
+		Translate3D translate_3d;
+		ScaleX scale_x;
+		ScaleY scale_y;
+		ScaleZ scale_z;
+		Scale2D scale_2d;
+		Scale3D scale_3d;
+		RotateX rotate_x;
+		RotateY rotate_y;
+		RotateZ rotate_z;
+		Rotate2D rotate_2d;
+		Rotate3D rotate_3d;
+		SkewX skew_x;
+		SkewY skew_y;
+		Skew2D skew_2d;
+		Perspective perspective;
+		DecomposedMatrix4 decomposed_matrix_4;
+	};
+};
 
 
 /**
@@ -300,8 +332,28 @@ struct Primitive
 {
 	PrimitiveVariant primitive;
 
-	template<typename PrimitiveType>
-	Primitive(PrimitiveType primitive) : primitive(primitive) {}
+	Primitive(Matrix2D          p) : primitive(PrimitiveVariant::MATRIX2D) { primitive.matrix_2d = p; }
+	Primitive(Matrix3D          p) : primitive(PrimitiveVariant::MATRIX3D) { primitive.matrix_3d = p; }
+	Primitive(TranslateX        p) : primitive(PrimitiveVariant::TRANSLATEX) { primitive.translate_x = p; }
+	Primitive(TranslateY        p) : primitive(PrimitiveVariant::TRANSLATEY) { primitive.translate_y = p; }
+	Primitive(TranslateZ        p) : primitive(PrimitiveVariant::TRANSLATEZ) { primitive.translate_z = p; }
+	Primitive(Translate2D       p) : primitive(PrimitiveVariant::TRANSLATE2D) { primitive.translate_2d = p; }
+	Primitive(Translate3D       p) : primitive(PrimitiveVariant::TRANSLATE3D) { primitive.translate_3d = p; }
+	Primitive(ScaleX            p) : primitive(PrimitiveVariant::SCALEX) { primitive.scale_x = p; }
+	Primitive(ScaleY            p) : primitive(PrimitiveVariant::SCALEY) { primitive.scale_y = p; }
+	Primitive(ScaleZ            p) : primitive(PrimitiveVariant::SCALEZ) { primitive.scale_z = p; }
+	Primitive(Scale2D           p) : primitive(PrimitiveVariant::SCALE2D) { primitive.scale_2d = p; }
+	Primitive(Scale3D           p) : primitive(PrimitiveVariant::SCALE3D) { primitive.scale_3d = p; }
+	Primitive(RotateX           p) : primitive(PrimitiveVariant::ROTATEX) { primitive.rotate_x = p; }
+	Primitive(RotateY           p) : primitive(PrimitiveVariant::ROTATEY) { primitive.rotate_y = p; }
+	Primitive(RotateZ           p) : primitive(PrimitiveVariant::ROTATEZ) { primitive.rotate_z = p; }
+	Primitive(Rotate2D          p) : primitive(PrimitiveVariant::ROTATE2D) { primitive.rotate_2d = p; }
+	Primitive(Rotate3D          p) : primitive(PrimitiveVariant::ROTATE3D) { primitive.rotate_3d = p; }
+	Primitive(SkewX             p) : primitive(PrimitiveVariant::SKEWX) { primitive.skew_x = p; }
+	Primitive(SkewY             p) : primitive(PrimitiveVariant::SKEWY) { primitive.skew_y = p; }
+	Primitive(Skew2D            p) : primitive(PrimitiveVariant::SKEW2D) { primitive.skew_2d = p; }
+	Primitive(Perspective       p) : primitive(PrimitiveVariant::PERSPECTIVE) { primitive.perspective = p; }
+	Primitive(DecomposedMatrix4 p) : primitive(PrimitiveVariant::DECOMPOSEDMATRIX4) { primitive.decomposed_matrix_4 = p; }
 
 	void SetIdentity() noexcept;
 

+ 4 - 2
Source/Core/Element.cpp

@@ -2312,7 +2312,8 @@ bool Element::Animate(const String & property_name, const Property & target_valu
 {
 	bool result = false;
 
-	if (auto it_animation = StartAnimation(property_name, start_value, num_iterations, alternate_direction, delay); it_animation != animations.end())
+	auto it_animation = StartAnimation(property_name, start_value, num_iterations, alternate_direction, delay);
+	if (it_animation != animations.end())
 	{
 		result = it_animation->AddKey(duration, target_value, *this, tween, true);
 		if (!result)
@@ -2517,7 +2518,8 @@ void Element::AdvanceAnimations()
 
 		for (auto it = it_completed; it != animations.end(); ++it)
 		{
-			dictionary_list.emplace_back().Set("property", it->GetPropertyName());
+			dictionary_list.emplace_back();
+			dictionary_list.back().Set("property", it->GetPropertyName());
 			is_transition.push_back(it->IsTransition());
 		}
 

+ 11 - 30
Source/Core/ElementAnimation.cpp

@@ -171,8 +171,8 @@ static PrepareTransformResult PrepareTransformPair(Transform& t0, Transform& t1,
 		bool same_primitives = true;
 		for (size_t i = 0; i < prims0.size(); i++)
 		{
-			auto p0_type = prims0[i].primitive.index();
-			auto p1_type = prims1[i].primitive.index();
+			auto p0_type = prims0[i].primitive.type;
+			auto p1_type = prims1[i].primitive.type;
 			if (p0_type != p1_type)
 			{
 				// They are not the same, but see if we can convert them to their more generic form
@@ -181,9 +181,9 @@ static PrepareTransformResult PrepareTransformPair(Transform& t0, Transform& t1,
 					same_primitives = false;
 					break;
 				}
-				if (prims0[i].primitive.index() != p0_type)
+				if (prims0[i].primitive.type != p0_type)
 					(int&)result |= (int)PrepareTransformResult::ChangedT0;
-				if (prims1[i].primitive.index() != p1_type)
+				if (prims1[i].primitive.type != p1_type)
 					(int&)result |= (int)PrepareTransformResult::ChangedT1;
 			}
 		}
@@ -217,11 +217,11 @@ static PrepareTransformResult PrepareTransformPair(Transform& t0, Transform& t1,
 		for (size_t i_small = 0; i_small < small.size(); i_small++)
 		{
 			match_success = false;
-			auto small_type = small[i_small].primitive.index();
+			auto small_type = small[i_small].primitive.type;
 
 			for (; i_big < big.size(); i_big++)
 			{
-				auto big_type = big[i_big].primitive.index();
+				auto big_type = big[i_big].primitive.type;
 
 				if (small_type == big_type)
 				{
@@ -232,7 +232,7 @@ static PrepareTransformResult PrepareTransformPair(Transform& t0, Transform& t1,
 				{
 					// They matched in their more generic form, one or both primitives converted
 					match_success = true;
-					if (big[i_big].primitive.index() != big_type)
+					if (big[i_big].primitive.type != big_type)
 						changed_big = true;
 				}
 
@@ -282,29 +282,10 @@ static PrepareTransformResult PrepareTransformPair(Transform& t0, Transform& t1,
 	// If we get here, things get tricky. Need to do full matrix interpolation.
 	// In short, we decompose the Transforms into translation, rotation, scale, skew and perspective components. 
 	// Then, during update, interpolate these components and combine into a new transform matrix.
-	if constexpr(true)
-	{
-		if (!CombineAndDecompose(t0, element))
-			return PrepareTransformResult::Invalid;
-		if (!CombineAndDecompose(t1, element))
-			return PrepareTransformResult::Invalid;
-	}
-	else
-	{
-		// Bad "flat" matrix interpolation
-		for (Transform* t : { &t0, &t1 })
-		{
-			Matrix4f transform_value = Matrix4f::Identity();
-			for (const auto& primitive : t->GetPrimitives())
-			{
-				Matrix4f m;
-				if (primitive.ResolveTransform(m, element))
-					transform_value *= m;
-			}
-			t->ClearPrimitives();
-			t->AddPrimitive({ Matrix3D{transform_value} });
-		}
-	}
+	if (!CombineAndDecompose(t0, element))
+		return PrepareTransformResult::Invalid;
+	if (!CombineAndDecompose(t1, element))
+		return PrepareTransformResult::Invalid;
 
 	return PrepareTransformResult::ChangedT0andT1;
 }

+ 2 - 1
Source/Core/ElementStyle.cpp

@@ -184,7 +184,8 @@ void ElementStyle::TransitionPropertyChanges(Element* element, PropertyNameList&
 			{
 				for (auto& transition : transition_list.transitions)
 				{
-					if (auto it = properties.find(transition.name); it != properties.end())
+					auto it = properties.find(transition.name);
+					if (it != properties.end())
 					{
 						if (add_transition(transition))
 							properties.erase(it);

+ 4 - 2
Source/Core/PropertyParserAnimation.cpp

@@ -132,7 +132,8 @@ static bool ParseAnimation(Property & property, const StringList& animation_valu
 				continue;
 
 			// See if we have a <keyword> or <tween> specifier as defined in keywords
-			if (auto it = keywords.find(argument); it != keywords.end() && it->second.ValidAnimation())
+			auto it = keywords.find(argument); 
+			if (it != keywords.end() && it->second.ValidAnimation())
 			{
 				switch (it->second.type)
 				{
@@ -247,7 +248,8 @@ static bool ParseTransition(Property & property, const StringList& transition_va
 				continue;
 
 			// See if we have a <keyword> or <tween> specifier as defined in keywords
-			if (auto it = keywords.find(argument); it != keywords.end() && it->second.ValidTransition())
+			auto it = keywords.find(argument);
+			if (it != keywords.end() && it->second.ValidTransition())
 			{
 				if (it->second.type == Keyword::NONE)
 				{

+ 223 - 29
Source/Core/TransformPrimitive.cpp

@@ -303,6 +303,39 @@ struct ResolveTransformVisitor
 		return false;
 	}
 
+
+	bool run(const PrimitiveVariant& primitive)
+	{
+		switch (primitive.type)
+		{
+		case PrimitiveVariant::MATRIX2D: return this->operator()(primitive.matrix_2d);
+		case PrimitiveVariant::MATRIX3D: return this->operator()(primitive.matrix_3d);
+		case PrimitiveVariant::TRANSLATEX: return this->operator()(primitive.translate_x);
+		case PrimitiveVariant::TRANSLATEY: return this->operator()(primitive.translate_y);
+		case PrimitiveVariant::TRANSLATEZ: return this->operator()(primitive.translate_z);
+		case PrimitiveVariant::TRANSLATE2D: return this->operator()(primitive.translate_2d);
+		case PrimitiveVariant::TRANSLATE3D: return this->operator()(primitive.translate_3d);
+		case PrimitiveVariant::SCALEX: return this->operator()(primitive.scale_x);
+		case PrimitiveVariant::SCALEY: return this->operator()(primitive.scale_y);
+		case PrimitiveVariant::SCALEZ: return this->operator()(primitive.scale_z);
+		case PrimitiveVariant::SCALE2D: return this->operator()(primitive.scale_2d);
+		case PrimitiveVariant::SCALE3D: return this->operator()(primitive.scale_3d);
+		case PrimitiveVariant::ROTATEX: return this->operator()(primitive.rotate_x);
+		case PrimitiveVariant::ROTATEY: return this->operator()(primitive.rotate_y);
+		case PrimitiveVariant::ROTATEZ: return this->operator()(primitive.rotate_z);
+		case PrimitiveVariant::ROTATE2D: return this->operator()(primitive.rotate_2d);
+		case PrimitiveVariant::ROTATE3D: return this->operator()(primitive.rotate_3d);
+		case PrimitiveVariant::SKEWX: return this->operator()(primitive.skew_x);
+		case PrimitiveVariant::SKEWY: return this->operator()(primitive.skew_y);
+		case PrimitiveVariant::SKEW2D: return this->operator()(primitive.skew_2d);
+		case PrimitiveVariant::PERSPECTIVE: return this->operator()(primitive.perspective);
+		case PrimitiveVariant::DECOMPOSEDMATRIX4: return this->operator()(primitive.decomposed_matrix_4);
+		default:
+			break;
+		}
+		ROCKET_ASSERT(false);
+		return false;
+	}
 };
 
 
@@ -313,7 +346,7 @@ bool Primitive::ResolveTransform(Matrix4f & m, Element & e) const noexcept
 {
 	ResolveTransformVisitor visitor{ m, e };
 
-	bool result = std::visit(visitor, primitive);
+	bool result = visitor.run(primitive);
 
 	return result;
 }
@@ -322,9 +355,10 @@ bool Primitive::ResolvePerspective(float & p, Element & e) const noexcept
 {
 	bool result = false;
 
-	if (const Perspective* perspective = std::get_if<Perspective>(&primitive))
+	if (primitive.type == PrimitiveVariant::PERSPECTIVE)
 	{
-		p = perspective->values[0].ResolveDepth(e);
+
+		p = primitive.perspective.values[0].ResolveDepth(e);
 		result = true;
 	}
 
@@ -384,12 +418,44 @@ struct SetIdentityVisitor
 		p.scale = Vector3f(1, 1, 1);
 		p.skew = Vector3f(0, 0, 0);
 	}
-};
 
 
+	void run(PrimitiveVariant& primitive)
+	{
+		switch (primitive.type)
+		{
+		case PrimitiveVariant::MATRIX2D: this->operator()(primitive.matrix_2d); break;
+		case PrimitiveVariant::MATRIX3D: this->operator()(primitive.matrix_3d); break;
+		case PrimitiveVariant::TRANSLATEX: this->operator()(primitive.translate_x); break;
+		case PrimitiveVariant::TRANSLATEY: this->operator()(primitive.translate_y); break;
+		case PrimitiveVariant::TRANSLATEZ: this->operator()(primitive.translate_z); break;
+		case PrimitiveVariant::TRANSLATE2D: this->operator()(primitive.translate_2d); break;
+		case PrimitiveVariant::TRANSLATE3D: this->operator()(primitive.translate_3d); break;
+		case PrimitiveVariant::SCALEX: this->operator()(primitive.scale_x); break;
+		case PrimitiveVariant::SCALEY: this->operator()(primitive.scale_y); break;
+		case PrimitiveVariant::SCALEZ: this->operator()(primitive.scale_z); break;
+		case PrimitiveVariant::SCALE2D: this->operator()(primitive.scale_2d); break;
+		case PrimitiveVariant::SCALE3D: this->operator()(primitive.scale_3d); break;
+		case PrimitiveVariant::ROTATEX: this->operator()(primitive.rotate_x); break;
+		case PrimitiveVariant::ROTATEY: this->operator()(primitive.rotate_y); break;
+		case PrimitiveVariant::ROTATEZ: this->operator()(primitive.rotate_z); break;
+		case PrimitiveVariant::ROTATE2D: this->operator()(primitive.rotate_2d); break;
+		case PrimitiveVariant::ROTATE3D: this->operator()(primitive.rotate_3d); break;
+		case PrimitiveVariant::SKEWX: this->operator()(primitive.skew_x); break;
+		case PrimitiveVariant::SKEWY: this->operator()(primitive.skew_y); break;
+		case PrimitiveVariant::SKEW2D: this->operator()(primitive.skew_2d); break;
+		case PrimitiveVariant::PERSPECTIVE: this->operator()(primitive.perspective); break;
+		case PrimitiveVariant::DECOMPOSEDMATRIX4: this->operator()(primitive.decomposed_matrix_4); break;
+		default:
+			ROCKET_ASSERT(false);
+			break;
+		}
+	}
+};
+
 void Primitive::SetIdentity() noexcept
 {
-	std::visit(SetIdentityVisitor{}, primitive);
+	SetIdentityVisitor{}.run(primitive);
 }
 
 
@@ -457,12 +523,45 @@ struct PrepareVisitor
 		// Perspective must be decomposed
 		return false;
 	}
+
+	bool run(PrimitiveVariant& primitive)
+	{
+		switch (primitive.type)
+		{
+		case PrimitiveVariant::MATRIX2D: return this->operator()(primitive.matrix_2d);
+		case PrimitiveVariant::MATRIX3D: return this->operator()(primitive.matrix_3d);
+		case PrimitiveVariant::TRANSLATEX: return this->operator()(primitive.translate_x);
+		case PrimitiveVariant::TRANSLATEY: return this->operator()(primitive.translate_y);
+		case PrimitiveVariant::TRANSLATEZ: return this->operator()(primitive.translate_z);
+		case PrimitiveVariant::TRANSLATE2D: return this->operator()(primitive.translate_2d);
+		case PrimitiveVariant::TRANSLATE3D: return this->operator()(primitive.translate_3d);
+		case PrimitiveVariant::SCALEX: return this->operator()(primitive.scale_x);
+		case PrimitiveVariant::SCALEY: return this->operator()(primitive.scale_y);
+		case PrimitiveVariant::SCALEZ: return this->operator()(primitive.scale_z);
+		case PrimitiveVariant::SCALE2D: return this->operator()(primitive.scale_2d);
+		case PrimitiveVariant::SCALE3D: return this->operator()(primitive.scale_3d);
+		case PrimitiveVariant::ROTATEX: return this->operator()(primitive.rotate_x);
+		case PrimitiveVariant::ROTATEY: return this->operator()(primitive.rotate_y);
+		case PrimitiveVariant::ROTATEZ: return this->operator()(primitive.rotate_z);
+		case PrimitiveVariant::ROTATE2D: return this->operator()(primitive.rotate_2d);
+		case PrimitiveVariant::ROTATE3D: return this->operator()(primitive.rotate_3d);
+		case PrimitiveVariant::SKEWX: return this->operator()(primitive.skew_x);
+		case PrimitiveVariant::SKEWY: return this->operator()(primitive.skew_y);
+		case PrimitiveVariant::SKEW2D: return this->operator()(primitive.skew_2d);
+		case PrimitiveVariant::PERSPECTIVE: return this->operator()(primitive.perspective);
+		case PrimitiveVariant::DECOMPOSEDMATRIX4: return this->operator()(primitive.decomposed_matrix_4);
+		default:
+			break;
+		}
+		ROCKET_ASSERT(false);
+		return false;
+	}
 };
 
 
 bool Primitive::PrepareForInterpolation(Element & e) noexcept
 {
-	return std::visit(PrepareVisitor{ e }, primitive);
+	return PrepareVisitor{ e }.run(primitive);
 }
 
 
@@ -484,38 +583,79 @@ struct GetGenericTypeVisitor
 
 	template <typename T>
 	GenericType operator()(const T& p) { return GenericType::None; }
+
+	GenericType run(const PrimitiveVariant& primitive)
+	{
+		PrimitiveVariant result = primitive;
+		switch (primitive.type)
+		{
+		case PrimitiveVariant::TRANSLATEX:  return this->operator()(primitive.translate_x); break;
+		case PrimitiveVariant::TRANSLATEY:  return this->operator()(primitive.translate_y); break;
+		case PrimitiveVariant::TRANSLATEZ:  return this->operator()(primitive.translate_z); break;
+		case PrimitiveVariant::TRANSLATE2D: return this->operator()(primitive.translate_2d); break;
+		case PrimitiveVariant::SCALEX:      return this->operator()(primitive.scale_x); break;
+		case PrimitiveVariant::SCALEY:      return this->operator()(primitive.scale_y); break;
+		case PrimitiveVariant::SCALEZ:      return this->operator()(primitive.scale_z); break;
+		case PrimitiveVariant::SCALE2D:     return this->operator()(primitive.scale_2d); break;
+		default:
+			break;
+		}
+		return GenericType::None;
+	}
 };
 
 
 struct ConvertToGenericTypeVisitor
 {
-	PrimitiveVariant operator()(const TranslateX& p) { return Translate3D{ p.values[0], {0.0f, Property::PX}, {0.0f, Property::PX} }; }
-	PrimitiveVariant operator()(const TranslateY& p) { return Translate3D{ {0.0f, Property::PX}, p.values[0], {0.0f, Property::PX} }; }
-	PrimitiveVariant operator()(const TranslateZ& p) { return Translate3D{ {0.0f, Property::PX}, {0.0f, Property::PX}, p.values[0] }; }
-	PrimitiveVariant operator()(const Translate2D& p) { return Translate3D{ p.values[0], p.values[1], {0.0f, Property::PX} }; }
-	PrimitiveVariant operator()(const ScaleX& p) { return Scale3D{ p.values[0], 1.0f, 1.0f }; }
-	PrimitiveVariant operator()(const ScaleY& p) { return Scale3D{  1.0f, p.values[0], 1.0f }; }
-	PrimitiveVariant operator()(const ScaleZ& p) { return Scale3D{  1.0f, 1.0f, p.values[0] }; }
-	PrimitiveVariant operator()(const Scale2D& p) { return Scale3D{ p.values[0], p.values[1], 1.0f }; }
+	Translate3D operator()(const TranslateX& p) { return Translate3D{ p.values[0], {0.0f, Property::PX}, {0.0f, Property::PX} }; }
+	Translate3D operator()(const TranslateY& p) { return Translate3D{ {0.0f, Property::PX}, p.values[0], {0.0f, Property::PX} }; }
+	Translate3D operator()(const TranslateZ& p) { return Translate3D{ {0.0f, Property::PX}, {0.0f, Property::PX}, p.values[0] }; }
+	Translate3D operator()(const Translate2D& p) { return Translate3D{ p.values[0], p.values[1], {0.0f, Property::PX} }; }
+	Scale3D operator()(const ScaleX& p) { return Scale3D{ p.values[0], 1.0f, 1.0f }; }
+	Scale3D operator()(const ScaleY& p) { return Scale3D{  1.0f, p.values[0], 1.0f }; }
+	Scale3D operator()(const ScaleZ& p) { return Scale3D{  1.0f, 1.0f, p.values[0] }; }
+	Scale3D operator()(const Scale2D& p) { return Scale3D{ p.values[0], p.values[1], 1.0f }; }
 
 	template <typename T>
 	PrimitiveVariant operator()(const T& p) { ROCKET_ERROR; return p; }
+
+
+
+	PrimitiveVariant run(const PrimitiveVariant& primitive)
+	{
+		PrimitiveVariant result = primitive;
+		switch (primitive.type)
+		{
+		case PrimitiveVariant::TRANSLATEX: result.translate_3d = this->operator()(primitive.translate_x); break;
+		case PrimitiveVariant::TRANSLATEY: result.translate_3d = this->operator()(primitive.translate_y); break;
+		case PrimitiveVariant::TRANSLATEZ: result.translate_3d = this->operator()(primitive.translate_z); break;
+		case PrimitiveVariant::TRANSLATE2D: result.translate_3d = this->operator()(primitive.translate_2d); break;
+		case PrimitiveVariant::SCALEX: result.scale_3d = this->operator()(primitive.scale_x); break;
+		case PrimitiveVariant::SCALEY: result.scale_3d = this->operator()(primitive.scale_y); break;
+		case PrimitiveVariant::SCALEZ: result.scale_3d = this->operator()(primitive.scale_z); break;
+		case PrimitiveVariant::SCALE2D: result.scale_3d = this->operator()(primitive.scale_2d); break;
+		default:
+			ROCKET_ASSERT(false);
+			break;
+		}
+		return result;
+	}
 };
 
 
 
 bool Primitive::TryConvertToMatchingGenericType(Primitive & p0, Primitive & p1) noexcept
 {
-	if (p0.primitive.index() == p1.primitive.index())
+	if (p0.primitive.type == p1.primitive.type)
 		return true;
 
-	GenericType c0 = std::visit(GetGenericTypeVisitor{}, p0.primitive);
-	GenericType c1 = std::visit(GetGenericTypeVisitor{}, p1.primitive);
+	GenericType c0 = GetGenericTypeVisitor{}.run(p0.primitive);
+	GenericType c1 = GetGenericTypeVisitor{}.run(p1.primitive);
 
 	if (c0 == c1 && c0 != GenericType::None)
 	{
-		p0.primitive = std::visit(ConvertToGenericTypeVisitor{}, p0.primitive);
-		p1.primitive = std::visit(ConvertToGenericTypeVisitor{}, p1.primitive);
+		p0.primitive = ConvertToGenericTypeVisitor{}.run(p0.primitive);
+		p1.primitive = ConvertToGenericTypeVisitor{}.run(p1.primitive);
 		return true;
 	}
 
@@ -565,21 +705,48 @@ struct InterpolateVisitor
 		return true;
 	}
 
-	template <typename T>
-	bool operator()(T& p0)
+	bool run(PrimitiveVariant& variant)
 	{
-		auto& p1 = std::get<T>(other_variant);
-		return Interpolate(p0, p1);
+		ROCKET_ASSERT(variant.type == other_variant.type);
+		switch (variant.type)
+		{
+		case PrimitiveVariant::MATRIX2D: return Interpolate(variant.matrix_2d, other_variant.matrix_2d);
+		case PrimitiveVariant::MATRIX3D: return Interpolate(variant.matrix_3d, other_variant.matrix_3d);
+		case PrimitiveVariant::TRANSLATEX: return Interpolate(variant.translate_x, other_variant.translate_x);
+		case PrimitiveVariant::TRANSLATEY: return Interpolate(variant.translate_y, other_variant.translate_y);
+		case PrimitiveVariant::TRANSLATEZ: return Interpolate(variant.translate_z, other_variant.translate_z);
+		case PrimitiveVariant::TRANSLATE2D: return Interpolate(variant.translate_2d, other_variant.translate_2d);
+		case PrimitiveVariant::TRANSLATE3D: return Interpolate(variant.translate_3d, other_variant.translate_3d);
+		case PrimitiveVariant::SCALEX: return Interpolate(variant.scale_x, other_variant.scale_x);
+		case PrimitiveVariant::SCALEY: return Interpolate(variant.scale_y, other_variant.scale_y);
+		case PrimitiveVariant::SCALEZ: return Interpolate(variant.scale_z, other_variant.scale_z);
+		case PrimitiveVariant::SCALE2D: return Interpolate(variant.scale_2d, other_variant.scale_2d);
+		case PrimitiveVariant::SCALE3D: return Interpolate(variant.scale_3d, other_variant.scale_3d);
+		case PrimitiveVariant::ROTATEX: return Interpolate(variant.rotate_x, other_variant.rotate_x);
+		case PrimitiveVariant::ROTATEY: return Interpolate(variant.rotate_y, other_variant.rotate_y);
+		case PrimitiveVariant::ROTATEZ: return Interpolate(variant.rotate_z, other_variant.rotate_z);
+		case PrimitiveVariant::ROTATE2D: return Interpolate(variant.rotate_2d, other_variant.rotate_2d);
+		case PrimitiveVariant::ROTATE3D: return Interpolate(variant.rotate_3d, other_variant.rotate_3d);
+		case PrimitiveVariant::SKEWX: return Interpolate(variant.skew_x, other_variant.skew_x);
+		case PrimitiveVariant::SKEWY: return Interpolate(variant.skew_y, other_variant.skew_y);
+		case PrimitiveVariant::SKEW2D: return Interpolate(variant.skew_2d, other_variant.skew_2d);
+		case PrimitiveVariant::PERSPECTIVE: return Interpolate(variant.perspective, other_variant.perspective);
+		case PrimitiveVariant::DECOMPOSEDMATRIX4: return Interpolate(variant.decomposed_matrix_4, other_variant.decomposed_matrix_4);
+		default:
+			break;
+		}
+		ROCKET_ASSERT(false);
+		return false;
 	}
 };
 
 
 bool Primitive::InterpolateWith(const Primitive & other, float alpha) noexcept
 {
-	if (primitive.index() != other.primitive.index())
+	if (primitive.type != other.primitive.type)
 		return false;
 
-	bool result = std::visit(InterpolateVisitor{ other.primitive, alpha }, primitive);
+	bool result = InterpolateVisitor{ other.primitive, alpha }.run(primitive);
 
 	return result;
 }
@@ -589,16 +756,43 @@ bool Primitive::InterpolateWith(const Primitive & other, float alpha) noexcept
 
 struct ToStringVisitor
 {
-	template <typename T>
-	String operator()(T& p0)
+	String run(const PrimitiveVariant& variant)
 	{
-		return p0.ToString();
+		switch (variant.type)
+		{
+		case PrimitiveVariant::MATRIX2D: return variant.matrix_2d.ToString();
+		case PrimitiveVariant::MATRIX3D: return variant.matrix_3d.ToString();
+		case PrimitiveVariant::TRANSLATEX: return variant.translate_x.ToString();
+		case PrimitiveVariant::TRANSLATEY: return variant.translate_y.ToString();
+		case PrimitiveVariant::TRANSLATEZ: return variant.translate_z.ToString();
+		case PrimitiveVariant::TRANSLATE2D: return variant.translate_2d.ToString();
+		case PrimitiveVariant::TRANSLATE3D: return variant.translate_3d.ToString();
+		case PrimitiveVariant::SCALEX: return variant.scale_x.ToString();
+		case PrimitiveVariant::SCALEY: return variant.scale_y.ToString();
+		case PrimitiveVariant::SCALEZ: return variant.scale_z.ToString();
+		case PrimitiveVariant::SCALE2D: return variant.scale_2d.ToString();
+		case PrimitiveVariant::SCALE3D: return variant.scale_3d.ToString();
+		case PrimitiveVariant::ROTATEX: return variant.rotate_x.ToString();
+		case PrimitiveVariant::ROTATEY: return variant.rotate_y.ToString();
+		case PrimitiveVariant::ROTATEZ: return variant.rotate_z.ToString();
+		case PrimitiveVariant::ROTATE2D: return variant.rotate_2d.ToString();
+		case PrimitiveVariant::ROTATE3D: return variant.rotate_3d.ToString();
+		case PrimitiveVariant::SKEWX: return variant.skew_x.ToString();
+		case PrimitiveVariant::SKEWY: return variant.skew_y.ToString();
+		case PrimitiveVariant::SKEW2D: return variant.skew_2d.ToString();
+		case PrimitiveVariant::PERSPECTIVE: return variant.perspective.ToString();
+		case PrimitiveVariant::DECOMPOSEDMATRIX4: return variant.decomposed_matrix_4.ToString();
+		default:
+			break;
+		}
+		ROCKET_ASSERT(false);
+		return String();
 	}
 };
 
 String Primitive::ToString() const noexcept
 {
-	String result = std::visit(ToStringVisitor{}, primitive);
+	String result = ToStringVisitor{}.run(primitive);
 	return result;
 }
 

+ 1 - 1
readme.md

@@ -7,7 +7,7 @@ Original website at http://librocket.com
 
 ## Fork features
 
-This fork contains some additional features over the [original libRocket branch](https://github.com/libRocket/libRocket), briefly documented here. Some of the new features utilize features from C++17, thus, a C++17-compliant compiler should be used.
+This fork contains some additional features over the [original libRocket branch](https://github.com/libRocket/libRocket), briefly documented here.
 
 
 ## Transform property