take animation for isTranslucent
diff --git a/include/rive/animation/linear_animation.hpp b/include/rive/animation/linear_animation.hpp index 717351f..68e52c1 100644 --- a/include/rive/animation/linear_animation.hpp +++ b/include/rive/animation/linear_animation.hpp
@@ -13,6 +13,7 @@ private: std::vector<KeyedObject*> m_KeyedObjects; + friend class Artboard; public: ~LinearAnimation(); StatusCode onAddedDirty(CoreContext* context) override; @@ -36,4 +37,4 @@ }; } // namespace rive -#endif \ No newline at end of file +#endif
diff --git a/include/rive/artboard.hpp b/include/rive/artboard.hpp index a418d15..c3afe0c 100644 --- a/include/rive/artboard.hpp +++ b/include/rive/artboard.hpp
@@ -74,7 +74,7 @@ const std::vector<Core*>& objects() const { return m_Objects; } AABB bounds() const; - bool isTranslucent() const; + bool isTranslucent(const LinearAnimation*) const; template <typename T = Component> T* find(std::string name) {
diff --git a/include/rive/shapes/paint/linear_gradient.hpp b/include/rive/shapes/paint/linear_gradient.hpp index 4ac2ad3..a4a17a4 100644 --- a/include/rive/shapes/paint/linear_gradient.hpp +++ b/include/rive/shapes/paint/linear_gradient.hpp
@@ -31,7 +31,8 @@ void opacityChanged() override; void renderOpacityChanged() override; virtual void makeGradient(const Vec2D& start, const Vec2D& end); + bool onIsTranslucent() const override; }; } // namespace rive -#endif \ No newline at end of file +#endif
diff --git a/include/rive/shapes/paint/shape_paint.hpp b/include/rive/shapes/paint/shape_paint.hpp index c450134..ad61ea2 100644 --- a/include/rive/shapes/paint/shape_paint.hpp +++ b/include/rive/shapes/paint/shape_paint.hpp
@@ -40,7 +40,11 @@ /// ShapePaint. It'll be one of SolidColor, LinearGradient, or /// RadialGradient. Component* paint() const { return m_PaintMutator->component(); } + + bool isTranslucent() const { + return m_PaintMutator->isTranslucent(); + } }; } // namespace rive -#endif \ No newline at end of file +#endif
diff --git a/include/rive/shapes/paint/shape_paint_mutator.hpp b/include/rive/shapes/paint/shape_paint_mutator.hpp index b046900..6e69c58 100644 --- a/include/rive/shapes/paint/shape_paint_mutator.hpp +++ b/include/rive/shapes/paint/shape_paint_mutator.hpp
@@ -21,11 +21,17 @@ RenderPaint* renderPaint() const { return m_RenderPaint; } + virtual bool onIsTranslucent() const = 0; + public: float renderOpacity() const { return m_RenderOpacity; } void renderOpacity(float value); Component* component() const { return m_Component; } + + bool isTranslucent() const { + return m_RenderOpacity < 1 || this->onIsTranslucent(); + } }; } // namespace rive -#endif \ No newline at end of file +#endif
diff --git a/include/rive/shapes/paint/solid_color.hpp b/include/rive/shapes/paint/solid_color.hpp index 26b822f..a662e9d 100644 --- a/include/rive/shapes/paint/solid_color.hpp +++ b/include/rive/shapes/paint/solid_color.hpp
@@ -12,7 +12,8 @@ protected: void renderOpacityChanged() override; void colorValueChanged() override; + bool onIsTranslucent() const override; }; } // namespace rive -#endif \ No newline at end of file +#endif
diff --git a/src/artboard.cpp b/src/artboard.cpp index 3d27e37..1b59a85 100644 --- a/src/artboard.cpp +++ b/src/artboard.cpp
@@ -6,6 +6,7 @@ #include "rive/draw_target.hpp" #include "rive/draw_target_placement.hpp" #include "rive/drawable.hpp" +#include "rive/animation/keyed_object.hpp" #include "rive/node.hpp" #include "rive/renderer.hpp" #include "rive/shapes/paint/shape_paint.hpp" @@ -486,11 +487,23 @@ AABB Artboard::bounds() const { return AABB(0.0f, 0.0f, width(), height()); } -bool Artboard::isTranslucent() const { - constexpr float effectlyOpaqueAlpha = 0.999f; // will turn into 0xFF when drawn +bool Artboard::isTranslucent(const LinearAnimation* anim) const { + // For now we're conservative/lazy -- if we see that any of our paints are animated + // we assume that might make it non-opaque, so we early out + for (const auto obj : anim->m_KeyedObjects) { + auto ptr = this->resolve(obj->objectId()); + for (const auto sp : m_ShapePaints) { + if (ptr == sp) { + return true; + } + } + } + + // If we get here, we have no animations, so just check our paints for opacity + for (const auto sp : m_ShapePaints) { - if (sp->renderOpacity() >= effectlyOpaqueAlpha) { - return false; // one opaque background fill is all we need to be opaque + if (!sp->isTranslucent()) { + return false; // one opaque fill is sufficient to be opaque } } return true;
diff --git a/src/shapes/paint/linear_gradient.cpp b/src/shapes/paint/linear_gradient.cpp index 05e1587..8f680de 100644 --- a/src/shapes/paint/linear_gradient.cpp +++ b/src/shapes/paint/linear_gradient.cpp
@@ -125,4 +125,14 @@ void LinearGradient::startYChanged() { addDirt(ComponentDirt::Transform); } void LinearGradient::endXChanged() { addDirt(ComponentDirt::Transform); } void LinearGradient::endYChanged() { addDirt(ComponentDirt::Transform); } -void LinearGradient::opacityChanged() { markGradientDirty(); } \ No newline at end of file +void LinearGradient::opacityChanged() { markGradientDirty(); } + +bool LinearGradient::onIsTranslucent() const { + for (const auto stop : m_Stops) { + unsigned alpha = stop->colorValue() >> 24; // helper for this? + if (alpha != 0xFF) { + return true; + } + } + return false; // all of our stops are opaque +}
diff --git a/src/shapes/paint/solid_color.cpp b/src/shapes/paint/solid_color.cpp index 47f4ea7..66a4c06 100644 --- a/src/shapes/paint/solid_color.cpp +++ b/src/shapes/paint/solid_color.cpp
@@ -30,4 +30,9 @@ colorModulateOpacity((unsigned int)colorValue(), renderOpacity())); } -void SolidColor::colorValueChanged() { renderOpacityChanged(); } \ No newline at end of file +void SolidColor::colorValueChanged() { renderOpacityChanged(); } + +bool SolidColor::onIsTranslucent() const { + unsigned alpha = colorValue() >> 24; + return alpha != 0xFF; +}