mirror of
https://github.com/rive-app/rive-flutter.git
synced 2025-06-26 01:18:13 +08:00
Adding support for TransformConstraints.
This commit is contained in:
78
lib/src/generated/constraints/transform_constraint_base.dart
Normal file
78
lib/src/generated/constraints/transform_constraint_base.dart
Normal file
@ -0,0 +1,78 @@
|
||||
/// Core automatically generated
|
||||
/// lib/src/generated/constraints/transform_constraint_base.dart.
|
||||
/// Do not modify manually.
|
||||
|
||||
import 'package:rive/src/generated/component_base.dart';
|
||||
import 'package:rive/src/generated/constraints/constraint_base.dart';
|
||||
import 'package:rive/src/generated/constraints/targeted_constraint_base.dart';
|
||||
import 'package:rive/src/rive_core/constraints/targeted_constraint.dart';
|
||||
|
||||
abstract class TransformConstraintBase extends TargetedConstraint {
|
||||
static const int typeKey = 83;
|
||||
@override
|
||||
int get coreType => TransformConstraintBase.typeKey;
|
||||
@override
|
||||
Set<int> get coreTypes => {
|
||||
TransformConstraintBase.typeKey,
|
||||
TargetedConstraintBase.typeKey,
|
||||
ConstraintBase.typeKey,
|
||||
ComponentBase.typeKey
|
||||
};
|
||||
|
||||
/// --------------------------------------------------------------------------
|
||||
/// SourceSpaceValue field with key 179.
|
||||
static const int sourceSpaceValueInitialValue = 0;
|
||||
int _sourceSpaceValue = sourceSpaceValueInitialValue;
|
||||
static const int sourceSpaceValuePropertyKey = 179;
|
||||
|
||||
/// The source transform space.
|
||||
int get sourceSpaceValue => _sourceSpaceValue;
|
||||
|
||||
/// Change the [_sourceSpaceValue] field value.
|
||||
/// [sourceSpaceValueChanged] will be invoked only if the field's value has
|
||||
/// changed.
|
||||
set sourceSpaceValue(int value) {
|
||||
if (_sourceSpaceValue == value) {
|
||||
return;
|
||||
}
|
||||
int from = _sourceSpaceValue;
|
||||
_sourceSpaceValue = value;
|
||||
if (hasValidated) {
|
||||
sourceSpaceValueChanged(from, value);
|
||||
}
|
||||
}
|
||||
|
||||
void sourceSpaceValueChanged(int from, int to);
|
||||
|
||||
/// --------------------------------------------------------------------------
|
||||
/// DestSpaceValue field with key 180.
|
||||
static const int destSpaceValueInitialValue = 0;
|
||||
int _destSpaceValue = destSpaceValueInitialValue;
|
||||
static const int destSpaceValuePropertyKey = 180;
|
||||
|
||||
/// The destination transform space.
|
||||
int get destSpaceValue => _destSpaceValue;
|
||||
|
||||
/// Change the [_destSpaceValue] field value.
|
||||
/// [destSpaceValueChanged] will be invoked only if the field's value has
|
||||
/// changed.
|
||||
set destSpaceValue(int value) {
|
||||
if (_destSpaceValue == value) {
|
||||
return;
|
||||
}
|
||||
int from = _destSpaceValue;
|
||||
_destSpaceValue = value;
|
||||
if (hasValidated) {
|
||||
destSpaceValueChanged(from, value);
|
||||
}
|
||||
}
|
||||
|
||||
void destSpaceValueChanged(int from, int to);
|
||||
|
||||
@override
|
||||
void copy(TransformConstraintBase source) {
|
||||
super.copy(source);
|
||||
_sourceSpaceValue = source._sourceSpaceValue;
|
||||
_destSpaceValue = source._destSpaceValue;
|
||||
}
|
||||
}
|
@ -49,6 +49,7 @@ import 'package:rive/src/generated/constraints/constraint_base.dart';
|
||||
import 'package:rive/src/generated/constraints/distance_constraint_base.dart';
|
||||
import 'package:rive/src/generated/constraints/ik_constraint_base.dart';
|
||||
import 'package:rive/src/generated/constraints/targeted_constraint_base.dart';
|
||||
import 'package:rive/src/generated/constraints/transform_constraint_base.dart';
|
||||
import 'package:rive/src/generated/draw_rules_base.dart';
|
||||
import 'package:rive/src/generated/draw_target_base.dart';
|
||||
import 'package:rive/src/generated/drawable_base.dart';
|
||||
@ -113,6 +114,7 @@ import 'package:rive/src/rive_core/bones/tendon.dart';
|
||||
import 'package:rive/src/rive_core/bones/weight.dart';
|
||||
import 'package:rive/src/rive_core/constraints/distance_constraint.dart';
|
||||
import 'package:rive/src/rive_core/constraints/ik_constraint.dart';
|
||||
import 'package:rive/src/rive_core/constraints/transform_constraint.dart';
|
||||
import 'package:rive/src/rive_core/draw_rules.dart';
|
||||
import 'package:rive/src/rive_core/draw_target.dart';
|
||||
import 'package:rive/src/rive_core/node.dart';
|
||||
@ -146,6 +148,8 @@ class RiveCoreContext {
|
||||
return DistanceConstraint();
|
||||
case IKConstraintBase.typeKey:
|
||||
return IKConstraint();
|
||||
case TransformConstraintBase.typeKey:
|
||||
return TransformConstraint();
|
||||
case AnimationStateBase.typeKey:
|
||||
return AnimationState();
|
||||
case KeyedObjectBase.typeKey:
|
||||
@ -313,6 +317,16 @@ class RiveCoreContext {
|
||||
object.parentBoneCount = value;
|
||||
}
|
||||
break;
|
||||
case TransformConstraintBase.sourceSpaceValuePropertyKey:
|
||||
if (object is TransformConstraintBase && value is int) {
|
||||
object.sourceSpaceValue = value;
|
||||
}
|
||||
break;
|
||||
case TransformConstraintBase.destSpaceValuePropertyKey:
|
||||
if (object is TransformConstraintBase && value is int) {
|
||||
object.destSpaceValue = value;
|
||||
}
|
||||
break;
|
||||
case AnimationStateBase.animationIdPropertyKey:
|
||||
if (object is AnimationStateBase && value is int) {
|
||||
object.animationId = value;
|
||||
@ -933,6 +947,8 @@ class RiveCoreContext {
|
||||
case TargetedConstraintBase.targetIdPropertyKey:
|
||||
case DistanceConstraintBase.modeValuePropertyKey:
|
||||
case IKConstraintBase.parentBoneCountPropertyKey:
|
||||
case TransformConstraintBase.sourceSpaceValuePropertyKey:
|
||||
case TransformConstraintBase.destSpaceValuePropertyKey:
|
||||
case AnimationStateBase.animationIdPropertyKey:
|
||||
case KeyedObjectBase.objectIdPropertyKey:
|
||||
case BlendAnimationBase.animationIdPropertyKey:
|
||||
@ -1089,6 +1105,10 @@ class RiveCoreContext {
|
||||
return (object as DistanceConstraintBase).modeValue;
|
||||
case IKConstraintBase.parentBoneCountPropertyKey:
|
||||
return (object as IKConstraintBase).parentBoneCount;
|
||||
case TransformConstraintBase.sourceSpaceValuePropertyKey:
|
||||
return (object as TransformConstraintBase).sourceSpaceValue;
|
||||
case TransformConstraintBase.destSpaceValuePropertyKey:
|
||||
return (object as TransformConstraintBase).destSpaceValue;
|
||||
case AnimationStateBase.animationIdPropertyKey:
|
||||
return (object as AnimationStateBase).animationId;
|
||||
case KeyedObjectBase.objectIdPropertyKey:
|
||||
@ -1405,6 +1425,16 @@ class RiveCoreContext {
|
||||
object.parentBoneCount = value;
|
||||
}
|
||||
break;
|
||||
case TransformConstraintBase.sourceSpaceValuePropertyKey:
|
||||
if (object is TransformConstraintBase) {
|
||||
object.sourceSpaceValue = value;
|
||||
}
|
||||
break;
|
||||
case TransformConstraintBase.destSpaceValuePropertyKey:
|
||||
if (object is TransformConstraintBase) {
|
||||
object.destSpaceValue = value;
|
||||
}
|
||||
break;
|
||||
case AnimationStateBase.animationIdPropertyKey:
|
||||
if (object is AnimationStateBase) {
|
||||
object.animationId = value;
|
||||
|
@ -1,3 +1,6 @@
|
||||
import 'package:rive/src/rive_core/artboard.dart';
|
||||
import 'package:rive/src/rive_core/component.dart';
|
||||
import 'package:rive/src/rive_core/math/mat2d.dart';
|
||||
import 'package:rive/src/generated/constraints/constraint_base.dart';
|
||||
import 'package:rive/src/rive_core/transform_component.dart';
|
||||
export 'package:rive/src/generated/constraints/constraint_base.dart';
|
||||
@ -29,4 +32,19 @@ abstract class Constraint extends ConstraintBase {
|
||||
void update(int dirt) {}
|
||||
|
||||
void markConstraintDirty() => constrainedComponent?.markTransformDirty();
|
||||
|
||||
@override
|
||||
void onDirty(int mask) => markConstraintDirty();
|
||||
}
|
||||
|
||||
/// Get the parent's world transform. Takes into consideration when the parent
|
||||
/// is an artboard.
|
||||
Mat2D parentWorld(TransformComponent component) {
|
||||
var parent = component.parent;
|
||||
if (parent is Artboard) {
|
||||
return parent.worldTransform;
|
||||
} else if (parent is TransformComponent) {
|
||||
return parent.worldTransform;
|
||||
}
|
||||
return Mat2D();
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import 'package:rive/src/generated/constraints/distance_constraint_base.dart';
|
||||
import 'package:rive/src/rive_core/transform_component.dart';
|
||||
export 'package:rive/src/generated/constraints/distance_constraint_base.dart';
|
||||
|
||||
/// [DistanceConstraint]'s logical distancing method.
|
||||
enum DistanceConstraintMode { closer, further, exact }
|
||||
|
||||
const _distanceEpsilon = 0.001;
|
||||
@ -57,7 +58,4 @@ class DistanceConstraint extends DistanceConstraintBase {
|
||||
|
||||
DistanceConstraintMode get mode => DistanceConstraintMode.values[modeValue];
|
||||
set mode(DistanceConstraintMode value) => modeValue = value.index;
|
||||
|
||||
@override
|
||||
bool validate() => super.validate() && parent is TransformComponent;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'dart:math';
|
||||
import 'package:rive/src/rive_core/artboard.dart';
|
||||
import 'package:rive/src/rive_core/bones/bone.dart';
|
||||
import 'package:rive/src/rive_core/constraints/constraint.dart';
|
||||
import 'package:rive/src/rive_core/math/mat2d.dart';
|
||||
import 'package:rive/src/rive_core/math/transform_components.dart';
|
||||
import 'package:rive/src/rive_core/math/vec2d.dart';
|
||||
@ -68,7 +68,6 @@ class IKConstraint extends IKConstraintBase {
|
||||
}
|
||||
// Now put them in FK order (top to bottom).
|
||||
for (final bone in bones.reversed) {
|
||||
bone.addPeerConstraint(this);
|
||||
nextFKChain.add(_BoneChainLink(
|
||||
index: nextFKChain.length,
|
||||
bone: bone,
|
||||
@ -117,9 +116,9 @@ class IKConstraint extends IKConstraintBase {
|
||||
// Decompose the chain.
|
||||
for (final item in _fkChain) {
|
||||
var bone = item.bone;
|
||||
Mat2D parentWorld = _parentWorld(bone);
|
||||
Mat2D parentWorldTransform = parentWorld(bone);
|
||||
|
||||
Mat2D.invert(item.parentWorldInverse, parentWorld);
|
||||
Mat2D.invert(item.parentWorldInverse, parentWorldTransform);
|
||||
|
||||
var boneTransform = bone.transform;
|
||||
Mat2D.multiply(
|
||||
@ -145,7 +144,7 @@ class IKConstraint extends IKConstraintBase {
|
||||
j < end;
|
||||
j++) {
|
||||
var fk = _fkChain[j];
|
||||
Mat2D.invert(fk.parentWorldInverse, _parentWorld(fk.bone));
|
||||
Mat2D.invert(fk.parentWorldInverse, parentWorld(fk.bone));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -249,7 +248,7 @@ class IKConstraint extends IKConstraintBase {
|
||||
_constrainRotation(firstChild, r2);
|
||||
if (firstChild != fk2) {
|
||||
var bone = fk2.bone;
|
||||
Mat2D.multiply(bone.worldTransform, _parentWorld(bone), bone.transform);
|
||||
Mat2D.multiply(bone.worldTransform, parentWorld(bone), bone.transform);
|
||||
}
|
||||
|
||||
// Simple storage, need this for interpolation.
|
||||
@ -273,7 +272,7 @@ class _BoneChainLink {
|
||||
|
||||
void _constrainRotation(_BoneChainLink link, double rotation) {
|
||||
var bone = link.bone;
|
||||
Mat2D parentWorld = _parentWorld(bone);
|
||||
Mat2D parentWorldTransform = parentWorld(bone);
|
||||
var boneTransform = bone.transform;
|
||||
if (rotation == 0) {
|
||||
Mat2D.setIdentity(boneTransform);
|
||||
@ -295,14 +294,5 @@ void _constrainRotation(_BoneChainLink link, double rotation) {
|
||||
boneTransform[2] = boneTransform[0] * skew + boneTransform[2];
|
||||
boneTransform[3] = boneTransform[1] * skew + boneTransform[3];
|
||||
}
|
||||
Mat2D.multiply(bone.worldTransform, parentWorld, boneTransform);
|
||||
}
|
||||
|
||||
Mat2D _parentWorld(TransformComponent component) {
|
||||
var parent = component.parent;
|
||||
if (parent is Artboard) {
|
||||
return parent.worldTransform;
|
||||
} else {
|
||||
return (parent as TransformComponent).worldTransform;
|
||||
}
|
||||
Mat2D.multiply(bone.worldTransform, parentWorldTransform, boneTransform);
|
||||
}
|
||||
|
74
lib/src/rive_core/constraints/transform_constraint.dart
Normal file
74
lib/src/rive_core/constraints/transform_constraint.dart
Normal file
@ -0,0 +1,74 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:rive/src/rive_core/constraints/constraint.dart';
|
||||
import 'package:rive/src/rive_core/math/mat2d.dart';
|
||||
import 'package:rive/src/rive_core/math/transform_components.dart';
|
||||
import 'package:rive/src/generated/constraints/transform_constraint_base.dart';
|
||||
import 'package:rive/src/rive_core/transform_component.dart';
|
||||
import 'package:rive/src/rive_core/transform_space.dart';
|
||||
export 'package:rive/src/generated/constraints/transform_constraint_base.dart';
|
||||
|
||||
/// A constraint copies the transform from the target component to the
|
||||
/// constrained component in world or local space.
|
||||
class TransformConstraint extends TransformConstraintBase {
|
||||
final TransformComponents componentsA = TransformComponents();
|
||||
final TransformComponents componentsB = TransformComponents();
|
||||
|
||||
TransformSpace get destSpace => TransformSpace.values[destSpaceValue];
|
||||
set destSpace(TransformSpace value) => destSpaceValue = value.index;
|
||||
|
||||
TransformSpace get sourceSpace => TransformSpace.values[sourceSpaceValue];
|
||||
set sourceSpace(TransformSpace value) => sourceSpaceValue = value.index;
|
||||
|
||||
@override
|
||||
void destSpaceValueChanged(int from, int to) => markConstraintDirty();
|
||||
|
||||
@override
|
||||
void sourceSpaceValueChanged(int from, int to) => markConstraintDirty();
|
||||
|
||||
@override
|
||||
void constrain(TransformComponent component) {
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
var transformA = component.worldTransform;
|
||||
var transformB = Mat2D.clone(target!.worldTransform);
|
||||
if (sourceSpace == TransformSpace.local) {
|
||||
var targetParentWorld = parentWorld(target!);
|
||||
|
||||
var inverse = Mat2D();
|
||||
if (!Mat2D.invert(inverse, targetParentWorld)) {
|
||||
return;
|
||||
}
|
||||
Mat2D.multiply(transformB, inverse, transformB);
|
||||
}
|
||||
if (destSpace == TransformSpace.local && component.parent != null) {
|
||||
var targetParentWorld = parentWorld(component);
|
||||
Mat2D.multiply(transformB, targetParentWorld, transformB);
|
||||
}
|
||||
|
||||
Mat2D.decompose(transformA, componentsA);
|
||||
Mat2D.decompose(transformB, componentsB);
|
||||
|
||||
var angleA = componentsA[4] % (pi * 2);
|
||||
var angleB = componentsB[4] % (pi * 2);
|
||||
var diff = angleB - angleA;
|
||||
if (diff > pi) {
|
||||
diff -= pi * 2;
|
||||
} else if (diff < -pi) {
|
||||
diff += pi * 2;
|
||||
}
|
||||
|
||||
var t = strength;
|
||||
var ti = 1 - t;
|
||||
|
||||
componentsB[4] = angleA + diff * t;
|
||||
componentsB[0] = componentsA[0] * ti + componentsB[0] * t;
|
||||
componentsB[1] = componentsA[1] * ti + componentsB[1] * t;
|
||||
componentsB[2] = componentsA[2] * ti + componentsB[2] * t;
|
||||
componentsB[3] = componentsA[3] * ti + componentsB[3] * t;
|
||||
componentsB[5] = componentsA[5] * ti + componentsB[5] * t;
|
||||
|
||||
Mat2D.compose(component.worldTransform, componentsB);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ import 'package:rive/src/rive_core/component.dart';
|
||||
import 'package:rive/src/rive_core/component_dirt.dart';
|
||||
import 'package:rive/src/rive_core/constraints/constraint.dart';
|
||||
import 'package:rive/src/rive_core/constraints/ik_constraint.dart';
|
||||
import 'package:rive/src/rive_core/constraints/transform_constraint.dart';
|
||||
import 'package:rive/src/rive_core/container_component.dart';
|
||||
import 'package:rive/src/rive_core/draw_rules.dart';
|
||||
import 'package:rive/src/rive_core/drawable.dart';
|
||||
@ -165,6 +166,7 @@ abstract class TransformComponent extends TransformComponentBase {
|
||||
addDirt(ComponentDirt.clip, recurse: true);
|
||||
|
||||
break;
|
||||
case TransformConstraintBase.typeKey:
|
||||
case IKConstraintBase.typeKey:
|
||||
case DistanceConstraintBase.typeKey:
|
||||
_constraints.add(child as Constraint);
|
||||
@ -187,6 +189,7 @@ abstract class TransformComponent extends TransformComponentBase {
|
||||
addDirt(ComponentDirt.clip, recurse: true);
|
||||
}
|
||||
break;
|
||||
case TransformConstraintBase.typeKey:
|
||||
case IKConstraintBase.typeKey:
|
||||
case DistanceConstraintBase.typeKey:
|
||||
_constraints.remove(child as Constraint);
|
||||
|
Reference in New Issue
Block a user