Skip to content

lorents/rtl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RTL - Reactive Template Library

It solves all my C++ animation problems
-- me

Using RTL

Lazy, caching, reactive variables

Use rtl::var<T>

#include <rtl/var.h>
...

rtl::var<float> bar = 2.0f;
rtl::var<float> foo = 3.0f;
rtl::var<float> foobar = [&](){ return foo() + bar(); };

printf("foobar = %f\n", foobar());

foo = 2.0f;
printf("foobar = %f\n", foobar());

bar = 1.0f;
printf("foobar = %f\n", foobar());

Animation and time

RTL uses the rtl::clock class as a source of time, and if no instance is explicitly provided for rtl::var and rtl::animator they will use whatever the thread static rtl::clock::current_clock points to.

This clock is by default pointing to the thread static rtl::clock::default_clock. However, we need to update this clock every frame by calling rtl::clock::default_clock.adjust() with the current time in seconds:

#include <rtl/clock.h>
...

rtl:clock::default_clock.adjust(get_time_in_seconds()); 

Reacting to value changes

With rtl::clock set up, you can now use rtl::animator to react to changes.

Even if multiple dependencies change the animator callback is run at max once per frame, avoiding wrong intermediate states.

#include <rtl/animator.h>
...

rtl::animator foo_printer = [&]()
{
	printf("foo = %f\n", foo());
};
rtl::animator bar_printer = [&]()
{
	printf("bar = %f\n", bar());
};
rtl::animator foobar_printer = [&]()
{
	printf("foobar = %f\n", foobar());
};

foo = 3.0f; // prints nothing yet
bar = 2.0f; // prints nothing yet

// later..
rtl:clock::default_clock.adjust(get_time_in_seconds()); // prints foo = 3, bar = 2, foobar = 5

bar = 3.0f; // prints nothing again

rtl:clock::default_clock.adjust(get_time_in_seconds()); // prints bar = 3, foobar = 6

Triggering animations

foo.animate(1.0f, 0.5, &rtl::easing::linear, [&]()
{
	foo.animate(0.0f, 0.5, &rtl::easing::linear, [&]()
	{
		printf("animation complete!\n");
	});
});

Again note that rtl::clock::frame_clock.adjust() must have been called at least once before triggering any animations.

Extending RTL

While it is often easier to just use an internal rtl::var<T> or rtl::animator, RTL can be extended at a lower level through the graph API.

Adding new value producers

  1. Include relevant header

    #include <rtl/graph/dependency.h>
  2. Make an rtl::dependency

    dependency my_dependency;
  3. When evaluated, notify the current visitor

    my_dependency.visit();
  4. When changed, invalidate dependants

    my_dependency.invalidate();

Adding new value consumers

  1. Include relevant headers

    #include <rtl/graph/dependant.h>
    #include <rtl/graph/visitor.h>
  2. Implement rtl::invalidatable, e.g. using rtl::invalidator

    #include <rtl/invalidator.h>
    
    invalidator my_invalidator = []()
    {
    	// one of the dependencies was invalidated
    	...
    };
  3. Make an rtl::dependant

    dependant my_dependant(&my_invalidator);
  4. Guard any calls to reactive functions with an instance of rtl::visitor

    {
    	visitor my_visitor(&my_dependant);
    
    	// evaluate dependencies here
    	...
    }

Limitations

Inteded for single-threaded use

Licence

MIT-licence here

About

RTL - Reactive Template Library for C++

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published