<commit_before>package com.cjmalloy.gameui.client.anim;

import com.cjmalloy.gameui.client.anim.ease.Easing;
import com.cjmalloy.gameui.client.anim.ease.EasingFn;
import com.cjmalloy.gameui.client.component.UiElement;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;


public abstract class Animation extends UiElement
{
    public Easing easingFn = EasingFn.easeInOutQuad;

    protected int duration;

    private boolean started = false;
    private boolean ended = false;
    private double startTime;

    public Animation(int duration)
    {
        this.duration = duration;
    }

    @Override
    public void redrawIfNecessary(Context2d g, double timestamp)
    {
        if (ended) return;
        render(g, timestamp);
    }

    @Override
    public void render(Context2d g, double timestamp)
    {
        if (ended) return;

        if (!started)
        {
            startTime = timestamp;
            started = true;
            onStart();
        }
        double elapsed = timestamp-startTime;
        if (elapsed > duration)
        {
            ended = true;
            onEnd();
        }
        else
        {
            animate(g, ease(elapsed/duration), timestamp);
            parent.redrawNeeded();
        }
    }

    protected abstract void animate(Context2d g, double p, double timestamp);

    protected void onEnd() {}

    protected void onStart() {}

    protected void removeSelf()
    {
        Scheduler.get().scheduleDeferred(new ScheduledCommand()
        {
            @Override
            public void execute()
            {
                parent.remove(Animation.this);
            }
        });
    };

    private double ease(double d)
    {
        if (easingFn != null)
        {
            return easingFn.ease(d);
        }
        return d;
    };

    public static double interp(double a, double b, double p)
    {<commit_msg>Fixed bug adding/removing animations while inside the render loop.<commit_after>package com.cjmalloy.gameui.client.anim;

import com.cjmalloy.gameui.client.anim.ease.Easing;
import com.cjmalloy.gameui.client.anim.ease.EasingFn;
import com.cjmalloy.gameui.client.component.UiElement;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;


public abstract class Animation extends UiElement
{
    public Easing easingFn = EasingFn.easeInOutQuad;

    protected int duration;

    private boolean started = false;
    private boolean ended = false;
    private double startTime;

    public Animation(int duration)
    {
        this.duration = duration;
    }

    @Override
    public void redrawIfNecessary(Context2d g, double timestamp)
    {
        if (ended) return;
        render(g, timestamp);
    }

    @Override
    public void render(Context2d g, double timestamp)
    {
        if (ended) return;

        if (!started)
        {
            startTime = timestamp;
            started = true;

            // Let the current render loop end before we possibly
            // trigger a new event. This prevents adding/removing
            // children which would cause errors with the for loop.
            Scheduler.get().scheduleFinally(new ScheduledCommand()
            {
                @Override
                public void execute()
                {
                    onStart();
                }
            });
        }
        double elapsed = timestamp-startTime;
        if (elapsed > duration)
        {
            ended = true;

            // Let the current render loop end before we possibly
            // trigger a new event. This prevents adding/removing
            // children which would cause errors with the for loop.
            Scheduler.get().scheduleFinally(new ScheduledCommand()
            {
                @Override
                public void execute()
                {
                    onEnd();
                }
            });
        }
        else
        {
            animate(g, ease(elapsed/duration), timestamp);
            parent.redrawNeeded();
        }
    }

    protected abstract void animate(Context2d g, double p, double timestamp);

    protected void onEnd() {}

    protected void onStart() {}

    protected void removeSelf()
    {
        parent.remove(Animation.this);
    }

    private double ease(double d)
    {
        if (easingFn != null)
        {
            return easingFn.ease(d);
        }
        return d;
    }

    public static double interp(double a, double b, double p)
    {
{'fraction_non_alphanumeric': 0.08688208859405093, 'fraction_numerical': 0.0017119623368285898, 'mean_word_length': 1.855222968845449, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6339655', 'n_tokens_mistral': 1320, 'n_tokens_neox': 1255, 'n_words': 326}