add bindable properties for state machines This PR sets the fundamental pieces for PRs that will be coming afterward to support data binding state machines. The most important parts are: - bindable properties that will be used as binding points for conditions, listeners, and blend animations - data bind objects don't extend from Component anymore to decouple them from artboards - because of that, now data bind objects are written in the context of their bound object so there is a unified way for setting data bind targets The rest is the usual boilerplate code from core objects and some inheritance changes Diffs= b5f342002 add bindable properties for state machines (#7640) Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head index 080a680..518b856 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -f55ebd34f3938bfe1e36ebf83bbc92c0e5d34a62 +b5f342002be71c61608ad6c37835349eb4e7c719
diff --git a/dev/defs/data_bind/bindable_property.json b/dev/defs/data_bind/bindable_property.json new file mode 100644 index 0000000..dbc57e5 --- /dev/null +++ b/dev/defs/data_bind/bindable_property.json
@@ -0,0 +1,20 @@ +{ + "name": "BindableProperty", + "key": { + "int": 9, + "string": "bindableproperty" + }, + "abstract": true, + "properties": { + "dataBindId": { + "type": "Id", + "initialValue": "Core.missingId", + "key": { + "int": 633, + "string": "databindid" + }, + "description": "Id of the data bind binded to this property", + "runtime": false + } + } +} \ No newline at end of file
diff --git a/dev/defs/data_bind/bindable_property_boolean.json b/dev/defs/data_bind/bindable_property_boolean.json new file mode 100644 index 0000000..78c24f2 --- /dev/null +++ b/dev/defs/data_bind/bindable_property_boolean.json
@@ -0,0 +1,19 @@ +{ + "name": "BindablePropertyBoolean", + "key": { + "int": 472, + "string": "bindablepropertyboolean" + }, + "extends": "data_bind/bindable_property.json", + "properties": { + "propertyValue": { + "type": "bool", + "initialValue": "false", + "key": { + "int": 634, + "string": "propertyvalue" + }, + "description": "A property of type bool that can be used for data binding." + } + } +} \ No newline at end of file
diff --git a/dev/defs/data_bind/bindable_property_color.json b/dev/defs/data_bind/bindable_property_color.json new file mode 100644 index 0000000..1dd5134 --- /dev/null +++ b/dev/defs/data_bind/bindable_property_color.json
@@ -0,0 +1,19 @@ +{ + "name": "BindablePropertyColor", + "key": { + "int": 475, + "string": "bindablepropertycolor" + }, + "extends": "data_bind/bindable_property.json", + "properties": { + "propertyValue": { + "type": "Color", + "initialValue": "0xFF1D1D1D", + "key": { + "int": 638, + "string": "propertyvalue" + }, + "description": "A property of type int that can be used for data binding." + } + } +} \ No newline at end of file
diff --git a/dev/defs/data_bind/bindable_property_enum.json b/dev/defs/data_bind/bindable_property_enum.json new file mode 100644 index 0000000..b3faf03 --- /dev/null +++ b/dev/defs/data_bind/bindable_property_enum.json
@@ -0,0 +1,21 @@ +{ + "name": "BindablePropertyEnum", + "key": { + "int": 474, + "string": "bindablepropertyenum" + }, + "extends": "data_bind/bindable_property.json", + "properties": { + "propertyValue": { + "type": "Id", + "typeRuntime": "uint", + "initialValue": "Core.missingId", + "initialValueRuntime": "-1", + "key": { + "int": 637, + "string": "propertyvalue" + }, + "description": "The id of the enum that can be used for data binding." + } + } +} \ No newline at end of file
diff --git a/dev/defs/data_bind/bindable_property_number.json b/dev/defs/data_bind/bindable_property_number.json new file mode 100644 index 0000000..a2ab667 --- /dev/null +++ b/dev/defs/data_bind/bindable_property_number.json
@@ -0,0 +1,19 @@ +{ + "name": "BindablePropertyNumber", + "key": { + "int": 473, + "string": "bindablepropertynumber" + }, + "extends": "data_bind/bindable_property.json", + "properties": { + "propertyValue": { + "type": "double", + "initialValue": "0", + "key": { + "int": 636, + "string": "propertyvalue" + }, + "description": "A property of type double that can be used for data binding." + } + } +} \ No newline at end of file
diff --git a/dev/defs/data_bind/bindable_property_string.json b/dev/defs/data_bind/bindable_property_string.json new file mode 100644 index 0000000..aac63df --- /dev/null +++ b/dev/defs/data_bind/bindable_property_string.json
@@ -0,0 +1,19 @@ +{ + "name": "BindablePropertyString", + "key": { + "int": 471, + "string": "bindablepropertystring" + }, + "extends": "data_bind/bindable_property.json", + "properties": { + "propertyValue": { + "type": "String", + "initialValue": "''", + "key": { + "int": 635, + "string": "propertyvalue" + }, + "description": "A property of type String that can be used for data binding." + } + } +} \ 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 c93b559..3e3124d 100644 --- a/dev/defs/data_bind/data_bind.json +++ b/dev/defs/data_bind/data_bind.json
@@ -4,18 +4,16 @@ "int": 446, "string": "databind" }, - "extends": "component.json", "properties": { "targetId": { "type": "Id", - "typeRuntime": "uint", "initialValue": "Core.missingId", - "initialValueRuntime": "-1", "key": { "int": 585, "string": "targetid" }, - "description": "Identifier used to track the object that is targetted." + "description": "Identifier used to track the object that is targetted.", + "runtime": false }, "propertyKey": { "type": "uint",
diff --git a/include/rive/animation/nested_state_machine.hpp b/include/rive/animation/nested_state_machine.hpp index 8c0476b..f3e557c 100644 --- a/include/rive/animation/nested_state_machine.hpp +++ b/include/rive/animation/nested_state_machine.hpp
@@ -36,6 +36,8 @@ size_t inputCount() { return m_nestedInputs.size(); } NestedInput* input(size_t index); NestedInput* input(std::string name); + void dataContextFromInstance(ViewModelInstance* viewModelInstance); + void dataContext(DataContext* dataContext); }; } // namespace rive
diff --git a/include/rive/animation/state_machine.hpp b/include/rive/animation/state_machine.hpp index 9899893..258fe61 100644 --- a/include/rive/animation/state_machine.hpp +++ b/include/rive/animation/state_machine.hpp
@@ -10,6 +10,7 @@ class StateMachineInput; class StateMachineListener; class StateMachineImporter; +class DataBind; class StateMachine : public StateMachineBase { friend class StateMachineImporter; @@ -18,10 +19,12 @@ std::vector<std::unique_ptr<StateMachineLayer>> m_Layers; std::vector<std::unique_ptr<StateMachineInput>> m_Inputs; std::vector<std::unique_ptr<StateMachineListener>> m_Listeners; + std::vector<std::unique_ptr<DataBind>> m_dataBinds; void addLayer(std::unique_ptr<StateMachineLayer>); void addInput(std::unique_ptr<StateMachineInput>); void addListener(std::unique_ptr<StateMachineListener>); + void addDataBind(std::unique_ptr<DataBind>); public: StateMachine(); @@ -32,11 +35,13 @@ size_t layerCount() const { return m_Layers.size(); } size_t inputCount() const { return m_Inputs.size(); } size_t listenerCount() const { return m_Listeners.size(); } + size_t dataBindCount() const { return m_dataBinds.size(); } const StateMachineInput* input(std::string name) const; const StateMachineInput* input(size_t index) const; const StateMachineLayer* layer(std::string name) const; const StateMachineLayer* layer(size_t index) const; + const DataBind* dataBind(size_t index) const; const StateMachineListener* listener(size_t index) const; StatusCode onAddedDirty(CoreContext* context) override;
diff --git a/include/rive/animation/state_machine_instance.hpp b/include/rive/animation/state_machine_instance.hpp index c59ee17..679ade0 100644 --- a/include/rive/animation/state_machine_instance.hpp +++ b/include/rive/animation/state_machine_instance.hpp
@@ -4,6 +4,7 @@ #include <string> #include <stddef.h> #include <vector> +#include <unordered_map> #include "rive/animation/linear_animation_instance.hpp" #include "rive/animation/state_instance.hpp" #include "rive/animation/state_transition.hpp" @@ -31,6 +32,8 @@ class Event; class KeyedProperty; class EventReport; +class DataBind; +class BindableProperty; #ifdef WITH_RIVE_TOOLS class StateMachineInstance; @@ -56,6 +59,7 @@ double randomValue(); StateTransition* findRandomTransition(StateInstance* stateFromInstance, bool ignoreTriggers); StateTransition* findAllowedTransition(StateInstance* stateFromInstance, bool ignoreTriggers); + DataContext* m_DataContext; public: StateMachineInstance(const StateMachine* machine, ArtboardInstance* instance); @@ -78,6 +82,8 @@ SMIBool* getBool(const std::string& name) const override; SMINumber* getNumber(const std::string& name) const override; SMITrigger* getTrigger(const std::string& name) const override; + void dataContextFromInstance(ViewModelInstance* viewModelInstance) override; + void dataContext(DataContext* dataContext); size_t currentAnimationCount() const; const LinearAnimationInstance* currentAnimationByIndex(size_t index) const; @@ -128,6 +134,7 @@ /// Gets a reported event at an index < reportedEventCount(). const EventReport reportedEventAt(std::size_t index) const; bool playsAudio() override { return true; } + BindableProperty* bindablePropertyInstance(BindableProperty* bindableProperty); private: std::vector<EventReport> m_reportedEvents; @@ -139,6 +146,8 @@ std::vector<std::unique_ptr<HitComponent>> m_hitComponents; StateMachineInstance* m_parentStateMachineInstance = nullptr; NestedArtboard* m_parentNestedArtboard = nullptr; + std::vector<DataBind*> m_dataBinds; + std::unordered_map<BindableProperty*, BindableProperty*> m_bindablePropertyInstances; #ifdef WITH_RIVE_TOOLS public: void onInputChanged(InputChanged callback) { m_inputChangedCallback = callback; }
diff --git a/include/rive/artboard.hpp b/include/rive/artboard.hpp index 85353c1..9411ceb 100644 --- a/include/rive/artboard.hpp +++ b/include/rive/artboard.hpp
@@ -182,9 +182,9 @@ DataContext* parent, bool isRoot); void dataContextFromInstance(ViewModelInstance* viewModelInstance); - void populateDataBinds(std::vector<Component*>* dataBinds); - void buildDataBindDependencies(std::vector<Component*>* dataBinds); - void sortDataBinds(std::vector<Component*> dataBinds); + void addDataBind(DataBind* dataBind); + void populateDataBinds(std::vector<DataBind*>* dataBinds); + void sortDataBinds(std::vector<DataBind*> dataBinds); bool hasAudio() const; template <typename T = Component> T* find(const std::string& name) @@ -284,6 +284,16 @@ { auto object = *itr; cloneObjects.push_back(object == nullptr ? nullptr : object->clone()); + // For each object, clone its data bind objects and target their clones + for (auto dataBind : m_DataBinds) + { + if (dataBind->target() == object) + { + auto dataBindClone = static_cast<DataBind*>(dataBind->clone()); + dataBindClone->target(cloneObjects.back()); + artboardClone->m_DataBinds.push_back(dataBindClone); + } + } } }
diff --git a/include/rive/data_bind/bindable_property.hpp b/include/rive/data_bind/bindable_property.hpp new file mode 100644 index 0000000..3294401 --- /dev/null +++ b/include/rive/data_bind/bindable_property.hpp
@@ -0,0 +1,19 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_HPP_ +#define _RIVE_BINDABLE_PROPERTY_HPP_ +#include "rive/generated/data_bind/bindable_property_base.hpp" +#include "rive/data_bind/data_bind.hpp" +#include <stdio.h> +namespace rive +{ +class BindableProperty : public BindablePropertyBase +{ +public: + void dataBind(DataBind* value) { m_dataBind = value; }; + DataBind* dataBind() { return m_dataBind; }; + +private: + DataBind* m_dataBind; +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/data_bind/bindable_property_boolean.hpp b/include/rive/data_bind/bindable_property_boolean.hpp new file mode 100644 index 0000000..18037b6 --- /dev/null +++ b/include/rive/data_bind/bindable_property_boolean.hpp
@@ -0,0 +1,13 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_BOOLEAN_HPP_ +#define _RIVE_BINDABLE_PROPERTY_BOOLEAN_HPP_ +#include "rive/generated/data_bind/bindable_property_boolean_base.hpp" +#include <stdio.h> +namespace rive +{ +class BindablePropertyBoolean : public BindablePropertyBooleanBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/data_bind/bindable_property_color.hpp b/include/rive/data_bind/bindable_property_color.hpp new file mode 100644 index 0000000..dd128ca --- /dev/null +++ b/include/rive/data_bind/bindable_property_color.hpp
@@ -0,0 +1,13 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_COLOR_HPP_ +#define _RIVE_BINDABLE_PROPERTY_COLOR_HPP_ +#include "rive/generated/data_bind/bindable_property_color_base.hpp" +#include <stdio.h> +namespace rive +{ +class BindablePropertyColor : public BindablePropertyColorBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/data_bind/bindable_property_enum.hpp b/include/rive/data_bind/bindable_property_enum.hpp new file mode 100644 index 0000000..48692c2 --- /dev/null +++ b/include/rive/data_bind/bindable_property_enum.hpp
@@ -0,0 +1,13 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_ENUM_HPP_ +#define _RIVE_BINDABLE_PROPERTY_ENUM_HPP_ +#include "rive/generated/data_bind/bindable_property_enum_base.hpp" +#include <stdio.h> +namespace rive +{ +class BindablePropertyEnum : public BindablePropertyEnumBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/data_bind/bindable_property_number.hpp b/include/rive/data_bind/bindable_property_number.hpp new file mode 100644 index 0000000..38a72fd --- /dev/null +++ b/include/rive/data_bind/bindable_property_number.hpp
@@ -0,0 +1,13 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_NUMBER_HPP_ +#define _RIVE_BINDABLE_PROPERTY_NUMBER_HPP_ +#include "rive/generated/data_bind/bindable_property_number_base.hpp" +#include <stdio.h> +namespace rive +{ +class BindablePropertyNumber : public BindablePropertyNumberBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/data_bind/bindable_property_string.hpp b/include/rive/data_bind/bindable_property_string.hpp new file mode 100644 index 0000000..302caf0 --- /dev/null +++ b/include/rive/data_bind/bindable_property_string.hpp
@@ -0,0 +1,13 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_STRING_HPP_ +#define _RIVE_BINDABLE_PROPERTY_STRING_HPP_ +#include "rive/generated/data_bind/bindable_property_string_base.hpp" +#include <stdio.h> +namespace rive +{ +class BindablePropertyString : public BindablePropertyStringBase +{ +public: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/data_bind/context/context_value.hpp b/include/rive/data_bind/context/context_value.hpp index 1f08e45..370f46f 100644 --- a/include/rive/data_bind/context/context_value.hpp +++ b/include/rive/data_bind/context/context_value.hpp
@@ -13,9 +13,9 @@ public: DataBindContextValue(){}; virtual ~DataBindContextValue(){}; - virtual void applyToSource(Component* component, uint32_t propertyKey){}; - virtual void apply(Component* component, uint32_t propertyKey){}; - virtual void update(Component* component){}; + virtual void applyToSource(Core* component, uint32_t propertyKey){}; + virtual void apply(Core* component, uint32_t propertyKey){}; + virtual void update(Core* component){}; }; } // 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 b7a963b..82e9a7f 100644 --- a/include/rive/data_bind/context/context_value_boolean.hpp +++ b/include/rive/data_bind/context/context_value_boolean.hpp
@@ -8,8 +8,8 @@ public: DataBindContextValueBoolean(ViewModelInstanceValue* value); - void apply(Component* component, uint32_t propertyKey) override; - virtual void applyToSource(Component* component, uint32_t propertyKey) override; + void apply(Core* component, uint32_t propertyKey) override; + virtual void applyToSource(Core* component, uint32_t propertyKey) override; private: bool m_Value;
diff --git a/include/rive/data_bind/context/context_value_color.hpp b/include/rive/data_bind/context/context_value_color.hpp index c1c7f48..22fe8f8 100644 --- a/include/rive/data_bind/context/context_value_color.hpp +++ b/include/rive/data_bind/context/context_value_color.hpp
@@ -8,8 +8,8 @@ public: DataBindContextValueColor(ViewModelInstanceValue* value); - void apply(Component* component, uint32_t propertyKey) override; - virtual void applyToSource(Component* component, uint32_t propertyKey) override; + void apply(Core* component, uint32_t propertyKey) override; + virtual void applyToSource(Core* component, uint32_t propertyKey) override; private: double m_Value;
diff --git a/include/rive/data_bind/context/context_value_enum.hpp b/include/rive/data_bind/context/context_value_enum.hpp index e78a1b5..98c21c4 100644 --- a/include/rive/data_bind/context/context_value_enum.hpp +++ b/include/rive/data_bind/context/context_value_enum.hpp
@@ -8,8 +8,8 @@ public: DataBindContextValueEnum(ViewModelInstanceValue* value); - void apply(Component* component, uint32_t propertyKey) override; - virtual void applyToSource(Component* component, uint32_t propertyKey) override; + void apply(Core* component, uint32_t propertyKey) override; + virtual void applyToSource(Core* component, uint32_t propertyKey) override; private: int m_Value;
diff --git a/include/rive/data_bind/context/context_value_list.hpp b/include/rive/data_bind/context/context_value_list.hpp index 3ee4f2d..0c12f91 100644 --- a/include/rive/data_bind/context/context_value_list.hpp +++ b/include/rive/data_bind/context/context_value_list.hpp
@@ -12,17 +12,15 @@ public: DataBindContextValueList(ViewModelInstanceValue* value); - void apply(Component* component, uint32_t propertyKey) override; - void update(Component* target) override; - virtual void applyToSource(Component* component, uint32_t propertyKey) override; + void apply(Core* component, uint32_t propertyKey) override; + void update(Core* target) override; + virtual void applyToSource(Core* component, uint32_t propertyKey) override; private: std::vector<std::unique_ptr<DataBindContextValueListItem>> m_ListItemsCache; - void insertItem(Component* target, - ViewModelInstanceListItem* viewModelInstanceListItem, - int index); - void swapItems(Component* target, int index1, int index2); - void popItem(Component* target); + void insertItem(Core* target, ViewModelInstanceListItem* viewModelInstanceListItem, int index); + void swapItems(Core* target, int index1, int index2); + void popItem(Core* target); std::unique_ptr<ArtboardInstance> createArtboard(Component* target, Artboard* artboard, ViewModelInstanceListItem* listItem) const;
diff --git a/include/rive/data_bind/context/context_value_number.hpp b/include/rive/data_bind/context/context_value_number.hpp index da866d3..b2d850a 100644 --- a/include/rive/data_bind/context/context_value_number.hpp +++ b/include/rive/data_bind/context/context_value_number.hpp
@@ -8,8 +8,8 @@ public: DataBindContextValueNumber(ViewModelInstanceValue* value); - void apply(Component* component, uint32_t propertyKey) override; - virtual void applyToSource(Component* component, uint32_t propertyKey) override; + void apply(Core* component, uint32_t propertyKey) override; + virtual void applyToSource(Core* component, uint32_t propertyKey) override; private: double m_Value;
diff --git a/include/rive/data_bind/context/context_value_string.hpp b/include/rive/data_bind/context/context_value_string.hpp index 52f2ac3..0b32528 100644 --- a/include/rive/data_bind/context/context_value_string.hpp +++ b/include/rive/data_bind/context/context_value_string.hpp
@@ -8,8 +8,8 @@ public: DataBindContextValueString(ViewModelInstanceValue* value); - void apply(Component* component, uint32_t propertyKey) override; - virtual void applyToSource(Component* component, uint32_t propertyKey) override; + void apply(Core* component, uint32_t propertyKey) override; + virtual void applyToSource(Core* component, uint32_t propertyKey) override; private: std::string m_Value;
diff --git a/include/rive/data_bind/data_bind.hpp b/include/rive/data_bind/data_bind.hpp index 7efbcc8..0ccccb3 100644 --- a/include/rive/data_bind/data_bind.hpp +++ b/include/rive/data_bind/data_bind.hpp
@@ -1,8 +1,10 @@ #ifndef _RIVE_DATA_BIND_HPP_ #define _RIVE_DATA_BIND_HPP_ +#include "rive/component_dirt.hpp" #include "rive/generated/data_bind/data_bind_base.hpp" #include "rive/viewmodel/viewmodel_instance_value.hpp" #include "rive/data_bind/context/context_value.hpp" +#include "rive/data_bind/data_context.hpp" #include <stdio.h> namespace rive { @@ -11,14 +13,18 @@ public: StatusCode onAddedDirty(CoreContext* context) override; StatusCode import(ImportStack& importStack) override; - void buildDependencies() override; virtual void updateSourceBinding(); - void update(ComponentDirt value) override; - Component* target() { return m_target; }; + virtual void update(ComponentDirt value); + Core* target() const { return m_target; }; + void target(Core* value) { m_target = value; }; virtual void bind(); + ComponentDirt dirt() { return m_Dirt; }; + void dirt(ComponentDirt value) { m_Dirt = value; }; + bool addDirt(ComponentDirt value, bool recurse); protected: - Component* m_target; + ComponentDirt m_Dirt = ComponentDirt::Filthy; + Core* m_target; ViewModelInstanceValue* m_Source; std::unique_ptr<DataBindContextValue> m_ContextValue; };
diff --git a/include/rive/data_bind/data_bind_context.hpp b/include/rive/data_bind/data_bind_context.hpp index a6bdd46..b7e2ad4 100644 --- a/include/rive/data_bind/data_bind_context.hpp +++ b/include/rive/data_bind/data_bind_context.hpp
@@ -3,6 +3,7 @@ #include "rive/generated/data_bind/data_bind_context_base.hpp" #include "rive/viewmodel/viewmodel_instance_value.hpp" #include "rive/data_bind/context/context_value.hpp" +#include "rive/data_bind/data_context.hpp" #include "rive/refcnt.hpp" #include <stdio.h> namespace rive @@ -15,7 +16,7 @@ public: void decodeSourcePathIds(Span<const uint8_t> value) override; void copySourcePathIds(const DataBindContextBase& object) override; - void bind() override; + void bindFromContext(DataContext* dataContext); ViewModelInstanceValue* source() { return m_Source; }; }; } // namespace rive
diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp index eb3a240..3096b79 100644 --- a/include/rive/generated/core_registry.hpp +++ b/include/rive/generated/core_registry.hpp
@@ -100,6 +100,12 @@ #include "rive/custom_property_boolean.hpp" #include "rive/custom_property_number.hpp" #include "rive/custom_property_string.hpp" +#include "rive/data_bind/bindable_property.hpp" +#include "rive/data_bind/bindable_property_boolean.hpp" +#include "rive/data_bind/bindable_property_color.hpp" +#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/data_bind.hpp" #include "rive/data_bind/data_bind_context.hpp" #include "rive/draw_rules.hpp" @@ -408,10 +414,20 @@ return new Backboard(); case OpenUrlEventBase::typeKey: return new OpenUrlEvent(); + case BindablePropertyBooleanBase::typeKey: + return new BindablePropertyBoolean(); case DataBindBase::typeKey: return new DataBind(); case DataBindContextBase::typeKey: return new DataBindContext(); + case BindablePropertyStringBase::typeKey: + return new BindablePropertyString(); + case BindablePropertyNumberBase::typeKey: + return new BindablePropertyNumber(); + case BindablePropertyEnumBase::typeKey: + return new BindablePropertyEnum(); + case BindablePropertyColorBase::typeKey: + return new BindablePropertyColor(); case WeightBase::typeKey: return new Weight(); case BoneBase::typeKey: @@ -542,6 +558,9 @@ case LayoutComponentBase::clipPropertyKey: object->as<LayoutComponentBase>()->clip(value); break; + case BindablePropertyBooleanBase::propertyValuePropertyKey: + object->as<BindablePropertyBooleanBase>()->propertyValue(value); + break; case TextModifierRangeBase::clampPropertyKey: object->as<TextModifierRangeBase>()->clamp(value); break; @@ -920,15 +939,15 @@ case OpenUrlEventBase::targetValuePropertyKey: object->as<OpenUrlEventBase>()->targetValue(value); break; - case DataBindBase::targetIdPropertyKey: - object->as<DataBindBase>()->targetId(value); - break; case DataBindBase::propertyKeyPropertyKey: object->as<DataBindBase>()->propertyKey(value); break; case DataBindBase::flagsPropertyKey: object->as<DataBindBase>()->flags(value); break; + case BindablePropertyEnumBase::propertyValuePropertyKey: + object->as<BindablePropertyEnumBase>()->propertyValue(value); + break; case WeightBase::valuesPropertyKey: object->as<WeightBase>()->values(value); break; @@ -1019,6 +1038,9 @@ case GradientStopBase::colorValuePropertyKey: object->as<GradientStopBase>()->colorValue(value); break; + case BindablePropertyColorBase::propertyValuePropertyKey: + object->as<BindablePropertyColorBase>()->propertyValue(value); + break; } } static void setString(Core* object, int propertyKey, std::string value) @@ -1052,6 +1074,9 @@ case OpenUrlEventBase::urlPropertyKey: object->as<OpenUrlEventBase>()->url(value); break; + case BindablePropertyStringBase::propertyValuePropertyKey: + object->as<BindablePropertyStringBase>()->propertyValue(value); + break; case TextValueRunBase::textPropertyKey: object->as<TextValueRunBase>()->text(value); break; @@ -1427,6 +1452,9 @@ case JoystickBase::heightPropertyKey: object->as<JoystickBase>()->height(value); break; + case BindablePropertyNumberBase::propertyValuePropertyKey: + object->as<BindablePropertyNumberBase>()->propertyValue(value); + break; case BoneBase::lengthPropertyKey: object->as<BoneBase>()->length(value); break; @@ -1625,6 +1653,8 @@ return object->as<CustomPropertyBooleanBase>()->propertyValue(); case LayoutComponentBase::clipPropertyKey: return object->as<LayoutComponentBase>()->clip(); + case BindablePropertyBooleanBase::propertyValuePropertyKey: + return object->as<BindablePropertyBooleanBase>()->propertyValue(); case TextModifierRangeBase::clampPropertyKey: return object->as<TextModifierRangeBase>()->clamp(); } @@ -1880,12 +1910,12 @@ return object->as<JoystickBase>()->handleSourceId(); case OpenUrlEventBase::targetValuePropertyKey: return object->as<OpenUrlEventBase>()->targetValue(); - case DataBindBase::targetIdPropertyKey: - return object->as<DataBindBase>()->targetId(); case DataBindBase::propertyKeyPropertyKey: return object->as<DataBindBase>()->propertyKey(); case DataBindBase::flagsPropertyKey: return object->as<DataBindBase>()->flags(); + case BindablePropertyEnumBase::propertyValuePropertyKey: + return object->as<BindablePropertyEnumBase>()->propertyValue(); case WeightBase::valuesPropertyKey: return object->as<WeightBase>()->values(); case WeightBase::indicesPropertyKey: @@ -1949,6 +1979,8 @@ return object->as<SolidColorBase>()->colorValue(); case GradientStopBase::colorValuePropertyKey: return object->as<GradientStopBase>()->colorValue(); + case BindablePropertyColorBase::propertyValuePropertyKey: + return object->as<BindablePropertyColorBase>()->propertyValue(); } return 0; } @@ -1974,6 +2006,8 @@ return object->as<KeyFrameStringBase>()->value(); case OpenUrlEventBase::urlPropertyKey: return object->as<OpenUrlEventBase>()->url(); + case BindablePropertyStringBase::propertyValuePropertyKey: + return object->as<BindablePropertyStringBase>()->propertyValue(); case TextValueRunBase::textPropertyKey: return object->as<TextValueRunBase>()->text(); case CustomPropertyStringBase::propertyValuePropertyKey: @@ -2227,6 +2261,8 @@ return object->as<JoystickBase>()->width(); case JoystickBase::heightPropertyKey: return object->as<JoystickBase>()->height(); + case BindablePropertyNumberBase::propertyValuePropertyKey: + return object->as<BindablePropertyNumberBase>()->propertyValue(); case BoneBase::lengthPropertyKey: return object->as<BoneBase>()->length(); case RootBoneBase::xPropertyKey: @@ -2345,6 +2381,7 @@ case ClippingShapeBase::isVisiblePropertyKey: case CustomPropertyBooleanBase::propertyValuePropertyKey: case LayoutComponentBase::clipPropertyKey: + case BindablePropertyBooleanBase::propertyValuePropertyKey: case TextModifierRangeBase::clampPropertyKey: return CoreBoolType::id; case ViewModelInstanceListItemBase::viewModelIdPropertyKey: @@ -2470,9 +2507,9 @@ case JoystickBase::joystickFlagsPropertyKey: case JoystickBase::handleSourceIdPropertyKey: case OpenUrlEventBase::targetValuePropertyKey: - case DataBindBase::targetIdPropertyKey: case DataBindBase::propertyKeyPropertyKey: case DataBindBase::flagsPropertyKey: + case BindablePropertyEnumBase::propertyValuePropertyKey: case WeightBase::valuesPropertyKey: case WeightBase::indicesPropertyKey: case TendonBase::boneIdPropertyKey: @@ -2502,6 +2539,7 @@ case KeyFrameColorBase::valuePropertyKey: case SolidColorBase::colorValuePropertyKey: case GradientStopBase::colorValuePropertyKey: + case BindablePropertyColorBase::propertyValuePropertyKey: return CoreColorType::id; case ViewModelComponentBase::namePropertyKey: case ViewModelInstanceStringBase::propertyValuePropertyKey: @@ -2512,6 +2550,7 @@ case StateMachineComponentBase::namePropertyKey: case KeyFrameStringBase::valuePropertyKey: case OpenUrlEventBase::urlPropertyKey: + case BindablePropertyStringBase::propertyValuePropertyKey: case TextValueRunBase::textPropertyKey: case CustomPropertyStringBase::propertyValuePropertyKey: case AssetBase::namePropertyKey: @@ -2636,6 +2675,7 @@ case JoystickBase::originYPropertyKey: case JoystickBase::widthPropertyKey: case JoystickBase::heightPropertyKey: + case BindablePropertyNumberBase::propertyValuePropertyKey: case BoneBase::lengthPropertyKey: case RootBoneBase::xPropertyKey: case RootBoneBase::yPropertyKey: @@ -2758,6 +2798,8 @@ return object->is<CustomPropertyBooleanBase>(); case LayoutComponentBase::clipPropertyKey: return object->is<LayoutComponentBase>(); + case BindablePropertyBooleanBase::propertyValuePropertyKey: + return object->is<BindablePropertyBooleanBase>(); case TextModifierRangeBase::clampPropertyKey: return object->is<TextModifierRangeBase>(); case ViewModelInstanceListItemBase::viewModelIdPropertyKey: @@ -3006,12 +3048,12 @@ return object->is<JoystickBase>(); case OpenUrlEventBase::targetValuePropertyKey: return object->is<OpenUrlEventBase>(); - case DataBindBase::targetIdPropertyKey: - return object->is<DataBindBase>(); case DataBindBase::propertyKeyPropertyKey: return object->is<DataBindBase>(); case DataBindBase::flagsPropertyKey: return object->is<DataBindBase>(); + case BindablePropertyEnumBase::propertyValuePropertyKey: + return object->is<BindablePropertyEnumBase>(); case WeightBase::valuesPropertyKey: return object->is<WeightBase>(); case WeightBase::indicesPropertyKey: @@ -3068,6 +3110,8 @@ return object->is<SolidColorBase>(); case GradientStopBase::colorValuePropertyKey: return object->is<GradientStopBase>(); + case BindablePropertyColorBase::propertyValuePropertyKey: + return object->is<BindablePropertyColorBase>(); case ViewModelComponentBase::namePropertyKey: return object->is<ViewModelComponentBase>(); case ViewModelInstanceStringBase::propertyValuePropertyKey: @@ -3086,6 +3130,8 @@ return object->is<KeyFrameStringBase>(); case OpenUrlEventBase::urlPropertyKey: return object->is<OpenUrlEventBase>(); + case BindablePropertyStringBase::propertyValuePropertyKey: + return object->is<BindablePropertyStringBase>(); case TextValueRunBase::textPropertyKey: return object->is<TextValueRunBase>(); case CustomPropertyStringBase::propertyValuePropertyKey: @@ -3332,6 +3378,8 @@ return object->is<JoystickBase>(); case JoystickBase::heightPropertyKey: return object->is<JoystickBase>(); + case BindablePropertyNumberBase::propertyValuePropertyKey: + return object->is<BindablePropertyNumberBase>(); case BoneBase::lengthPropertyKey: return object->is<BoneBase>(); case RootBoneBase::xPropertyKey:
diff --git a/include/rive/generated/data_bind/bindable_property_base.hpp b/include/rive/generated/data_bind/bindable_property_base.hpp new file mode 100644 index 0000000..b5d5f14 --- /dev/null +++ b/include/rive/generated/data_bind/bindable_property_base.hpp
@@ -0,0 +1,37 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_BASE_HPP_ +#define _RIVE_BINDABLE_PROPERTY_BASE_HPP_ +#include "rive/core.hpp" +namespace rive +{ +class BindablePropertyBase : public Core +{ +protected: + typedef Core Super; + +public: + static const uint16_t typeKey = 9; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case BindablePropertyBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + void copy(const BindablePropertyBase& object) {} + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override { return false; } + +protected: +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/generated/data_bind/bindable_property_boolean_base.hpp b/include/rive/generated/data_bind/bindable_property_boolean_base.hpp new file mode 100644 index 0000000..366b551 --- /dev/null +++ b/include/rive/generated/data_bind/bindable_property_boolean_base.hpp
@@ -0,0 +1,71 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_BOOLEAN_BASE_HPP_ +#define _RIVE_BINDABLE_PROPERTY_BOOLEAN_BASE_HPP_ +#include "rive/core/field_types/core_bool_type.hpp" +#include "rive/data_bind/bindable_property.hpp" +namespace rive +{ +class BindablePropertyBooleanBase : public BindableProperty +{ +protected: + typedef BindableProperty Super; + +public: + static const uint16_t typeKey = 472; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case BindablePropertyBooleanBase::typeKey: + case BindablePropertyBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t propertyValuePropertyKey = 634; + +private: + bool m_PropertyValue = false; + +public: + inline bool propertyValue() const { return m_PropertyValue; } + void propertyValue(bool value) + { + if (m_PropertyValue == value) + { + return; + } + m_PropertyValue = value; + propertyValueChanged(); + } + + Core* clone() const override; + void copy(const BindablePropertyBooleanBase& object) + { + m_PropertyValue = object.m_PropertyValue; + BindableProperty::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case propertyValuePropertyKey: + m_PropertyValue = CoreBoolType::deserialize(reader); + return true; + } + return BindableProperty::deserialize(propertyKey, reader); + } + +protected: + virtual void propertyValueChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/generated/data_bind/bindable_property_color_base.hpp b/include/rive/generated/data_bind/bindable_property_color_base.hpp new file mode 100644 index 0000000..a14617d --- /dev/null +++ b/include/rive/generated/data_bind/bindable_property_color_base.hpp
@@ -0,0 +1,71 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_COLOR_BASE_HPP_ +#define _RIVE_BINDABLE_PROPERTY_COLOR_BASE_HPP_ +#include "rive/core/field_types/core_color_type.hpp" +#include "rive/data_bind/bindable_property.hpp" +namespace rive +{ +class BindablePropertyColorBase : public BindableProperty +{ +protected: + typedef BindableProperty Super; + +public: + static const uint16_t typeKey = 475; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case BindablePropertyColorBase::typeKey: + case BindablePropertyBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t propertyValuePropertyKey = 638; + +private: + int m_PropertyValue = 0xFF1D1D1D; + +public: + inline int propertyValue() const { return m_PropertyValue; } + void propertyValue(int value) + { + if (m_PropertyValue == value) + { + return; + } + m_PropertyValue = value; + propertyValueChanged(); + } + + Core* clone() const override; + void copy(const BindablePropertyColorBase& object) + { + m_PropertyValue = object.m_PropertyValue; + BindableProperty::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case propertyValuePropertyKey: + m_PropertyValue = CoreColorType::deserialize(reader); + return true; + } + return BindableProperty::deserialize(propertyKey, reader); + } + +protected: + virtual void propertyValueChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/generated/data_bind/bindable_property_enum_base.hpp b/include/rive/generated/data_bind/bindable_property_enum_base.hpp new file mode 100644 index 0000000..30c6f44 --- /dev/null +++ b/include/rive/generated/data_bind/bindable_property_enum_base.hpp
@@ -0,0 +1,71 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_ENUM_BASE_HPP_ +#define _RIVE_BINDABLE_PROPERTY_ENUM_BASE_HPP_ +#include "rive/core/field_types/core_uint_type.hpp" +#include "rive/data_bind/bindable_property.hpp" +namespace rive +{ +class BindablePropertyEnumBase : public BindableProperty +{ +protected: + typedef BindableProperty Super; + +public: + static const uint16_t typeKey = 474; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case BindablePropertyEnumBase::typeKey: + case BindablePropertyBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t propertyValuePropertyKey = 637; + +private: + uint32_t m_PropertyValue = -1; + +public: + inline uint32_t propertyValue() const { return m_PropertyValue; } + void propertyValue(uint32_t value) + { + if (m_PropertyValue == value) + { + return; + } + m_PropertyValue = value; + propertyValueChanged(); + } + + Core* clone() const override; + void copy(const BindablePropertyEnumBase& object) + { + m_PropertyValue = object.m_PropertyValue; + BindableProperty::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case propertyValuePropertyKey: + m_PropertyValue = CoreUintType::deserialize(reader); + return true; + } + return BindableProperty::deserialize(propertyKey, reader); + } + +protected: + virtual void propertyValueChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/generated/data_bind/bindable_property_number_base.hpp b/include/rive/generated/data_bind/bindable_property_number_base.hpp new file mode 100644 index 0000000..72596c1 --- /dev/null +++ b/include/rive/generated/data_bind/bindable_property_number_base.hpp
@@ -0,0 +1,71 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_NUMBER_BASE_HPP_ +#define _RIVE_BINDABLE_PROPERTY_NUMBER_BASE_HPP_ +#include "rive/core/field_types/core_double_type.hpp" +#include "rive/data_bind/bindable_property.hpp" +namespace rive +{ +class BindablePropertyNumberBase : public BindableProperty +{ +protected: + typedef BindableProperty Super; + +public: + static const uint16_t typeKey = 473; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case BindablePropertyNumberBase::typeKey: + case BindablePropertyBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t propertyValuePropertyKey = 636; + +private: + float m_PropertyValue = 0.0f; + +public: + inline float propertyValue() const { return m_PropertyValue; } + void propertyValue(float value) + { + if (m_PropertyValue == value) + { + return; + } + m_PropertyValue = value; + propertyValueChanged(); + } + + Core* clone() const override; + void copy(const BindablePropertyNumberBase& object) + { + m_PropertyValue = object.m_PropertyValue; + BindableProperty::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case propertyValuePropertyKey: + m_PropertyValue = CoreDoubleType::deserialize(reader); + return true; + } + return BindableProperty::deserialize(propertyKey, reader); + } + +protected: + virtual void propertyValueChanged() {} +}; +} // namespace rive + +#endif \ No newline at end of file
diff --git a/include/rive/generated/data_bind/bindable_property_string_base.hpp b/include/rive/generated/data_bind/bindable_property_string_base.hpp new file mode 100644 index 0000000..88d5121 --- /dev/null +++ b/include/rive/generated/data_bind/bindable_property_string_base.hpp
@@ -0,0 +1,72 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_STRING_BASE_HPP_ +#define _RIVE_BINDABLE_PROPERTY_STRING_BASE_HPP_ +#include <string> +#include "rive/core/field_types/core_string_type.hpp" +#include "rive/data_bind/bindable_property.hpp" +namespace rive +{ +class BindablePropertyStringBase : public BindableProperty +{ +protected: + typedef BindableProperty Super; + +public: + static const uint16_t typeKey = 471; + + /// Helper to quickly determine if a core object extends another without RTTI + /// at runtime. + bool isTypeOf(uint16_t typeKey) const override + { + switch (typeKey) + { + case BindablePropertyStringBase::typeKey: + case BindablePropertyBase::typeKey: + return true; + default: + return false; + } + } + + uint16_t coreType() const override { return typeKey; } + + static const uint16_t propertyValuePropertyKey = 635; + +private: + std::string m_PropertyValue = ""; + +public: + inline const std::string& propertyValue() const { return m_PropertyValue; } + void propertyValue(std::string value) + { + if (m_PropertyValue == value) + { + return; + } + m_PropertyValue = value; + propertyValueChanged(); + } + + Core* clone() const override; + void copy(const BindablePropertyStringBase& object) + { + m_PropertyValue = object.m_PropertyValue; + BindableProperty::copy(object); + } + + bool deserialize(uint16_t propertyKey, BinaryReader& reader) override + { + switch (propertyKey) + { + case propertyValuePropertyKey: + m_PropertyValue = CoreStringType::deserialize(reader); + return true; + } + return BindableProperty::deserialize(propertyKey, reader); + } + +protected: + virtual void propertyValueChanged() {} +}; +} // 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 4c73ffc..b900663 100644 --- a/include/rive/generated/data_bind/data_bind_base.hpp +++ b/include/rive/generated/data_bind/data_bind_base.hpp
@@ -1,13 +1,13 @@ #ifndef _RIVE_DATA_BIND_BASE_HPP_ #define _RIVE_DATA_BIND_BASE_HPP_ -#include "rive/component.hpp" +#include "rive/core.hpp" #include "rive/core/field_types/core_uint_type.hpp" namespace rive { -class DataBindBase : public Component +class DataBindBase : public Core { protected: - typedef Component Super; + typedef Core Super; public: static const uint16_t typeKey = 446; @@ -19,7 +19,6 @@ switch (typeKey) { case DataBindBase::typeKey: - case ComponentBase::typeKey: return true; default: return false; @@ -28,27 +27,14 @@ uint16_t coreType() const override { return typeKey; } - static const uint16_t targetIdPropertyKey = 585; static const uint16_t propertyKeyPropertyKey = 586; static const uint16_t flagsPropertyKey = 587; private: - uint32_t m_TargetId = -1; uint32_t m_PropertyKey = Core::invalidPropertyKey; uint32_t m_Flags = 0; public: - inline uint32_t targetId() const { return m_TargetId; } - void targetId(uint32_t value) - { - if (m_TargetId == value) - { - return; - } - m_TargetId = value; - targetIdChanged(); - } - inline uint32_t propertyKey() const { return m_PropertyKey; } void propertyKey(uint32_t value) { @@ -74,19 +60,14 @@ Core* clone() const override; void copy(const DataBindBase& object) { - m_TargetId = object.m_TargetId; m_PropertyKey = object.m_PropertyKey; m_Flags = object.m_Flags; - Component::copy(object); } bool deserialize(uint16_t propertyKey, BinaryReader& reader) override { switch (propertyKey) { - case targetIdPropertyKey: - m_TargetId = CoreUintType::deserialize(reader); - return true; case propertyKeyPropertyKey: m_PropertyKey = CoreUintType::deserialize(reader); return true; @@ -94,11 +75,10 @@ m_Flags = CoreUintType::deserialize(reader); return true; } - return Component::deserialize(propertyKey, reader); + return false; } protected: - virtual void targetIdChanged() {} virtual void propertyKeyChanged() {} virtual void flagsChanged() {} };
diff --git a/include/rive/generated/data_bind/data_bind_context_base.hpp b/include/rive/generated/data_bind/data_bind_context_base.hpp index d1871d4..e8b772a 100644 --- a/include/rive/generated/data_bind/data_bind_context_base.hpp +++ b/include/rive/generated/data_bind/data_bind_context_base.hpp
@@ -21,7 +21,6 @@ { case DataBindContextBase::typeKey: case DataBindBase::typeKey: - case ComponentBase::typeKey: return true; default: return false;
diff --git a/include/rive/importers/artboard_importer.hpp b/include/rive/importers/artboard_importer.hpp index 1525803..102bfd0 100644 --- a/include/rive/importers/artboard_importer.hpp +++ b/include/rive/importers/artboard_importer.hpp
@@ -11,6 +11,7 @@ class StateMachine; class TextValueRun; class Event; +class DataBind; class ArtboardImporter : public ImportStackObject { private: @@ -21,6 +22,7 @@ void addComponent(Core* object); void addAnimation(LinearAnimation* animation); void addStateMachine(StateMachine* stateMachine); + void addDataBind(DataBind* dataBind); StatusCode resolve() override; const Artboard* artboard() const { return m_Artboard; }
diff --git a/include/rive/importers/bindable_property_importer.hpp b/include/rive/importers/bindable_property_importer.hpp new file mode 100644 index 0000000..002ebe7 --- /dev/null +++ b/include/rive/importers/bindable_property_importer.hpp
@@ -0,0 +1,20 @@ +#ifndef _RIVE_BINDABLE_PROPERTY_IMPORTER_HPP_ +#define _RIVE_BINDABLE_PROPERTY_IMPORTER_HPP_ + +#include "rive/importers/import_stack.hpp" + +namespace rive +{ +class Core; +class BindableProperty; +class BindablePropertyImporter : public ImportStackObject +{ +private: + BindableProperty* m_bindableProperty; + +public: + BindablePropertyImporter(BindableProperty* bindableProperty); + BindableProperty* bindableProperty() { return m_bindableProperty; } +}; +} // namespace rive +#endif \ No newline at end of file
diff --git a/include/rive/importers/state_machine_importer.hpp b/include/rive/importers/state_machine_importer.hpp index f00ae45..dc08236 100644 --- a/include/rive/importers/state_machine_importer.hpp +++ b/include/rive/importers/state_machine_importer.hpp
@@ -9,6 +9,7 @@ class StateMachineLayer; class StateMachineListener; class StateMachine; +class DataBind; class StateMachineImporter : public ImportStackObject { private: @@ -21,6 +22,7 @@ void addLayer(std::unique_ptr<StateMachineLayer>); void addInput(std::unique_ptr<StateMachineInput>); void addListener(std::unique_ptr<StateMachineListener>); + void addDataBind(std::unique_ptr<DataBind>); StatusCode resolve() override; bool readNullObject() override;
diff --git a/include/rive/nested_artboard.hpp b/include/rive/nested_artboard.hpp index 9f57ec4..5759815 100644 --- a/include/rive/nested_artboard.hpp +++ b/include/rive/nested_artboard.hpp
@@ -2,6 +2,8 @@ #define _RIVE_NESTED_ARTBOARD_HPP_ #include "rive/generated/nested_artboard_base.hpp" +#include "rive/data_bind/data_context.hpp" +#include "rive/viewmodel/viewmodel_instance_value.hpp" #include "rive/hit_info.hpp" #include "rive/span.hpp" #include <stdio.h> @@ -97,6 +99,8 @@ void decodeDataBindPathIds(Span<const uint8_t> value) override; void copyDataBindPathIds(const NestedArtboardBase& object) override; std::vector<uint32_t> dataBindPathIds() { return m_DataBindPathIdsBuffer; }; + void dataContextFromInstance(ViewModelInstance* viewModelInstance, DataContext* parent); + void internalDataContext(DataContext* dataContext, DataContext* parent); }; } // namespace rive
diff --git a/include/rive/scene.hpp b/include/rive/scene.hpp index fd96d8e..7d36204 100644 --- a/include/rive/scene.hpp +++ b/include/rive/scene.hpp
@@ -13,6 +13,7 @@ { class ArtboardInstance; class Renderer; +class ViewModelInstance; class SMIInput; class SMIBool; @@ -47,6 +48,8 @@ void draw(Renderer*); + virtual void dataContextFromInstance(ViewModelInstance* viewModelInstance); + virtual HitResult pointerDown(Vec2D); virtual HitResult pointerMove(Vec2D); virtual HitResult pointerUp(Vec2D);
diff --git a/src/animation/nested_state_machine.cpp b/src/animation/nested_state_machine.cpp index 6045b56..8176757 100644 --- a/src/animation/nested_state_machine.cpp +++ b/src/animation/nested_state_machine.cpp
@@ -107,4 +107,20 @@ return nullptr; } -void NestedStateMachine::addNestedInput(NestedInput* input) { m_nestedInputs.push_back(input); } \ No newline at end of file +void NestedStateMachine::addNestedInput(NestedInput* input) { m_nestedInputs.push_back(input); } + +void NestedStateMachine::dataContextFromInstance(ViewModelInstance* viewModelInstance) +{ + if (m_StateMachineInstance != nullptr) + { + m_StateMachineInstance->dataContextFromInstance(viewModelInstance); + } +} + +void NestedStateMachine::dataContext(DataContext* dataContext) +{ + if (m_StateMachineInstance != nullptr) + { + m_StateMachineInstance->dataContext(dataContext); + } +} \ No newline at end of file
diff --git a/src/animation/state_machine.cpp b/src/animation/state_machine.cpp index 0450691..9b44672 100644 --- a/src/animation/state_machine.cpp +++ b/src/animation/state_machine.cpp
@@ -91,6 +91,11 @@ m_Listeners.push_back(std::move(listener)); } +void StateMachine::addDataBind(std::unique_ptr<DataBind> dataBind) +{ + m_dataBinds.push_back(std::move(dataBind)); +} + const StateMachineInput* StateMachine::input(std::string name) const { for (auto& input : m_Inputs) @@ -140,4 +145,13 @@ return m_Listeners[index].get(); } return nullptr; +} + +const DataBind* StateMachine::dataBind(size_t index) const +{ + if (index < m_dataBinds.size()) + { + return m_dataBinds[index].get(); + } + return nullptr; } \ No newline at end of file
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp index 90bafbc..274ea78 100644 --- a/src/animation/state_machine_instance.cpp +++ b/src/animation/state_machine_instance.cpp
@@ -904,6 +904,23 @@ return getNamedInput<StateMachineTrigger, SMITrigger>(name); } +void StateMachineInstance::dataContextFromInstance(ViewModelInstance* viewModelInstance) +{ + dataContext(new DataContext(viewModelInstance)); +} + +void StateMachineInstance::dataContext(DataContext* dataContext) +{ + m_DataContext = dataContext; + for (auto dataBind : m_dataBinds) + { + if (dataBind->is<DataBindContext>()) + { + dataBind->as<DataBindContext>()->bindFromContext(dataContext); + } + } +} + size_t StateMachineInstance::stateChangedCount() const { size_t count = 0; @@ -1039,4 +1056,14 @@ } } } +} + +BindableProperty* StateMachineInstance::bindablePropertyInstance(BindableProperty* bindableProperty) +{ + auto bindablePropertyInstance = m_bindablePropertyInstances.find(bindableProperty); + if (bindablePropertyInstance == m_bindablePropertyInstances.end()) + { + return nullptr; + } + return bindablePropertyInstance->second; } \ No newline at end of file
diff --git a/src/artboard.cpp b/src/artboard.cpp index 47c5d04..3a0b299 100644 --- a/src/artboard.cpp +++ b/src/artboard.cpp
@@ -173,9 +173,6 @@ case NestedArtboardBase::typeKey: m_NestedArtboards.push_back(object->as<NestedArtboard>()); break; - case DataBindContext::typeKey: - m_DataBinds.push_back(object->as<DataBind>()); - break; case JoystickBase::typeKey: { @@ -515,12 +512,12 @@ for (auto dataBind : m_AllDataBinds) { dataBind->updateSourceBinding(); - auto d = dataBind->m_Dirt; + auto d = dataBind->dirt(); if (d == ComponentDirt::None) { continue; } - dataBind->m_Dirt = ComponentDirt::None; + dataBind->dirt(ComponentDirt::None); dataBind->update(d); } } @@ -1004,102 +1001,38 @@ auto value = m_DataContext->getViewModelInstance(nestedArtboard->dataBindPathIds()); if (value != nullptr && value->is<ViewModelInstance>()) { - nestedArtboard->artboard()->dataContextFromInstance(value, m_DataContext, false); + nestedArtboard->dataContextFromInstance(value, m_DataContext); } else { - nestedArtboard->artboard()->internalDataContext(m_DataContext, - m_DataContext->parent(), - false); + nestedArtboard->internalDataContext(m_DataContext, m_DataContext->parent()); } } for (auto dataBind : m_DataBinds) { if (dataBind->is<DataBindContext>()) { - dataBind->as<DataBindContext>()->bind(); + dataBind->as<DataBindContext>()->bindFromContext(m_DataContext); } } if (isRoot) { - std::vector<Component*> dataBinds; + std::vector<DataBind*> dataBinds; populateDataBinds(&dataBinds); - buildDataBindDependencies(&dataBinds); sortDataBinds(dataBinds); } } -void Artboard::sortDataBinds(std::vector<Component*> dataBinds) +void Artboard::sortDataBinds(std::vector<DataBind*> dataBinds) { - DependencySorter sorter; // TODO: @hernan review this. Should not need to push to a component list to sort. - std::vector<Component*> dbOrder; - sorter.sort(dataBinds, dbOrder); - for (auto dataBind : dbOrder) + for (auto dataBind : dataBinds) { m_AllDataBinds.push_back(dataBind->as<DataBind>()); } } -void Artboard::buildDataBindDependencies(std::vector<Component*>* dataBinds) -{ - // TODO: @hernan review this dependency building - // Do we really need this? If a property is bound to a data bind, it can't be bound - // to a second data bind object. - for (auto component : *dataBinds) - { - auto dataBind = component->as<DataBind>(); - auto flags = static_cast<DataBindFlags>(dataBind->flags()); - // If the data bind reads from the target, we want to add it as dependent from any other - // parent data bind that writes into that target. - if (((flags & DataBindFlags::Direction) == DataBindFlags::ToSource) || - ((flags & DataBindFlags::TwoWay) == DataBindFlags::TwoWay)) - { - for (auto innerComponent : *dataBinds) - { - auto dataBindParent = innerComponent->as<DataBind>(); - auto parentFlags = static_cast<DataBindFlags>(dataBindParent->flags()); - if (dataBindParent != dataBind && - (((parentFlags & DataBindFlags::Direction) == DataBindFlags::ToTarget) || - ((parentFlags & DataBindFlags::TwoWay) == DataBindFlags::TwoWay)) && - dataBindParent->target() == dataBind->target() && - dataBindParent->propertyKey() == dataBind->propertyKey()) - { - dataBindParent->addDependent(dataBind); - break; - } - } - } - else - { - // If the data bind reads from a source we want to add it as dependent - // from any other parent data bind that writes into that source. - if (dataBind->is<DataBindContext>()) - { - for (auto innerComponent : *dataBinds) - { - auto dataBindParent = innerComponent->as<DataBind>(); - if (dataBindParent != dataBind) - { - auto parentFlags = static_cast<DataBindFlags>(dataBindParent->flags()); - if (((parentFlags & DataBindFlags::Direction) == DataBindFlags::ToSource) || - ((parentFlags & DataBindFlags::TwoWay) == DataBindFlags::TwoWay)) - { - if (dataBindParent->is<DataBindContext>() && - dataBindParent->as<DataBindContext>()->source() == - dataBind->as<DataBindContext>()->source()) - { - dataBindParent->addDependent(dataBind); - break; - } - } - } - } - } - } - } -} float Artboard::volume() const { return m_volume; } void Artboard::volume(float value) { @@ -1114,7 +1047,7 @@ } } -void Artboard::populateDataBinds(std::vector<Component*>* dataBinds) +void Artboard::populateDataBinds(std::vector<DataBind*>* dataBinds) { for (auto dataBind : m_DataBinds) { @@ -1129,6 +1062,8 @@ } } +void Artboard::addDataBind(DataBind* dataBind) { m_DataBinds.push_back(dataBind); } + void Artboard::dataContext(DataContext* value, DataContext* parent) { internalDataContext(value, parent, true);
diff --git a/src/data_bind/context/context_value_boolean.cpp b/src/data_bind/context/context_value_boolean.cpp index 3116aa9..b7b708b 100644 --- a/src/data_bind/context/context_value_boolean.cpp +++ b/src/data_bind/context/context_value_boolean.cpp
@@ -6,16 +6,17 @@ DataBindContextValueBoolean::DataBindContextValueBoolean(ViewModelInstanceValue* value) { m_Source = value; + m_Value = m_Source->as<ViewModelInstanceBoolean>()->propertyValue(); } -void DataBindContextValueBoolean::apply(Component* target, uint32_t propertyKey) +void DataBindContextValueBoolean::apply(Core* target, uint32_t propertyKey) { CoreRegistry::setBool(target, propertyKey, m_Source->as<ViewModelInstanceBoolean>()->propertyValue()); } -void DataBindContextValueBoolean::applyToSource(Component* target, uint32_t propertyKey) +void DataBindContextValueBoolean::applyToSource(Core* target, uint32_t propertyKey) { auto value = CoreRegistry::getBool(target, propertyKey); if (m_Value != value)
diff --git a/src/data_bind/context/context_value_color.cpp b/src/data_bind/context/context_value_color.cpp index 18d392f..44a1857 100644 --- a/src/data_bind/context/context_value_color.cpp +++ b/src/data_bind/context/context_value_color.cpp
@@ -6,16 +6,17 @@ DataBindContextValueColor::DataBindContextValueColor(ViewModelInstanceValue* value) { m_Source = value; + m_Value = m_Source->as<ViewModelInstanceColor>()->propertyValue(); } -void DataBindContextValueColor::apply(Component* target, uint32_t propertyKey) +void DataBindContextValueColor::apply(Core* target, uint32_t propertyKey) { CoreRegistry::setColor(target, propertyKey, m_Source->as<ViewModelInstanceColor>()->propertyValue()); } -void DataBindContextValueColor::applyToSource(Component* target, uint32_t propertyKey) +void DataBindContextValueColor::applyToSource(Core* target, uint32_t propertyKey) { auto value = CoreRegistry::getColor(target, propertyKey); if (m_Value != value)
diff --git a/src/data_bind/context/context_value_enum.cpp b/src/data_bind/context/context_value_enum.cpp index 8569ce9..a0064bc 100644 --- a/src/data_bind/context/context_value_enum.cpp +++ b/src/data_bind/context/context_value_enum.cpp
@@ -6,17 +6,23 @@ DataBindContextValueEnum::DataBindContextValueEnum(ViewModelInstanceValue* value) { m_Source = value; + m_Value = m_Source->as<ViewModelInstanceEnum>()->propertyValue(); } -void DataBindContextValueEnum::apply(Component* target, uint32_t propertyKey) +void DataBindContextValueEnum::apply(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(Component* target, uint32_t propertyKey) +void DataBindContextValueEnum::applyToSource(Core* target, uint32_t propertyKey) { auto value = CoreRegistry::getString(target, propertyKey); auto enumSource = m_Source->as<ViewModelInstanceEnum>();
diff --git a/src/data_bind/context/context_value_list.cpp b/src/data_bind/context/context_value_list.cpp index 59f0f55..f0aa427 100644 --- a/src/data_bind/context/context_value_list.cpp +++ b/src/data_bind/context/context_value_list.cpp
@@ -40,12 +40,12 @@ return nullptr; } -void DataBindContextValueList::insertItem(Component* target, +void DataBindContextValueList::insertItem(Core* target, ViewModelInstanceListItem* listItem, int index) { auto artboard = listItem->artboard(); - auto artboardCopy = createArtboard(target, artboard, listItem); + auto artboardCopy = createArtboard(target->as<Component>(), artboard, listItem); auto stateMachineInstance = createStateMachineInstance(artboardCopy.get()); std::unique_ptr<DataBindContextValueListItem> cacheListItem = rivestd::make_unique<DataBindContextValueListItem>(std::move(artboardCopy), @@ -61,14 +61,14 @@ } } -void DataBindContextValueList::swapItems(Component* target, int index1, int index2) +void DataBindContextValueList::swapItems(Core* target, int index1, int index2) { std::iter_swap(m_ListItemsCache.begin() + index1, m_ListItemsCache.begin() + index2); } -void DataBindContextValueList::popItem(Component* target) { m_ListItemsCache.pop_back(); } +void DataBindContextValueList::popItem(Core* target) { m_ListItemsCache.pop_back(); } -void DataBindContextValueList::update(Component* target) +void DataBindContextValueList::update(Core* target) { if (target != nullptr) { @@ -125,9 +125,9 @@ } } -void DataBindContextValueList::apply(Component* target, uint32_t propertyKey) {} +void DataBindContextValueList::apply(Core* target, uint32_t propertyKey) {} -void DataBindContextValueList::applyToSource(Component* target, uint32_t propertyKey) +void DataBindContextValueList::applyToSource(Core* target, uint32_t propertyKey) { // 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 ecc5b7f..63fabf8 100644 --- a/src/data_bind/context/context_value_number.cpp +++ b/src/data_bind/context/context_value_number.cpp
@@ -6,16 +6,17 @@ DataBindContextValueNumber::DataBindContextValueNumber(ViewModelInstanceValue* value) { m_Source = value; + m_Value = m_Source->as<ViewModelInstanceNumber>()->propertyValue(); } -void DataBindContextValueNumber::apply(Component* target, uint32_t propertyKey) +void DataBindContextValueNumber::apply(Core* target, uint32_t propertyKey) { CoreRegistry::setDouble(target, propertyKey, m_Source->as<ViewModelInstanceNumber>()->propertyValue()); } -void DataBindContextValueNumber::applyToSource(Component* target, uint32_t propertyKey) +void DataBindContextValueNumber::applyToSource(Core* target, uint32_t propertyKey) { auto value = CoreRegistry::getDouble(target, propertyKey); if (m_Value != value)
diff --git a/src/data_bind/context/context_value_string.cpp b/src/data_bind/context/context_value_string.cpp index 6a62e75..9cf19f7 100644 --- a/src/data_bind/context/context_value_string.cpp +++ b/src/data_bind/context/context_value_string.cpp
@@ -6,16 +6,17 @@ DataBindContextValueString::DataBindContextValueString(ViewModelInstanceValue* value) { m_Source = value; + m_Value = m_Source->as<ViewModelInstanceString>()->propertyValue(); } -void DataBindContextValueString::apply(Component* target, uint32_t propertyKey) +void DataBindContextValueString::apply(Core* target, uint32_t propertyKey) { CoreRegistry::setString(target, propertyKey, m_Source->as<ViewModelInstanceString>()->propertyValue()); } -void DataBindContextValueString::applyToSource(Component* target, uint32_t propertyKey) +void DataBindContextValueString::applyToSource(Core* target, uint32_t propertyKey) { auto value = CoreRegistry::getString(target, propertyKey); if (m_Value != value)
diff --git a/src/data_bind/data_bind.cpp b/src/data_bind/data_bind.cpp index adfa276..a1ab715 100644 --- a/src/data_bind/data_bind.cpp +++ b/src/data_bind/data_bind.cpp
@@ -2,6 +2,11 @@ #include "rive/artboard.hpp" #include "rive/data_bind_flags.hpp" #include "rive/generated/core_registry.hpp" +#include "rive/data_bind/bindable_property_number.hpp" +#include "rive/data_bind/bindable_property_string.hpp" +#include "rive/data_bind/bindable_property_color.hpp" +#include "rive/data_bind/bindable_property_enum.hpp" +#include "rive/data_bind/bindable_property_boolean.hpp" #include "rive/data_bind/context/context_value.hpp" #include "rive/data_bind/context/context_value_boolean.hpp" #include "rive/data_bind/context/context_value_number.hpp" @@ -9,14 +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/animation/state_machine.hpp" +#include "rive/importers/artboard_importer.hpp" +#include "rive/importers/state_machine_importer.hpp" using namespace rive; -// StatusCode DataBind::onAddedClean(CoreContext* context) -// { -// return Super::onAddedClean(context); -// } - StatusCode DataBind::onAddedDirty(CoreContext* context) { StatusCode code = Super::onAddedDirty(context); @@ -24,28 +27,44 @@ { return code; } - auto coreObject = context->resolve(targetId()); - if (coreObject == nullptr || !coreObject->is<Component>()) - { - return StatusCode::MissingObject; - } - - m_target = static_cast<Component*>(coreObject); return StatusCode::Ok; } -StatusCode DataBind::import(ImportStack& importStack) { return Super::import(importStack); } - -void DataBind::buildDependencies() +StatusCode DataBind::import(ImportStack& importStack) { - Super::buildDependencies(); - auto flagsValue = static_cast<DataBindFlags>(flags()); - if (((flagsValue & DataBindFlags::Direction) == DataBindFlags::ToSource) || - ((flagsValue & DataBindFlags::TwoWay) == DataBindFlags::TwoWay)) + if (target()) { - m_target->addDependent(this); + switch (target()->coreType()) + { + case BindablePropertyNumberBase::typeKey: + case BindablePropertyStringBase::typeKey: + case BindablePropertyBooleanBase::typeKey: + case BindablePropertyEnumBase::typeKey: + case BindablePropertyColorBase::typeKey: + { + auto stateMachineImporter = + importStack.latest<StateMachineImporter>(StateMachineBase::typeKey); + if (stateMachineImporter != nullptr) + { + stateMachineImporter->addDataBind(std::unique_ptr<DataBind>(this)); + return Super::import(importStack); + } + break; + } + default: + { + auto artboardImporter = importStack.latest<ArtboardImporter>(ArtboardBase::typeKey); + if (artboardImporter != nullptr) + { + artboardImporter->addDataBind(this); + return Super::import(importStack); + } + break; + } + } } + return Super::import(importStack); } void DataBind::bind() @@ -97,7 +116,6 @@ } } } - Super::update(value); } void DataBind::updateSourceBinding() @@ -111,4 +129,16 @@ m_ContextValue->applyToSource(m_target, propertyKey()); } } +} + +bool DataBind::addDirt(ComponentDirt value, bool recurse) +{ + if ((m_Dirt & value) == value) + { + // Already marked. + return false; + } + + m_Dirt |= value; + return true; } \ No newline at end of file
diff --git a/src/data_bind/data_bind_context.cpp b/src/data_bind/data_bind_context.cpp index 4bb86f6..62eae73 100644 --- a/src/data_bind/data_bind_context.cpp +++ b/src/data_bind/data_bind_context.cpp
@@ -26,9 +26,8 @@ m_SourcePathIdsBuffer = object.as<DataBindContext>()->m_SourcePathIdsBuffer; } -void DataBindContext::bind() +void DataBindContext::bindFromContext(DataContext* dataContext) { - auto dataContext = artboard()->dataContext(); if (dataContext != nullptr) { auto value = dataContext->getViewModelProperty(m_SourcePathIdsBuffer); @@ -36,7 +35,7 @@ { value->addDependent(this); m_Source = value; - Super::bind(); + bind(); } } } \ No newline at end of file
diff --git a/src/file.cpp b/src/file.cpp index 93bdf04..57fb4a7 100644 --- a/src/file.cpp +++ b/src/file.cpp
@@ -8,6 +8,7 @@ #include "rive/generated/core_registry.hpp" #include "rive/importers/artboard_importer.hpp" #include "rive/importers/backboard_importer.hpp" +#include "rive/importers/bindable_property_importer.hpp" #include "rive/importers/enum_importer.hpp" #include "rive/importers/file_asset_importer.hpp" #include "rive/importers/import_stack.hpp" @@ -30,6 +31,12 @@ #include "rive/animation/animation_state.hpp" #include "rive/animation/blend_state_1d.hpp" #include "rive/animation/blend_state_direct.hpp" +#include "rive/data_bind/bindable_property.hpp" +#include "rive/data_bind/bindable_property_number.hpp" +#include "rive/data_bind/bindable_property_string.hpp" +#include "rive/data_bind/bindable_property_color.hpp" +#include "rive/data_bind/bindable_property_enum.hpp" +#include "rive/data_bind/bindable_property_boolean.hpp" #include "rive/assets/file_asset.hpp" #include "rive/assets/audio_asset.hpp" #include "rive/assets/file_asset_contents.hpp" @@ -204,6 +211,10 @@ ImportResult File::read(BinaryReader& reader, const RuntimeHeader& header) { ImportStack importStack; + // TODO: @hernan consider moving this to a special importer. It's not that + // simple because Core doesn't have a typeKey, so it should be treated as + // a special case. In any case, it's not that bad having it here for now. + Core* lastBindableObject; while (!reader.reachedEnd()) { auto object = readRuntimeObject(reader, header); @@ -212,6 +223,14 @@ importStack.readNullObject(); continue; } + if (!object->is<DataBind>()) + { + lastBindableObject = object; + } + else if (lastBindableObject != nullptr) + { + object->as<DataBind>()->target(lastBindableObject); + } if (object->import(importStack) == StatusCode::Ok) { switch (object->coreType()) @@ -353,6 +372,15 @@ object->as<ViewModelInstanceList>()); stackType = ViewModelInstanceList::typeKey; break; + case BindablePropertyNumber::typeKey: + case BindablePropertyString::typeKey: + case BindablePropertyColor::typeKey: + case BindablePropertyEnum::typeKey: + case BindablePropertyBoolean::typeKey: + stackObject = + rivestd::make_unique<BindablePropertyImporter>(object->as<BindableProperty>()); + stackType = BindablePropertyBase::typeKey; + break; } if (importStack.makeLatest(stackType, std::move(stackObject)) != StatusCode::Ok) {
diff --git a/src/generated/data_bind/bindable_property_boolean_base.cpp b/src/generated/data_bind/bindable_property_boolean_base.cpp new file mode 100644 index 0000000..4e3dcc2 --- /dev/null +++ b/src/generated/data_bind/bindable_property_boolean_base.cpp
@@ -0,0 +1,11 @@ +#include "rive/generated/data_bind/bindable_property_boolean_base.hpp" +#include "rive/data_bind/bindable_property_boolean.hpp" + +using namespace rive; + +Core* BindablePropertyBooleanBase::clone() const +{ + auto cloned = new BindablePropertyBoolean(); + cloned->copy(*this); + return cloned; +}
diff --git a/src/generated/data_bind/bindable_property_color_base.cpp b/src/generated/data_bind/bindable_property_color_base.cpp new file mode 100644 index 0000000..fa64a07 --- /dev/null +++ b/src/generated/data_bind/bindable_property_color_base.cpp
@@ -0,0 +1,11 @@ +#include "rive/generated/data_bind/bindable_property_color_base.hpp" +#include "rive/data_bind/bindable_property_color.hpp" + +using namespace rive; + +Core* BindablePropertyColorBase::clone() const +{ + auto cloned = new BindablePropertyColor(); + cloned->copy(*this); + return cloned; +}
diff --git a/src/generated/data_bind/bindable_property_enum_base.cpp b/src/generated/data_bind/bindable_property_enum_base.cpp new file mode 100644 index 0000000..acd5be6 --- /dev/null +++ b/src/generated/data_bind/bindable_property_enum_base.cpp
@@ -0,0 +1,11 @@ +#include "rive/generated/data_bind/bindable_property_enum_base.hpp" +#include "rive/data_bind/bindable_property_enum.hpp" + +using namespace rive; + +Core* BindablePropertyEnumBase::clone() const +{ + auto cloned = new BindablePropertyEnum(); + cloned->copy(*this); + return cloned; +}
diff --git a/src/generated/data_bind/bindable_property_number_base.cpp b/src/generated/data_bind/bindable_property_number_base.cpp new file mode 100644 index 0000000..95b0453 --- /dev/null +++ b/src/generated/data_bind/bindable_property_number_base.cpp
@@ -0,0 +1,11 @@ +#include "rive/generated/data_bind/bindable_property_number_base.hpp" +#include "rive/data_bind/bindable_property_number.hpp" + +using namespace rive; + +Core* BindablePropertyNumberBase::clone() const +{ + auto cloned = new BindablePropertyNumber(); + cloned->copy(*this); + return cloned; +}
diff --git a/src/generated/data_bind/bindable_property_string_base.cpp b/src/generated/data_bind/bindable_property_string_base.cpp new file mode 100644 index 0000000..04133c7 --- /dev/null +++ b/src/generated/data_bind/bindable_property_string_base.cpp
@@ -0,0 +1,11 @@ +#include "rive/generated/data_bind/bindable_property_string_base.hpp" +#include "rive/data_bind/bindable_property_string.hpp" + +using namespace rive; + +Core* BindablePropertyStringBase::clone() const +{ + auto cloned = new BindablePropertyString(); + cloned->copy(*this); + return cloned; +}
diff --git a/src/importers/artboard_importer.cpp b/src/importers/artboard_importer.cpp index d0d93df..f2957b0 100644 --- a/src/importers/artboard_importer.cpp +++ b/src/importers/artboard_importer.cpp
@@ -2,6 +2,7 @@ #include "rive/importers/artboard_importer.hpp" #include "rive/animation/linear_animation.hpp" #include "rive/animation/state_machine.hpp" +#include "rive/data_bind/data_bind.hpp" #include "rive/text/text_value_run.hpp" #include "rive/event.hpp" #include "rive/artboard.hpp" @@ -22,6 +23,8 @@ m_Artboard->addStateMachine(stateMachine); } +void ArtboardImporter::addDataBind(DataBind* dataBind) { m_Artboard->addDataBind(dataBind); } + StatusCode ArtboardImporter::resolve() { return m_Artboard->initialize(); } bool ArtboardImporter::readNullObject()
diff --git a/src/importers/bindable_property_importer.cpp b/src/importers/bindable_property_importer.cpp new file mode 100644 index 0000000..1d992af --- /dev/null +++ b/src/importers/bindable_property_importer.cpp
@@ -0,0 +1,9 @@ +#include "rive/artboard.hpp" +#include "rive/importers/bindable_property_importer.hpp" +#include "rive/data_bind/bindable_property.hpp" + +using namespace rive; + +BindablePropertyImporter::BindablePropertyImporter(BindableProperty* bindableProperty) : + m_bindableProperty(bindableProperty) +{} \ No newline at end of file
diff --git a/src/importers/state_machine_importer.cpp b/src/importers/state_machine_importer.cpp index 7994c37..70a3985 100644 --- a/src/importers/state_machine_importer.cpp +++ b/src/importers/state_machine_importer.cpp
@@ -3,6 +3,7 @@ #include "rive/animation/state_machine_listener.hpp" #include "rive/animation/state_machine_input.hpp" #include "rive/animation/state_machine_layer.hpp" +#include "rive/data_bind/data_bind.hpp" using namespace rive; @@ -23,6 +24,11 @@ m_StateMachine->addListener(std::move(listener)); } +void StateMachineImporter::addDataBind(std::unique_ptr<DataBind> dataBind) +{ + m_StateMachine->addDataBind(std::move(dataBind)); +} + bool StateMachineImporter::readNullObject() { // Hard assumption that we won't add new layer types...
diff --git a/src/nested_artboard.cpp b/src/nested_artboard.cpp index 6ef8cf3..19437dc 100644 --- a/src/nested_artboard.cpp +++ b/src/nested_artboard.cpp
@@ -273,4 +273,29 @@ void NestedArtboard::copyDataBindPathIds(const NestedArtboardBase& object) { m_DataBindPathIdsBuffer = object.as<NestedArtboard>()->m_DataBindPathIdsBuffer; +} + +void NestedArtboard::internalDataContext(DataContext* value, DataContext* parent) +{ + artboard()->internalDataContext(value, parent, false); + for (auto animation : m_NestedAnimations) + { + if (animation->is<NestedStateMachine>()) + { + animation->as<NestedStateMachine>()->dataContext(value); + } + } +} + +void NestedArtboard::dataContextFromInstance(ViewModelInstance* viewModelInstance, + DataContext* parent) +{ + artboard()->dataContextFromInstance(viewModelInstance, parent, false); + for (auto animation : m_NestedAnimations) + { + if (animation->is<NestedStateMachine>()) + { + animation->as<NestedStateMachine>()->dataContextFromInstance(viewModelInstance); + } + } } \ No newline at end of file
diff --git a/src/scene.cpp b/src/scene.cpp index a987dfe..679f33e 100644 --- a/src/scene.cpp +++ b/src/scene.cpp
@@ -25,6 +25,7 @@ SMIBool* Scene::getBool(const std::string&) const { return nullptr; } SMINumber* Scene::getNumber(const std::string&) const { return nullptr; } SMITrigger* Scene::getTrigger(const std::string&) const { return nullptr; } +void Scene::dataContextFromInstance(ViewModelInstance* viewModelInstance) {} void Scene::reportKeyedCallback(uint32_t objectId, uint32_t propertyKey, float elapsedSeconds) {
diff --git a/src/viewmodel/viewmodel_instance_enum.cpp b/src/viewmodel/viewmodel_instance_enum.cpp index 0cdbc60..3b7a755 100644 --- a/src/viewmodel/viewmodel_instance_enum.cpp +++ b/src/viewmodel/viewmodel_instance_enum.cpp
@@ -8,7 +8,7 @@ using namespace rive; -void ViewModelInstanceEnum::propertyValueChanged() { addDirt(ComponentDirt::Components); } +void ViewModelInstanceEnum::propertyValueChanged() { addDirt(ComponentDirt::Bindings); } bool ViewModelInstanceEnum::value(std::string name) {