From dabe3a7b28e719a486db1a584fba0e4f83b83d17 Mon Sep 17 00:00:00 2001 From: luigi-rosso Date: Wed, 19 Jul 2023 23:31:39 +0000 Subject: [PATCH] Fixing modifier ranges not updating on the right frame. This animation wasn't ending up on the right frame when quickly moving the cursor left->right. This was an error with update cycle order of the text modifier group vs the text object itself. The modifier group needs to always update before the text object! @JcToon showed this issue to me in the office today... https://github.com/rive-app/rive/assets/454182/76692e1d-e670-4324-a8ac-8c8ce0748e52 Diffs= b17671130 Fixing modifier ranges not updating on the right frame. (#5623) Co-authored-by: Luigi Rosso --- .rive_head | 2 +- include/rive/text/text_modifier_group.hpp | 5 +---- src/text/text.cpp | 17 ++++++++++++--- src/text/text_modifier_group.cpp | 26 +++++++++++------------ 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/.rive_head b/.rive_head index e85ba01a..799bb02d 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -d1f8710f5bfda934cbbb20727fe7ca2d88a15ff8 +b176711307aaa8dade145024af8a29a32b48296a diff --git a/include/rive/text/text_modifier_group.hpp b/include/rive/text/text_modifier_group.hpp index 866c9e37..719ff5f2 100644 --- a/include/rive/text/text_modifier_group.hpp +++ b/include/rive/text/text_modifier_group.hpp @@ -18,7 +18,6 @@ class TextModifierGroup : public TextModifierGroupBase { public: StatusCode onAddedDirty(CoreContext* context) override; - void buildDependencies() override; void addModifierRange(TextModifierRange* range); void addModifier(TextModifier* modifier); @@ -29,7 +28,7 @@ class TextModifierGroup : public TextModifierGroupBase const rive::SimpleArray& shape, const SimpleArray>& lines, const GlyphLookup& glyphLookup); - void computeCoverage(); + void computeCoverage(uint32_t textSize); float glyphCoverage(uint32_t textIndex, uint32_t codePointCount); float coverage(uint32_t textIndex) { @@ -37,7 +36,6 @@ class TextModifierGroup : public TextModifierGroupBase return m_coverage[textIndex]; } void transform(float amount, Mat2D& ctm); - void update(ComponentDirt value) override; TextRun modifyShape(const Text& text, TextRun run, float strength); void applyShapeModifiers(const Text& text, StyledText& styledText); @@ -78,7 +76,6 @@ class TextModifierGroup : public TextModifierGroupBase std::vector m_modifiers; std::vector m_shapeModifiers; std::vector m_coverage; - uint32_t m_textSize = 0; rcp m_variableFont; std::vector m_variationCoords; std::vector m_nextTextRuns; diff --git a/src/text/text.cpp b/src/text/text.cpp index 90c7f82c..638c48b9 100644 --- a/src/text/text.cpp +++ b/src/text/text.cpp @@ -301,6 +301,16 @@ void Text::buildRenderStyles() y -= m_lines[0][0].baseline; minY = y; } + + bool hasModifiers = haveModifiers(); + if (hasModifiers) + { + uint32_t textSize = (uint32_t)m_styledText.unichars().size(); + for (TextModifierGroup* modifierGroup : m_modifierGroups) + { + modifierGroup->computeCoverage(textSize); + } + } for (const SimpleArray& paragraphLines : m_lines) { const Paragraph& paragraph = m_shape[paragraphIndex++]; @@ -350,7 +360,6 @@ void Text::buildRenderStyles() RawPath path = font->getPath(glyphId); - bool hasModifiers = haveModifiers(); uint32_t textIndex = 0; uint32_t glyphCount = 0; if (hasModifiers) @@ -634,13 +643,14 @@ void Text::update(ComponentDirt value) sizing() == TextSizing::autoWidth ? -1.0f : width(), (TextAlign)alignValue()); m_glyphLookup.compute(m_modifierStyledText.unichars(), m_modifierShape); + uint32_t textSize = (uint32_t)m_modifierStyledText.unichars().size(); for (TextModifierGroup* group : m_modifierGroups) { group->computeRangeMap(m_modifierStyledText.unichars(), m_modifierShape, m_modifierLines, m_glyphLookup); - group->computeCoverage(); + group->computeCoverage(textSize); } } if (makeStyled(m_styledText)) @@ -653,13 +663,14 @@ void Text::update(ComponentDirt value) if (!precomputeModifierCoverage && haveModifiers()) { m_glyphLookup.compute(m_styledText.unichars(), m_shape); + uint32_t textSize = (uint32_t)m_styledText.unichars().size(); for (TextModifierGroup* group : m_modifierGroups) { group->computeRangeMap(m_styledText.unichars(), m_shape, m_lines, m_glyphLookup); - group->computeCoverage(); + group->computeCoverage(textSize); } } } diff --git a/src/text/text_modifier_group.cpp b/src/text/text_modifier_group.cpp index 0c222ba6..19d93a8c 100644 --- a/src/text/text_modifier_group.cpp +++ b/src/text/text_modifier_group.cpp @@ -4,6 +4,7 @@ #include "rive/text/text_modifier_range.hpp" #include "rive/text/glyph_lookup.hpp" #include "rive/text/text_style.hpp" +#include "rive/artboard.hpp" #include using namespace rive; @@ -25,8 +26,6 @@ StatusCode TextModifierGroup::onAddedDirty(CoreContext* context) return StatusCode::MissingObject; } -void TextModifierGroup::buildDependencies() { parent()->addDependent(this); } - void TextModifierGroup::addModifierRange(TextModifierRange* range) { m_ranges.push_back(range); } void TextModifierGroup::addModifier(TextModifier* modifier) @@ -67,14 +66,6 @@ void TextModifierGroup::rangeChanged() } } -void TextModifierGroup::update(ComponentDirt value) -{ - if (hasDirt(value, ComponentDirt::TextCoverage)) - { - computeCoverage(); - } -} - /// Clear any cached selector range maps so they can be recomputed after next /// shaping. void TextModifierGroup::clearRangeMaps() @@ -91,17 +82,26 @@ void TextModifierGroup::computeRangeMap(Span text, const SimpleArray>& lines, const GlyphLookup& glyphLookup) { - m_textSize = (uint32_t)text.size(); for (TextModifierRange* range : m_ranges) { range->computeRange(text, shape, lines, glyphLookup); } } -void TextModifierGroup::computeCoverage() +void TextModifierGroup::computeCoverage(uint32_t textSize) { + if (!hasDirt(ComponentDirt::TextCoverage)) + { + + return; + } + + // Because we're not dependent on anything we need to reset our dirt + // ourselves. We're not in the DAG so we'll never get reset. + m_Dirt = ComponentDirt::None; + // When the text re-shapes, we udpate our coverage values. - m_coverage.resize(m_textSize); + m_coverage.resize(textSize); std::fill(m_coverage.begin(), m_coverage.end(), 0); for (TextModifierRange* range : m_ranges) {