short version:
The AnimationTask owns the proxy via a unique_ptr but the DrawableComposite deletes all children - including the proxy - in its destructor.
longer version:
- ComponentAnimator::fadeOut() creates an AnimationTask with useProxyComponent = true
- The proxy is a std::unique_ptr
- the proxy is added as a sibling to the animated component. The proxy may now be a child of a DrawableComposite.
- DrawableComposite calls deleteAllChildren() in its destructor
- the destructor of Desktop calls animator.cancelAllAnimations() which deletes all AnimationTasks and with it the proxy hold via a unique_ptr. But the proxy was already deleted by deleteAllChildren()
reproduction:
- load SVG into a (owned) member of your component
- call
Desktop::getInstance().getAnimator().fadeOut(someChildOfTheSvg, 1000 * 1000);
- quit the application via cmd+q
possible solution:
- do not delete the ProxyComponent in DrawableComposite
- do not delete the proxy if it was deleted elsewhere. This can be accomplished by using a Component::SafePointer instead of a unique_ptr. A patch for this is attached.
Patch:
--- a/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp
+++ b/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp
@@ -32,6 +32,11 @@ class ComponentAnimator::AnimationTask
public:
AnimationTask (Component* c) noexcept : component (c) {}
+ ~AnimationTask()
+ {
+ proxy.deleteAndZero();
+ }
+
void reset (const Rectangle<int>& finalBounds,
float finalAlpha,
int millisecondsToSpendMoving,
@@ -58,17 +63,17 @@ public:
midSpeed = invTotalDistance;
endSpeed = jmax (0.0, endSpd * invTotalDistance);
+ proxy.deleteAndZero();
+
if (useProxyComponent)
- proxy.reset (new ProxyComponent (*component));
- else
- proxy.reset();
+ proxy = new ProxyComponent (*component);
component->setVisible (! useProxyComponent);
}
bool useTimeslice (const int elapsed)
{
- if (auto* c = proxy != nullptr ? proxy.get()
+ if (auto* c = proxy != nullptr ? proxy.getComponent()
: component.get())
{
msElapsed += elapsed;
@@ -167,6 +172,7 @@ public:
toBehind (&c);
}
+
void paint (Graphics& g) override
{
g.setOpacity (1.0f);
@@ -181,7 +187,7 @@ public:
};
WeakReference<Component> component;
- std::unique_ptr<Component> proxy;
+ Component::SafePointer<Component> proxy;
Rectangle<int> destination;
double destAlpha;