Xxxx data binding data context some small code improvements - reorganize code to get things ready for binding text runs - support to bind color two way - fix bug: new data binds not updating if they were created in animate mode Diffs= 9cd8759a0 Xxxx data binding data context (#7454) Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head index bd73d8c..d6e407c 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -31f5ee5c480ab9b2c1a0d263305f56bfd943d780 +9cd8759a02aaa45684e80a8d77671c1536ab387d
diff --git a/include/rive/data_bind/data_bind.hpp b/include/rive/data_bind/data_bind.hpp index ec9b5ae..7efbcc8 100644 --- a/include/rive/data_bind/data_bind.hpp +++ b/include/rive/data_bind/data_bind.hpp
@@ -1,6 +1,8 @@ #ifndef _RIVE_DATA_BIND_HPP_ #define _RIVE_DATA_BIND_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 <stdio.h> namespace rive { @@ -11,10 +13,14 @@ StatusCode import(ImportStack& importStack) override; void buildDependencies() override; virtual void updateSourceBinding(); + void update(ComponentDirt value) override; Component* target() { return m_target; }; + virtual void bind(); protected: Component* m_target; + ViewModelInstanceValue* m_Source; + std::unique_ptr<DataBindContextValue> m_ContextValue; }; } // namespace rive
diff --git a/include/rive/data_bind/data_bind_context.hpp b/include/rive/data_bind/data_bind_context.hpp index 93028b4..113b7fb 100644 --- a/include/rive/data_bind/data_bind_context.hpp +++ b/include/rive/data_bind/data_bind_context.hpp
@@ -11,14 +11,12 @@ { protected: std::vector<uint32_t> m_SourcePathIdsBuffer; - ViewModelInstanceValue* m_Source; - std::unique_ptr<DataBindContextValue> m_ContextValue; public: void update(ComponentDirt value) override; void decodeSourcePathIds(Span<const uint8_t> value) override; void copySourcePathIds(const DataBindContextBase& object) override; - void bindToContext(); + void bind() override; void updateSourceBinding() override; ViewModelInstanceValue* source() { return m_Source; }; };
diff --git a/include/rive/viewmodel/viewmodel_instance_value.hpp b/include/rive/viewmodel/viewmodel_instance_value.hpp index 7e3d5c7..484aa8e 100644 --- a/include/rive/viewmodel/viewmodel_instance_value.hpp +++ b/include/rive/viewmodel/viewmodel_instance_value.hpp
@@ -8,7 +8,7 @@ #include <stdio.h> namespace rive { -class DataBindContext; +class DataBind; class ViewModelInstance; class ViewModelInstanceValue : public ViewModelInstanceValueBase { @@ -16,14 +16,14 @@ ViewModelProperty* m_ViewModelProperty; protected: - DependencyHelper<ViewModelInstance, DataBindContext> m_DependencyHelper; + DependencyHelper<ViewModelInstance, DataBind> m_DependencyHelper; void addDirt(ComponentDirt value); public: StatusCode import(ImportStack& importStack) override; void viewModelProperty(ViewModelProperty* value); ViewModelProperty* viewModelProperty(); - void addDependent(DataBindContext* value); + void addDependent(DataBind* value); virtual void setRoot(ViewModelInstance* value); }; } // namespace rive
diff --git a/src/artboard.cpp b/src/artboard.cpp index 4ecf5da..dbd2f6e 100644 --- a/src/artboard.cpp +++ b/src/artboard.cpp
@@ -973,7 +973,7 @@ { if (dataBind->is<DataBindContext>()) { - dataBind->as<DataBindContext>()->bindToContext(); + dataBind->as<DataBindContext>()->bind(); } } if (isRoot)
diff --git a/src/data_bind/data_bind.cpp b/src/data_bind/data_bind.cpp index 4f59d89..441be60 100644 --- a/src/data_bind/data_bind.cpp +++ b/src/data_bind/data_bind.cpp
@@ -2,6 +2,12 @@ #include "rive/data_bind/data_bind_mode.hpp" #include "rive/artboard.hpp" #include "rive/generated/core_registry.hpp" +#include "rive/data_bind/context/context_value.hpp" +#include "rive/data_bind/context/context_value_number.hpp" +#include "rive/data_bind/context/context_value_string.hpp" +#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" using namespace rive; @@ -40,4 +46,62 @@ } } -void DataBind::updateSourceBinding() {} \ No newline at end of file +void DataBind::bind() +{ + switch (m_Source->coreType()) + { + case ViewModelInstanceNumberBase::typeKey: + m_ContextValue = rivestd::make_unique<DataBindContextValueNumber>(m_Source); + break; + case ViewModelInstanceStringBase::typeKey: + m_ContextValue = rivestd::make_unique<DataBindContextValueString>(m_Source); + break; + case ViewModelInstanceEnumBase::typeKey: + m_ContextValue = rivestd::make_unique<DataBindContextValueEnum>(m_Source); + break; + case ViewModelInstanceListBase::typeKey: + m_ContextValue = rivestd::make_unique<DataBindContextValueList>(m_Source); + m_ContextValue->update(m_target); + break; + case ViewModelInstanceColorBase::typeKey: + m_ContextValue = rivestd::make_unique<DataBindContextValueColor>(m_Source); + break; + } +} + +void DataBind::update(ComponentDirt value) +{ + if (m_Source != nullptr && m_ContextValue != nullptr) + { + + // Use the ComponentDirt::Components flag to indicate the viewmodel has added or removed + // an element to a list. + if ((value & ComponentDirt::Components) == ComponentDirt::Components) + { + m_ContextValue->update(m_target); + } + if ((value & ComponentDirt::Bindings) == ComponentDirt::Bindings) + { + // TODO: @hernan review how dirt and mode work together. If dirt is not set for + // certain modes, we might be able to skip the mode validation. + auto mode = static_cast<DataBindMode>(modeValue()); + if (mode == DataBindMode::oneWay || mode == DataBindMode::twoWay) + { + m_ContextValue->apply(m_target, propertyKey()); + } + } + } + Super::update(value); +} + +void DataBind::updateSourceBinding() +{ + auto mode = static_cast<DataBindMode>(modeValue()); + if (mode == DataBindMode::oneWayToSource || mode == DataBindMode::twoWay) + { + if (m_ContextValue != nullptr) + { + m_ContextValue->applyToSource(m_target, propertyKey()); + } + } +} \ 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 77194d4..a249226 100644 --- a/src/data_bind/data_bind_context.cpp +++ b/src/data_bind/data_bind_context.cpp
@@ -26,7 +26,7 @@ m_SourcePathIdsBuffer = object.as<DataBindContext>()->m_SourcePathIdsBuffer; } -void DataBindContext::bindToContext() +void DataBindContext::bind() { auto dataContext = artboard()->dataContext(); if (dataContext != nullptr) @@ -36,28 +36,7 @@ { value->addDependent(this); m_Source = value; - if (m_Source->is<ViewModelInstanceNumber>()) - { - m_ContextValue = rivestd::make_unique<DataBindContextValueNumber>(m_Source); - } - else if (m_Source->is<ViewModelInstanceString>()) - { - m_ContextValue = rivestd::make_unique<DataBindContextValueString>(m_Source); - } - else if (m_Source->is<ViewModelInstanceEnum>()) - { - m_ContextValue = rivestd::make_unique<DataBindContextValueEnum>(m_Source); - } - else if (m_Source->is<ViewModelInstanceList>()) - { - m_ContextValue = rivestd::make_unique<DataBindContextValueList>(m_Source); - // TODO: @hernan decide the best place to initialize this - m_ContextValue->update(m_target); - } - else if (m_Source->is<ViewModelInstanceColor>()) - { - m_ContextValue = rivestd::make_unique<DataBindContextValueColor>(m_Source); - } + Super::bind(); } } }
diff --git a/src/viewmodel/viewmodel_instance_value.cpp b/src/viewmodel/viewmodel_instance_value.cpp index 2e4fac2..de7bdba 100644 --- a/src/viewmodel/viewmodel_instance_value.cpp +++ b/src/viewmodel/viewmodel_instance_value.cpp
@@ -5,7 +5,7 @@ #include "rive/viewmodel/viewmodel_instance.hpp" #include "rive/viewmodel/viewmodel_instance_value.hpp" #include "rive/importers/viewmodel_instance_importer.hpp" -#include "rive/data_bind/data_bind_context.hpp" +#include "rive/data_bind/data_bind.hpp" using namespace rive; @@ -28,7 +28,7 @@ } ViewModelProperty* ViewModelInstanceValue::viewModelProperty() { return m_ViewModelProperty; } -void ViewModelInstanceValue::addDependent(DataBindContext* value) +void ViewModelInstanceValue::addDependent(DataBind* value) { m_DependencyHelper.addDependent(value); }