From 9e26b7620e0f0c8494818f74df4fe31ba264be3b Mon Sep 17 00:00:00 2001 From: bodymovin Date: Fri, 9 Aug 2024 22:23:15 +0000 Subject: [PATCH] add two data converters this PR adds the UI to create converters in the editor, and includes the first two: - a rounder that accepts a property for rounding - a toString converter that can convert for now numbers and enum. It could be extended to colors and booleans in the future. https://github.com/user-attachments/assets/2946d8ea-0fdf-4039-83d4-79b5fdfc6169 https://github.com/user-attachments/assets/ec60b523-ecb2-4453-9280-c99822706b2e Diffs= 2c0927fc5 add two data converters (#7742) Co-authored-by: hernan --- .rive_head | 2 +- .../converters/data_converter_rounder.json | 20 ++++++ .../converters/data_converter_to_string.json | 8 +++ dev/defs/node.json | 6 +- .../converters/data_converter_rounder.hpp | 16 +++++ .../converters/data_converter_to_string.hpp | 15 ++++ include/rive/generated/core_registry.hpp | 14 ++++ .../data_converter_rounder_base.hpp | 71 +++++++++++++++++++ .../data_converter_to_string_base.hpp | 36 ++++++++++ .../converters/data_converter_rounder.cpp | 19 +++++ .../converters/data_converter_to_string.cpp | 36 ++++++++++ .../data_converter_rounder_base.cpp | 11 +++ .../data_converter_to_string_base.cpp | 11 +++ 13 files changed, 262 insertions(+), 3 deletions(-) create mode 100644 dev/defs/data_bind/converters/data_converter_rounder.json create mode 100644 dev/defs/data_bind/converters/data_converter_to_string.json create mode 100644 include/rive/data_bind/converters/data_converter_rounder.hpp create mode 100644 include/rive/data_bind/converters/data_converter_to_string.hpp create mode 100644 include/rive/generated/data_bind/converters/data_converter_rounder_base.hpp create mode 100644 include/rive/generated/data_bind/converters/data_converter_to_string_base.hpp create mode 100644 src/data_bind/converters/data_converter_rounder.cpp create mode 100644 src/data_bind/converters/data_converter_to_string.cpp create mode 100644 src/generated/data_bind/converters/data_converter_rounder_base.cpp create mode 100644 src/generated/data_bind/converters/data_converter_to_string_base.cpp diff --git a/.rive_head b/.rive_head index 16f26cbd..c15f5b7f 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -8c7ac03294339ae2ad856b541c730dc16cec018d +2c0927fc5e9a5c420305a81446ac41eb5b896b2c diff --git a/dev/defs/data_bind/converters/data_converter_rounder.json b/dev/defs/data_bind/converters/data_converter_rounder.json new file mode 100644 index 00000000..30dfbfd1 --- /dev/null +++ b/dev/defs/data_bind/converters/data_converter_rounder.json @@ -0,0 +1,20 @@ +{ + "name": "DataConverterRounder", + "key": { + "int": 489, + "string": "dataconverterrounder" + }, + "extends": "data_bind/converters/data_converter.json", + "properties": { + "decimals": { + "type": "uint", + "typeRuntime": "uint", + "initialValue": "0", + "key": { + "int": 669, + "string": "decimals" + }, + "description": "Number of decimals to round to" + } + } +} \ No newline at end of file diff --git a/dev/defs/data_bind/converters/data_converter_to_string.json b/dev/defs/data_bind/converters/data_converter_to_string.json new file mode 100644 index 00000000..5584ce4e --- /dev/null +++ b/dev/defs/data_bind/converters/data_converter_to_string.json @@ -0,0 +1,8 @@ +{ + "name": "DataConverterToString", + "key": { + "int": 490, + "string": "dataconvertertostring" + }, + "extends": "data_bind/converters/data_converter.json" +} \ No newline at end of file diff --git a/dev/defs/node.json b/dev/defs/node.json index 90ff1820..36a1ea32 100644 --- a/dev/defs/node.json +++ b/dev/defs/node.json @@ -21,7 +21,8 @@ "string": "xArtboard" } ] - } + }, + "bindable": true }, "y": { "type": "double", @@ -38,7 +39,8 @@ "string": "yArtboard" } ] - } + }, + "bindable": true }, "styleValue": { "type": "uint", diff --git a/include/rive/data_bind/converters/data_converter_rounder.hpp b/include/rive/data_bind/converters/data_converter_rounder.hpp new file mode 100644 index 00000000..063d38c5 --- /dev/null +++ b/include/rive/data_bind/converters/data_converter_rounder.hpp @@ -0,0 +1,16 @@ +#ifndef _RIVE_DATA_CONVERTER_ROUND_HPP_ +#define _RIVE_DATA_CONVERTER_ROUND_HPP_ +#include "rive/generated/data_bind/converters/data_converter_rounder_base.hpp" +#include "rive/data_bind/data_values/data_value.hpp" +#include +namespace rive +{ +class DataConverterRounder : public DataConverterRounderBase +{ +public: + DataValue* convert(DataValue* value) override; + 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_to_string.hpp b/include/rive/data_bind/converters/data_converter_to_string.hpp new file mode 100644 index 00000000..0757e60f --- /dev/null +++ b/include/rive/data_bind/converters/data_converter_to_string.hpp @@ -0,0 +1,15 @@ +#ifndef _RIVE_DATA_CONVERTER_TO_STRING_HPP_ +#define _RIVE_DATA_CONVERTER_TO_STRING_HPP_ +#include "rive/generated/data_bind/converters/data_converter_to_string_base.hpp" +#include +namespace rive +{ +class DataConverterToString : public DataConverterToStringBase +{ +public: + DataValue* convert(DataValue* value) override; + DataType outputType() override { return DataType::string; }; +}; +} // 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 3d23e26e..d38b4517 100644 --- a/include/rive/generated/core_registry.hpp +++ b/include/rive/generated/core_registry.hpp @@ -119,6 +119,8 @@ #include "rive/data_bind/bindable_property_number.hpp" #include "rive/data_bind/bindable_property_string.hpp" #include "rive/data_bind/converters/data_converter.hpp" +#include "rive/data_bind/converters/data_converter_rounder.hpp" +#include "rive/data_bind/converters/data_converter_to_string.hpp" #include "rive/data_bind/data_bind.hpp" #include "rive/data_bind/data_bind_context.hpp" #include "rive/draw_rules.hpp" @@ -451,6 +453,10 @@ class CoreRegistry return new BindablePropertyBoolean(); case DataBindBase::typeKey: return new DataBind(); + case DataConverterRounderBase::typeKey: + return new DataConverterRounder(); + case DataConverterToStringBase::typeKey: + return new DataConverterToString(); case DataBindContextBase::typeKey: return new DataBindContext(); case BindablePropertyStringBase::typeKey: @@ -1010,6 +1016,9 @@ class CoreRegistry case DataBindBase::converterIdPropertyKey: object->as()->converterId(value); break; + case DataConverterRounderBase::decimalsPropertyKey: + object->as()->decimals(value); + break; case BindablePropertyEnumBase::propertyValuePropertyKey: object->as()->propertyValue(value); break; @@ -2034,6 +2043,8 @@ class CoreRegistry return object->as()->flags(); case DataBindBase::converterIdPropertyKey: return object->as()->converterId(); + case DataConverterRounderBase::decimalsPropertyKey: + return object->as()->decimals(); case BindablePropertyEnumBase::propertyValuePropertyKey: return object->as()->propertyValue(); case NestedArtboardLeafBase::fitPropertyKey: @@ -2663,6 +2674,7 @@ class CoreRegistry case DataBindBase::propertyKeyPropertyKey: case DataBindBase::flagsPropertyKey: case DataBindBase::converterIdPropertyKey: + case DataConverterRounderBase::decimalsPropertyKey: case BindablePropertyEnumBase::propertyValuePropertyKey: case NestedArtboardLeafBase::fitPropertyKey: case WeightBase::valuesPropertyKey: @@ -3239,6 +3251,8 @@ class CoreRegistry return object->is(); case DataBindBase::converterIdPropertyKey: return object->is(); + case DataConverterRounderBase::decimalsPropertyKey: + return object->is(); case BindablePropertyEnumBase::propertyValuePropertyKey: return object->is(); case NestedArtboardLeafBase::fitPropertyKey: diff --git a/include/rive/generated/data_bind/converters/data_converter_rounder_base.hpp b/include/rive/generated/data_bind/converters/data_converter_rounder_base.hpp new file mode 100644 index 00000000..b1098fbd --- /dev/null +++ b/include/rive/generated/data_bind/converters/data_converter_rounder_base.hpp @@ -0,0 +1,71 @@ +#ifndef _RIVE_DATA_CONVERTER_ROUNDER_BASE_HPP_ +#define _RIVE_DATA_CONVERTER_ROUNDER_BASE_HPP_ +#include "rive/core/field_types/core_uint_type.hpp" +#include "rive/data_bind/converters/data_converter.hpp" +namespace rive +{ +class DataConverterRounderBase : public DataConverter +{ +protected: + typedef DataConverter Super; + +public: + static const uint16_t typeKey = 489; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case DataConverterRounderBase::typeKey: + case DataConverterBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t decimalsPropertyKey = 669; + +private: + uint32_t m_Decimals = 0; + +public: + inline uint32_t decimals() const { return m_Decimals; } + void decimals(uint32_t value) + { + if (m_Decimals == value) + { + return; + } + m_Decimals = value; + decimalsChanged(); + } + + Core* clone() const override; + void copy(const DataConverterRounderBase& object) + { + m_Decimals = object.m_Decimals; + DataConverter::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case decimalsPropertyKey: + m_Decimals = CoreUintType::deserialize(reader); + return true; + } + return DataConverter::deserialize(propertyKey, reader); + } + +protected: + virtual void decimalsChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/include/rive/generated/data_bind/converters/data_converter_to_string_base.hpp b/include/rive/generated/data_bind/converters/data_converter_to_string_base.hpp new file mode 100644 index 00000000..c919cbad --- /dev/null +++ b/include/rive/generated/data_bind/converters/data_converter_to_string_base.hpp @@ -0,0 +1,36 @@ +#ifndef _RIVE_DATA_CONVERTER_TO_STRING_BASE_HPP_ +#define _RIVE_DATA_CONVERTER_TO_STRING_BASE_HPP_ +#include "rive/data_bind/converters/data_converter.hpp" +namespace rive +{ +class DataConverterToStringBase : public DataConverter +{ +protected: + typedef DataConverter Super; + +public: + static const uint16_t typeKey = 490; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case DataConverterToStringBase::typeKey: + case DataConverterBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + Core* clone() const override; + +protected: +}; +} // namespace rive + +#endif \ No newline at end of file diff --git a/src/data_bind/converters/data_converter_rounder.cpp b/src/data_bind/converters/data_converter_rounder.cpp new file mode 100644 index 00000000..86422ff4 --- /dev/null +++ b/src/data_bind/converters/data_converter_rounder.cpp @@ -0,0 +1,19 @@ +#include "rive/math/math_types.hpp" +#include "rive/data_bind/converters/data_converter_rounder.hpp" +#include "rive/data_bind/data_values/data_value_number.hpp" + +using namespace rive; + +DataValue* DataConverterRounder::convert(DataValue* input) +{ + auto output = new DataValueNumber(); + if (input->is()) + { + float value = input->as()->value(); + auto numberOfPlaces = decimals(); + // TODO: @hernan review this way of rounding + float rounder = pow(10.0f, (float)numberOfPlaces); + output->value(std::round(value * rounder) / rounder); + } + return output; +} \ No newline at end of file diff --git a/src/data_bind/converters/data_converter_to_string.cpp b/src/data_bind/converters/data_converter_to_string.cpp new file mode 100644 index 00000000..6c62f38a --- /dev/null +++ b/src/data_bind/converters/data_converter_to_string.cpp @@ -0,0 +1,36 @@ +#include "rive/math/math_types.hpp" +#include "rive/data_bind/converters/data_converter_to_string.hpp" +#include "rive/data_bind/data_values/data_value_number.hpp" +#include "rive/data_bind/data_values/data_value_enum.hpp" +#include "rive/data_bind/data_values/data_value_string.hpp" + +using namespace rive; + +DataValue* DataConverterToString::convert(DataValue* input) +{ + auto output = new DataValueString(); + if (input->is()) + { + float value = input->as()->value(); + std::string str = std::to_string(value); + if (str.find('.') != std::string::npos) + { + // Remove trailing zeroes + str = str.substr(0, str.find_last_not_of('0') + 1); + // If the decimal point is now the last character, remove that as well + if (str.find('.') == str.size() - 1) + { + str = str.substr(0, str.size() - 1); + } + } + output->value(str); + } + else if (input->is()) + { + auto dataEnum = input->as()->dataEnum(); + auto index = input->as()->value(); + auto enumValue = dataEnum->value(index); + output->value(enumValue); + } + return output; +} \ No newline at end of file diff --git a/src/generated/data_bind/converters/data_converter_rounder_base.cpp b/src/generated/data_bind/converters/data_converter_rounder_base.cpp new file mode 100644 index 00000000..e6a03a31 --- /dev/null +++ b/src/generated/data_bind/converters/data_converter_rounder_base.cpp @@ -0,0 +1,11 @@ +#include "rive/generated/data_bind/converters/data_converter_rounder_base.hpp" +#include "rive/data_bind/converters/data_converter_rounder.hpp" + +using namespace rive; + +Core* DataConverterRounderBase::clone() const +{ + auto cloned = new DataConverterRounder(); + cloned->copy(*this); + return cloned; +} diff --git a/src/generated/data_bind/converters/data_converter_to_string_base.cpp b/src/generated/data_bind/converters/data_converter_to_string_base.cpp new file mode 100644 index 00000000..c600a8d8 --- /dev/null +++ b/src/generated/data_bind/converters/data_converter_to_string_base.cpp @@ -0,0 +1,11 @@ +#include "rive/generated/data_bind/converters/data_converter_to_string_base.hpp" +#include "rive/data_bind/converters/data_converter_to_string.hpp" + +using namespace rive; + +Core* DataConverterToStringBase::clone() const +{ + auto cloned = new DataConverterToString(); + cloned->copy(*this); + return cloned; +}