add data converter and data types for conversion
First PR for converters support.
It adds the abstract data_converter class
And adds new data value objects that can be passed between converters to easily transform one type of data to another
https://github.com/user-attachments/assets/e8a0fdee-8845-4d0d-a894-c948c2b0a209
Diffs=
4bf7c7545 add data converter and data types for conversion (#7734)
Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head
index a891ec7..b080470 100644
--- a/.rive_head
+++ b/.rive_head
@@ -1 +1 @@
-d9f5701ec10c0d0eecb0e3d2f5b0ee80499c746d
+4bf7c75453f0fc3fec1519a9a3dfe7a4ed63a054
diff --git a/dev/defs/data_bind/converters/data_converter.json b/dev/defs/data_bind/converters/data_converter.json
new file mode 100644
index 0000000..b5a0c49
--- /dev/null
+++ b/dev/defs/data_bind/converters/data_converter.json
@@ -0,0 +1,30 @@
+{
+ "name": "DataConverter",
+ "key": {
+ "int": 488,
+ "string": "dataconverter"
+ },
+ "abstract": true,
+ "properties": {
+ "order": {
+ "type": "FractionalIndex",
+ "initialValue": "FractionalIndex.invalid",
+ "initialValueRuntime": "0",
+ "key": {
+ "int": 661,
+ "string": "order"
+ },
+ "description": "Order value for sorting data converters",
+ "runtime": false
+ },
+ "name": {
+ "type": "String",
+ "initialValue": "''",
+ "key": {
+ "int": 662,
+ "string": "name"
+ },
+ "description": "Non-unique identifier, used to give friendly names to data converters."
+ }
+ }
+}
\ No newline at end of file
diff --git a/dev/defs/data_bind/data_bind.json b/dev/defs/data_bind/data_bind.json
index 3e3124d..3ec525b 100644
--- a/dev/defs/data_bind/data_bind.json
+++ b/dev/defs/data_bind/data_bind.json
@@ -31,6 +31,17 @@
"int": 587,
"string": "flags"
}
+ },
+ "converterId": {
+ "type": "Id",
+ "typeRuntime": "uint",
+ "initialValue": "Core.missingId",
+ "initialValueRuntime": "-1",
+ "key": {
+ "int": 660,
+ "string": "converterid"
+ },
+ "description": "Identifier used to link to a data converter."
}
}
}
\ No newline at end of file
diff --git a/include/rive/artboard.hpp b/include/rive/artboard.hpp
index 2e78c7e..e3cf802 100644
--- a/include/rive/artboard.hpp
+++ b/include/rive/artboard.hpp
@@ -295,6 +295,7 @@
{
auto dataBindClone = static_cast<DataBind*>(dataBind->clone());
dataBindClone->target(cloneObjects.back());
+ dataBindClone->converter(dataBind->converter());
artboardClone->m_DataBinds.push_back(dataBindClone);
}
}
diff --git a/include/rive/data_bind/context/context_value.hpp b/include/rive/data_bind/context/context_value.hpp
index 370f46f..c26730b 100644
--- a/include/rive/data_bind/context/context_value.hpp
+++ b/include/rive/data_bind/context/context_value.hpp
@@ -1,21 +1,48 @@
#ifndef _RIVE_DATA_BIND_CONTEXT_VALUE_HPP_
#define _RIVE_DATA_BIND_CONTEXT_VALUE_HPP_
-#include "rive/refcnt.hpp"
#include "rive/viewmodel/viewmodel_instance_value.hpp"
+#include "rive/data_bind/converters/data_converter.hpp"
#include <stdio.h>
namespace rive
{
class DataBindContextValue
{
protected:
- ViewModelInstanceValue* m_Source;
+ ViewModelInstanceValue* m_source;
+ DataConverter* m_converter;
+ DataValue* m_dataValue;
public:
- DataBindContextValue(){};
+ DataBindContextValue(ViewModelInstanceValue* source, DataConverter* converter);
virtual ~DataBindContextValue(){};
- virtual void applyToSource(Core* component, uint32_t propertyKey){};
- virtual void apply(Core* component, uint32_t propertyKey){};
+ virtual void applyToSource(Core* component, uint32_t propertyKey, bool isMainDirection);
+ virtual void apply(Core* component, uint32_t propertyKey, bool isMainDirection){};
virtual void update(Core* component){};
+ virtual DataValue* getTargetValue(Core* target, uint32_t propertyKey) { return nullptr; };
+ void updateSourceValue();
+ template <typename T = DataValue, typename U> U getDataValue(DataValue* input)
+ {
+ auto dataValue = m_converter != nullptr ? m_converter->convert(input) : input;
+ if (dataValue->is<T>())
+ {
+ return dataValue->as<T>()->value();
+ }
+ return (new T())->value();
+ };
+ template <typename T = DataValue, typename U> U getReverseDataValue(DataValue* input)
+ {
+ auto dataValue = m_converter != nullptr ? m_converter->reverseConvert(input) : input;
+ if (dataValue->is<T>())
+ {
+ return dataValue->as<T>()->value();
+ }
+ return (new T())->value();
+ };
+ template <typename T = DataValue, typename U>
+ U calculateValue(DataValue* input, bool isMainDirection)
+ {
+ return isMainDirection ? getDataValue<T, U>(input) : getReverseDataValue<T, U>(input);
+ };
};
} // namespace rive
diff --git a/include/rive/data_bind/context/context_value_boolean.hpp b/include/rive/data_bind/context/context_value_boolean.hpp
index 82e9a7f..678e7fc 100644
--- a/include/rive/data_bind/context/context_value_boolean.hpp
+++ b/include/rive/data_bind/context/context_value_boolean.hpp
@@ -7,12 +7,9 @@
{
public:
- DataBindContextValueBoolean(ViewModelInstanceValue* value);
- void apply(Core* component, uint32_t propertyKey) override;
- virtual void applyToSource(Core* component, uint32_t propertyKey) override;
-
-private:
- bool m_Value;
+ DataBindContextValueBoolean(ViewModelInstanceValue* source, DataConverter* converter);
+ void apply(Core* component, uint32_t propertyKey, bool isMainDirection) override;
+ DataValue* getTargetValue(Core* target, uint32_t propertyKey) override;
};
} // namespace rive
diff --git a/include/rive/data_bind/context/context_value_color.hpp b/include/rive/data_bind/context/context_value_color.hpp
index 22fe8f8..207062a 100644
--- a/include/rive/data_bind/context/context_value_color.hpp
+++ b/include/rive/data_bind/context/context_value_color.hpp
@@ -7,12 +7,9 @@
{
public:
- DataBindContextValueColor(ViewModelInstanceValue* value);
- void apply(Core* component, uint32_t propertyKey) override;
- virtual void applyToSource(Core* component, uint32_t propertyKey) override;
-
-private:
- double m_Value;
+ DataBindContextValueColor(ViewModelInstanceValue* source, DataConverter* converter);
+ void apply(Core* component, uint32_t propertyKey, bool isMainDirection) override;
+ DataValue* getTargetValue(Core* target, uint32_t propertyKey) override;
};
} // namespace rive
diff --git a/include/rive/data_bind/context/context_value_enum.hpp b/include/rive/data_bind/context/context_value_enum.hpp
index 98c21c4..dd097b2 100644
--- a/include/rive/data_bind/context/context_value_enum.hpp
+++ b/include/rive/data_bind/context/context_value_enum.hpp
@@ -7,12 +7,9 @@
{
public:
- DataBindContextValueEnum(ViewModelInstanceValue* value);
- void apply(Core* component, uint32_t propertyKey) override;
- virtual void applyToSource(Core* component, uint32_t propertyKey) override;
-
-private:
- int m_Value;
+ DataBindContextValueEnum(ViewModelInstanceValue* source, DataConverter* converter);
+ void apply(Core* component, uint32_t propertyKey, bool isMainDirection) override;
+ DataValue* getTargetValue(Core* target, uint32_t propertyKey) override;
};
} // namespace rive
diff --git a/include/rive/data_bind/context/context_value_list.hpp b/include/rive/data_bind/context/context_value_list.hpp
index 0c12f91..5dd9586 100644
--- a/include/rive/data_bind/context/context_value_list.hpp
+++ b/include/rive/data_bind/context/context_value_list.hpp
@@ -11,10 +11,12 @@
{
public:
- DataBindContextValueList(ViewModelInstanceValue* value);
- void apply(Core* component, uint32_t propertyKey) override;
+ DataBindContextValueList(ViewModelInstanceValue* source, DataConverter* converter);
+ void apply(Core* component, uint32_t propertyKey, bool isMainDirection) override;
void update(Core* target) override;
- virtual void applyToSource(Core* component, uint32_t propertyKey) override;
+ virtual void applyToSource(Core* component,
+ uint32_t propertyKey,
+ bool isMainDirection) override;
private:
std::vector<std::unique_ptr<DataBindContextValueListItem>> m_ListItemsCache;
diff --git a/include/rive/data_bind/context/context_value_number.hpp b/include/rive/data_bind/context/context_value_number.hpp
index b2d850a..f3a56fa 100644
--- a/include/rive/data_bind/context/context_value_number.hpp
+++ b/include/rive/data_bind/context/context_value_number.hpp
@@ -7,12 +7,9 @@
{
public:
- DataBindContextValueNumber(ViewModelInstanceValue* value);
- void apply(Core* component, uint32_t propertyKey) override;
- virtual void applyToSource(Core* component, uint32_t propertyKey) override;
-
-private:
- double m_Value;
+ DataBindContextValueNumber(ViewModelInstanceValue* source, DataConverter* converter);
+ void apply(Core* component, uint32_t propertyKey, bool isMainDirection) override;
+ DataValue* getTargetValue(Core* target, uint32_t propertyKey) override;
};
} // namespace rive
diff --git a/include/rive/data_bind/context/context_value_string.hpp b/include/rive/data_bind/context/context_value_string.hpp
index 0b32528..fb8f3cf 100644
--- a/include/rive/data_bind/context/context_value_string.hpp
+++ b/include/rive/data_bind/context/context_value_string.hpp
@@ -7,12 +7,9 @@
{
public:
- DataBindContextValueString(ViewModelInstanceValue* value);
- void apply(Core* component, uint32_t propertyKey) override;
- virtual void applyToSource(Core* component, uint32_t propertyKey) override;
-
-private:
- std::string m_Value;
+ DataBindContextValueString(ViewModelInstanceValue* source, DataConverter* converter);
+ void apply(Core* component, uint32_t propertyKey, bool isMainDirection) override;
+ DataValue* getTargetValue(Core* target, uint32_t propertyKey) override;
};
} // namespace rive
diff --git a/include/rive/data_bind/converters/data_converter.hpp b/include/rive/data_bind/converters/data_converter.hpp
new file mode 100644
index 0000000..bf6deb6
--- /dev/null
+++ b/include/rive/data_bind/converters/data_converter.hpp
@@ -0,0 +1,18 @@
+#ifndef _RIVE_DATA_CONVERTER_HPP_
+#define _RIVE_DATA_CONVERTER_HPP_
+#include "rive/generated/data_bind/converters/data_converter_base.hpp"
+#include "rive/data_bind/data_values/data_value.hpp"
+#include <stdio.h>
+namespace rive
+{
+class DataConverter : public DataConverterBase
+{
+public:
+ virtual DataValue* convert(DataValue* value) { return value; };
+ virtual DataValue* reverseConvert(DataValue* value) { return value; };
+ virtual DataType outputType() { return DataType::none; };
+ StatusCode import(ImportStack& importStack) override;
+};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/data_bind/data_bind.hpp b/include/rive/data_bind/data_bind.hpp
index 0ccccb3..a62cfd6 100644
--- a/include/rive/data_bind/data_bind.hpp
+++ b/include/rive/data_bind/data_bind.hpp
@@ -5,6 +5,8 @@
#include "rive/viewmodel/viewmodel_instance_value.hpp"
#include "rive/data_bind/context/context_value.hpp"
#include "rive/data_bind/data_context.hpp"
+#include "rive/data_bind/converters/data_converter.hpp"
+#include "rive/data_bind/data_values/data_type.hpp"
#include <stdio.h>
namespace rive
{
@@ -21,12 +23,16 @@
ComponentDirt dirt() { return m_Dirt; };
void dirt(ComponentDirt value) { m_Dirt = value; };
bool addDirt(ComponentDirt value, bool recurse);
+ DataConverter* converter() const { return m_dataConverter; };
+ void converter(DataConverter* value) { m_dataConverter = value; };
protected:
ComponentDirt m_Dirt = ComponentDirt::Filthy;
Core* m_target;
ViewModelInstanceValue* m_Source;
std::unique_ptr<DataBindContextValue> m_ContextValue;
+ DataConverter* m_dataConverter;
+ DataType outputType();
};
} // namespace rive
diff --git a/include/rive/data_bind/data_values/data_type.hpp b/include/rive/data_bind/data_values/data_type.hpp
new file mode 100644
index 0000000..c1740b5
--- /dev/null
+++ b/include/rive/data_bind/data_values/data_type.hpp
@@ -0,0 +1,30 @@
+#ifndef _RIVE_DATA_TYPE_HPP_
+#define _RIVE_DATA_TYPE_HPP_
+namespace rive
+{
+/// Data types used for converters.
+enum class DataType : unsigned int
+{
+ /// None.
+ none = 0,
+
+ /// String.
+ string = 1,
+
+ /// Number.
+ number = 2,
+
+ /// Bool.
+ boolean = 3,
+
+ /// Color.
+ color = 4,
+
+ /// List.
+ list = 5,
+
+ /// Enum.
+ enumType = 6
+};
+} // namespace rive
+#endif
\ No newline at end of file
diff --git a/include/rive/data_bind/data_values/data_value.hpp b/include/rive/data_bind/data_values/data_value.hpp
new file mode 100644
index 0000000..e412183
--- /dev/null
+++ b/include/rive/data_bind/data_values/data_value.hpp
@@ -0,0 +1,21 @@
+#ifndef _RIVE_DATA_VALUE_HPP_
+#define _RIVE_DATA_VALUE_HPP_
+#include "rive/data_bind/data_values/data_type.hpp"
+
+#include <stdio.h>
+namespace rive
+{
+class DataValue
+{
+public:
+ virtual bool isTypeOf(DataType dataType) const { return false; }
+ template <typename T> inline bool is() const { return isTypeOf(T::typeKey); }
+ template <typename T> inline T* as()
+ {
+ assert(is<T>());
+ return static_cast<T*>(this);
+ }
+};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/data_bind/data_values/data_value_boolean.hpp b/include/rive/data_bind/data_values/data_value_boolean.hpp
new file mode 100644
index 0000000..4fd8575
--- /dev/null
+++ b/include/rive/data_bind/data_values/data_value_boolean.hpp
@@ -0,0 +1,23 @@
+#ifndef _RIVE_DATA_VALUE_BOOLEAN_HPP_
+#define _RIVE_DATA_VALUE_BOOLEAN_HPP_
+#include "rive/data_bind/data_values/data_value.hpp"
+
+#include <stdio.h>
+namespace rive
+{
+class DataValueBoolean : public DataValue
+{
+private:
+ bool m_value = false;
+
+public:
+ DataValueBoolean(bool value) : m_value(value){};
+ DataValueBoolean(){};
+ static const DataType typeKey = DataType::boolean;
+ bool isTypeOf(DataType typeKey) const override { return typeKey == DataType::boolean; }
+ bool value() { return m_value; };
+ void value(bool value) { m_value = value; };
+};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/data_bind/data_values/data_value_color.hpp b/include/rive/data_bind/data_values/data_value_color.hpp
new file mode 100644
index 0000000..fdc88b5
--- /dev/null
+++ b/include/rive/data_bind/data_values/data_value_color.hpp
@@ -0,0 +1,23 @@
+#ifndef _RIVE_DATA_VALUE_COLOR_HPP_
+#define _RIVE_DATA_VALUE_COLOR_HPP_
+#include "rive/data_bind/data_values/data_value.hpp"
+
+#include <stdio.h>
+namespace rive
+{
+class DataValueColor : public DataValue
+{
+private:
+ int m_value = false;
+
+public:
+ DataValueColor(int value) : m_value(value){};
+ DataValueColor(){};
+ static const DataType typeKey = DataType::color;
+ bool isTypeOf(DataType typeKey) const override { return typeKey == DataType::color; }
+ int value() { return m_value; };
+ void value(int value) { m_value = value; };
+};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/data_bind/data_values/data_value_enum.hpp b/include/rive/data_bind/data_values/data_value_enum.hpp
new file mode 100644
index 0000000..9c2dbe5
--- /dev/null
+++ b/include/rive/data_bind/data_values/data_value_enum.hpp
@@ -0,0 +1,26 @@
+#ifndef _RIVE_DATA_VALUE_ENUM_HPP_
+#define _RIVE_DATA_VALUE_ENUM_HPP_
+#include "rive/data_bind/data_values/data_value.hpp"
+#include "rive/viewmodel/data_enum.hpp"
+
+#include <iostream>
+namespace rive
+{
+class DataValueEnum : public DataValue
+{
+private:
+ uint32_t m_value = 0;
+ DataEnum* m_dataEnum;
+
+public:
+ DataValueEnum(uint32_t value, DataEnum* dataEnum) : m_value(value), m_dataEnum(dataEnum){};
+ DataValueEnum(){};
+ static const DataType typeKey = DataType::enumType;
+ bool isTypeOf(DataType typeKey) const override { return typeKey == DataType::enumType; };
+ uint32_t value() { return m_value; };
+ void value(uint32_t value) { m_value = value; };
+ DataEnum* dataEnum() { return m_dataEnum; };
+ void dataEnum(DataEnum* value) { m_dataEnum = value; };
+};
+} // namespace rive
+#endif
\ No newline at end of file
diff --git a/include/rive/data_bind/data_values/data_value_number.hpp b/include/rive/data_bind/data_values/data_value_number.hpp
new file mode 100644
index 0000000..90a3b5d
--- /dev/null
+++ b/include/rive/data_bind/data_values/data_value_number.hpp
@@ -0,0 +1,23 @@
+#ifndef _RIVE_DATA_VALUE_NUMBER_HPP_
+#define _RIVE_DATA_VALUE_NUMBER_HPP_
+#include "rive/data_bind/data_values/data_value.hpp"
+
+#include <stdio.h>
+namespace rive
+{
+class DataValueNumber : public DataValue
+{
+private:
+ float m_value = 0;
+
+public:
+ DataValueNumber(float value) : m_value(value){};
+ DataValueNumber(){};
+ static const DataType typeKey = DataType::number;
+ bool isTypeOf(DataType typeKey) const override { return typeKey == DataType::number; }
+ float value() { return m_value; };
+ void value(float value) { m_value = value; };
+};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/data_bind/data_values/data_value_string.hpp b/include/rive/data_bind/data_values/data_value_string.hpp
new file mode 100644
index 0000000..7bf2676
--- /dev/null
+++ b/include/rive/data_bind/data_values/data_value_string.hpp
@@ -0,0 +1,22 @@
+#ifndef _RIVE_DATA_VALUE_STRING_HPP_
+#define _RIVE_DATA_VALUE_STRING_HPP_
+#include "rive/data_bind/data_values/data_value.hpp"
+
+#include <iostream>
+namespace rive
+{
+class DataValueString : public DataValue
+{
+private:
+ std::string m_value = "";
+
+public:
+ DataValueString(std::string value) : m_value(value){};
+ DataValueString(){};
+ static const DataType typeKey = DataType::string;
+ bool isTypeOf(DataType typeKey) const override { return typeKey == DataType::string; };
+ std::string value() { return m_value; };
+ void value(std::string value) { m_value = value; };
+};
+} // 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 592e41b..d8e9eb9 100644
--- a/include/rive/generated/core_registry.hpp
+++ b/include/rive/generated/core_registry.hpp
@@ -118,6 +118,7 @@
#include "rive/data_bind/bindable_property_enum.hpp"
#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/data_bind.hpp"
#include "rive/data_bind/data_bind_context.hpp"
#include "rive/draw_rules.hpp"
@@ -994,6 +995,9 @@
case DataBindBase::flagsPropertyKey:
object->as<DataBindBase>()->flags(value);
break;
+ case DataBindBase::converterIdPropertyKey:
+ object->as<DataBindBase>()->converterId(value);
+ break;
case BindablePropertyEnumBase::propertyValuePropertyKey:
object->as<BindablePropertyEnumBase>()->propertyValue(value);
break;
@@ -1132,6 +1136,9 @@
case OpenUrlEventBase::urlPropertyKey:
object->as<OpenUrlEventBase>()->url(value);
break;
+ case DataConverterBase::namePropertyKey:
+ object->as<DataConverterBase>()->name(value);
+ break;
case BindablePropertyStringBase::propertyValuePropertyKey:
object->as<BindablePropertyStringBase>()->propertyValue(value);
break;
@@ -1999,6 +2006,8 @@
return object->as<DataBindBase>()->propertyKey();
case DataBindBase::flagsPropertyKey:
return object->as<DataBindBase>()->flags();
+ case DataBindBase::converterIdPropertyKey:
+ return object->as<DataBindBase>()->converterId();
case BindablePropertyEnumBase::propertyValuePropertyKey:
return object->as<BindablePropertyEnumBase>()->propertyValue();
case NestedArtboardLeafBase::fitPropertyKey:
@@ -2097,6 +2106,8 @@
return object->as<TransitionValueStringComparatorBase>()->value();
case OpenUrlEventBase::urlPropertyKey:
return object->as<OpenUrlEventBase>()->url();
+ case DataConverterBase::namePropertyKey:
+ return object->as<DataConverterBase>()->name();
case BindablePropertyStringBase::propertyValuePropertyKey:
return object->as<BindablePropertyStringBase>()->propertyValue();
case TextValueRunBase::textPropertyKey:
@@ -2617,6 +2628,7 @@
case OpenUrlEventBase::targetValuePropertyKey:
case DataBindBase::propertyKeyPropertyKey:
case DataBindBase::flagsPropertyKey:
+ case DataBindBase::converterIdPropertyKey:
case BindablePropertyEnumBase::propertyValuePropertyKey:
case NestedArtboardLeafBase::fitPropertyKey:
case WeightBase::valuesPropertyKey:
@@ -2661,6 +2673,7 @@
case KeyFrameStringBase::valuePropertyKey:
case TransitionValueStringComparatorBase::valuePropertyKey:
case OpenUrlEventBase::urlPropertyKey:
+ case DataConverterBase::namePropertyKey:
case BindablePropertyStringBase::propertyValuePropertyKey:
case TextValueRunBase::textPropertyKey:
case CustomPropertyStringBase::propertyValuePropertyKey:
@@ -3180,6 +3193,8 @@
return object->is<DataBindBase>();
case DataBindBase::flagsPropertyKey:
return object->is<DataBindBase>();
+ case DataBindBase::converterIdPropertyKey:
+ return object->is<DataBindBase>();
case BindablePropertyEnumBase::propertyValuePropertyKey:
return object->is<BindablePropertyEnumBase>();
case NestedArtboardLeafBase::fitPropertyKey:
@@ -3264,6 +3279,8 @@
return object->is<TransitionValueStringComparatorBase>();
case OpenUrlEventBase::urlPropertyKey:
return object->is<OpenUrlEventBase>();
+ case DataConverterBase::namePropertyKey:
+ return object->is<DataConverterBase>();
case BindablePropertyStringBase::propertyValuePropertyKey:
return object->is<BindablePropertyStringBase>();
case TextValueRunBase::textPropertyKey:
diff --git a/include/rive/generated/data_bind/converters/data_converter_base.hpp b/include/rive/generated/data_bind/converters/data_converter_base.hpp
new file mode 100644
index 0000000..737b567
--- /dev/null
+++ b/include/rive/generated/data_bind/converters/data_converter_base.hpp
@@ -0,0 +1,66 @@
+#ifndef _RIVE_DATA_CONVERTER_BASE_HPP_
+#define _RIVE_DATA_CONVERTER_BASE_HPP_
+#include <string>
+#include "rive/core.hpp"
+#include "rive/core/field_types/core_string_type.hpp"
+namespace rive
+{
+class DataConverterBase : public Core
+{
+protected:
+ typedef Core Super;
+
+public:
+ static const uint16_t typeKey = 488;
+
+ /// Helper to quickly determine if a core object extends another without RTTI
+ /// at runtime.
+ bool isTypeOf(uint16_t typeKey) const override
+ {
+ switch (typeKey)
+ {
+ case DataConverterBase::typeKey:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ uint16_t coreType() const override { return typeKey; }
+
+ static const uint16_t namePropertyKey = 662;
+
+private:
+ std::string m_Name = "";
+
+public:
+ inline const std::string& name() const { return m_Name; }
+ void name(std::string value)
+ {
+ if (m_Name == value)
+ {
+ return;
+ }
+ m_Name = value;
+ nameChanged();
+ }
+
+ void copy(const DataConverterBase& object) { m_Name = object.m_Name; }
+
+ bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
+ {
+ switch (propertyKey)
+ {
+ case namePropertyKey:
+ m_Name = CoreStringType::deserialize(reader);
+ return true;
+ }
+ return false;
+ }
+
+protected:
+ virtual void nameChanged() {}
+};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/generated/data_bind/data_bind_base.hpp b/include/rive/generated/data_bind/data_bind_base.hpp
index b900663..77db021 100644
--- a/include/rive/generated/data_bind/data_bind_base.hpp
+++ b/include/rive/generated/data_bind/data_bind_base.hpp
@@ -29,10 +29,12 @@
static const uint16_t propertyKeyPropertyKey = 586;
static const uint16_t flagsPropertyKey = 587;
+ static const uint16_t converterIdPropertyKey = 660;
private:
uint32_t m_PropertyKey = Core::invalidPropertyKey;
uint32_t m_Flags = 0;
+ uint32_t m_ConverterId = -1;
public:
inline uint32_t propertyKey() const { return m_PropertyKey; }
@@ -57,11 +59,23 @@
flagsChanged();
}
+ inline uint32_t converterId() const { return m_ConverterId; }
+ void converterId(uint32_t value)
+ {
+ if (m_ConverterId == value)
+ {
+ return;
+ }
+ m_ConverterId = value;
+ converterIdChanged();
+ }
+
Core* clone() const override;
void copy(const DataBindBase& object)
{
m_PropertyKey = object.m_PropertyKey;
m_Flags = object.m_Flags;
+ m_ConverterId = object.m_ConverterId;
}
bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
@@ -74,6 +88,9 @@
case flagsPropertyKey:
m_Flags = CoreUintType::deserialize(reader);
return true;
+ case converterIdPropertyKey:
+ m_ConverterId = CoreUintType::deserialize(reader);
+ return true;
}
return false;
}
@@ -81,6 +98,7 @@
protected:
virtual void propertyKeyChanged() {}
virtual void flagsChanged() {}
+ virtual void converterIdChanged() {}
};
} // namespace rive
diff --git a/include/rive/importers/backboard_importer.hpp b/include/rive/importers/backboard_importer.hpp
index f237931..c92454f 100644
--- a/include/rive/importers/backboard_importer.hpp
+++ b/include/rive/importers/backboard_importer.hpp
@@ -12,6 +12,8 @@
class Backboard;
class FileAsset;
class FileAssetReferencer;
+class DataConverter;
+class DataBind;
class BackboardImporter : public ImportStackObject
{
private:
@@ -20,6 +22,8 @@
std::vector<NestedArtboard*> m_NestedArtboards;
std::vector<FileAsset*> m_FileAssets;
std::vector<FileAssetReferencer*> m_FileAssetReferencers;
+ std::vector<DataConverter*> m_DataConverters;
+ std::vector<DataBind*> m_DataConverterReferencers;
int m_NextArtboardId;
public:
@@ -29,6 +33,8 @@
void addNestedArtboard(NestedArtboard* artboard);
void addFileAsset(FileAsset* asset);
void addFileAssetReferencer(FileAssetReferencer* referencer);
+ void addDataConverterReferencer(DataBind* referencer);
+ void addDataConverter(DataConverter* converter);
StatusCode resolve() override;
const Backboard* backboard() const { return m_Backboard; }
diff --git a/src/data_bind/context/context_value.cpp b/src/data_bind/context/context_value.cpp
new file mode 100644
index 0000000..5a12954
--- /dev/null
+++ b/src/data_bind/context/context_value.cpp
@@ -0,0 +1,122 @@
+#include "rive/data_bind/context/context_value.hpp"
+#include "rive/data_bind/context/context_value_color.hpp"
+#include "rive/data_bind/data_values/data_type.hpp"
+#include "rive/data_bind/data_values/data_value.hpp"
+#include "rive/data_bind/data_values/data_value_number.hpp"
+#include "rive/data_bind/data_values/data_value_string.hpp"
+#include "rive/data_bind/data_values/data_value_enum.hpp"
+#include "rive/data_bind/data_values/data_value_color.hpp"
+#include "rive/data_bind/data_values/data_value_boolean.hpp"
+#include "rive/generated/core_registry.hpp"
+
+using namespace rive;
+
+DataBindContextValue::DataBindContextValue(ViewModelInstanceValue* source,
+ DataConverter* converter) :
+ m_source(source), m_converter(converter)
+{
+ if (m_source != nullptr)
+ {
+ switch (m_source->coreType())
+ {
+ case ViewModelInstanceNumberBase::typeKey:
+ m_dataValue =
+ new DataValueNumber(m_source->as<ViewModelInstanceNumber>()->propertyValue());
+ break;
+ case ViewModelInstanceStringBase::typeKey:
+ m_dataValue =
+ new DataValueString(m_source->as<ViewModelInstanceString>()->propertyValue());
+ break;
+ case ViewModelInstanceColorBase::typeKey:
+ m_dataValue =
+ new DataValueColor(m_source->as<ViewModelInstanceColor>()->propertyValue());
+ break;
+ case ViewModelInstanceBooleanBase::typeKey:
+ m_dataValue =
+ new DataValueBoolean(m_source->as<ViewModelInstanceBoolean>()->propertyValue());
+ break;
+ case ViewModelInstanceEnumBase::typeKey:
+ {
+ auto viewmodelInstanceEnum = m_source->as<ViewModelInstanceEnum>();
+ auto viewModelPropertyEnum =
+ viewmodelInstanceEnum->viewModelProperty()->as<ViewModelPropertyEnum>();
+ m_dataValue = new DataValueEnum(viewmodelInstanceEnum->propertyValue(),
+ viewModelPropertyEnum->dataEnum());
+ }
+ break;
+ default:
+ m_dataValue = new DataValue();
+ }
+ }
+}
+
+void DataBindContextValue::updateSourceValue()
+{
+ if (m_source != nullptr)
+ {
+ switch (m_source->coreType())
+ {
+ case ViewModelInstanceNumberBase::typeKey:
+ m_dataValue->as<DataValueNumber>()->value(
+ m_source->as<ViewModelInstanceNumber>()->propertyValue());
+ break;
+ case ViewModelInstanceStringBase::typeKey:
+ m_dataValue->as<DataValueString>()->value(
+ m_source->as<ViewModelInstanceString>()->propertyValue());
+ break;
+ case ViewModelInstanceColorBase::typeKey:
+ m_dataValue->as<DataValueColor>()->value(
+ m_source->as<ViewModelInstanceColor>()->propertyValue());
+ break;
+ case ViewModelInstanceBooleanBase::typeKey:
+ m_dataValue->as<DataValueBoolean>()->value(
+ m_source->as<ViewModelInstanceBoolean>()->propertyValue());
+ break;
+ case ViewModelInstanceEnumBase::typeKey:
+ m_dataValue->as<DataValueEnum>()->value(
+ m_source->as<ViewModelInstanceEnum>()->propertyValue());
+ break;
+ }
+ }
+}
+
+void DataBindContextValue::applyToSource(Core* component,
+ uint32_t propertyKey,
+ bool isMainDirection)
+{
+ auto targetValue = getTargetValue(component, propertyKey);
+ switch (m_source->coreType())
+ {
+ case ViewModelInstanceNumberBase::typeKey:
+ {
+
+ auto value = calculateValue<DataValueNumber, float>(targetValue, isMainDirection);
+ m_source->as<ViewModelInstanceNumber>()->propertyValue(value);
+ }
+ break;
+ case ViewModelInstanceStringBase::typeKey:
+ {
+ auto value = calculateValue<DataValueString, std::string>(targetValue, isMainDirection);
+ m_source->as<ViewModelInstanceString>()->propertyValue(value);
+ }
+ break;
+ case ViewModelInstanceColorBase::typeKey:
+ {
+ auto value = calculateValue<DataValueColor, int>(targetValue, isMainDirection);
+ m_source->as<ViewModelInstanceColor>()->propertyValue(value);
+ }
+ break;
+ case ViewModelInstanceBooleanBase::typeKey:
+ {
+ auto value = calculateValue<DataValueBoolean, bool>(targetValue, isMainDirection);
+ m_source->as<ViewModelInstanceBoolean>()->propertyValue(value);
+ }
+ break;
+ case ViewModelInstanceEnumBase::typeKey:
+ {
+ auto value = calculateValue<DataValueEnum, uint32_t>(targetValue, isMainDirection);
+ m_source->as<ViewModelInstanceEnum>()->propertyValue(value);
+ }
+ break;
+ }
+}
\ No newline at end of file
diff --git a/src/data_bind/context/context_value_boolean.cpp b/src/data_bind/context/context_value_boolean.cpp
index b7b708b..b08b8f5 100644
--- a/src/data_bind/context/context_value_boolean.cpp
+++ b/src/data_bind/context/context_value_boolean.cpp
@@ -1,27 +1,23 @@
#include "rive/data_bind/context/context_value_boolean.hpp"
+#include "rive/data_bind/data_values/data_value_boolean.hpp"
#include "rive/generated/core_registry.hpp"
using namespace rive;
-DataBindContextValueBoolean::DataBindContextValueBoolean(ViewModelInstanceValue* value)
+DataBindContextValueBoolean::DataBindContextValueBoolean(ViewModelInstanceValue* source,
+ DataConverter* converter) :
+ DataBindContextValue(source, converter)
+{}
+
+void DataBindContextValueBoolean::apply(Core* target, uint32_t propertyKey, bool isMainDirection)
{
- m_Source = value;
- m_Value = m_Source->as<ViewModelInstanceBoolean>()->propertyValue();
+ updateSourceValue();
+ auto value = calculateValue<DataValueBoolean, bool>(m_dataValue, isMainDirection);
+ CoreRegistry::setBool(target, propertyKey, value);
}
-void DataBindContextValueBoolean::apply(Core* target, uint32_t propertyKey)
-{
- CoreRegistry::setBool(target,
- propertyKey,
- m_Source->as<ViewModelInstanceBoolean>()->propertyValue());
-}
-
-void DataBindContextValueBoolean::applyToSource(Core* target, uint32_t propertyKey)
+DataValue* DataBindContextValueBoolean::getTargetValue(Core* target, uint32_t propertyKey)
{
auto value = CoreRegistry::getBool(target, propertyKey);
- if (m_Value != value)
- {
- m_Value = value;
- m_Source->as<ViewModelInstanceBoolean>()->propertyValue(value);
- }
+ return new DataValueBoolean(value);
}
\ No newline at end of file
diff --git a/src/data_bind/context/context_value_color.cpp b/src/data_bind/context/context_value_color.cpp
index 44a1857..c66171d 100644
--- a/src/data_bind/context/context_value_color.cpp
+++ b/src/data_bind/context/context_value_color.cpp
@@ -1,27 +1,23 @@
#include "rive/data_bind/context/context_value_color.hpp"
+#include "rive/data_bind/data_values/data_value_color.hpp"
#include "rive/generated/core_registry.hpp"
using namespace rive;
-DataBindContextValueColor::DataBindContextValueColor(ViewModelInstanceValue* value)
+DataBindContextValueColor::DataBindContextValueColor(ViewModelInstanceValue* source,
+ DataConverter* converter) :
+ DataBindContextValue(source, converter)
+{}
+
+void DataBindContextValueColor::apply(Core* target, uint32_t propertyKey, bool isMainDirection)
{
- m_Source = value;
- m_Value = m_Source->as<ViewModelInstanceColor>()->propertyValue();
+ updateSourceValue();
+ auto value = calculateValue<DataValueColor, int>(m_dataValue, isMainDirection);
+ CoreRegistry::setColor(target, propertyKey, value);
}
-void DataBindContextValueColor::apply(Core* target, uint32_t propertyKey)
-{
- CoreRegistry::setColor(target,
- propertyKey,
- m_Source->as<ViewModelInstanceColor>()->propertyValue());
-}
-
-void DataBindContextValueColor::applyToSource(Core* target, uint32_t propertyKey)
+DataValue* DataBindContextValueColor::getTargetValue(Core* target, uint32_t propertyKey)
{
auto value = CoreRegistry::getColor(target, propertyKey);
- if (m_Value != value)
- {
- m_Value = value;
- m_Source->as<ViewModelInstanceColor>()->propertyValue(value);
- }
+ return new DataValueColor(value);
}
\ No newline at end of file
diff --git a/src/data_bind/context/context_value_enum.cpp b/src/data_bind/context/context_value_enum.cpp
index a0064bc..dac5920 100644
--- a/src/data_bind/context/context_value_enum.cpp
+++ b/src/data_bind/context/context_value_enum.cpp
@@ -1,36 +1,27 @@
#include "rive/data_bind/context/context_value_enum.hpp"
+#include "rive/data_bind/data_values/data_value_enum.hpp"
#include "rive/generated/core_registry.hpp"
using namespace rive;
-DataBindContextValueEnum::DataBindContextValueEnum(ViewModelInstanceValue* value)
+DataBindContextValueEnum::DataBindContextValueEnum(ViewModelInstanceValue* source,
+ DataConverter* converter) :
+ DataBindContextValue(source, converter)
+{}
+
+void DataBindContextValueEnum::apply(Core* target, uint32_t propertyKey, bool isMainDirection)
{
- m_Source = value;
- m_Value = m_Source->as<ViewModelInstanceEnum>()->propertyValue();
+
+ updateSourceValue();
+ auto value = calculateValue<DataValueEnum, uint32_t>(m_dataValue, isMainDirection);
+ CoreRegistry::setUint(target, propertyKey, value);
}
-void DataBindContextValueEnum::apply(Core* target, uint32_t propertyKey)
+DataValue* DataBindContextValueEnum::getTargetValue(Core* target, uint32_t propertyKey)
{
- auto enumSource = m_Source->as<ViewModelInstanceEnum>();
- auto enumProperty = enumSource->viewModelProperty()->as<ViewModelPropertyEnum>();
- auto enumValue = enumProperty->value(m_Source->as<ViewModelInstanceEnum>()->propertyValue());
- // TODO: @hernan decide which one makes more sense. Probably setUint, but setString was used to
- // update text input with enum values.
- CoreRegistry::setString(target, propertyKey, enumValue);
- CoreRegistry::setUint(target,
- propertyKey,
- m_Source->as<ViewModelInstanceEnum>()->propertyValue());
-}
-
-void DataBindContextValueEnum::applyToSource(Core* target, uint32_t propertyKey)
-{
- auto value = CoreRegistry::getString(target, propertyKey);
- auto enumSource = m_Source->as<ViewModelInstanceEnum>();
- auto enumProperty = enumSource->viewModelProperty()->as<ViewModelPropertyEnum>();
- auto valueIndex = enumProperty->valueIndex(value);
- if (valueIndex != -1 && m_Value != valueIndex)
- {
- m_Value = valueIndex;
- m_Source->as<ViewModelInstanceEnum>()->value(static_cast<uint32_t>(valueIndex));
- }
+ auto value = CoreRegistry::getUint(target, propertyKey);
+ auto viewmodelInstanceEnum = m_source->as<ViewModelInstanceEnum>();
+ auto viewModelPropertyEnum =
+ viewmodelInstanceEnum->viewModelProperty()->as<ViewModelPropertyEnum>();
+ return new DataValueEnum(value, viewModelPropertyEnum->dataEnum());
}
\ No newline at end of file
diff --git a/src/data_bind/context/context_value_list.cpp b/src/data_bind/context/context_value_list.cpp
index f0aa427..92fc2fd 100644
--- a/src/data_bind/context/context_value_list.cpp
+++ b/src/data_bind/context/context_value_list.cpp
@@ -5,10 +5,10 @@
using namespace rive;
-DataBindContextValueList::DataBindContextValueList(ViewModelInstanceValue* value)
-{
- m_Source = value;
-}
+DataBindContextValueList::DataBindContextValueList(ViewModelInstanceValue* source,
+ DataConverter* converter) :
+ DataBindContextValue(source, converter)
+{}
std::unique_ptr<ArtboardInstance> DataBindContextValueList::createArtboard(
Component* target,
@@ -72,7 +72,7 @@
{
if (target != nullptr)
{
- auto sourceList = m_Source->as<ViewModelInstanceList>();
+ auto sourceList = m_source->as<ViewModelInstanceList>();
auto listItems = sourceList->listItems();
int listIndex = 0;
@@ -125,9 +125,11 @@
}
}
-void DataBindContextValueList::apply(Core* target, uint32_t propertyKey) {}
+void DataBindContextValueList::apply(Core* target, uint32_t propertyKey, bool isMainDirection) {}
-void DataBindContextValueList::applyToSource(Core* target, uint32_t propertyKey)
+void DataBindContextValueList::applyToSource(Core* target,
+ uint32_t propertyKey,
+ bool isMainDirection)
{
// TODO: @hernan does applyToSource make sense? Should we block it somehow?
}
\ No newline at end of file
diff --git a/src/data_bind/context/context_value_number.cpp b/src/data_bind/context/context_value_number.cpp
index 63fabf8..4f40997 100644
--- a/src/data_bind/context/context_value_number.cpp
+++ b/src/data_bind/context/context_value_number.cpp
@@ -1,27 +1,23 @@
#include "rive/data_bind/context/context_value_number.hpp"
+#include "rive/data_bind/data_values/data_value_number.hpp"
#include "rive/generated/core_registry.hpp"
using namespace rive;
-DataBindContextValueNumber::DataBindContextValueNumber(ViewModelInstanceValue* value)
+DataBindContextValueNumber::DataBindContextValueNumber(ViewModelInstanceValue* source,
+ DataConverter* converter) :
+ DataBindContextValue(source, converter)
+{}
+
+void DataBindContextValueNumber::apply(Core* target, uint32_t propertyKey, bool isMainDirection)
{
- m_Source = value;
- m_Value = m_Source->as<ViewModelInstanceNumber>()->propertyValue();
+ updateSourceValue();
+ auto value = calculateValue<DataValueNumber, float>(m_dataValue, isMainDirection);
+ CoreRegistry::setDouble(target, propertyKey, value);
}
-void DataBindContextValueNumber::apply(Core* target, uint32_t propertyKey)
-{
- CoreRegistry::setDouble(target,
- propertyKey,
- m_Source->as<ViewModelInstanceNumber>()->propertyValue());
-}
-
-void DataBindContextValueNumber::applyToSource(Core* target, uint32_t propertyKey)
+DataValue* DataBindContextValueNumber::getTargetValue(Core* target, uint32_t propertyKey)
{
auto value = CoreRegistry::getDouble(target, propertyKey);
- if (m_Value != value)
- {
- m_Value = value;
- m_Source->as<ViewModelInstanceNumber>()->propertyValue(value);
- }
+ return new DataValueNumber(value);
}
\ No newline at end of file
diff --git a/src/data_bind/context/context_value_string.cpp b/src/data_bind/context/context_value_string.cpp
index 9cf19f7..2c73dc8 100644
--- a/src/data_bind/context/context_value_string.cpp
+++ b/src/data_bind/context/context_value_string.cpp
@@ -1,27 +1,23 @@
#include "rive/data_bind/context/context_value_string.hpp"
+#include "rive/data_bind/data_values/data_value_string.hpp"
#include "rive/generated/core_registry.hpp"
using namespace rive;
-DataBindContextValueString::DataBindContextValueString(ViewModelInstanceValue* value)
+DataBindContextValueString::DataBindContextValueString(ViewModelInstanceValue* source,
+ DataConverter* converter) :
+ DataBindContextValue(source, converter)
+{}
+
+void DataBindContextValueString::apply(Core* target, uint32_t propertyKey, bool isMainDirection)
{
- m_Source = value;
- m_Value = m_Source->as<ViewModelInstanceString>()->propertyValue();
+ updateSourceValue();
+ auto value = calculateValue<DataValueString, std::string>(m_dataValue, isMainDirection);
+ CoreRegistry::setString(target, propertyKey, value);
}
-void DataBindContextValueString::apply(Core* target, uint32_t propertyKey)
-{
- CoreRegistry::setString(target,
- propertyKey,
- m_Source->as<ViewModelInstanceString>()->propertyValue());
-}
-
-void DataBindContextValueString::applyToSource(Core* target, uint32_t propertyKey)
+DataValue* DataBindContextValueString::getTargetValue(Core* target, uint32_t propertyKey)
{
auto value = CoreRegistry::getString(target, propertyKey);
- if (m_Value != value)
- {
- m_Value = value;
- m_Source->as<ViewModelInstanceString>()->propertyValue(value);
- }
+ return new DataValueString(value);
}
\ No newline at end of file
diff --git a/src/data_bind/converters/data_converter.cpp b/src/data_bind/converters/data_converter.cpp
new file mode 100644
index 0000000..d9645b9
--- /dev/null
+++ b/src/data_bind/converters/data_converter.cpp
@@ -0,0 +1,18 @@
+#include "rive/data_bind/converters/data_converter.hpp"
+#include "rive/importers/import_stack.hpp"
+#include "rive/importers/backboard_importer.hpp"
+#include "rive/backboard.hpp"
+
+using namespace rive;
+
+StatusCode DataConverter::import(ImportStack& importStack)
+{
+ auto backboardImporter = importStack.latest<BackboardImporter>(Backboard::typeKey);
+ if (backboardImporter == nullptr)
+ {
+ return StatusCode::MissingObject;
+ }
+ backboardImporter->addDataConverter(this);
+
+ return Super::import(importStack);
+}
\ No newline at end of file
diff --git a/src/data_bind/data_bind.cpp b/src/data_bind/data_bind.cpp
index 9877f5b..e4c52c9 100644
--- a/src/data_bind/data_bind.cpp
+++ b/src/data_bind/data_bind.cpp
@@ -14,10 +14,12 @@
#include "rive/data_bind/context/context_value_enum.hpp"
#include "rive/data_bind/context/context_value_list.hpp"
#include "rive/data_bind/context/context_value_color.hpp"
+#include "rive/data_bind/data_values/data_type.hpp"
#include "rive/animation/transition_viewmodel_condition.hpp"
#include "rive/animation/state_machine.hpp"
#include "rive/importers/artboard_importer.hpp"
#include "rive/importers/state_machine_importer.hpp"
+#include "rive/importers/backboard_importer.hpp"
using namespace rive;
@@ -34,6 +36,13 @@
StatusCode DataBind::import(ImportStack& importStack)
{
+
+ auto backboardImporter = importStack.latest<BackboardImporter>(Backboard::typeKey);
+ if (backboardImporter == nullptr)
+ {
+ return StatusCode::MissingObject;
+ }
+ backboardImporter->addDataConverterReferencer(this);
if (target())
{
switch (target()->coreType())
@@ -66,31 +75,61 @@
}
}
}
+
return Super::import(importStack);
}
+DataType DataBind::outputType()
+{
+ if (converter())
+ {
+ return converter()->outputType();
+ }
+ switch (m_Source->coreType())
+ {
+ case ViewModelInstanceNumberBase::typeKey:
+ return DataType::number;
+ case ViewModelInstanceStringBase::typeKey:
+ return DataType::string;
+ case ViewModelInstanceEnumBase::typeKey:
+ return DataType::enumType;
+ case ViewModelInstanceColorBase::typeKey:
+ return DataType::color;
+ case ViewModelInstanceBooleanBase::typeKey:
+ return DataType::boolean;
+ case ViewModelInstanceListBase::typeKey:
+ return DataType::list;
+ }
+ return DataType::none;
+}
+
void DataBind::bind()
{
- switch (m_Source->coreType())
+ switch (outputType())
{
- case ViewModelInstanceNumberBase::typeKey:
- m_ContextValue = rivestd::make_unique<DataBindContextValueNumber>(m_Source);
+ case DataType::number:
+ m_ContextValue =
+ rivestd::make_unique<DataBindContextValueNumber>(m_Source, converter());
break;
- case ViewModelInstanceStringBase::typeKey:
- m_ContextValue = rivestd::make_unique<DataBindContextValueString>(m_Source);
+ case DataType::string:
+ m_ContextValue =
+ rivestd::make_unique<DataBindContextValueString>(m_Source, converter());
break;
- case ViewModelInstanceEnumBase::typeKey:
- m_ContextValue = rivestd::make_unique<DataBindContextValueEnum>(m_Source);
+ case DataType::boolean:
+ m_ContextValue =
+ rivestd::make_unique<DataBindContextValueBoolean>(m_Source, converter());
break;
- case ViewModelInstanceListBase::typeKey:
- m_ContextValue = rivestd::make_unique<DataBindContextValueList>(m_Source);
+ case DataType::color:
+ m_ContextValue = rivestd::make_unique<DataBindContextValueColor>(m_Source, converter());
+ break;
+ case DataType::enumType:
+ m_ContextValue = rivestd::make_unique<DataBindContextValueEnum>(m_Source, converter());
+ break;
+ case DataType::list:
+ m_ContextValue = rivestd::make_unique<DataBindContextValueList>(m_Source, converter());
m_ContextValue->update(m_target);
break;
- case ViewModelInstanceColorBase::typeKey:
- m_ContextValue = rivestd::make_unique<DataBindContextValueColor>(m_Source);
- break;
- case ViewModelInstanceBooleanBase::typeKey:
- m_ContextValue = rivestd::make_unique<DataBindContextValueBoolean>(m_Source);
+ default:
break;
}
}
@@ -114,7 +153,10 @@
if (((flagsValue & DataBindFlags::Direction) == DataBindFlags::ToTarget) ||
((flagsValue & DataBindFlags::TwoWay) == DataBindFlags::TwoWay))
{
- m_ContextValue->apply(m_target, propertyKey());
+ m_ContextValue->apply(m_target,
+ propertyKey(),
+ (flagsValue & DataBindFlags::Direction) ==
+ DataBindFlags::ToTarget);
}
}
}
@@ -128,7 +170,10 @@
{
if (m_ContextValue != nullptr)
{
- m_ContextValue->applyToSource(m_target, propertyKey());
+ m_ContextValue->applyToSource(m_target,
+ propertyKey(),
+ (flagsValue & DataBindFlags::Direction) ==
+ DataBindFlags::ToSource);
}
}
}
diff --git a/src/importers/backboard_importer.cpp b/src/importers/backboard_importer.cpp
index 286f133..845c536 100644
--- a/src/importers/backboard_importer.cpp
+++ b/src/importers/backboard_importer.cpp
@@ -7,6 +7,8 @@
#include "rive/assets/file_asset.hpp"
#include "rive/viewmodel/viewmodel.hpp"
#include "rive/viewmodel/viewmodel_instance.hpp"
+#include "rive/data_bind/converters/data_converter.hpp"
+#include "rive/data_bind/data_bind.hpp"
#include <unordered_set>
using namespace rive;
@@ -85,6 +87,25 @@
auto asset = m_FileAssets[index];
referencer->setAsset(asset);
}
+ for (auto referencer : m_DataConverterReferencers)
+ {
+ auto index = (size_t)referencer->converterId();
+ if (index >= m_DataConverters.size() || index < 0)
+ {
+ continue;
+ }
+ referencer->converter(m_DataConverters[index]);
+ }
return StatusCode::Ok;
+}
+
+void BackboardImporter::addDataConverter(DataConverter* dataConverter)
+{
+ m_DataConverters.push_back(dataConverter);
+}
+
+void BackboardImporter::addDataConverterReferencer(DataBind* dataBind)
+{
+ m_DataConverterReferencers.push_back(dataBind);
}
\ No newline at end of file