diff --git a/.rive_head b/.rive_head index 862f7be4..69de675a 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -a2b0cb230ae3f3834d13096d7dc7688ef908c1d3 +88543fa79295566065b700bfcf66130f327ff562 diff --git a/dev/defs/data_bind/converters/data_converter_range_mapper.json b/dev/defs/data_bind/converters/data_converter_range_mapper.json new file mode 100644 index 00000000..7ff25887 --- /dev/null +++ b/dev/defs/data_bind/converters/data_converter_range_mapper.json @@ -0,0 +1,39 @@ +{ + "name": "DataConverterRangeMapper", + "key": { + "int": 518, + "string": "dataconverterrangemapper" + }, + "abstract": true, + "extends": "data_bind/converters/data_converter.json", + "properties": { + "interpolationType": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 713, + "string": "interpolationtype" + }, + "description": "The type of interpolation index in KeyframeInterpolation applied to this layout." + }, + "interpolatorId": { + "type": "Id", + "typeRuntime": "uint", + "initialValue": "Core.missingId", + "initialValueRuntime": "-1", + "key": { + "int": 714, + "string": "interpolatorid" + }, + "description": "The id of the custom interpolator used when interpolation is Cubic." + }, + "flags": { + "type": "uint", + "initialValue": "0", + "key": { + "int": 715, + "string": "flags" + } + } + } +} \ No newline at end of file diff --git a/dev/defs/data_bind/converters/data_converter_range_mapper_values.json b/dev/defs/data_bind/converters/data_converter_range_mapper_values.json new file mode 100644 index 00000000..f4c2aee2 --- /dev/null +++ b/dev/defs/data_bind/converters/data_converter_range_mapper_values.json @@ -0,0 +1,46 @@ +{ + "name": "DataConverterRangeMapperValues", + "key": { + "int": 519, + "string": "dataconverterrangemappervalues" + }, + "extends": "data_bind/converters/data_converter_range_mapper.json", + "properties": { + "minInput": { + "type": "double", + "initialValue": "1", + "key": { + "int": 716, + "string": "mininput" + }, + "description": "Min value the input will map from" + }, + "maxInput": { + "type": "double", + "initialValue": "1", + "key": { + "int": 717, + "string": "maxinput" + }, + "description": "Max value the input will map from" + }, + "minOutput": { + "type": "double", + "initialValue": "1", + "key": { + "int": 718, + "string": "minoutput" + }, + "description": "Min value the output will map to" + }, + "maxOutput": { + "type": "double", + "initialValue": "1", + "key": { + "int": 719, + "string": "maxoutput" + }, + "description": "Max value the output will map to" + } + } +} \ No newline at end of file diff --git a/include/rive/animation/cubic_interpolator.hpp b/include/rive/animation/cubic_interpolator.hpp index 4b276210..1737f189 100644 --- a/include/rive/animation/cubic_interpolator.hpp +++ b/include/rive/animation/cubic_interpolator.hpp @@ -9,6 +9,7 @@ class CubicInterpolator : public CubicInterpolatorBase { public: StatusCode onAddedDirty(CoreContext* context) override; + void initialize() override; protected: CubicInterpolatorSolver m_solver; diff --git a/include/rive/animation/data_converter_range_mapper_flags.hpp b/include/rive/animation/data_converter_range_mapper_flags.hpp new file mode 100644 index 00000000..a76da2df --- /dev/null +++ b/include/rive/animation/data_converter_range_mapper_flags.hpp @@ -0,0 +1,27 @@ +#ifndef _RIVE_DATA_CONVERTER_RANGE_MAPPER_FLAGS_HPP_ +#define _RIVE_DATA_CONVERTER_RANGE_MAPPER_FLAGS_HPP_ + +#include "rive/enum_bitset.hpp" + +namespace rive +{ +enum class DataConverterRangeMapperFlags : unsigned short +{ + + /// Whether the lower bound should be clamped + ClampLower = 1 << 0, + + /// Whether the upper bound should be clamped + ClampUpper = 1 << 1, + + /// Whether the value should wrap if it exceeds the range + Modulo = 1 << 2, + + /// Whether to reverse the mapping + Reverse = 1 << 3, + +}; + +RIVE_MAKE_ENUM_BITSET(DataConverterRangeMapperFlags) +} // namespace rive +#endif \ No newline at end of file diff --git a/include/rive/animation/elastic_interpolator.hpp b/include/rive/animation/elastic_interpolator.hpp index 0661f38f..6708d775 100644 --- a/include/rive/animation/elastic_interpolator.hpp +++ b/include/rive/animation/elastic_interpolator.hpp @@ -15,6 +15,7 @@ class ElasticInterpolator : public ElasticInterpolatorBase float transform(float factor) const override; Easing easing() const { return (Easing)easingValue(); } + void initialize() override; private: ElasticEase m_elastic; diff --git a/include/rive/animation/keyframe_interpolator.hpp b/include/rive/animation/keyframe_interpolator.hpp index 3b9b3fc5..af0a7caa 100644 --- a/include/rive/animation/keyframe_interpolator.hpp +++ b/include/rive/animation/keyframe_interpolator.hpp @@ -25,6 +25,8 @@ class KeyFrameInterpolator : public KeyFrameInterpolatorBase virtual float transform(float factor) const = 0; StatusCode import(ImportStack& importStack) override; + + virtual void initialize(){}; }; } // namespace rive diff --git a/include/rive/data_bind/converters/data_converter_group_item.hpp b/include/rive/data_bind/converters/data_converter_group_item.hpp index 0a6202d8..37440913 100644 --- a/include/rive/data_bind/converters/data_converter_group_item.hpp +++ b/include/rive/data_bind/converters/data_converter_group_item.hpp @@ -13,7 +13,7 @@ class DataConverterGroupItem : public DataConverterGroupItemBase void converter(DataConverter* value) { m_dataConverter = value; }; protected: - DataConverter* m_dataConverter; + DataConverter* m_dataConverter = nullptr; }; } // namespace rive diff --git a/include/rive/data_bind/converters/data_converter_range_mapper.hpp b/include/rive/data_bind/converters/data_converter_range_mapper.hpp new file mode 100644 index 00000000..c6ab172f --- /dev/null +++ b/include/rive/data_bind/converters/data_converter_range_mapper.hpp @@ -0,0 +1,31 @@ +#ifndef _RIVE_DATA_CONVERTER_RANGE_MAPPER_HPP_ +#define _RIVE_DATA_CONVERTER_RANGE_MAPPER_HPP_ +#include "rive/generated/data_bind/converters/data_converter_range_mapper_base.hpp" +#include "rive/data_bind/data_values/data_value_number.hpp" +#include "rive/data_bind/data_values/data_value.hpp" +#include "rive/animation/keyframe_interpolator.hpp" +#include +namespace rive +{ +class DataConverterRangeMapper : public DataConverterRangeMapperBase +{ +protected: + KeyFrameInterpolator* m_interpolator; + DataValueNumber* calculateRange(DataValue* input, + float minInput, + float maxInput, + float minOutput, + float maxOutput); + DataValueNumber* calculateReverseRange(DataValue* input, + float minInput, + float maxInput, + float minOutput, + float maxOutput); + +public: + void interpolator(KeyFrameInterpolator* interpolator); + DataType outputType() override { return DataType::number; }; +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/data_bind/converters/data_converter_range_mapper_values.hpp b/include/rive/data_bind/converters/data_converter_range_mapper_values.hpp new file mode 100644 index 00000000..294510ab --- /dev/null +++ b/include/rive/data_bind/converters/data_converter_range_mapper_values.hpp @@ -0,0 +1,15 @@ +#ifndef _RIVE_DATA_CONVERTER_RANGE_MAPPER_VALUES_HPP_ +#define _RIVE_DATA_CONVERTER_RANGE_MAPPER_VALUES_HPP_ +#include "rive/generated/data_bind/converters/data_converter_range_mapper_values_base.hpp" +#include +namespace rive +{ +class DataConverterRangeMapperValues : public DataConverterRangeMapperValuesBase +{ +public: + DataValue* convert(DataValue* value, DataBind* dataBind) override; + DataValue* reverseConvert(DataValue* value, DataBind* dataBind) override; +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp index 531fa73c..203f8576 100644 --- a/include/rive/generated/core_registry.hpp +++ b/include/rive/generated/core_registry.hpp @@ -128,6 +128,8 @@ #include "rive/data_bind/converters/data_converter_operation.hpp" #include "rive/data_bind/converters/data_converter_operation_value.hpp" #include "rive/data_bind/converters/data_converter_operation_viewmodel.hpp" +#include "rive/data_bind/converters/data_converter_range_mapper.hpp" +#include "rive/data_bind/converters/data_converter_range_mapper_values.hpp" #include "rive/data_bind/converters/data_converter_rounder.hpp" #include "rive/data_bind/converters/data_converter_system_degs_to_rads.hpp" #include "rive/data_bind/converters/data_converter_system_normalizer.hpp" @@ -532,6 +534,8 @@ class CoreRegistry return new DataConverterRounder(); case DataConverterTriggerBase::typeKey: return new DataConverterTrigger(); + case DataConverterRangeMapperValuesBase::typeKey: + return new DataConverterRangeMapperValues(); case DataConverterOperationViewModelBase::typeKey: return new DataConverterOperationViewModel(); case DataConverterToStringBase::typeKey: @@ -1195,6 +1199,17 @@ class CoreRegistry case DataConverterOperationBase::operationTypePropertyKey: object->as()->operationType(value); break; + case DataConverterRangeMapperBase::interpolationTypePropertyKey: + object->as()->interpolationType( + value); + break; + case DataConverterRangeMapperBase::interpolatorIdPropertyKey: + object->as()->interpolatorId( + value); + break; + case DataConverterRangeMapperBase::flagsPropertyKey: + object->as()->flags(value); + break; case DataConverterGroupItemBase::converterIdPropertyKey: object->as()->converterId(value); break; @@ -1781,6 +1796,22 @@ class CoreRegistry case DataConverterOperationValueBase::valuePropertyKey: object->as()->value(value); break; + case DataConverterRangeMapperValuesBase::minInputPropertyKey: + object->as()->minInput( + value); + break; + case DataConverterRangeMapperValuesBase::maxInputPropertyKey: + object->as()->maxInput( + value); + break; + case DataConverterRangeMapperValuesBase::minOutputPropertyKey: + object->as()->minOutput( + value); + break; + case DataConverterRangeMapperValuesBase::maxOutputPropertyKey: + object->as()->maxOutput( + value); + break; case BindablePropertyNumberBase::propertyValuePropertyKey: object->as()->propertyValue(value); break; @@ -2368,6 +2399,14 @@ class CoreRegistry case DataConverterOperationBase::operationTypePropertyKey: return object->as() ->operationType(); + case DataConverterRangeMapperBase::interpolationTypePropertyKey: + return object->as() + ->interpolationType(); + case DataConverterRangeMapperBase::interpolatorIdPropertyKey: + return object->as() + ->interpolatorId(); + case DataConverterRangeMapperBase::flagsPropertyKey: + return object->as()->flags(); case DataConverterGroupItemBase::converterIdPropertyKey: return object->as()->converterId(); case DataConverterRounderBase::decimalsPropertyKey: @@ -2779,6 +2818,18 @@ class CoreRegistry return object->as()->height(); case DataConverterOperationValueBase::valuePropertyKey: return object->as()->value(); + case DataConverterRangeMapperValuesBase::minInputPropertyKey: + return object->as() + ->minInput(); + case DataConverterRangeMapperValuesBase::maxInputPropertyKey: + return object->as() + ->maxInput(); + case DataConverterRangeMapperValuesBase::minOutputPropertyKey: + return object->as() + ->minOutput(); + case DataConverterRangeMapperValuesBase::maxOutputPropertyKey: + return object->as() + ->maxOutput(); case BindablePropertyNumberBase::propertyValuePropertyKey: return object->as() ->propertyValue(); @@ -3058,6 +3109,9 @@ class CoreRegistry case DataBindBase::flagsPropertyKey: case DataBindBase::converterIdPropertyKey: case DataConverterOperationBase::operationTypePropertyKey: + case DataConverterRangeMapperBase::interpolationTypePropertyKey: + case DataConverterRangeMapperBase::interpolatorIdPropertyKey: + case DataConverterRangeMapperBase::flagsPropertyKey: case DataConverterGroupItemBase::converterIdPropertyKey: case DataConverterRounderBase::decimalsPropertyKey: case BindablePropertyEnumBase::propertyValuePropertyKey: @@ -3250,6 +3304,10 @@ class CoreRegistry case JoystickBase::widthPropertyKey: case JoystickBase::heightPropertyKey: case DataConverterOperationValueBase::valuePropertyKey: + case DataConverterRangeMapperValuesBase::minInputPropertyKey: + case DataConverterRangeMapperValuesBase::maxInputPropertyKey: + case DataConverterRangeMapperValuesBase::minOutputPropertyKey: + case DataConverterRangeMapperValuesBase::maxOutputPropertyKey: case BindablePropertyNumberBase::propertyValuePropertyKey: case NestedArtboardLeafBase::alignmentXPropertyKey: case NestedArtboardLeafBase::alignmentYPropertyKey: @@ -3680,6 +3738,12 @@ class CoreRegistry return object->is(); case DataConverterOperationBase::operationTypePropertyKey: return object->is(); + case DataConverterRangeMapperBase::interpolationTypePropertyKey: + return object->is(); + case DataConverterRangeMapperBase::interpolatorIdPropertyKey: + return object->is(); + case DataConverterRangeMapperBase::flagsPropertyKey: + return object->is(); case DataConverterGroupItemBase::converterIdPropertyKey: return object->is(); case DataConverterRounderBase::decimalsPropertyKey: @@ -4056,6 +4120,14 @@ class CoreRegistry return object->is(); case DataConverterOperationValueBase::valuePropertyKey: return object->is(); + case DataConverterRangeMapperValuesBase::minInputPropertyKey: + return object->is(); + case DataConverterRangeMapperValuesBase::maxInputPropertyKey: + return object->is(); + case DataConverterRangeMapperValuesBase::minOutputPropertyKey: + return object->is(); + case DataConverterRangeMapperValuesBase::maxOutputPropertyKey: + return object->is(); case BindablePropertyNumberBase::propertyValuePropertyKey: return object->is(); case NestedArtboardLeafBase::alignmentXPropertyKey: diff --git a/include/rive/generated/data_bind/converters/data_converter_range_mapper_base.hpp b/include/rive/generated/data_bind/converters/data_converter_range_mapper_base.hpp new file mode 100644 index 00000000..c4f635d0 --- /dev/null +++ b/include/rive/generated/data_bind/converters/data_converter_range_mapper_base.hpp @@ -0,0 +1,106 @@ +#ifndef _RIVE_DATA_CONVERTER_RANGE_MAPPER_BASE_HPP_ +#define _RIVE_DATA_CONVERTER_RANGE_MAPPER_BASE_HPP_ +#include "rive/core/field_types/core_uint_type.hpp" +#include "rive/data_bind/converters/data_converter.hpp" +namespace rive +{ +class DataConverterRangeMapperBase : public DataConverter +{ +protected: + typedef DataConverter Super; + +public: + static const uint16_t typeKey = 518; + + /// Helper to quickly determine if a core object extends another without + /// RTTI at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case DataConverterRangeMapperBase::typeKey: + case DataConverterBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t interpolationTypePropertyKey = 713; + static const uint16_t interpolatorIdPropertyKey = 714; + static const uint16_t flagsPropertyKey = 715; + +protected: + uint32_t m_InterpolationType = 0; + uint32_t m_InterpolatorId = -1; + uint32_t m_Flags = 0; + +public: + 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(); + } + + inline uint32_t flags() const { return m_Flags; } + void flags(uint32_t value) + { + if (m_Flags == value) + { + return; + } + m_Flags = value; + flagsChanged(); + } + + void copy(const DataConverterRangeMapperBase& object) + { + m_InterpolationType = object.m_InterpolationType; + m_InterpolatorId = object.m_InterpolatorId; + m_Flags = object.m_Flags; + DataConverter::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case interpolationTypePropertyKey: + m_InterpolationType = CoreUintType::deserialize(reader); + return true; + case interpolatorIdPropertyKey: + m_InterpolatorId = CoreUintType::deserialize(reader); + return true; + case flagsPropertyKey: + m_Flags = CoreUintType::deserialize(reader); + return true; + } + return DataConverter::deserialize(propertyKey, reader); + } + +protected: + virtual void interpolationTypeChanged() {} + virtual void interpolatorIdChanged() {} + virtual void flagsChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/generated/data_bind/converters/data_converter_range_mapper_values_base.hpp b/include/rive/generated/data_bind/converters/data_converter_range_mapper_values_base.hpp new file mode 100644 index 00000000..563db604 --- /dev/null +++ b/include/rive/generated/data_bind/converters/data_converter_range_mapper_values_base.hpp @@ -0,0 +1,126 @@ +#ifndef _RIVE_DATA_CONVERTER_RANGE_MAPPER_VALUES_BASE_HPP_ +#define _RIVE_DATA_CONVERTER_RANGE_MAPPER_VALUES_BASE_HPP_ +#include "rive/core/field_types/core_double_type.hpp" +#include "rive/data_bind/converters/data_converter_range_mapper.hpp" +namespace rive +{ +class DataConverterRangeMapperValuesBase : public DataConverterRangeMapper +{ +protected: + typedef DataConverterRangeMapper Super; + +public: + static const uint16_t typeKey = 519; + + /// Helper to quickly determine if a core object extends another without + /// RTTI at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case DataConverterRangeMapperValuesBase::typeKey: + case DataConverterRangeMapperBase::typeKey: + case DataConverterBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t minInputPropertyKey = 716; + static const uint16_t maxInputPropertyKey = 717; + static const uint16_t minOutputPropertyKey = 718; + static const uint16_t maxOutputPropertyKey = 719; + +protected: + float m_MinInput = 1.0f; + float m_MaxInput = 1.0f; + float m_MinOutput = 1.0f; + float m_MaxOutput = 1.0f; + +public: + inline float minInput() const { return m_MinInput; } + void minInput(float value) + { + if (m_MinInput == value) + { + return; + } + m_MinInput = value; + minInputChanged(); + } + + inline float maxInput() const { return m_MaxInput; } + void maxInput(float value) + { + if (m_MaxInput == value) + { + return; + } + m_MaxInput = value; + maxInputChanged(); + } + + inline float minOutput() const { return m_MinOutput; } + void minOutput(float value) + { + if (m_MinOutput == value) + { + return; + } + m_MinOutput = value; + minOutputChanged(); + } + + inline float maxOutput() const { return m_MaxOutput; } + void maxOutput(float value) + { + if (m_MaxOutput == value) + { + return; + } + m_MaxOutput = value; + maxOutputChanged(); + } + + Core* clone() const override; + void copy(const DataConverterRangeMapperValuesBase& object) + { + m_MinInput = object.m_MinInput; + m_MaxInput = object.m_MaxInput; + m_MinOutput = object.m_MinOutput; + m_MaxOutput = object.m_MaxOutput; + DataConverterRangeMapper::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case minInputPropertyKey: + m_MinInput = CoreDoubleType::deserialize(reader); + return true; + case maxInputPropertyKey: + m_MaxInput = CoreDoubleType::deserialize(reader); + return true; + case minOutputPropertyKey: + m_MinOutput = CoreDoubleType::deserialize(reader); + return true; + case maxOutputPropertyKey: + m_MaxOutput = CoreDoubleType::deserialize(reader); + return true; + } + return DataConverterRangeMapper::deserialize(propertyKey, reader); + } + +protected: + virtual void minInputChanged() {} + virtual void maxInputChanged() {} + virtual void minOutputChanged() {} + virtual void maxOutputChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/importers/backboard_importer.hpp b/include/rive/importers/backboard_importer.hpp index 0a676f57..b6142f9f 100644 --- a/include/rive/importers/backboard_importer.hpp +++ b/include/rive/importers/backboard_importer.hpp @@ -2,6 +2,7 @@ #define _RIVE_BACKBOARD_IMPORTER_HPP_ #include "rive/importers/import_stack.hpp" +#include "rive/animation/keyframe_interpolator.hpp" #include #include @@ -26,6 +27,7 @@ class BackboardImporter : public ImportStackObject std::vector m_DataConverters; std::vector m_DataConverterReferencers; std::vector m_DataConverterGroupItemReferencers; + std::vector m_interpolators; int m_NextArtboardId; public: @@ -39,6 +41,7 @@ class BackboardImporter : public ImportStackObject void addDataConverter(DataConverter* converter); void addDataConverterGroupItemReferencer( DataConverterGroupItem* referencer); + void addInterpolator(KeyFrameInterpolator* interpolator); StatusCode resolve() override; const Backboard* backboard() const { return m_Backboard; } diff --git a/src/animation/cubic_interpolator.cpp b/src/animation/cubic_interpolator.cpp index e1e0b3c0..d6e55267 100644 --- a/src/animation/cubic_interpolator.cpp +++ b/src/animation/cubic_interpolator.cpp @@ -6,4 +6,6 @@ StatusCode CubicInterpolator::onAddedDirty(CoreContext* context) { m_solver.build(x1(), x2()); return StatusCode::Ok; -} \ No newline at end of file +} + +void CubicInterpolator::initialize() { m_solver.build(x1(), x2()); } \ No newline at end of file diff --git a/src/animation/elastic_interpolator.cpp b/src/animation/elastic_interpolator.cpp index 208da37e..b953d57f 100644 --- a/src/animation/elastic_interpolator.cpp +++ b/src/animation/elastic_interpolator.cpp @@ -4,9 +4,14 @@ using namespace rive; ElasticInterpolator::ElasticInterpolator() : m_elastic(1.0f, 0.5f) {} -StatusCode ElasticInterpolator::onAddedDirty(CoreContext* context) +void ElasticInterpolator::initialize() { m_elastic = ElasticEase(amplitude(), period() == 0.0f ? 0.5f : period()); +} + +StatusCode ElasticInterpolator::onAddedDirty(CoreContext* context) +{ + initialize(); return StatusCode::Ok; } diff --git a/src/animation/keyframe_interpolator.cpp b/src/animation/keyframe_interpolator.cpp index 9f88f5d0..cc763781 100644 --- a/src/animation/keyframe_interpolator.cpp +++ b/src/animation/keyframe_interpolator.cpp @@ -1,7 +1,9 @@ #include "rive/animation/keyframe_interpolator.hpp" #include "rive/artboard.hpp" +#include "rive/backboard.hpp" #include "rive/core.hpp" #include "rive/importers/artboard_importer.hpp" +#include "rive/importers/backboard_importer.hpp" #include "rive/importers/import_stack.hpp" #include "rive/layout_component.hpp" @@ -23,10 +25,22 @@ StatusCode KeyFrameInterpolator::import(ImportStack& importStack) { auto artboardImporter = importStack.latest(ArtboardBase::typeKey); - if (artboardImporter == nullptr) + if (artboardImporter != nullptr) { - return StatusCode::MissingObject; + artboardImporter->addComponent(this); + } + else + { + auto backboardImporter = + importStack.latest(BackboardBase::typeKey); + if (backboardImporter != nullptr) + { + backboardImporter->addInterpolator(this); + } + else + { + return StatusCode::MissingObject; + } } - artboardImporter->addComponent(this); return Super::import(importStack); } \ No newline at end of file diff --git a/src/data_bind/converters/data_converter_range_mapper.cpp b/src/data_bind/converters/data_converter_range_mapper.cpp new file mode 100644 index 00000000..448356ea --- /dev/null +++ b/src/data_bind/converters/data_converter_range_mapper.cpp @@ -0,0 +1,97 @@ +#include "rive/math/math_types.hpp" +#include "rive/data_bind/converters/data_converter_range_mapper.hpp" +#include "rive/data_bind/data_values/data_value_number.hpp" +#include "rive/animation/data_converter_range_mapper_flags.hpp" + +using namespace rive; + +DataValueNumber* DataConverterRangeMapper::calculateRange(DataValue* input, + float minInput, + float maxInput, + float minOutput, + float maxOutput) +{ + auto output = new DataValueNumber(); + if (input->is()) + { + if (minOutput == maxOutput) + { + output->value(minOutput); + } + else + { + auto flagsValue = + static_cast(flags()); + float value = input->as()->value(); + + // Clamp value to min input if flag is on + if (value < minInput && + (flagsValue & DataConverterRangeMapperFlags::ClampLower) == + DataConverterRangeMapperFlags::ClampLower) + { + value = minInput; + } + // Clamp value to max input if flag is on + else if (value > maxInput && + (flagsValue & DataConverterRangeMapperFlags::ClampUpper) == + DataConverterRangeMapperFlags::ClampUpper) + { + value = maxInput; + } + if ((value < minInput || value > maxInput) && + (flagsValue & DataConverterRangeMapperFlags::Modulo) == + DataConverterRangeMapperFlags::Modulo) + { + // apply modulo to value to wrap whithin the min - max input if + // it exceeds its range + value = + std::abs(fmodf(value, (maxInput - minInput)) + minInput); + } + if (value < minInput) + { + output->value(minOutput); + } + else if (value > maxInput) + { + output->value(maxOutput); + } + else + { + float perc = (value - minInput) / (maxInput - minInput); + // If reverse flag is on, flip the values + if ((flagsValue & DataConverterRangeMapperFlags::Reverse) == + DataConverterRangeMapperFlags::Reverse) + { + perc = 1 - perc; + } + // hold keyframe interpolation + else if (interpolationType() == 0) + { + perc = perc <= 0 ? 0 : 1; + } + // Apply interpolator if exists + if (m_interpolator != nullptr) + { + perc = m_interpolator->transform(perc); + } + output->value(perc * maxOutput + (1 - perc) * minOutput); + } + } + } + return output; +} + +DataValueNumber* DataConverterRangeMapper::calculateReverseRange( + DataValue* input, + float minInput, + float maxInput, + float minOutput, + float maxOutnput) +{ + return calculateRange(input, minOutput, maxOutnput, minInput, maxInput); +} + +void DataConverterRangeMapper::interpolator(KeyFrameInterpolator* interpolator) +{ + m_interpolator = interpolator; +} \ No newline at end of file diff --git a/src/data_bind/converters/data_converter_range_mapper_values.cpp b/src/data_bind/converters/data_converter_range_mapper_values.cpp new file mode 100644 index 00000000..95113f9b --- /dev/null +++ b/src/data_bind/converters/data_converter_range_mapper_values.cpp @@ -0,0 +1,26 @@ +#include "rive/math/math_types.hpp" +#include "rive/data_bind/converters/data_converter_range_mapper_values.hpp" +#include "rive/data_bind/data_values/data_value_number.hpp" +#include "rive/animation/data_converter_range_mapper_flags.hpp" + +using namespace rive; + +DataValue* DataConverterRangeMapperValues::convert(DataValue* input, + DataBind* dataBind) +{ + return calculateRange(input, + minInput(), + maxInput(), + minOutput(), + maxOutput()); +} + +DataValue* DataConverterRangeMapperValues::reverseConvert(DataValue* input, + DataBind* dataBind) +{ + return calculateReverseRange(input, + minInput(), + maxInput(), + minOutput(), + maxOutput()); +} \ No newline at end of file diff --git a/src/data_bind/converters/data_converter_system_degs_to_rads.cpp b/src/data_bind/converters/data_converter_system_degs_to_rads.cpp index fda83d8f..707f03ea 100644 --- a/src/data_bind/converters/data_converter_system_degs_to_rads.cpp +++ b/src/data_bind/converters/data_converter_system_degs_to_rads.cpp @@ -11,9 +11,9 @@ DataValue* DataConverterSystemDegsToRads::convert(DataValue* input, auto flagsValue = static_cast(dataBind->flags()); if (((flagsValue & DataBindFlags::Direction) == DataBindFlags::ToSource)) { - return DataConverterOperation::reverseConvert(input, dataBind); + return DataConverterOperationValue::reverseConvert(input, dataBind); } - return DataConverterOperation::convert(input, dataBind); + return DataConverterOperationValue::convert(input, dataBind); } DataValue* DataConverterSystemDegsToRads::reverseConvert(DataValue* input, @@ -22,7 +22,7 @@ DataValue* DataConverterSystemDegsToRads::reverseConvert(DataValue* input, auto flagsValue = static_cast(dataBind->flags()); if (((flagsValue & DataBindFlags::Direction) == DataBindFlags::ToTarget)) { - return DataConverterOperation::convert(input, dataBind); + return DataConverterOperationValue::convert(input, dataBind); } - return DataConverterOperation::reverseConvert(input, dataBind); + return DataConverterOperationValue::reverseConvert(input, dataBind); } \ No newline at end of file diff --git a/src/data_bind/converters/data_converter_system_normalizer.cpp b/src/data_bind/converters/data_converter_system_normalizer.cpp index b3a37288..851dfc7d 100644 --- a/src/data_bind/converters/data_converter_system_normalizer.cpp +++ b/src/data_bind/converters/data_converter_system_normalizer.cpp @@ -10,9 +10,9 @@ DataValue* DataConverterSystemNormalizer::convert(DataValue* input, auto flagsValue = static_cast(dataBind->flags()); if (((flagsValue & DataBindFlags::Direction) == DataBindFlags::ToSource)) { - return DataConverterOperation::reverseConvert(input, dataBind); + return DataConverterOperationValue::reverseConvert(input, dataBind); } - return DataConverterOperation::convert(input, dataBind); + return DataConverterOperationValue::convert(input, dataBind); } DataValue* DataConverterSystemNormalizer::reverseConvert(DataValue* input, @@ -21,7 +21,7 @@ DataValue* DataConverterSystemNormalizer::reverseConvert(DataValue* input, auto flagsValue = static_cast(dataBind->flags()); if (((flagsValue & DataBindFlags::Direction) == DataBindFlags::ToTarget)) { - return DataConverterOperation::convert(input, dataBind); + return DataConverterOperationValue::convert(input, dataBind); } - return DataConverterOperation::reverseConvert(input, dataBind); + return DataConverterOperationValue::reverseConvert(input, dataBind); } \ No newline at end of file diff --git a/src/generated/data_bind/converters/data_converter_range_mapper_values_base.cpp b/src/generated/data_bind/converters/data_converter_range_mapper_values_base.cpp new file mode 100644 index 00000000..3b7befaa --- /dev/null +++ b/src/generated/data_bind/converters/data_converter_range_mapper_values_base.cpp @@ -0,0 +1,11 @@ +#include "rive/generated/data_bind/converters/data_converter_range_mapper_values_base.hpp" +#include "rive/data_bind/converters/data_converter_range_mapper_values.hpp" + +using namespace rive; + +Core* DataConverterRangeMapperValuesBase::clone() const +{ + auto cloned = new DataConverterRangeMapperValues(); + cloned->copy(*this); + return cloned; +} diff --git a/src/importers/backboard_importer.cpp b/src/importers/backboard_importer.cpp index 83630e6a..631dfd02 100644 --- a/src/importers/backboard_importer.cpp +++ b/src/importers/backboard_importer.cpp @@ -9,6 +9,7 @@ #include "rive/viewmodel/viewmodel_instance.hpp" #include "rive/data_bind/converters/data_converter.hpp" #include "rive/data_bind/converters/data_converter_group_item.hpp" +#include "rive/data_bind/converters/data_converter_range_mapper.hpp" #include "rive/data_bind/data_bind.hpp" #include @@ -106,6 +107,19 @@ StatusCode BackboardImporter::resolve() } referencer->converter(m_DataConverters[index]); } + for (auto converter : m_DataConverters) + { + if (converter->is()) + { + size_t converterId = + converter->as()->interpolatorId(); + if (converterId != -1 && converterId < m_interpolators.size()) + { + converter->as()->interpolator( + m_interpolators[converterId]); + } + } + } return StatusCode::Ok; } @@ -123,4 +137,12 @@ void BackboardImporter::addDataConverterGroupItemReferencer( DataConverterGroupItem* dataBind) { m_DataConverterGroupItemReferencers.push_back(dataBind); +} + +void BackboardImporter::addInterpolator(KeyFrameInterpolator* interpolator) +{ + // Since these interpolators do not belong to an artboard, we have to + // initialize them + interpolator->initialize(); + m_interpolators.push_back(interpolator); } \ No newline at end of file