Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Custom Properties #236

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flare_dart/lib/actor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import "dart:convert";
import "dart:typed_data";

import 'package:flare_dart/actor_layer_effect_renderer.dart';
import 'package:flare_dart/custom_property.dart';

import "actor_artboard.dart";
import "actor_color.dart";
Expand Down
11 changes: 7 additions & 4 deletions flare_dart/lib/actor_artboard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import "dart:math";
import "dart:typed_data";

import 'package:flare_dart/actor_layer_effect_renderer.dart';
import 'package:flare_dart/custom_property.dart';

import "actor.dart";
import 'actor_blur.dart';
Expand Down Expand Up @@ -419,19 +420,21 @@ class ActorArtboard {
break;

case BlockTypes.customIntProperty:
//component = CustomIntProperty.Read(this, nodeBlock);
component = CustomProperty.readCustomProperty<int>(this, nodeBlock);
break;

case BlockTypes.customFloatProperty:
//component = CustomFloatProperty.Read(this, nodeBlock);
component =
CustomProperty.readCustomProperty<double>(this, nodeBlock);
break;

case BlockTypes.customStringProperty:
//component = CustomStringProperty.Read(this, nodeBlock);
component =
CustomProperty.readCustomProperty<String>(this, nodeBlock);
break;

case BlockTypes.customBooleanProperty:
//component = CustomBooleanProperty.Read(this, nodeBlock);
component = CustomProperty.readCustomProperty<bool>(this, nodeBlock);
break;

case BlockTypes.actorColliderRectangle:
Expand Down
16 changes: 16 additions & 0 deletions flare_dart/lib/actor_component.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'package:flare_dart/custom_property.dart';

import "actor_artboard.dart";
import "actor_node.dart";
import "stream_reader.dart";
Expand All @@ -23,6 +25,7 @@ abstract class ActorComponent {
int graphOrder = 0;
int dirtMask = 0;
List<ActorComponent> dependents;
List<CustomProperty> _customProperties;

ActorComponent();
ActorComponent.withArtboard(this.artboard);
Expand All @@ -31,6 +34,8 @@ abstract class ActorComponent {
return _name;
}

int get parentIdx => _parentIdx;

void resolveComponentIndices(List<ActorComponent> components) {
ActorNode node = components[_parentIdx] as ActorNode;
if (node != null) {
Expand Down Expand Up @@ -59,4 +64,15 @@ abstract class ActorComponent {
_parentIdx = component._parentIdx;
idx = component.idx;
}

void addCustomProperty(CustomProperty property) {
_customProperties ??= [];
_customProperties.add(property);
}

/// Finds the [CustomProperty] with the given name.
CustomProperty getCustomProperty(String name) {
return _customProperties?.firstWhere((element) => element.name == name,
orElse: () => null);
}
}
32 changes: 18 additions & 14 deletions flare_dart/lib/animation/actor_animation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ class ActorAnimation {

List<ComponentAnimation> get animatedComponents => _components;

/// Call this function once per frame, as you advance the animation.
/// Call from the time [fromTime] of the last frame, to the time [toTime]
/// of the current frame, and it'll add the triggered events in that
/// time frame in the [triggerEvents] list.
void triggerEvents(List<ActorComponent> components, double fromTime,
double toTime, List<AnimationEventArgs> triggerEvents) {
for (int i = 0; i < _triggerComponents.length; i++) {
Expand All @@ -332,25 +336,25 @@ class ActorAnimation {
int idx = 0;
// Binary find the keyframe index.
{
int mid = 0;
double element = 0.0;
int start = 0;
int end = kfl - 1;

while (start <= end) {
mid = (start + end) >> 1;
element = keyFrames[mid].time;
if (element < toTime) {
start = mid + 1;
} else if (element > toTime) {
end = mid - 1;
var elementTime = 0.0;
var startIdx = 0;
var midIdx = 0;
var endIdx = kfl - 1;

while (startIdx <= endIdx) {
midIdx = (startIdx + endIdx) >> 1;
elementTime = keyFrames[midIdx].time;
if (elementTime < toTime) {
startIdx = midIdx + 1;
} else if (elementTime > toTime) {
endIdx = midIdx - 1;
} else {
start = mid;
startIdx = midIdx;
break;
}
}

idx = start;
idx = startIdx;
}

if (idx == 0) {
Expand Down
22 changes: 11 additions & 11 deletions flare_dart/lib/animation/keyframe.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import "dart:collection";
import "dart:typed_data";

import 'package:flare_dart/custom_property.dart';

import "../actor_artboard.dart";
import "../actor_blur.dart";
import "../actor_bone_base.dart";
Expand Down Expand Up @@ -94,8 +96,8 @@ class KeyFrameBooleanProperty extends KeyFrame {
bool _value;
@override
void apply(ActorComponent component, double mix) {
// CustomBooleanProperty prop = component as CustomBooleanProperty;
// prop.value = _value;
var prop = component as CustomProperty<bool>;
prop.value = _value;
}

@override
Expand Down Expand Up @@ -299,9 +301,8 @@ class KeyFrameFillColor extends KeyFrameWithInterpolation {
class KeyFrameFloatProperty extends KeyFrameNumeric {
@override
void setValue(ActorComponent component, double value, double mix) {
// TODO
// CustomFloatProperty node = component as CustomFloatProperty;
// node.value = node.value * (1.0 - mix) + value * mix;
var node = component as CustomProperty<double>;
node.value = node.value * (1.0 - mix) + value * mix;
}

static KeyFrame read(StreamReader reader, ActorComponent component) {
Expand Down Expand Up @@ -526,7 +527,7 @@ abstract class KeyFrameInt extends KeyFrameWithInterpolation {
@override
void applyInterpolation(
ActorComponent component, double time, KeyFrame toFrame, double mix) {
KeyFrameNumeric to = toFrame as KeyFrameNumeric;
var to = toFrame as KeyFrameInt;
double f = (time - _time) / (to._time - _time);
if (_interpolator != null) {
f = _interpolator.getEasedMix(f);
Expand All @@ -548,9 +549,8 @@ abstract class KeyFrameInt extends KeyFrameWithInterpolation {
class KeyFrameIntProperty extends KeyFrameInt {
@override
void setValue(ActorComponent component, double value, double mix) {
// TODO
//CustomIntProperty node = component as CustomIntProperty;
//node.value = (node.value * (1.0 - mix) + value * mix).round();
var node = component as CustomProperty<int>;
node.value = (node.value * (1.0 - mix) + value * mix).round();
}

static KeyFrame read(StreamReader reader, ActorComponent component) {
Expand Down Expand Up @@ -1057,8 +1057,8 @@ class KeyFrameStringProperty extends KeyFrame {
String _value;
@override
void apply(ActorComponent component, double mix) {
// CustomStringProperty prop = component as CustomStringProperty;
// prop.value = _value;
var prop = component as CustomProperty<String>;
prop.value = _value;
}

@override
Expand Down
71 changes: 71 additions & 0 deletions flare_dart/lib/custom_property.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import 'package:flare_dart/actor_artboard.dart';
import 'package:flare_dart/actor_component.dart';
import 'package:flare_dart/stream_reader.dart';

/// Generic class for CustomProperties in the Rive editor.
/// They are represented by a single value of generic type T,
/// where T can be a [int], [double], [String] or [bool].
///
/// Trying to [read()] a CustomProperty with any other type will result
/// in an [UnsupportedError].
class CustomProperty<T> extends ActorComponent {
T _value;

CustomProperty._();

T get value => _value;
set value(T newValue) {
if (newValue != _value) {
_value = newValue;
}
}

@override
ActorComponent makeInstance(ActorArtboard resetArtboard) {
var instance = CustomProperty<T>._();
instance.copyComponent(this, resetArtboard);
instance._value = _value;
return instance;
}

@override
void completeResolve() {}

@override
void onDirty(int dirt) {}

@override
void update(int dirt) {}

static CustomProperty<T> readCustomProperty<T>(
ActorArtboard artboard, StreamReader reader) {
var component = CustomProperty<T>._();
ActorComponent.read(artboard, reader, component);
switch (T) {
case int:
component._value = reader.readInt32("int") as T;
break;
case double:
component._value = reader.readFloat32("float") as T;
break;
case String:
component._value = reader.readString("string") as T;
break;
case bool:
component._value = reader.readBool("bool") as T;
break;
default:
throw UnsupportedError(
"Custom Property for type $T is not currently supported");
}
return component;
}

@override
void resolveComponentIndices(List<ActorComponent> components) {
super.resolveComponentIndices(components);
if (parentIdx >= 0) {
parent.addCustomProperty(this);
}
}
}