Browse Source

Support animation of keyword properties

Michael Ragazzon 6 years ago
parent
commit
11af13a776

+ 34 - 1
Samples/basic/animation/data/animation.rml

@@ -48,6 +48,40 @@
 		#high_scores {
 			margin-left: -100px;
 		}
+		
+		@keyframes fadeout {
+			from {
+				opacity: 1;
+			}
+			to {
+				opacity: 0;
+				visibility: hidden;
+			}
+		}
+		@keyframes fadein {
+			from {
+				opacity: 0;
+			}
+			to {
+				opacity: 1;
+				visibility: visible;
+			}
+		}
+		@keyframes textalign {
+			20% { text-align: left; }
+			50% { text-align: center; }
+			80% { text-align: right; }
+		}
+		.fadein {
+			animation: 1.2s cubic-out fadein;
+		}
+		.fadeout {
+			animation: 1.2s cubic-in fadeout;
+		}
+		.textalign {
+			animation: 1.5s textalign;
+		}
+		
 		#exit {
 			transform: rotate(45deg);
 			transform-origin: 50% 50% 0;
@@ -184,7 +218,6 @@
 			left: -100px;
 			transform: scale(0.5) rotate(-90deg);
 		}
-		
 	</style>
 </head>
 

+ 34 - 5
Samples/basic/animation/src/main.cpp

@@ -74,10 +74,6 @@ public:
 				el->AddAnimationKey("image-color", Property(Colourb(64, 128, 255, 0), Property::COLOUR), 0.9f);
 				el->AddAnimationKey("image-color", Property(Colourb(255, 255, 255, 255), Property::COLOUR), 0.3f);
 			}
-			{
-				auto el = document->GetElementById("help");
-				el->Animate("margin-left", Property(100.f, Property::PX), 1.0f, Tween{ Tween::Quadratic, Tween::InOut }, -1, true);
-			}
 			{
 				auto el = document->GetElementById("exit");
 				PropertyDictionary pd;
@@ -122,6 +118,34 @@ public:
 		}
 	}
 
+	void Update(double t)
+	{
+		if (document)
+		{
+			if (t - t_prev_fade >= 1.5)
+			{
+				auto el = document->GetElementById("help");
+				if (el->IsClassSet("fadeout"))
+				{
+					el->SetClass("fadeout", false);
+					el->SetClass("fadein", true);
+				}
+				else if (el->IsClassSet("fadein"))
+				{
+					el->SetClass("fadein", false);
+					el->SetClass("textalign", true);
+				}
+				else
+				{
+					el->SetClass("textalign", false);
+					el->SetClass("fadeout", true);
+				}
+
+				t_prev_fade = t;
+			}
+		}
+	}
+
 	~DemoWindow()
 	{
 		if (document)
@@ -136,6 +160,7 @@ public:
 
 private:
 	Rml::Core::ElementDocument *document;
+	double t_prev_fade = 0;
 };
 
 
@@ -149,8 +174,13 @@ int nudge = 0;
 
 void GameLoop()
 {
+	double t = Shell::GetElapsedTime();
+
 	if(run_loop || single_loop)
 	{
+		if (window)
+			window->Update(t);
+
 		context->Update();
 
 		shell_renderer->PrepareRenderBuffer();
@@ -161,7 +191,6 @@ void GameLoop()
 	}
 
 	static double t_prev = 0.0f;
-	double t = Shell::GetElapsedTime();
 	float dt = float(t - t_prev);
 	static int count_frames = 0;
 	count_frames += 1;

+ 18 - 1
Source/Core/ElementAnimation.cpp

@@ -104,6 +104,22 @@ static Property InterpolateProperties(const Property & p0, const Property& p1, f
 		}
 	}
 
+	if (p0.unit == Property::KEYWORD && p1.unit == Property::KEYWORD)
+	{
+		// Discrete interpolation, swap at alpha = 0.5.
+		// Special case for the 'visibility' property as in the CSS specs: 
+		//   Apply the visible property if present during the entire transition period, ie. alpha (0,1).
+		if (definition && definition->GetId() == PropertyId::Visibility)
+		{
+			if (p0.Get<int>() == (int)Style::Visibility::Visible)
+				return alpha < 1.f ? p0 : p1;
+			else if (p1.Get<int>() == (int)Style::Visibility::Visible)
+				return alpha <= 0.f ? p0 : p1;
+		}
+
+		return alpha < 0.5f ? p0 : p1;
+	}
+
 	if (p0.unit == Property::COLOUR && p1.unit == Property::COLOUR)
 	{
 		Colourf c0 = ColourToLinearSpace(p0.value.Get<Colourb>());
@@ -148,6 +164,7 @@ static Property InterpolateProperties(const Property & p0, const Property& p1, f
 		return Property{ TransformPtr(std::move(t)), Property::TRANSFORM };
 	}
 
+	// Fall back to discrete interpolation for incompatible units.
 	return alpha < 0.5f ? p0 : p1;
 }
 
@@ -388,7 +405,7 @@ ElementAnimation::ElementAnimation(PropertyId property_id, ElementAnimationOrigi
 
 bool ElementAnimation::InternalAddKey(float time, const Property& in_property, Element& element, Tween tween)
 {
-	int valid_properties = (Property::NUMBER_LENGTH_PERCENT | Property::ANGLE | Property::COLOUR | Property::TRANSFORM);
+	int valid_properties = (Property::NUMBER_LENGTH_PERCENT | Property::ANGLE | Property::COLOUR | Property::TRANSFORM | Property::KEYWORD);
 
 	if (!(in_property.unit & valid_properties))
 	{

+ 19 - 0
changelog.md

@@ -5,6 +5,25 @@
 
 ## RmlUi WIP
 
+### Animating keyword properties
+
+Keyword properties can now be animated. Keywords are always interpolated in discrete steps, and normally applied half-way to the next keyframe. The single exception to this rule is for the `visibility` property. As in the CSS specifications, this property always applies the `visible` keyword during transition when present either in the previous or next keyframe.
+
+Thus, the following can produce a fade-out animation, removing visibility of the element at animation end (thanks to @uniquejack for the example).
+```css
+@keyframes fadeout {
+	from {
+		opacity: 1;
+	}
+	to {
+		opacity: 0;
+		visibility: hidden;
+	}
+}
+.fadeout {
+	animation: 1.2s cubic-in fadeout;
+}
+```
 
 ### Bug fixes