Skip to main content

Data binding and properties

Capy has a system of properties, which allow to easily do animations, data binding and other things.

This features revolves around the Atom(T) struct, this struct also has a nice guarantee as is automatically makes properties thread-safe.

The way some struct in Capy could have a property is like so:

const TestStruct = struct {
int: Atom(u32) = Atom(u32).of(0)
};

Here we first see that to initialise an atom, we use the of(value: T) function, simple enough.

We can also set it and get it:

var testStruct = TestStruct {};
std.debug.print("int is {}\n", .{ testStruct.int.get() });
testStruct.int.set(5);
std.debug.print("int is now {}\n", .{ testStruct.int.get() });

which would print

int is 0
int is now 5

This scales simply with threads as using an atom is thread-safe.

Change listeners

It is possible to get notified every time the value of a atom changes (including when animating, at an arbitrary rate).

It can be used like so:

fn onChange(newValue: u32, userdata: usize) void {
_ = userdata;
std.debug.print("value is now {}\n", .{ newValue });
}

var testStruct = TestStruct {};
_ = try testStruct.int.addChangeListener(.{
.function = onChange,
.userdata = 0
});
testStruct.int.set(5);
testStruct.int.set(3);

which will print

value is now 5
value is now 3

Binding

By binding two atoms together, they will always have the same value because when one changes, the other changes too.

fn bind(other: *Atom(T)) void

Animations

Animations snapshot the current value of the atom and realise a transition to a new value, while taking a given amount of time.

It can be used like so:

testStruct.int.animate(capy.Easings.InOut, 1000);

where the duration is in milliseconds.

Note: capy.Easings.InOut, capy.Easings.In... are actually functions that transform the t parameter of the linear interpolation, for example Linear is

fn Linear(t: f64) f64 {
return t;
}

It is thus trivial to implement your own easing function. (a good reference library of easings that you can implement is available easings.net)

To animate a value that isn't a number, like a struct, but also other containers like unions, you need to implement the fn lerp(a: T, b: T, t: f64) T) function which should perform a linear interpolation between a and b of the type you're implementing.

Read-Modify-Write operations

You should lock, read and write the value manually.