001package squidpony.squidgrid.gui.gdx;
002
003import com.badlogic.gdx.graphics.Color;
004import com.badlogic.gdx.graphics.Texture;
005import com.badlogic.gdx.graphics.g2d.TextureRegion;
006import com.badlogic.gdx.scenes.scene2d.ui.Image;
007import squidpony.squidgrid.Direction;
008
009import java.util.ArrayList;
010import java.util.Collections;
011import java.util.List;
012
013/**
014 * An Image that has multiple possible color tints that it cycles through over time.
015 * Created by Tommy Ettinger on 3/23/2016.
016 */
017public class ColorChangeImage extends Image {
018
019    private List<Color> colors;
020    private float progress;
021    private float loopTime = 2f;
022
023    /**
024     * Creates an image stretched and aligned center, that will use the specified list of colors.
025     *
026     * @param texture the texture to use
027     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
028     */
029    public ColorChangeImage(Texture texture, List<Color> colors) {
030        this(texture, 2f, colors);
031    }
032
033    /**
034     * Creates an image stretched and aligned center, that will use the specified list of colors.
035     *
036     * @param texture the texture to use
037     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
038     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
039     */
040    public ColorChangeImage(Texture texture, float loopTime, List<Color> colors) {
041        this(texture, loopTime, false, colors);
042    }
043
044    /**
045     * Creates an image stretched and aligned center, that will use the specified list of colors.
046     *
047     * @param texture the texture to use
048     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
049     * @param doubleWidth true if this takes up two grid cells; only matters if you use {@link AnimatedEntity#setDirection(Direction)}
050     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
051     */
052    public ColorChangeImage(Texture texture, float loopTime, boolean doubleWidth, List<Color> colors) {
053
054        super(texture);
055
056        if(colors == null || colors.isEmpty())
057            this.colors = DefaultResources.getSCC().rainbow(12);
058        else
059            this.colors = colors;
060        this.loopTime = loopTime;
061        setSize(texture.getWidth(), texture.getHeight());
062        setOrigin(doubleWidth ? 16 : 1); //Align.right or Align.center
063    }
064
065    /**
066     * Creates an image stretched and aligned center, that will use the specified list of colors.
067     *
068     * @param texture the texture to use
069     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
070     * @param doubleWidth true if this takes up two grid cells; only matters if you use {@link AnimatedEntity#setDirection(Direction)}
071     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
072     */
073    public ColorChangeImage(Texture texture, float loopTime, boolean doubleWidth, float width, float height, List<Color> colors) {
074
075        super(texture);
076
077        if(colors == null || colors.isEmpty())
078            this.colors = DefaultResources.getSCC().rainbow(12);
079        else
080            this.colors = colors;
081        this.loopTime = loopTime;
082        setSize(width, height);
083        setOrigin(doubleWidth ? 16 : 1); //Align.right or Align.center
084    }
085
086    /**
087     * Creates an image stretched and aligned center, that will use the specified list of colors.
088     *
089     * @param texture the texture to use
090     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
091     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
092     */
093    public ColorChangeImage(Texture texture, float loopTime, Color... colors) {
094        this(texture, loopTime, false, colors);
095    }
096
097    /**
098     * Creates an image stretched and aligned center, that will use the specified list of colors.
099     *
100     * @param texture the texture to use
101     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
102     * @param doubleWidth true if this takes up two grid cells; only matters if you use {@link AnimatedEntity#setDirection(Direction)}
103     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
104     */
105    public ColorChangeImage(Texture texture, float loopTime, boolean doubleWidth, Color... colors) {
106        super(texture);
107
108        if(colors == null || colors.length == 0)
109            this.colors = DefaultResources.getSCC().rainbow(12);
110        else {
111            this.colors = new ArrayList<>(colors.length);
112            Collections.addAll(this.colors, colors);
113        }
114        this.loopTime = loopTime;
115        setSize(texture.getWidth(), texture.getHeight());
116        setOrigin(doubleWidth ? 16 : 1); //Align.right or Align.center
117    }
118    /**
119     * Creates an image stretched and aligned center, that will use the specified list of colors.
120     *
121     * @param texture the texture to use
122     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
123     * @param doubleWidth true if this takes up two grid cells; only matters if you use {@link AnimatedEntity#setDirection(Direction)}
124     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
125     */
126    public ColorChangeImage(Texture texture, float loopTime, boolean doubleWidth, float width, float height, Color... colors) {
127        super(texture);
128
129        if(colors == null || colors.length == 0)
130            this.colors = DefaultResources.getSCC().rainbow(12);
131        else {
132            this.colors = new ArrayList<>(colors.length);
133            Collections.addAll(this.colors, colors);
134        }
135        this.loopTime = loopTime;
136
137        setSize(width, height);
138        setOrigin(doubleWidth ? 16 : 1); //Align.right or Align.center
139    }
140
141    /**
142     * Creates an image stretched and aligned center, that will use the specified list of colors.
143     *
144     * @param texture the texture to use
145     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
146     */
147    public ColorChangeImage(TextureRegion texture, List<Color> colors) {
148        this(texture, 2f, colors);
149    }
150
151    /**
152     * Creates an image stretched and aligned center, that will use the specified list of colors.
153     *
154     * @param texture the texture to use
155     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
156     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
157     */
158    public ColorChangeImage(TextureRegion texture, float loopTime, List<Color> colors) {
159        this(texture, loopTime, false, colors);
160    }
161
162    /**
163     * Creates an image stretched and aligned center, that will use the specified list of colors.
164     *
165     * @param texture the texture to use
166     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
167     * @param doubleWidth true if this takes up two grid cells; only matters if you use {@link AnimatedEntity#setDirection(Direction)}
168     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
169     */
170    public ColorChangeImage(TextureRegion texture, float loopTime, boolean doubleWidth, List<Color> colors) {
171
172        super(texture);
173
174        if(colors == null || colors.isEmpty())
175            this.colors = DefaultResources.getSCC().rainbow(12);
176        else
177            this.colors = colors;
178        this.loopTime = loopTime;
179        setSize(texture.getRegionWidth(), texture.getRegionHeight());
180        setOrigin(doubleWidth ? 16 : 1); //Align.right or Align.center
181    }
182    /**
183     * Creates an image stretched and aligned center, that will use the specified list of colors.
184     *
185     * @param texture the texture to use
186     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
187     * @param doubleWidth true if this takes up two grid cells; only matters if you use {@link AnimatedEntity#setDirection(Direction)}
188     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
189     */
190    public ColorChangeImage(TextureRegion texture, float loopTime, boolean doubleWidth, float width, float height, List<Color> colors) {
191
192        super(texture);
193
194        if(colors == null || colors.isEmpty())
195            this.colors = DefaultResources.getSCC().rainbow(12);
196        else
197            this.colors = colors;
198        this.loopTime = loopTime;
199        setSize(width, height);
200        setOrigin(doubleWidth ? 16 : 1); //Align.right or Align.center
201    }
202    /**
203     * Creates an image stretched and aligned center, that will use the specified list of colors.
204     *
205     * @param texture the texture to use
206     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
207     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
208     */
209    public ColorChangeImage(TextureRegion texture, float loopTime, Color... colors) {
210        this(texture, loopTime, false, colors);
211    }
212
213    /**
214     * Creates an image stretched and aligned center, that will use the specified list of colors.
215     *
216     * @param texture the texture to use
217     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
218     * @param doubleWidth true if this takes up two grid cells; only matters if you use {@link AnimatedEntity#setDirection(Direction)}
219     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
220     */
221    public ColorChangeImage(TextureRegion texture, float loopTime, boolean doubleWidth, Color... colors) {
222        super(texture);
223
224        if(colors == null || colors.length == 0)
225            this.colors = DefaultResources.getSCC().rainbow(12);
226        else {
227            this.colors = new ArrayList<>(colors.length);
228            Collections.addAll(this.colors, colors);
229        }
230        this.loopTime = loopTime;
231
232        setSize(texture.getRegionWidth(), texture.getRegionHeight());
233        setOrigin(doubleWidth ? 16 : 1); //Align.right or Align.center
234    }
235    /**
236     * Creates an image stretched and aligned center, that will use the specified list of colors.
237     *
238     * @param texture the texture to use
239     * @param loopTime the amount of time, in seconds, to spend transitioning through the colors before repeating
240     * @param doubleWidth true if this takes up two grid cells; only matters if you use {@link AnimatedEntity#setDirection(Direction)}
241     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
242     */
243    public ColorChangeImage(TextureRegion texture, float loopTime, boolean doubleWidth, float width, float height, Color... colors) {
244
245        super(texture);
246
247        if(colors == null || colors.length == 0)
248            this.colors = DefaultResources.getSCC().rainbow(12);
249        else {
250            this.colors = new ArrayList<>(colors.length);
251            Collections.addAll(this.colors, colors);
252        }
253        this.loopTime = loopTime;
254        setSize(width, height);
255        setOrigin(doubleWidth ? 16 : 1); //Align.right or Align.center
256    }
257    /**
258     * Returns the color the actor will be tinted when drawn. Takes the Color from the List of Color this was constructed
259     * with or assigned with setColors, not the normal Actor color assigned with setColor.
260     * @return the Color this will be drawn with
261     */
262    @Override
263    public Color getColor() {
264        return colors.get((int)(progress * colors.size() / loopTime));
265    }
266
267    /**
268     * Sets the list of colors this uses to choose what color it draws with.
269     * @param colors a List of Color, such as one returned by SquidColorCenter's gradient or rainbow methods
270     */
271    public void setColors(List<Color> colors)
272    {
273        if(colors == null || colors.isEmpty())
274            this.colors = DefaultResources.getSCC().rainbow(12);
275        else
276            this.colors = colors;
277    }
278
279    /**
280     * Sets the list of colors this uses to choose what color it draws with.
281     * @param colors an array or vararg of Color
282     */
283    public void setColors(Color... colors)
284    {
285        if (colors == null || colors.length == 0)
286            this.colors = DefaultResources.getSCC().rainbow(12);
287        else {
288            this.colors = new ArrayList<>(colors.length);
289            Collections.addAll(this.colors, colors);
290        }
291    }
292    /**
293     * Updates the actor based on time. Typically this is called each frame by
294     * {@link com.badlogic.gdx.scenes.scene2d.Stage#act(float)}.
295     * <p>
296     * The default implementation calls
297     * {@link com.badlogic.gdx.scenes.scene2d.Action#act(float)} on each action and removes actions that are complete.
298     *
299     * @param delta Time in seconds since the last frame.
300     */
301    @Override
302    public void act(float delta) {
303        super.act(delta);
304        progress = (progress + delta) % (loopTime - 0.001f);
305    }
306
307    /**
308     * Changes the amount of time this takes to loop through all colors, and also resets the current loop to its start.
309     * @param loopTime the amount of time, in seconds, it takes to loop through all the colors in the list
310     */
311    public void resetLoopTime(float loopTime)
312    {
313        this.loopTime = loopTime;
314        progress = 0f;
315    }
316}