Renderer in editor Starting to let tests run. Diffs= a0a6c0d3b Renderer in editor (#7495) Co-authored-by: Luigi Rosso <luigi-rosso@users.noreply.github.com> Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head index f234bbf..7510dfe 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -876a2dca5228aa6a27e934c3e0f430853a157931 +a0a6c0d3bd385f32dd51e1fbcb75306332b9d1cc
diff --git a/build/premake5.lua b/build/premake5.lua index 576761c..52dd2a6 100644 --- a/build/premake5.lua +++ b/build/premake5.lua
@@ -48,7 +48,7 @@ harfbuzz .. '/src', sheenbidi .. '/Headers', miniaudio, - yoga + yoga, }) defines({ 'YOGA_EXPORT=' }) @@ -163,11 +163,6 @@ objdir('%{cfg.system}/arm64/obj/%{cfg.buildcfg}') end - filter('system:emscripten') - do - buildoptions({ '-pthread' }) - end - filter('configurations:debug') do defines({ 'DEBUG' }) @@ -217,4 +212,4 @@ newoption({ trigger = 'with_rive_layout', description = 'Compiles in layout features.', -}) \ No newline at end of file +})
diff --git a/build/rive_build_config.lua b/build/rive_build_config.lua index f6ff510..b6138c4 100644 --- a/build/rive_build_config.lua +++ b/build/rive_build_config.lua
@@ -141,7 +141,7 @@ default = 'default', }) --- This is just to match our old windows config. Gamekit specifically sets +-- This is just to match our old windows config. Rive Native specifically sets -- static/dynamic and maybe we should do the same elsewhere. filter({ 'system:windows', 'options:windows_runtime=default' }) do
diff --git a/include/rive/animation/nested_state_machine.hpp b/include/rive/animation/nested_state_machine.hpp index c76729a..8c0476b 100644 --- a/include/rive/animation/nested_state_machine.hpp +++ b/include/rive/animation/nested_state_machine.hpp
@@ -28,6 +28,9 @@ HitResult pointerDown(Vec2D position); HitResult pointerUp(Vec2D position); HitResult pointerExit(Vec2D position); +#ifdef WITH_RIVE_TOOLS + bool hitTest(Vec2D position) const; +#endif void addNestedInput(NestedInput* input); size_t inputCount() { return m_nestedInputs.size(); }
diff --git a/include/rive/animation/state_machine_input_instance.hpp b/include/rive/animation/state_machine_input_instance.hpp index e5f732c..8c82a71 100644 --- a/include/rive/animation/state_machine_input_instance.hpp +++ b/include/rive/animation/state_machine_input_instance.hpp
@@ -20,9 +20,6 @@ friend class StateMachineLayerInstance; private: - StateMachineInstance* m_MachineInstance; - const StateMachineInput* m_Input; - virtual void advanced() {} protected: @@ -32,10 +29,17 @@ public: virtual ~SMIInput() {} - const StateMachineInput* input() const { return m_Input; } + const StateMachineInput* input() const { return m_input; } const std::string& name() const; uint16_t inputCoreType() const; + +private: + StateMachineInstance* m_machineInstance; + const StateMachineInput* m_input; +#ifdef WITH_RIVE_TOOLS + uint64_t m_index = 0; +#endif }; class SMIBool : public SMIInput @@ -72,16 +76,16 @@ friend class TransitionTriggerCondition; private: - bool m_Fired = false; + bool m_fired = false; SMITrigger(const StateMachineTrigger* input, StateMachineInstance* machineInstance); - void advanced() override { m_Fired = false; } + void advanced() override { m_fired = false; } public: void fire(); #ifdef TESTING - bool didFire() { return m_Fired; } + bool didFire() { return m_fired; } #endif }; } // namespace rive
diff --git a/include/rive/animation/state_machine_instance.hpp b/include/rive/animation/state_machine_instance.hpp index 786366f..c59ee17 100644 --- a/include/rive/animation/state_machine_instance.hpp +++ b/include/rive/animation/state_machine_instance.hpp
@@ -32,6 +32,11 @@ class KeyedProperty; class EventReport; +#ifdef WITH_RIVE_TOOLS +class StateMachineInstance; +typedef void (*InputChanged)(StateMachineInstance*, uint64_t); +#endif + class StateMachineInstance : public Scene, public NestedEventNotifier, public NestedEventListener { friend class SMIInput; @@ -92,6 +97,9 @@ HitResult pointerDown(Vec2D position) override; HitResult pointerUp(Vec2D position) override; HitResult pointerExit(Vec2D position) override; +#ifdef WITH_RIVE_TOOLS + bool hitTest(Vec2D position) const; +#endif float durationSeconds() const override { return -1; } Loop loop() const override { return Loop::oneShot; } @@ -131,6 +139,11 @@ std::vector<std::unique_ptr<HitComponent>> m_hitComponents; StateMachineInstance* m_parentStateMachineInstance = nullptr; NestedArtboard* m_parentNestedArtboard = nullptr; +#ifdef WITH_RIVE_TOOLS +public: + void onInputChanged(InputChanged callback) { m_inputChangedCallback = callback; } + InputChanged m_inputChangedCallback = nullptr; +#endif }; } // namespace rive #endif
diff --git a/include/rive/artboard.hpp b/include/rive/artboard.hpp index 1051af9..85353c1 100644 --- a/include/rive/artboard.hpp +++ b/include/rive/artboard.hpp
@@ -44,6 +44,10 @@ class SMINumber; class SMITrigger; +#ifdef WITH_RIVE_TOOLS +typedef void (*ArtboardCallback)(Artboard*); +#endif + class Artboard : public ArtboardBase, public CoreContext, public ShapePaintContainer { friend class File; @@ -135,8 +139,8 @@ } #endif - bool advance(double elapsedSeconds); - bool advanceInternal(double elapsedSeconds, bool isRoot); + bool advance(double elapsedSeconds, bool nested = true); + bool advanceInternal(double elapsedSeconds, bool isRoot, bool nested = true); bool hasChangedDrawOrderInLastUpdate() { return m_HasChangedDrawOrderInLastUpdate; }; Drawable* firstDrawable() { return m_FirstDrawable; }; @@ -161,9 +165,10 @@ NestedArtboard* nestedArtboard(const std::string& name) const; NestedArtboard* nestedArtboardAtPath(const std::string& path) const; - float originalWidth() { return m_originalWidth; } - float originalHeight() { return m_originalHeight; } - + float originalWidth() const { return m_originalWidth; } + float originalHeight() const { return m_originalHeight; } + float layoutWidth() const; + float layoutHeight() const; AABB bounds() const; // Can we hide these from the public? (they use playable) @@ -341,8 +346,18 @@ rcp<AudioEngine> audioEngine() const; void audioEngine(rcp<AudioEngine> audioEngine); #endif + +#ifdef WITH_RIVE_LAYOUT + void propagateSize() override; +#endif private: float m_volume = 1.0f; +#ifdef WITH_RIVE_TOOLS + ArtboardCallback m_layoutChangedCallback = nullptr; + +public: + void onLayoutChanged(ArtboardCallback callback) { m_layoutChangedCallback = callback; } +#endif }; class ArtboardInstance : public Artboard
diff --git a/include/rive/core/binary_writer.hpp b/include/rive/core/binary_writer.hpp index 213e295..8d87cee 100644 --- a/include/rive/core/binary_writer.hpp +++ b/include/rive/core/binary_writer.hpp
@@ -1,4 +1,3 @@ - #ifndef _RIVE_CORE_BINARY_WRITER_HPP_ #define _RIVE_CORE_BINARY_WRITER_HPP_ @@ -24,6 +23,8 @@ void write(const uint8_t* bytes, std::size_t length); void write(uint8_t value); void writeDouble(double value); + void write(uint16_t value); + void write(uint32_t value); void clear(); }; } // namespace rive
diff --git a/include/rive/layout_component.hpp b/include/rive/layout_component.hpp index 6b6e31a..c070587 100644 --- a/include/rive/layout_component.hpp +++ b/include/rive/layout_component.hpp
@@ -32,7 +32,7 @@ class LayoutComponent : public LayoutComponentBase { -private: +protected: LayoutComponentStyle* m_style = nullptr; std::unique_ptr<LayoutData> m_layoutData; @@ -66,7 +66,7 @@ #ifdef WITH_RIVE_LAYOUT LayoutComponent(); void syncStyle(); - void propagateSize(); + virtual void propagateSize(); void updateLayoutBounds(); void update(ComponentDirt value) override; StatusCode onAddedDirty(CoreContext* context) override;
diff --git a/include/rive/nested_animation.hpp b/include/rive/nested_animation.hpp index fc31df6..70edc4d 100644 --- a/include/rive/nested_animation.hpp +++ b/include/rive/nested_animation.hpp
@@ -35,17 +35,14 @@ void notifyListeners(const std::vector<Event*>& events) { - if (m_nestedArtboard != nullptr) + std::vector<EventReport> eventReports; + for (auto event : events) { - std::vector<EventReport> eventReports; - for (auto event : events) - { - eventReports.push_back(EventReport(event, 0)); - } - for (auto listener : m_nestedEventListeners) - { - listener->notify(eventReports, m_nestedArtboard); - } + eventReports.push_back(EventReport(event, 0)); + } + for (auto listener : m_nestedEventListeners) + { + listener->notify(eventReports, m_nestedArtboard); } }
diff --git a/include/rive/shapes/paint/trim_path.hpp b/include/rive/shapes/paint/trim_path.hpp index d937481..150af98 100644 --- a/include/rive/shapes/paint/trim_path.hpp +++ b/include/rive/shapes/paint/trim_path.hpp
@@ -8,13 +8,12 @@ namespace rive { -enum class TrimPathMode : unsigned char +enum class TrimPathMode : uint8_t { sequential = 1, synchronized = 2 }; -class ContourMeasure; class TrimPath : public TrimPathBase, public StrokeEffect {
diff --git a/src/animation/nested_state_machine.cpp b/src/animation/nested_state_machine.cpp index f973429..6045b56 100644 --- a/src/animation/nested_state_machine.cpp +++ b/src/animation/nested_state_machine.cpp
@@ -39,6 +39,17 @@ return m_StateMachineInstance.get(); } +#ifdef WITH_RIVE_TOOLS +bool NestedStateMachine::hitTest(Vec2D position) const +{ + if (m_StateMachineInstance != nullptr) + { + return m_StateMachineInstance->hitTest(position); + } + return false; +} +#endif + HitResult NestedStateMachine::pointerMove(Vec2D position) { if (m_StateMachineInstance != nullptr)
diff --git a/src/animation/state_machine_input_instance.cpp b/src/animation/state_machine_input_instance.cpp index 5c2fb33..d2e98d6 100644 --- a/src/animation/state_machine_input_instance.cpp +++ b/src/animation/state_machine_input_instance.cpp
@@ -7,14 +7,24 @@ using namespace rive; SMIInput::SMIInput(const StateMachineInput* input, StateMachineInstance* machineInstance) : - m_MachineInstance(machineInstance), m_Input(input) + m_machineInstance(machineInstance), m_input(input) {} -uint16_t SMIInput::inputCoreType() const { return m_Input->coreType(); } +uint16_t SMIInput::inputCoreType() const { return m_input->coreType(); } -const std::string& SMIInput::name() const { return m_Input->name(); } +const std::string& SMIInput::name() const { return m_input->name(); } -void SMIInput::valueChanged() { m_MachineInstance->markNeedsAdvance(); } +void SMIInput::valueChanged() +{ + m_machineInstance->markNeedsAdvance(); +#ifdef WITH_RIVE_TOOLS + auto callback = m_machineInstance->m_inputChangedCallback; + if (callback != nullptr) + { + callback(m_machineInstance, m_index); + } +#endif +} // bool @@ -54,10 +64,10 @@ void SMITrigger::fire() { - if (m_Fired) + if (m_fired) { return; } - m_Fired = true; + m_fired = true; valueChanged(); }
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp index c6f7316..d564b87 100644 --- a/src/animation/state_machine_instance.cpp +++ b/src/animation/state_machine_instance.cpp
@@ -430,6 +430,9 @@ {} virtual ~HitComponent() {} virtual HitResult processEvent(Vec2D position, ListenerType hitType, bool canHit) = 0; +#ifdef WITH_RIVE_TOOLS + virtual bool hitTest(Vec2D position) const = 0; +#endif protected: Component* m_component; @@ -451,8 +454,10 @@ std::vector<const StateMachineListener*> listeners; bool hitTest(Vec2D position) const +#ifdef WITH_RIVE_TOOLS + override +#endif { - auto shape = m_component->as<Shape>(); auto worldBounds = shape->worldBounds(); if (!worldBounds.contains(position)) @@ -516,6 +521,36 @@ HitComponent(nestedArtboard, stateMachineInstance) {} ~HitNestedArtboard() override {} + +#ifdef WITH_RIVE_TOOLS + bool hitTest(Vec2D position) const override + { + auto nestedArtboard = m_component->as<NestedArtboard>(); + if (nestedArtboard->isCollapsed()) + { + return false; + } + Vec2D nestedPosition; + if (!nestedArtboard->worldToLocal(position, &nestedPosition)) + { + // Mounted artboard isn't ready or has a 0 scale transform. + return false; + } + + for (auto nestedAnimation : nestedArtboard->nestedAnimations()) + { + if (nestedAnimation->is<NestedStateMachine>()) + { + auto nestedStateMachine = nestedAnimation->as<NestedStateMachine>(); + if (nestedStateMachine->hitTest(nestedPosition)) + { + return true; + } + } + } + return false; + } +#endif HitResult processEvent(Vec2D position, ListenerType hitType, bool canHit) override { auto nestedArtboard = m_component->as<NestedArtboard>(); @@ -589,7 +624,6 @@ bool hitOpaque = false; for (const auto& hitShape : m_hitComponents) { - // TODO: quick reject. HitResult hitResult = hitShape->processEvent(position, hitType, !hitOpaque); @@ -605,6 +639,28 @@ return hitSomething ? hitOpaque ? HitResult::hitOpaque : HitResult::hit : HitResult::none; } +#ifdef WITH_RIVE_TOOLS +bool StateMachineInstance::hitTest(Vec2D position) const +{ + if (m_artboardInstance->frameOrigin()) + { + position -= Vec2D(m_artboardInstance->originX() * m_artboardInstance->width(), + m_artboardInstance->originY() * m_artboardInstance->height()); + } + + for (const auto& hitShape : m_hitComponents) + { + // TODO: quick reject. + + if (hitShape->hitTest(position)) + { + return true; + } + } + return false; +} +#endif + HitResult StateMachineInstance::pointerMove(Vec2D position) { return updateListeners(position, ListenerType::move); @@ -650,6 +706,13 @@ // Sanity check. break; } +#ifdef WITH_RIVE_TOOLS + auto instance = m_inputInstances[i]; + if (instance != nullptr) + { + instance->m_index = i; + } +#endif } m_layerCount = machine->layerCount(); @@ -958,12 +1021,9 @@ } } // Bubble the event up to parent artboard state machines immediately - if (nestedArtboard() != nullptr) + for (auto listener : nestedEventListeners()) { - for (auto listener : nestedEventListeners()) - { - listener->notify(events, nestedArtboard()); - } + listener->notify(events, nestedArtboard()); } for (auto report : events)
diff --git a/src/animation/transition_trigger_condition.cpp b/src/animation/transition_trigger_condition.cpp index a9ed142..86391fe 100644 --- a/src/animation/transition_trigger_condition.cpp +++ b/src/animation/transition_trigger_condition.cpp
@@ -21,7 +21,7 @@ } auto triggerInput = static_cast<const SMITrigger*>(inputInstance); - if (triggerInput->m_Fired) + if (triggerInput->m_fired) { return true; }
diff --git a/src/artboard.cpp b/src/artboard.cpp index 25aa369..a72cba2 100644 --- a/src/artboard.cpp +++ b/src/artboard.cpp
@@ -86,6 +86,8 @@ // these will be re-built in update() -- are they needed here? m_BackgroundPath = factory()->makeEmptyRenderPath(); m_ClipPath = factory()->makeEmptyRenderPath(); + m_layoutSizeWidth = width(); + m_layoutSizeHeight = height(); #ifdef WITH_RIVE_LAYOUT markLayoutDirty(this); @@ -444,6 +446,37 @@ void Artboard::onDirty(ComponentDirt dirt) { m_Dirt |= ComponentDirt::Components; } +#ifdef WITH_RIVE_LAYOUT +void Artboard::propagateSize() +{ + addDirt(ComponentDirt::Path); +#ifdef WITH_RIVE_TOOLS + if (m_layoutChangedCallback != nullptr) + { + m_layoutChangedCallback(this); + } +#endif +} +#endif + +float Artboard::layoutWidth() const +{ +#ifdef WITH_RIVE_LAYOUT + return m_layoutSizeWidth; +#else + return width(); +#endif +} + +float Artboard::layoutHeight() const +{ +#ifdef WITH_RIVE_LAYOUT + return m_layoutSizeHeight; +#else + return height(); +#endif +} + void Artboard::update(ComponentDirt value) { if (hasDirt(value, ComponentDirt::DrawOrder)) @@ -452,11 +485,14 @@ } if (hasDirt(value, ComponentDirt::Path)) { - AABB bg = AABB::fromLTWH(-width() * originX(), -height() * originY(), width(), height()); + AABB bg = AABB::fromLTWH(-layoutWidth() * originX(), + -layoutHeight() * originY(), + layoutWidth(), + layoutHeight()); AABB clip; if (m_FrameOrigin) { - clip = {0.0f, 0.0f, width(), height()}; + clip = {0.0f, 0.0f, layoutWidth(), layoutHeight()}; } else { @@ -530,7 +566,7 @@ return false; } -bool Artboard::advanceInternal(double elapsedSeconds, bool isRoot) +bool Artboard::advanceInternal(double elapsedSeconds, bool isRoot, bool nested) { bool didUpdate = false; m_HasChangedDrawOrderInLastUpdate = false; @@ -604,17 +640,23 @@ didUpdate = true; } } - for (auto nestedArtboard : m_NestedArtboards) + if (nested) { - if (nestedArtboard->advance((float)elapsedSeconds)) + for (auto nestedArtboard : m_NestedArtboards) { - didUpdate = true; + if (nestedArtboard->advance((float)elapsedSeconds)) + { + didUpdate = true; + } } } return didUpdate; } -bool Artboard::advance(double elapsedSeconds) { return advanceInternal(elapsedSeconds, true); } +bool Artboard::advance(double elapsedSeconds, bool nested) +{ + return advanceInternal(elapsedSeconds, true, nested); +} Core* Artboard::hitTest(HitInfo* hinfo, const Mat2D* xform) { @@ -626,7 +668,7 @@ auto mx = xform ? *xform : Mat2D(); if (m_FrameOrigin) { - mx *= Mat2D::fromTranslate(width() * originX(), height() * originY()); + mx *= Mat2D::fromTranslate(layoutWidth() * originX(), layoutHeight() * originY()); } Drawable* last = m_FirstDrawable; @@ -666,8 +708,8 @@ if (m_FrameOrigin) { Mat2D artboardTransform; - artboardTransform[4] = width() * originX(); - artboardTransform[5] = height() * originY(); + artboardTransform[4] = layoutWidth() * originX(); + artboardTransform[5] = layoutHeight() * originY(); renderer->transform(artboardTransform); } @@ -709,9 +751,11 @@ AABB Artboard::bounds() const { - return m_FrameOrigin - ? AABB(0.0f, 0.0f, width(), height()) - : AABB::fromLTWH(-width() * originX(), -height() * originY(), width(), height()); + return m_FrameOrigin ? AABB(0.0f, 0.0f, layoutWidth(), layoutHeight()) + : AABB::fromLTWH(-layoutWidth() * originX(), + -layoutHeight() * originY(), + layoutWidth(), + layoutHeight()); } bool Artboard::isTranslucent() const
diff --git a/src/core/binary_writer.cpp b/src/core/binary_writer.cpp index ef0fd68..323e586 100644 --- a/src/core/binary_writer.cpp +++ b/src/core/binary_writer.cpp
@@ -100,8 +100,6 @@ m_Stream->write(bytes, length); } -void BinaryWriter::write(uint8_t value) { m_Stream->write(&value, 1); } - void BinaryWriter::writeDouble(double value) { auto bytes = reinterpret_cast<uint8_t*>(&value); @@ -117,4 +115,10 @@ } } +void BinaryWriter::write(uint8_t value) { m_Stream->write((const uint8_t*)&value, 1); } + +void BinaryWriter::write(uint16_t value) { m_Stream->write((const uint8_t*)&value, 2); } + +void BinaryWriter::write(uint32_t value) { m_Stream->write((const uint8_t*)&value, 4); } + void BinaryWriter::clear() { m_Stream->clear(); } \ No newline at end of file
diff --git a/src/layout_component.cpp b/src/layout_component.cpp index 2f393e2..350b7cc 100644 --- a/src/layout_component.cpp +++ b/src/layout_component.cpp
@@ -236,7 +236,6 @@ YGValue{m_style->maxWidth(), m_style->maxWidthUnits()}; ygStyle.maxDimensions()[YGDimensionHeight] = YGValue{m_style->maxHeight(), m_style->maxHeightUnits()}; - ygStyle.gap()[YGGutterColumn] = YGValue{m_style->gapHorizontal(), m_style->gapHorizontalUnits()}; ygStyle.gap()[YGGutterRow] = YGValue{m_style->gapVertical(), m_style->gapVerticalUnits()};
diff --git a/src/shapes/paint/trim_path.cpp b/src/shapes/paint/trim_path.cpp index 6b0e334..8cdabd7 100644 --- a/src/shapes/paint/trim_path.cpp +++ b/src/shapes/paint/trim_path.cpp
@@ -146,9 +146,12 @@ void TrimPath::invalidateTrim() { m_renderPath = nullptr; - auto stroke = parent()->as<Stroke>(); - stroke->parent()->addDirt(ComponentDirt::Paint); - stroke->invalidateRendering(); + if (parent() != nullptr) + { + auto stroke = parent()->as<Stroke>(); + stroke->parent()->addDirt(ComponentDirt::Paint); + stroke->invalidateRendering(); + } } void TrimPath::startChanged() { invalidateTrim(); }
diff --git a/test/clip_test.cpp b/test/clip_test.cpp index d31a3dd..d4dbdeb 100644 --- a/test/clip_test.cpp +++ b/test/clip_test.cpp
@@ -60,7 +60,7 @@ auto artboard = file->artboard("Center"); REQUIRE(artboard != nullptr); - artboard->updateComponents(); + artboard->advance(0.0f); REQUIRE(artboard->originX() == 0.5); REQUIRE(artboard->originY() == 0.5); {