From 72d2238d1de20e5ea9c212ebc3c90cffda2c13c1 Mon Sep 17 00:00:00 2001 From: Luigi Rosso Date: Tue, 27 Jul 2021 15:38:05 -0700 Subject: [PATCH] Applying latest fix from editor for ik constraints with skinned bones. --- lib/src/rive_core/bones/bone.dart | 9 ++++ lib/src/rive_core/bones/skin.dart | 12 ++++- .../rive_core/constraints/ik_constraint.dart | 45 ++++++++++++++++--- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/lib/src/rive_core/bones/bone.dart b/lib/src/rive_core/bones/bone.dart index 9d0a604..a82fdca 100644 --- a/lib/src/rive_core/bones/bone.dart +++ b/lib/src/rive_core/bones/bone.dart @@ -1,3 +1,4 @@ +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/vec2d.dart'; import 'package:rive/src/generated/bones/bone_base.dart'; @@ -6,6 +7,14 @@ export 'package:rive/src/generated/bones/bone_base.dart'; typedef bool BoneCallback(Bone bone); class Bone extends BoneBase { + /// Child constraints applied to some child of this bone which also affect + /// this bone. + final Set _peerConstraints = {}; + Iterable get peerConstraints => _peerConstraints; + + bool addPeerConstraint(Constraint child) => _peerConstraints.add(child); + bool removePeerConstraint(Constraint child) => _peerConstraints.remove(child); + @override void lengthChanged(double from, double to) { for (final child in children) { diff --git a/lib/src/rive_core/bones/skin.dart b/lib/src/rive_core/bones/skin.dart index 4512467..266cb88 100644 --- a/lib/src/rive_core/bones/skin.dart +++ b/lib/src/rive_core/bones/skin.dart @@ -1,5 +1,6 @@ import 'dart:typed_data'; +import 'package:rive/src/rive_core/bones/bone.dart'; import 'package:rive/src/rive_core/bones/skinnable.dart'; import 'package:rive/src/rive_core/bones/tendon.dart'; import 'package:rive/src/rive_core/component.dart'; @@ -96,7 +97,16 @@ class Skin extends SkinBase { // A skin depends on all its bones. N.B. that we don't depend on the parent // skinnable. The skinnable depends on us. for (final tendon in _tendons) { - tendon.bone?.addDependent(this); + var bone = tendon.bone; + if (bone == null) { + continue; + } + bone.addDependent(this); + if (bone is Bone) { + for (final childConstraint in bone.peerConstraints) { + childConstraint.constrainedComponent?.addDependent(this); + } + } } } diff --git a/lib/src/rive_core/constraints/ik_constraint.dart b/lib/src/rive_core/constraints/ik_constraint.dart index faabdd1..148891a 100644 --- a/lib/src/rive_core/constraints/ik_constraint.dart +++ b/lib/src/rive_core/constraints/ik_constraint.dart @@ -35,11 +35,28 @@ class IKConstraint extends IKConstraintBase { Iterable<_BoneChainLink> get fkChain => _fkChain; @override - void buildDependencies() { - super.buildDependencies(); + void onAdded() { + super.onAdded(); + _buildFKChain(); + } - // Rebuild the FK chain when we update dependencies. + @override + void onRemoved() { + _clearFKChain(); + + super.onRemoved(); + } + + void _clearFKChain() { + for (final link in _fkChain) { + link.bone.markRebuildDependencies(); + link.bone.removePeerConstraint(this); + } _fkChain.clear(); + } + + bool _buildFKChain() { + var nextFKChain = <_BoneChainLink>[]; var boneCount = parentBoneCount; var bone = parent as Bone; var bones = [bone]; @@ -51,15 +68,33 @@ class IKConstraint extends IKConstraintBase { } // Now put them in FK order (top to bottom). for (final bone in bones.reversed) { - _fkChain.add(_BoneChainLink( - index: _fkChain.length, + bone.addPeerConstraint(this); + nextFKChain.add(_BoneChainLink( + index: nextFKChain.length, bone: bone, )); } + _clearFKChain(); + + _fkChain.addAll(nextFKChain); + for (final link in _fkChain) { + link.bone.markRebuildDependencies(); + link.bone.addPeerConstraint(this); + } + markRebuildDependencies(); + return true; + } + + @override + void buildDependencies() { + super.buildDependencies(); + // Make sure all of the first level children of each bone depend on the // tip (constrainedComponent). var tip = parent as Bone; + + var bones = _fkChain.reversed.map((link) => link.bone).toSet(); for (final bone in bones.skip(1)) { for (final child in bone.children) { if (child is TransformComponent && !bones.contains(child)) {