From b63d9cfec95fd99bdc5ce182580344648361bd94 Mon Sep 17 00:00:00 2001 From: umberto-sonnino Date: Fri, 23 Jun 2023 21:35:21 +0000 Subject: [PATCH] Runtime/interpolate states cpp Quite a lot of churn here, I created this off of https://github.com/rive-app/rive/pull/5429 which already generated a lot of code. On top of it, I also generated the C++ classes, which in turn added a bunch of other missing things related to text. There's *not that much non-generated* code here, but I'll keep this draft for now..? Diffs= 8b7587241 Runtime/interpolate states cpp (#5437) Co-authored-by: Umberto Sonnino --- .rive_head | 2 +- .../animation/blend_animation_direct.json | 2 +- .../animation/state_machine_component.json | 2 +- dev/defs/animation/state_transition.json | 20 ++++++++++ dev/defs/artboard.json | 2 +- dev/defs/assets/font_asset.json | 2 +- dev/defs/backboard.json | 4 +- dev/defs/joystick.json | 2 +- dev/defs/text/text.json | 2 +- dev/defs/text/text_style.json | 2 +- dev/generate_core.sh | 2 + .../cubic_interpolator_component.hpp | 13 +++++++ include/rive/animation/state_transition.hpp | 3 ++ .../animation/state_transition_base.hpp | 36 +++++++++++++++++ include/rive/generated/core_registry.hpp | 12 ++++++ src/animation/state_machine_instance.cpp | 39 ++++++++++++------- src/animation/state_transition.cpp | 24 +++++++++--- .../animation/cubic_interpolator_base.cpp | 4 -- 18 files changed, 138 insertions(+), 35 deletions(-) create mode 100644 include/rive/animation/cubic_interpolator_component.hpp delete mode 100644 src/generated/animation/cubic_interpolator_base.cpp diff --git a/.rive_head b/.rive_head index c6d0fe32..ae479263 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -9695de6e34a963dd4fa4dc73b72e366c7a68ff04 +8b7587241233b7b884c5fa2976ed0cecf45c8022 diff --git a/dev/defs/animation/blend_animation_direct.json b/dev/defs/animation/blend_animation_direct.json index 303dc450..b4c99b1f 100644 --- a/dev/defs/animation/blend_animation_direct.json +++ b/dev/defs/animation/blend_animation_direct.json @@ -36,4 +36,4 @@ "description": "Source to use when establishing the mix value for the animation. 0 means look at the input, 1 look at the mixValue." } } -} +} \ No newline at end of file diff --git a/dev/defs/animation/state_machine_component.json b/dev/defs/animation/state_machine_component.json index 0c6b9278..b3272fb9 100644 --- a/dev/defs/animation/state_machine_component.json +++ b/dev/defs/animation/state_machine_component.json @@ -36,4 +36,4 @@ "runtime": false } } -} \ No newline at end of file +} diff --git a/dev/defs/animation/state_transition.json b/dev/defs/animation/state_transition.json index 668273f7..072d10e0 100644 --- a/dev/defs/animation/state_transition.json +++ b/dev/defs/animation/state_transition.json @@ -62,6 +62,26 @@ "string": "exittime" }, "description": "Duration in milliseconds that must elapse before allowing the state to change. If the flags mark this property as being percentage based, the value is in 0-100% of the outgoing animation's duration" + }, + "interpolationType": { + "type": "uint", + "initialValue": "1", + "key": { + "int": 349, + "string": "interpolationtype" + }, + "description": "The type of interpolation index in Interpolation applied to this state transition ('linear' by default)." + }, + "interpolatorId": { + "type": "Id", + "typeRuntime": "uint", + "initialValue": "Core.missingId", + "initialValueRuntime": "-1", + "key": { + "int": 350, + "string": "interpolatorid" + }, + "description": "The id of the custom interpolator used when interpolation is Cubic." } } } \ No newline at end of file diff --git a/dev/defs/artboard.json b/dev/defs/artboard.json index 3a359a63..53190437 100644 --- a/dev/defs/artboard.json +++ b/dev/defs/artboard.json @@ -125,4 +125,4 @@ "coop": false } } -} \ No newline at end of file +} diff --git a/dev/defs/assets/font_asset.json b/dev/defs/assets/font_asset.json index cd39ee84..f10a7907 100644 --- a/dev/defs/assets/font_asset.json +++ b/dev/defs/assets/font_asset.json @@ -5,4 +5,4 @@ "string": "fontasset" }, "extends": "assets/file_asset.json" -} \ No newline at end of file +} diff --git a/dev/defs/backboard.json b/dev/defs/backboard.json index 66bd5f3c..b194d688 100644 --- a/dev/defs/backboard.json +++ b/dev/defs/backboard.json @@ -153,9 +153,9 @@ "int": 290, "string": "toolbaroutputaction" }, - "description": "Primary output action in the toolbar (share, publihs, download)", + "description": "Primary output action in the toolbar (share, publish, download)", "runtime": false, "coop": false } } -} \ No newline at end of file +} diff --git a/dev/defs/joystick.json b/dev/defs/joystick.json index 17137f09..461454eb 100644 --- a/dev/defs/joystick.json +++ b/dev/defs/joystick.json @@ -118,4 +118,4 @@ "description": "Identifier used to track the custom handle source of the joystick." } } -} \ No newline at end of file +} diff --git a/dev/defs/text/text.json b/dev/defs/text/text.json index d7cb62da..01868a81 100644 --- a/dev/defs/text/text.json +++ b/dev/defs/text/text.json @@ -52,4 +52,4 @@ "description": "Height of the text object." } } -} \ No newline at end of file +} diff --git a/dev/defs/text/text_style.json b/dev/defs/text/text_style.json index 16624fae..2c311378 100644 --- a/dev/defs/text/text_style.json +++ b/dev/defs/text/text_style.json @@ -26,4 +26,4 @@ } } } -} \ No newline at end of file +} diff --git a/dev/generate_core.sh b/dev/generate_core.sh index c25ec4d6..006def77 100755 --- a/dev/generate_core.sh +++ b/dev/generate_core.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash +set -e if [[ ! -f "./bin/core_generator" || "$1" == "build" ]]; then mkdir -p ./bin diff --git a/include/rive/animation/cubic_interpolator_component.hpp b/include/rive/animation/cubic_interpolator_component.hpp new file mode 100644 index 00000000..ebfd6922 --- /dev/null +++ b/include/rive/animation/cubic_interpolator_component.hpp @@ -0,0 +1,13 @@ +#ifndef _RIVE_CUBIC_INTERPOLATOR_COMPONENT_HPP_ +#define _RIVE_CUBIC_INTERPOLATOR_COMPONENT_HPP_ +#include "rive/generated/animation/cubic_interpolator_component_base.hpp" +#include +namespace rive +{ +class CubicInterpolatorComponent : public CubicInterpolatorComponentBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/animation/state_transition.hpp b/include/rive/animation/state_transition.hpp index 3d0529ef..5fefb4cd 100644 --- a/include/rive/animation/state_transition.hpp +++ b/include/rive/animation/state_transition.hpp @@ -1,5 +1,6 @@ #ifndef _RIVE_STATE_TRANSITION_HPP_ #define _RIVE_STATE_TRANSITION_HPP_ +#include "rive/animation/cubic_interpolator.hpp" #include "rive/animation/state_transition_flags.hpp" #include "rive/generated/animation/state_transition_base.hpp" #include @@ -34,6 +35,7 @@ private: return static_cast(flags()); } LayerState* m_StateTo = nullptr; + CubicInterpolator* m_Interpolator = nullptr; std::vector m_Conditions; void addCondition(TransitionCondition* condition); @@ -41,6 +43,7 @@ private: public: ~StateTransition() override; const LayerState* stateTo() const { return m_StateTo; } + inline CubicInterpolator* interpolator() const { return m_Interpolator; } StatusCode onAddedDirty(CoreContext* context) override; StatusCode onAddedClean(CoreContext* context) override; diff --git a/include/rive/generated/animation/state_transition_base.hpp b/include/rive/generated/animation/state_transition_base.hpp index d50874ab..9b526ac0 100644 --- a/include/rive/generated/animation/state_transition_base.hpp +++ b/include/rive/generated/animation/state_transition_base.hpp @@ -32,12 +32,16 @@ public: static const uint16_t flagsPropertyKey = 152; static const uint16_t durationPropertyKey = 158; static const uint16_t exitTimePropertyKey = 160; + static const uint16_t interpolationTypePropertyKey = 349; + static const uint16_t interpolatorIdPropertyKey = 350; private: uint32_t m_StateToId = -1; uint32_t m_Flags = 0; uint32_t m_Duration = 0; uint32_t m_ExitTime = 0; + uint32_t m_InterpolationType = 1; + uint32_t m_InterpolatorId = -1; public: inline uint32_t stateToId() const { return m_StateToId; } @@ -84,6 +88,28 @@ public: exitTimeChanged(); } + inline uint32_t interpolationType() const { return m_InterpolationType; } + void interpolationType(uint32_t value) + { + if (m_InterpolationType == value) + { + return; + } + m_InterpolationType = value; + interpolationTypeChanged(); + } + + inline uint32_t interpolatorId() const { return m_InterpolatorId; } + void interpolatorId(uint32_t value) + { + if (m_InterpolatorId == value) + { + return; + } + m_InterpolatorId = value; + interpolatorIdChanged(); + } + Core* clone() const override; void copy(const StateTransitionBase& object) { @@ -91,6 +117,8 @@ public: m_Flags = object.m_Flags; m_Duration = object.m_Duration; m_ExitTime = object.m_ExitTime; + m_InterpolationType = object.m_InterpolationType; + m_InterpolatorId = object.m_InterpolatorId; StateMachineLayerComponent::copy(object); } @@ -110,6 +138,12 @@ public: case exitTimePropertyKey: m_ExitTime = CoreUintType::deserialize(reader); return true; + case interpolationTypePropertyKey: + m_InterpolationType = CoreUintType::deserialize(reader); + return true; + case interpolatorIdPropertyKey: + m_InterpolatorId = CoreUintType::deserialize(reader); + return true; } return StateMachineLayerComponent::deserialize(propertyKey, reader); } @@ -119,6 +153,8 @@ protected: virtual void flagsChanged() {} virtual void durationChanged() {} virtual void exitTimeChanged() {} + virtual void interpolationTypeChanged() {} + virtual void interpolatorIdChanged() {} }; } // namespace rive diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp index 5ba4c823..7698ca95 100644 --- a/include/rive/generated/core_registry.hpp +++ b/include/rive/generated/core_registry.hpp @@ -457,6 +457,12 @@ public: case StateTransitionBase::exitTimePropertyKey: object->as()->exitTime(value); break; + case StateTransitionBase::interpolationTypePropertyKey: + object->as()->interpolationType(value); + break; + case StateTransitionBase::interpolatorIdPropertyKey: + object->as()->interpolatorId(value); + break; case LinearAnimationBase::fpsPropertyKey: object->as()->fps(value); break; @@ -1043,6 +1049,10 @@ public: return object->as()->duration(); case StateTransitionBase::exitTimePropertyKey: return object->as()->exitTime(); + case StateTransitionBase::interpolationTypePropertyKey: + return object->as()->interpolationType(); + case StateTransitionBase::interpolatorIdPropertyKey: + return object->as()->interpolatorId(); case LinearAnimationBase::fpsPropertyKey: return object->as()->fps(); case LinearAnimationBase::durationPropertyKey: @@ -1428,6 +1438,8 @@ public: case StateTransitionBase::flagsPropertyKey: case StateTransitionBase::durationPropertyKey: case StateTransitionBase::exitTimePropertyKey: + case StateTransitionBase::interpolationTypePropertyKey: + case StateTransitionBase::interpolatorIdPropertyKey: case LinearAnimationBase::fpsPropertyKey: case LinearAnimationBase::durationPropertyKey: case LinearAnimationBase::loopValuePropertyKey: diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp index 544aa9aa..5a1e00d6 100644 --- a/src/animation/state_machine_instance.cpp +++ b/src/animation/state_machine_instance.cpp @@ -1,26 +1,27 @@ -#include "rive/animation/state_machine_instance.hpp" -#include "rive/animation/state_machine_input.hpp" +#include "rive/animation/animation_state_instance.hpp" +#include "rive/animation/animation_state.hpp" +#include "rive/animation/any_state.hpp" +#include "rive/animation/cubic_interpolator.hpp" +#include "rive/animation/entry_state.hpp" +#include "rive/animation/nested_state_machine.hpp" +#include "rive/animation/state_instance.hpp" #include "rive/animation/state_machine_bool.hpp" +#include "rive/animation/state_machine_input_instance.hpp" +#include "rive/animation/state_machine_input.hpp" +#include "rive/animation/state_machine_instance.hpp" +#include "rive/animation/state_machine_layer.hpp" +#include "rive/animation/state_machine_listener.hpp" #include "rive/animation/state_machine_number.hpp" #include "rive/animation/state_machine_trigger.hpp" -#include "rive/animation/state_machine_input_instance.hpp" #include "rive/animation/state_machine.hpp" -#include "rive/animation/state_machine_layer.hpp" -#include "rive/animation/any_state.hpp" -#include "rive/animation/entry_state.hpp" #include "rive/animation/state_transition.hpp" #include "rive/animation/transition_condition.hpp" -#include "rive/animation/animation_state.hpp" -#include "rive/animation/state_instance.hpp" -#include "rive/animation/animation_state_instance.hpp" -#include "rive/animation/state_machine_listener.hpp" -#include "rive/shapes/shape.hpp" #include "rive/math/aabb.hpp" #include "rive/math/hit_test.hpp" -#include "rive/nested_artboard.hpp" #include "rive/nested_animation.hpp" -#include "rive/animation/nested_state_machine.hpp" +#include "rive/nested_artboard.hpp" #include "rive/rive_counter.hpp" +#include "rive/shapes/shape.hpp" #include using namespace rive; @@ -233,13 +234,21 @@ public: m_HoldAnimation = nullptr; } + CubicInterpolator* cubic = nullptr; + if (m_Transition != nullptr && m_Transition->interpolator() != nullptr) + { + cubic = m_Transition->interpolator(); + } + if (m_StateFrom != nullptr && m_Mix < 1.0f) { - m_StateFrom->apply(m_MixFrom); + auto fromMix = cubic != nullptr ? cubic->transform(m_MixFrom) : m_MixFrom; + m_StateFrom->apply(fromMix); } if (m_CurrentState != nullptr) { - m_CurrentState->apply(m_Mix); + auto mix = cubic != nullptr ? cubic->transform(m_Mix) : m_Mix; + m_CurrentState->apply(mix); } } diff --git a/src/animation/state_transition.cpp b/src/animation/state_transition.cpp index 5efa228e..208790b1 100644 --- a/src/animation/state_transition.cpp +++ b/src/animation/state_transition.cpp @@ -1,14 +1,15 @@ -#include "rive/animation/state_transition.hpp" -#include "rive/importers/import_stack.hpp" -#include "rive/importers/layer_state_importer.hpp" -#include "rive/animation/layer_state.hpp" -#include "rive/animation/transition_condition.hpp" +#include "rive/animation/animation_state_instance.hpp" #include "rive/animation/animation_state.hpp" +#include "rive/animation/cubic_interpolator.hpp" +#include "rive/animation/layer_state.hpp" #include "rive/animation/linear_animation.hpp" #include "rive/animation/state_machine_input_instance.hpp" #include "rive/animation/state_machine_trigger.hpp" -#include "rive/animation/animation_state_instance.hpp" +#include "rive/animation/state_transition.hpp" +#include "rive/animation/transition_condition.hpp" #include "rive/animation/transition_trigger_condition.hpp" +#include "rive/importers/import_stack.hpp" +#include "rive/importers/layer_state_importer.hpp" using namespace rive; @@ -23,6 +24,17 @@ StateTransition::~StateTransition() StatusCode StateTransition::onAddedDirty(CoreContext* context) { StatusCode code; + + if (interpolatorId() != -1) + { + auto coreObject = context->resolve(interpolatorId()); + if (coreObject == nullptr || !coreObject->is()) + { + return StatusCode::MissingObject; + } + m_Interpolator = coreObject->as(); + } + for (auto condition : m_Conditions) { if ((code = condition->onAddedDirty(context)) != StatusCode::Ok) diff --git a/src/generated/animation/cubic_interpolator_base.cpp b/src/generated/animation/cubic_interpolator_base.cpp deleted file mode 100644 index 1745e607..00000000 --- a/src/generated/animation/cubic_interpolator_base.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "rive/generated/animation/cubic_interpolator_base.hpp" -#include "rive/animation/cubic_interpolator.hpp" - -using namespace rive; \ No newline at end of file