add support to data bind solos by index and name (#10337) 64f828c9a2 Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head index ef0d699..76045c1 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -9af6af0361de2258ff05a708cacc8e58899e0d4a +64f828c9a278586f61b7636da99d68404c906176
diff --git a/include/rive/solo.hpp b/include/rive/solo.hpp index 8458d76..baf4b86 100644 --- a/include/rive/solo.hpp +++ b/include/rive/solo.hpp
@@ -9,6 +9,10 @@ void activeComponentIdChanged() override; StatusCode onAddedClean(CoreContext* context) override; bool collapse(bool value) override; + void updateByIndex(size_t index); + void updateByName(std::string& name); + int getActiveChildIndex(); + std::string getActiveChildName(); private: void propagateCollapse(bool collapse);
diff --git a/src/data_bind/context/context_value_number.cpp b/src/data_bind/context/context_value_number.cpp index 5a4fd7e..01d501d 100644 --- a/src/data_bind/context/context_value_number.cpp +++ b/src/data_bind/context/context_value_number.cpp
@@ -22,8 +22,16 @@ CoreRegistry::setDouble(target, propertyKey, value); break; case CoreUintType::id: - int rounded = value < 0 ? 0 : std::round(value); - CoreRegistry::setUint(target, propertyKey, rounded); + + if (target && target->is<Solo>()) + { + target->as<Solo>()->updateByIndex((size_t)std::round(value)); + } + else + { + int rounded = value < 0 ? 0 : std::round(value); + CoreRegistry::setUint(target, propertyKey, rounded); + } break; } } @@ -41,7 +49,14 @@ break; case CoreUintType::id: { - value = (float)CoreRegistry::getUint(target, propertyKey); + if (target && target->is<Solo>()) + { + value = (float)target->as<Solo>()->getActiveChildIndex(); + } + else + { + value = (float)CoreRegistry::getUint(target, propertyKey); + } break; } }
diff --git a/src/data_bind/context/context_value_string.cpp b/src/data_bind/context/context_value_string.cpp index e4b8c6c..899676d 100644 --- a/src/data_bind/context/context_value_string.cpp +++ b/src/data_bind/context/context_value_string.cpp
@@ -16,13 +16,40 @@ auto value = calculateValue<DataValueString, std::string>(m_dataValue, isMainDirection, m_dataBind); - CoreRegistry::setString(target, propertyKey, value); + switch (CoreRegistry::propertyFieldId(propertyKey)) + { + case CoreUintType::id: + { + if (target && target->is<Solo>()) + { + target->as<Solo>()->updateByName(value); + } + break; + } + default: + CoreRegistry::setString(target, propertyKey, value); + break; + } } bool DataBindContextValueString::syncTargetValue(Core* target, uint32_t propertyKey) { - auto value = CoreRegistry::getString(target, propertyKey); + std::string value = ""; + switch (CoreRegistry::propertyFieldId(propertyKey)) + { + case CoreUintType::id: + { + if (target && target->is<Solo>()) + { + value = target->as<Solo>()->getActiveChildName(); + } + break; + } + default: + value = CoreRegistry::getString(target, propertyKey); + break; + } if (m_previousValue != value) {
diff --git a/src/solo.cpp b/src/solo.cpp index 4eb0859..82632a8 100644 --- a/src/solo.cpp +++ b/src/solo.cpp
@@ -51,4 +51,56 @@ propagateCollapse(isCollapsed()); return StatusCode::Ok; -} \ No newline at end of file +} + +void Solo::updateByIndex(size_t index) +{ + if (index >= 0 && index < children().size() && artboard()) + { + auto child = children()[index]; + int globalIndex = artboard()->idOf(child); + activeComponentId(globalIndex); + } +} + +void Solo::updateByName(std::string& name) +{ + for (auto& child : children()) + { + if (child->name() == name) + { + + int globalIndex = artboard()->idOf(child); + activeComponentId(globalIndex); + break; + } + } +} + +int Solo::getActiveChildIndex() +{ + Core* active = artboard()->resolve(activeComponentId()); + if (active) + { + int index = 0; + for (auto& child : children()) + { + if (child == active) + { + return index; + } + index++; + } + } + return -1; +} + +std::string Solo::getActiveChildName() +{ + Core* active = artboard()->resolve(activeComponentId()); + if (active && active->is<Component>()) + { + return active->as<Component>()->name(); + } + return ""; +}
diff --git a/tests/unit_tests/assets/data_bind_solo.riv b/tests/unit_tests/assets/data_bind_solo.riv new file mode 100644 index 0000000..1367c84 --- /dev/null +++ b/tests/unit_tests/assets/data_bind_solo.riv Binary files differ
diff --git a/tests/unit_tests/runtime/data_binding_test.cpp b/tests/unit_tests/runtime/data_binding_test.cpp index 2109229..11a5935 100644 --- a/tests/unit_tests/runtime/data_binding_test.cpp +++ b/tests/unit_tests/runtime/data_binding_test.cpp
@@ -1222,4 +1222,76 @@ } CHECK(silver.matches("custom_property_trigger_bind")); -} \ No newline at end of file +} + +TEST_CASE("Data binding solos", "[data binding]") +{ + + rive::SerializingFactory silver; + auto file = ReadRiveFile("assets/data_bind_solo.riv", &silver); + + auto artboard = file->artboardNamed("values-to-solos"); + + silver.frameSize(artboard->width(), artboard->height()); + + REQUIRE(artboard != nullptr); + auto stateMachine = artboard->stateMachineAt(0); + int viewModelId = artboard.get()->viewModelId(); + + auto vmi = viewModelId == -1 + ? file->createViewModelInstance(artboard.get()) + : file->createViewModelInstance(viewModelId, 0); + + stateMachine->bindViewModelInstance(vmi); + stateMachine->advanceAndApply(0.0f); + stateMachine->advanceAndApply(0.016f); + + auto renderer = silver.makeRenderer(); + artboard->draw(renderer.get()); + + int frames = (int)(1.0f / 0.016f); + for (int i = 0; i < frames; i++) + { + silver.addFrame(); + stateMachine->advanceAndApply(0.016f); + artboard->draw(renderer.get()); + } + + CHECK(silver.matches("data_bind_solo-values-to-solos")); +} + +TEST_CASE("Data binding solos - target to source", "[data binding]") +{ + + rive::SerializingFactory silver; + auto file = ReadRiveFile("assets/data_bind_solo.riv", &silver); + + auto artboard = file->artboardNamed("solos-to-values"); + + silver.frameSize(artboard->width(), artboard->height()); + + REQUIRE(artboard != nullptr); + auto stateMachine = artboard->stateMachineAt(0); + int viewModelId = artboard.get()->viewModelId(); + + auto vmi = viewModelId == -1 + ? file->createViewModelInstance(artboard.get()) + : file->createViewModelInstance(viewModelId, 0); + + stateMachine->bindViewModelInstance(vmi); + stateMachine->advanceAndApply(0.0f); + stateMachine->advanceAndApply(0.016f); + + auto renderer = silver.makeRenderer(); + artboard->draw(renderer.get()); + + int frames = (int)(1.0f / 0.016f); + for (int i = 0; i < frames; i++) + { + silver.addFrame(); + stateMachine->advanceAndApply(0.016f); + artboard->draw(renderer.get()); + } + + CHECK(silver.matches("data_bind_solo-solos-to-values")); +}
diff --git a/tests/unit_tests/silvers/data_bind_solo-solos-to-values.sriv b/tests/unit_tests/silvers/data_bind_solo-solos-to-values.sriv new file mode 100644 index 0000000..af621a6 --- /dev/null +++ b/tests/unit_tests/silvers/data_bind_solo-solos-to-values.sriv Binary files differ
diff --git a/tests/unit_tests/silvers/data_bind_solo-values-to-solos.sriv b/tests/unit_tests/silvers/data_bind_solo-values-to-solos.sriv new file mode 100644 index 0000000..3880c22 --- /dev/null +++ b/tests/unit_tests/silvers/data_bind_solo-values-to-solos.sriv Binary files differ