| #include "rive/animation/transition_viewmodel_condition.hpp" |
| #include "rive/animation/state_transition.hpp" |
| #include "rive/importers/state_transition_importer.hpp" |
| #include "rive/importers/state_machine_importer.hpp" |
| #include "rive/animation/state_machine.hpp" |
| #include "rive/animation/state_machine_instance.hpp" |
| #include "rive/component_dirt.hpp" |
| |
| using namespace rive; |
| |
| class ConditionComparisonNone : public ConditionComparison |
| { |
| public: |
| ConditionComparisonNone() : ConditionComparison(nullptr) {} |
| bool compare(const StateMachineInstance* stateMachineInstance, |
| StateMachineLayerInstance* layerInstance) override |
| { |
| return false; |
| } |
| }; |
| |
| class ConditionComparisonSelf : public ConditionComparison |
| { |
| public: |
| ConditionComparisonSelf(BindableProperty* property) : |
| ConditionComparison(nullptr), m_bindableProperty(property) |
| {} |
| bool compare(const StateMachineInstance* stateMachineInstance, |
| StateMachineLayerInstance* layerInstance) override |
| { |
| auto bindableInstance = |
| stateMachineInstance->bindablePropertyInstance(m_bindableProperty); |
| auto dataBind = |
| stateMachineInstance->bindableDataBindToTarget(bindableInstance); |
| if (dataBind != nullptr) |
| { |
| auto source = dataBind->source(); |
| if (source != nullptr && source->hasChanged() && |
| !source->isUsedInLayer(layerInstance)) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private: |
| BindableProperty* m_bindableProperty; |
| }; |
| class ConditionComparisonNumber : public ConditionComparison |
| { |
| public: |
| ConditionComparisonNumber(ConditionComparandNumber* left, |
| ConditionComparandNumber* right, |
| ConditionOperation* operation) : |
| ConditionComparison(operation), |
| m_leftComparand(left), |
| m_rightComparand(right) |
| {} |
| ~ConditionComparisonNumber() |
| { |
| delete m_leftComparand; |
| delete m_rightComparand; |
| } |
| bool compare(const StateMachineInstance* stateMachineInstance, |
| StateMachineLayerInstance* layerInstance) override |
| { |
| return compareNumbers(m_leftComparand->value(stateMachineInstance), |
| m_rightComparand->value(stateMachineInstance)); |
| } |
| |
| private: |
| ConditionComparandNumber* m_leftComparand = nullptr; |
| ConditionComparandNumber* m_rightComparand = nullptr; |
| }; |
| class ConditionComparisonBoolean : public ConditionComparison |
| { |
| public: |
| ConditionComparisonBoolean(ConditionComparandBoolean* left, |
| ConditionComparandBoolean* right, |
| ConditionOperation* operation) : |
| ConditionComparison(operation), |
| m_leftComparand(left), |
| m_rightComparand(right) |
| {} |
| ~ConditionComparisonBoolean() override |
| { |
| delete m_leftComparand; |
| delete m_rightComparand; |
| } |
| bool compare(const StateMachineInstance* stateMachineInstance, |
| StateMachineLayerInstance* layerInstance) override |
| { |
| return compareBooleans(m_leftComparand->value(stateMachineInstance), |
| m_rightComparand->value(stateMachineInstance)); |
| } |
| |
| private: |
| ConditionComparandBoolean* m_leftComparand = nullptr; |
| ConditionComparandBoolean* m_rightComparand = nullptr; |
| }; |
| |
| class ConditionComparisonString : public ConditionComparison |
| { |
| public: |
| ConditionComparisonString(ConditionComparandString* left, |
| ConditionComparandString* right, |
| ConditionOperation* operation) : |
| ConditionComparison(operation), |
| m_leftComparand(left), |
| m_rightComparand(right) |
| {} |
| ~ConditionComparisonString() |
| { |
| delete m_leftComparand; |
| delete m_rightComparand; |
| } |
| bool compare(const StateMachineInstance* stateMachineInstance, |
| StateMachineLayerInstance* layerInstance) override |
| { |
| return compareStrings(m_leftComparand->value(stateMachineInstance), |
| m_rightComparand->value(stateMachineInstance)); |
| } |
| |
| private: |
| ConditionComparandString* m_leftComparand = nullptr; |
| ConditionComparandString* m_rightComparand = nullptr; |
| }; |
| |
| class ConditionComparisonColor : public ConditionComparison |
| { |
| public: |
| ConditionComparisonColor(ConditionComparandColor* left, |
| ConditionComparandColor* right, |
| ConditionOperation* operation) : |
| ConditionComparison(operation), |
| m_leftComparand(left), |
| m_rightComparand(right) |
| {} |
| ~ConditionComparisonColor() |
| { |
| delete m_leftComparand; |
| delete m_rightComparand; |
| } |
| bool compare(const StateMachineInstance* stateMachineInstance, |
| StateMachineLayerInstance* layerInstance) override |
| { |
| return compareColors(m_leftComparand->value(stateMachineInstance), |
| m_rightComparand->value(stateMachineInstance)); |
| } |
| |
| private: |
| ConditionComparandColor* m_leftComparand = nullptr; |
| ConditionComparandColor* m_rightComparand = nullptr; |
| }; |
| |
| class ConditionComparisonEnum : public ConditionComparison |
| { |
| public: |
| ConditionComparisonEnum(ConditionComparandUint32* left, |
| ConditionComparandUint32* right, |
| ConditionOperation* operation) : |
| ConditionComparison(operation), |
| m_leftComparand(left), |
| m_rightComparand(right) |
| {} |
| ~ConditionComparisonEnum() |
| { |
| delete m_leftComparand; |
| delete m_rightComparand; |
| } |
| bool compare(const StateMachineInstance* stateMachineInstance, |
| StateMachineLayerInstance* layerInstance) override |
| { |
| return compareUints32(m_leftComparand->value(stateMachineInstance), |
| m_rightComparand->value(stateMachineInstance)); |
| } |
| |
| private: |
| ConditionComparandUint32* m_leftComparand = nullptr; |
| ConditionComparandUint32* m_rightComparand = nullptr; |
| }; |
| |
| class ConditionComparisonUint32 : public ConditionComparison |
| { |
| public: |
| ConditionComparisonUint32(ConditionComparandUint32* left, |
| ConditionComparandUint32* right, |
| ConditionOperation* operation) : |
| ConditionComparison(operation), |
| m_leftComparand(left), |
| m_rightComparand(right) |
| {} |
| ~ConditionComparisonUint32() |
| { |
| delete m_leftComparand; |
| delete m_rightComparand; |
| } |
| bool compare(const StateMachineInstance* stateMachineInstance, |
| StateMachineLayerInstance* layerInstance) override |
| { |
| return compareUints32(m_leftComparand->value(stateMachineInstance), |
| m_rightComparand->value(stateMachineInstance)); |
| } |
| |
| private: |
| ConditionComparandUint32* m_leftComparand = nullptr; |
| ConditionComparandUint32* m_rightComparand = nullptr; |
| }; |
| |
| TransitionViewModelCondition::~TransitionViewModelCondition() |
| { |
| if (m_leftComparator != nullptr) |
| { |
| delete m_leftComparator; |
| m_leftComparator = nullptr; |
| } |
| if (m_rightComparator != nullptr) |
| { |
| delete m_rightComparator; |
| m_rightComparator = nullptr; |
| } |
| if (m_comparison != nullptr) |
| { |
| delete m_comparison; |
| m_comparison = nullptr; |
| } |
| } |
| |
| bool TransitionViewModelCondition::evaluate( |
| const StateMachineInstance* stateMachineInstance, |
| StateMachineLayerInstance* layerInstance) const |
| { |
| if (stateMachineInstance->dataContext()) |
| { |
| return m_comparison->compare(stateMachineInstance, layerInstance); |
| } |
| return false; |
| } |
| |
| void TransitionViewModelCondition::useInLayer( |
| const StateMachineInstance* stateMachineInstance, |
| StateMachineLayerInstance* layerInstance) const |
| { |
| if (leftComparator() != nullptr) |
| { |
| return leftComparator()->useInLayer(stateMachineInstance, |
| layerInstance); |
| } |
| } |
| |
| ConditionOperation* TransitionViewModelCondition::operation( |
| TransitionConditionOp op) |
| { |
| switch (op) |
| { |
| case TransitionConditionOp::equal: |
| return new ConditionOperationEqual(); |
| case TransitionConditionOp::notEqual: |
| return new ConditionOperationNotEqual(); |
| case TransitionConditionOp::lessThanOrEqual: |
| return new ConditionOperationLessThanOrEqual(); |
| case TransitionConditionOp::lessThan: |
| return new ConditionOperationLessThan(); |
| case TransitionConditionOp::greaterThanOrEqual: |
| return new ConditionOperationGreaterThanOrEqual(); |
| case TransitionConditionOp::greaterThan: |
| return new ConditionOperationGreaterThan(); |
| } |
| return new ConditionOperation(); |
| } |
| |
| void TransitionViewModelCondition::initialize() |
| { |
| if (leftComparator() && rightComparator()) |
| { |
| if (leftComparator()->is<TransitionPropertyArtboardComparator>()) |
| { |
| |
| auto leftProperty = |
| leftComparator()->as<TransitionPropertyArtboardComparator>(); |
| if (rightComparator()->is<TransitionPropertyViewModelComparator>()) |
| { |
| auto rightBindableProperty = |
| rightComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightBindableProperty->is<BindablePropertyNumber>()) |
| { |
| auto leftComparand = |
| new ConditionComparandArtboardProperty(leftProperty); |
| auto rightComparand = new ConditionComparandNumberBindable( |
| rightBindableProperty->as<BindablePropertyNumber>()); |
| m_comparison = |
| new ConditionComparisonNumber(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| else if (rightBindableProperty->is<BindablePropertyInteger>()) |
| { |
| auto leftComparand = |
| new ConditionComparandArtboardProperty(leftProperty); |
| auto rightComparand = |
| new ConditionComparandNumberBindableInteger( |
| rightBindableProperty |
| ->as<BindablePropertyInteger>()); |
| m_comparison = |
| new ConditionComparisonNumber(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| else if (rightComparator()->is<TransitionValueNumberComparator>()) |
| { |
| auto leftComparand = |
| new ConditionComparandArtboardProperty(leftProperty); |
| auto rightComparand = new ConditionComparandNumberValue( |
| rightComparator()->as<TransitionValueNumberComparator>()); |
| m_comparison = new ConditionComparisonNumber(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| auto leftBindableProperty = |
| leftComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightComparator()->is<TransitionSelfComparator>()) |
| { |
| m_comparison = new ConditionComparisonSelf(leftBindableProperty); |
| return; |
| } |
| switch (leftBindableProperty->coreType()) |
| { |
| case BindablePropertyNumber::typeKey: |
| { |
| if (rightComparator() |
| ->is<TransitionPropertyViewModelComparator>()) |
| { |
| auto rightBindableProperty = |
| rightComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightBindableProperty->is<BindablePropertyNumber>()) |
| { |
| auto leftComparand = |
| new ConditionComparandNumberBindable( |
| leftBindableProperty |
| ->as<BindablePropertyNumber>()); |
| auto rightComparand = |
| new ConditionComparandNumberBindable( |
| rightBindableProperty |
| ->as<BindablePropertyNumber>()); |
| m_comparison = |
| new ConditionComparisonNumber(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| else if (rightBindableProperty |
| ->is<BindablePropertyInteger>()) |
| { |
| auto leftComparand = |
| new ConditionComparandNumberBindable( |
| leftBindableProperty |
| ->as<BindablePropertyNumber>()); |
| auto rightComparand = |
| new ConditionComparandNumberBindableInteger( |
| rightBindableProperty |
| ->as<BindablePropertyInteger>()); |
| m_comparison = |
| new ConditionComparisonNumber(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| else if (rightComparator() |
| ->is<TransitionValueNumberComparator>()) |
| { |
| auto leftComparand = new ConditionComparandNumberBindable( |
| leftBindableProperty->as<BindablePropertyNumber>()); |
| auto rightComparand = new ConditionComparandNumberValue( |
| rightComparator() |
| ->as<TransitionValueNumberComparator>()); |
| m_comparison = |
| new ConditionComparisonNumber(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| break; |
| } |
| |
| case BindablePropertyBoolean::typeKey: |
| { |
| if (rightComparator() |
| ->is<TransitionPropertyViewModelComparator>()) |
| { |
| auto rightBindableProperty = |
| rightComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightBindableProperty->is<BindablePropertyBoolean>()) |
| { |
| auto leftComparand = |
| new ConditionComparandBooleanBindable( |
| leftBindableProperty |
| ->as<BindablePropertyBoolean>()); |
| auto rightComparand = |
| new ConditionComparandBooleanBindable( |
| rightBindableProperty |
| ->as<BindablePropertyBoolean>()); |
| m_comparison = |
| new ConditionComparisonBoolean(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| else if (rightComparator() |
| ->is<TransitionValueBooleanComparator>()) |
| { |
| auto leftComparand = new ConditionComparandBooleanBindable( |
| leftBindableProperty->as<BindablePropertyBoolean>()); |
| auto rightComparand = new ConditionComparandBooleanValue( |
| rightComparator() |
| ->as<TransitionValueBooleanComparator>()); |
| m_comparison = |
| new ConditionComparisonBoolean(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| break; |
| } |
| case BindablePropertyString::typeKey: |
| { |
| if (rightComparator() |
| ->is<TransitionPropertyViewModelComparator>()) |
| { |
| auto rightBindableProperty = |
| rightComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightBindableProperty->is<BindablePropertyString>()) |
| { |
| auto leftComparand = |
| new ConditionComparandStringBindable( |
| leftBindableProperty |
| ->as<BindablePropertyString>()); |
| auto rightComparand = |
| new ConditionComparandStringBindable( |
| rightBindableProperty |
| ->as<BindablePropertyString>()); |
| m_comparison = |
| new ConditionComparisonString(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| else if (rightComparator() |
| ->is<TransitionValueStringComparator>()) |
| { |
| auto leftComparand = new ConditionComparandStringBindable( |
| leftBindableProperty->as<BindablePropertyString>()); |
| auto rightComparand = new ConditionComparandStringValue( |
| rightComparator() |
| ->as<TransitionValueStringComparator>()); |
| m_comparison = |
| new ConditionComparisonString(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| break; |
| } |
| case BindablePropertyColor::typeKey: |
| { |
| if (rightComparator() |
| ->is<TransitionPropertyViewModelComparator>()) |
| { |
| auto rightBindableProperty = |
| rightComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightBindableProperty->is<BindablePropertyColor>()) |
| { |
| auto leftComparand = |
| new ConditionComparandColorBindable( |
| leftBindableProperty |
| ->as<BindablePropertyColor>()); |
| auto rightComparand = |
| new ConditionComparandColorBindable( |
| rightBindableProperty |
| ->as<BindablePropertyColor>()); |
| m_comparison = |
| new ConditionComparisonColor(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| else if (rightComparator() |
| ->is<TransitionValueColorComparator>()) |
| { |
| auto leftComparand = new ConditionComparandColorBindable( |
| leftBindableProperty->as<BindablePropertyColor>()); |
| auto rightComparand = new ConditionComparandColorValue( |
| rightComparator() |
| ->as<TransitionValueColorComparator>()); |
| m_comparison = |
| new ConditionComparisonColor(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| break; |
| } |
| case BindablePropertyEnum::typeKey: |
| { |
| if (rightComparator() |
| ->is<TransitionPropertyViewModelComparator>()) |
| { |
| auto rightBindableProperty = |
| rightComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightBindableProperty->is<BindablePropertyEnum>()) |
| { |
| auto leftComparand = new ConditionComparandEnumBindable( |
| leftBindableProperty->as<BindablePropertyEnum>()); |
| auto rightComparand = |
| new ConditionComparandEnumBindable( |
| rightBindableProperty |
| ->as<BindablePropertyEnum>()); |
| m_comparison = |
| new ConditionComparisonEnum(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| else if (rightComparator()->is<TransitionValueEnumComparator>()) |
| { |
| auto leftComparand = new ConditionComparandEnumBindable( |
| leftBindableProperty->as<BindablePropertyEnum>()); |
| auto rightComparand = new ConditionComparandEnumValue( |
| rightComparator()->as<TransitionValueEnumComparator>()); |
| m_comparison = new ConditionComparisonEnum(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| break; |
| } |
| case BindablePropertyTrigger::typeKey: |
| { |
| if (rightComparator() |
| ->is<TransitionPropertyViewModelComparator>()) |
| { |
| auto rightBindableProperty = |
| rightComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightBindableProperty->is<BindablePropertyTrigger>()) |
| { |
| auto leftComparand = |
| new ConditionComparandTriggerBindable( |
| leftBindableProperty |
| ->as<BindablePropertyTrigger>()); |
| auto rightComparand = |
| new ConditionComparandTriggerBindable( |
| rightBindableProperty |
| ->as<BindablePropertyTrigger>()); |
| m_comparison = |
| new ConditionComparisonUint32(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| else if (rightComparator() |
| ->is<TransitionValueTriggerComparator>()) |
| { |
| m_comparison = |
| new ConditionComparisonSelf(leftBindableProperty); |
| return; |
| } |
| break; |
| } |
| case BindablePropertyInteger::typeKey: |
| { |
| if (rightComparator() |
| ->is<TransitionPropertyViewModelComparator>()) |
| { |
| auto rightBindableProperty = |
| rightComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightBindableProperty->is<BindablePropertyInteger>()) |
| { |
| auto leftComparand = |
| new ConditionComparandIntegerBindable( |
| leftBindableProperty |
| ->as<BindablePropertyInteger>()); |
| auto rightComparand = |
| new ConditionComparandIntegerBindable( |
| rightBindableProperty |
| ->as<BindablePropertyInteger>()); |
| m_comparison = |
| new ConditionComparisonUint32(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| else if (rightBindableProperty |
| ->is<BindablePropertyNumber>()) |
| { |
| auto leftComparand = |
| new ConditionComparandNumberBindableInteger( |
| leftBindableProperty |
| ->as<BindablePropertyInteger>()); |
| auto rightComparand = |
| new ConditionComparandNumberBindable( |
| rightBindableProperty |
| ->as<BindablePropertyNumber>()); |
| m_comparison = |
| new ConditionComparisonNumber(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| else if (rightComparator() |
| ->is<TransitionValueNumberComparator>()) |
| { |
| auto leftComparand = |
| new ConditionComparandNumberBindableInteger( |
| leftBindableProperty |
| ->as<BindablePropertyInteger>()); |
| auto rightComparand = new ConditionComparandNumberValue( |
| rightComparator() |
| ->as<TransitionValueNumberComparator>()); |
| m_comparison = |
| new ConditionComparisonNumber(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| break; |
| } |
| case BindablePropertyAsset::typeKey: |
| { |
| if (rightComparator() |
| ->is<TransitionPropertyViewModelComparator>()) |
| { |
| auto rightBindableProperty = |
| rightComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightBindableProperty->is<BindablePropertyAsset>()) |
| { |
| auto leftComparand = |
| new ConditionComparandAssetBindable( |
| leftBindableProperty |
| ->as<BindablePropertyAsset>()); |
| auto rightComparand = |
| new ConditionComparandAssetBindable( |
| rightBindableProperty |
| ->as<BindablePropertyAsset>()); |
| m_comparison = |
| new ConditionComparisonUint32(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| else if (rightComparator() |
| ->is<TransitionValueAssetComparator>()) |
| { |
| auto leftComparand = new ConditionComparandAssetBindable( |
| leftBindableProperty->as<BindablePropertyAsset>()); |
| auto rightComparand = new ConditionComparandAssetValue( |
| rightComparator() |
| ->as<TransitionValueAssetComparator>()); |
| m_comparison = |
| new ConditionComparisonUint32(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| break; |
| } |
| case BindablePropertyArtboard::typeKey: |
| { |
| if (rightComparator() |
| ->is<TransitionPropertyViewModelComparator>()) |
| { |
| auto rightBindableProperty = |
| rightComparator() |
| ->as<TransitionPropertyViewModelComparator>() |
| ->bindableProperty(); |
| if (rightBindableProperty->is<BindablePropertyArtboard>()) |
| { |
| auto leftComparand = |
| new ConditionComparandArtboardBindable( |
| leftBindableProperty |
| ->as<BindablePropertyArtboard>()); |
| auto rightComparand = |
| new ConditionComparandArtboardBindable( |
| rightBindableProperty |
| ->as<BindablePropertyArtboard>()); |
| m_comparison = |
| new ConditionComparisonUint32(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| } |
| else if (rightComparator() |
| ->is<TransitionValueArtboardComparator>()) |
| { |
| auto leftComparand = new ConditionComparandArtboardBindable( |
| leftBindableProperty->as<BindablePropertyArtboard>()); |
| auto rightComparand = new ConditionComparandArtboardValue( |
| rightComparator() |
| ->as<TransitionValueArtboardComparator>()); |
| m_comparison = |
| new ConditionComparisonUint32(leftComparand, |
| rightComparand, |
| operation(op())); |
| return; |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| m_comparison = new ConditionComparisonNone(); |
| } |
| } |
| |
| bool ConditionComparison::compareNumbers(float left, float right) |
| { |
| return m_operation->compareNumbers(left, right); |
| } |
| |
| bool ConditionComparison::compareStrings(const std::string& left, |
| const std::string& right) |
| { |
| return m_operation->compareStrings(left, right); |
| } |
| |
| bool ConditionComparison::compareBooleans(bool left, bool right) |
| { |
| return m_operation->compareBooleans(left, right); |
| } |
| |
| bool ConditionComparison::compareColors(int left, int right) |
| { |
| return m_operation->compareInts(left, right); |
| } |
| |
| bool ConditionComparison::compareUints32(uint32_t left, uint32_t right) |
| { |
| return m_operation->compareUints32(left, right); |
| } |