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)
{