001package squidpony.squidgrid.gui.gdx;
002
003import com.badlogic.gdx.graphics.Color;
004import com.badlogic.gdx.graphics.g2d.Batch;
005import com.badlogic.gdx.graphics.g2d.BitmapFont;
006import com.badlogic.gdx.graphics.g2d.TextureRegion;
007import com.badlogic.gdx.scenes.scene2d.Group;
008import squidpony.IColorCenter;
009import squidpony.squidgrid.Direction;
010
011import java.util.*;
012
013/**
014 * A helper class to make using multiple SquidPanels easier.
015 * <br>
016 * There is some useful documentation in this class' getPalette method (honestly, I don't know where else to put
017 * documentation specifically about this class' default palette)..
018 * Created by Tommy Ettinger on 7/6/2015.
019 */
020public class SquidLayers extends Group {
021    protected int width;
022    protected int height;
023    protected int cellWidth;
024    protected int cellHeight;
025    protected SquidPanel backgroundPanel, foregroundPanel;
026    protected int[][] lightnesses;
027    protected ArrayList<SquidPanel> extraPanels;
028    protected TextCellFactory textFactory;
029    protected ArrayList<Color> palette;
030    protected boolean[][] values;
031    protected float animationDuration;
032
033    public static final char EMPTY_CELL = '\0';
034    /**
035     * The pixel width of the entire map.
036     *
037     * @return
038     */
039    @Override
040    public float getWidth() {
041        return width * cellWidth;
042    }
043
044    /**
045     * The pixel height of the entire map.
046     *
047     * @return
048     */
049    @Override
050    public float getHeight() {
051        return height * cellHeight;
052    }
053
054    /**
055     * Width of the map in grid cells.
056     *
057     * @return
058     */
059    public int getGridWidth() {
060        return width;
061    }
062
063    /**
064     * Height of the map in grid cells.
065     *
066     * @return
067     */
068    public int getGridHeight() {
069        return height;
070    }
071
072    /**
073     * Width of one cell in pixels.
074     *
075     * @return
076     */
077    public int getCellWidth() {
078        return cellWidth;
079    }
080
081    /**
082     * Height of one cell in pixels.
083     *
084     * @return
085     */
086    public int getCellHeight() {
087        return cellHeight;
088    }
089
090    public float getAnimationDuration() {
091        return animationDuration;
092    }
093
094    public void setAnimationDuration(float animationDuration) {
095        this.animationDuration = animationDuration;
096    }
097
098    public TextCellFactory getTextFactory() {
099        return textFactory;
100    }
101
102    /**
103     * Gets the current palette used when no other is specified.
104     *
105     * The palette can be customized with SquidLayers.alterPalette() and SquidLayers.extendPalette() .
106     * 
107     * The default palette has colors at these elements:
108     * <ul>
109     * <li>0: Black, also used for backgrounds if not specified</li>
110     * <li>1: Off-white, used as the default foreground at times</li>
111     * <li>2: Dark gray for walls</li>
112     * <li>3: Silver gray for floors</li>
113     * <li>4: Rust brown for doors</li>
114     * <li>5: Gray-blue for water</li>
115     * <li>6: Bright orange for traps</li>
116     * <li>7: White</li>
117     * <li>8: Light gray</li>
118     * <li>9: Dark gray</li>
119     * <li>10: Light red</li>
120     * <li>11: Medium red</li>
121     * <li>12: Dark red</li>
122     * <li>13: Light orange</li>
123     * <li>14: Medium orange</li>
124     * <li>15: Dark orange</li>
125     * <li>16: Light yellow</li>
126     * <li>17: Medium yellow</li>
127     * <li>18: Dark yellow</li>
128     * <li>19: Light green</li>
129     * <li>20: Medium green</li>
130     * <li>21: Dark green</li>
131     * <li>22: Light blue-green</li>
132     * <li>23: Medium blue-green</li>
133     * <li>24: Dark blue-green</li>
134     * <li>25: Light blue</li>
135     * <li>26: Medium blue</li>
136     * <li>27: Dark blue</li>
137     * <li>28: Light purple</li>
138     * <li>29: Medium purple</li>
139     * <li>30: Dark purple</li>
140     * <li>31: Light pink</li>
141     * <li>32: Medium pink</li>
142     * <li>33: Dark pink</li>
143     * <li>34: Light gray-brown</li>
144     * <li>35: Medium gray-brown</li>
145     * <li>36: Dark gray-brown</li>
146     * <li>37: Light brown</li>
147     * <li>38: Medium brown</li>
148     * <li>39: Dark brown</li>
149     * </ul>
150     *
151     * @return the current Color ArrayList used as a default palette.
152     */
153    public ArrayList<Color> getPalette() {
154        return palette;
155    }
156
157    /**
158     * Get the lightness modifiers used for background cells as an int[][], with elements between 0 and 511, 256 as the
159     * unmodified lightness level, lower numbers meaning darker, and higher meaning lighter.
160     *
161     * @return
162     */
163    public int[][] getLightnesses() {
164        return lightnesses;
165    }
166
167    /**
168     * Sets the lightness modifiers used for background cells with the int[][] passed as lightnesses. This 2D array
169     * should have elements between 0 to 511, with 256 as the unmodified lightness level, lower numbers meaning darker,
170     * and higher meaning lighter. Elements less than 0 or higher than 511 will probably cause array out-of-bounds
171     * exceptions to be thrown when this renders, so just don't do that. This doesn't validate because maps can get
172     * large, validating many cells could be expensive, and this might be called often if it's being called at all.
173     *
174     * @param lightnesses 2D array, width and height should match this class' gridWidth and gridHeight. elements must
175     *                    be between 0 and 511.
176     */
177    public void setLightnesses(int[][] lightnesses) {
178        this.lightnesses = lightnesses;
179    }
180
181    /**
182     * Create a new SquidLayers widget with the default <b>square</b> font, 40 cells wide and high, with a size of
183     * 12x12 pixels for each cell.
184     */
185    public SquidLayers() {
186        this(40, 40);
187    }
188
189    /**
190     * Create a new SquidLayers widget with the default <b>square</b> font, the given number of cells for gridWidth
191     * and gridHeight, and 12x12 pixels for each cell.
192     *
193     * @param gridWidth  in grid cells
194     * @param gridHeight in grid cells
195     */
196    public SquidLayers(int gridWidth, int gridHeight) {
197        this(gridWidth, gridHeight, 12, 12);
198    }
199
200    /**
201     * Create a new SquidLayers widget with a default font (it will be square if cellWidth and cellHeight are equal, or
202     * narrow otherwise), the given number of cells for gridWidth
203     * and gridHeight, and the size in pixels for each cell given by cellWidth and cellHeight.
204     *
205     * @param gridWidth  in grid cells
206     * @param gridHeight in grid cells
207     * @param cellWidth  in pixels
208     * @param cellHeight in pixels
209     */
210    public SquidLayers(int gridWidth, int gridHeight, int cellWidth, int cellHeight) {
211        this(gridWidth, gridHeight, cellWidth, cellHeight, DefaultResources.getSCC(), DefaultResources.getSCC());
212    }
213
214    /**
215     * Create a new SquidLayers widget with the given path to a BitmapFont file, the given number of cells for gridWidth
216     * and gridHeight, and the size in pixels for each cell given by cellWidth and cellHeight.
217     *
218     * @param gridWidth  in grid cells
219     * @param gridHeight in grid cells
220     * @param cellWidth  in pixels
221     * @param cellHeight in pixels
222     * @param fontpath   A path to a BitmapFont that can be on the classpath (in SquidLib) or in the assets folder
223     */
224    public SquidLayers(int gridWidth, int gridHeight, int cellWidth, int cellHeight, String fontpath) {
225        this(gridWidth, gridHeight, cellWidth, cellHeight, fontpath,
226                DefaultResources.getSCC(), DefaultResources.getSCC());
227    }
228    /**
229     * Create a new SquidLayers widget with the given path to a BitmapFont file, the given number of cells for gridWidth
230     * and gridHeight, and the size in pixels for each cell given by cellWidth and cellHeight.
231     *
232     * @param gridWidth  in grid cells
233     * @param gridHeight in grid cells
234     * @param cellWidth  in pixels
235     * @param cellHeight in pixels
236     * @param bitmapFont A BitmapFont that you already constructed
237     */
238    public SquidLayers(int gridWidth, int gridHeight, int cellWidth, int cellHeight, BitmapFont bitmapFont) {
239        this(gridWidth, gridHeight, cellWidth, cellHeight, bitmapFont,
240                DefaultResources.getSCC(), DefaultResources.getSCC());
241    }
242    /**
243     * Create a new SquidLayers widget with the given path pre-constructed TextCellFactory, the given number of cells
244     * for gridWidth and gridHeight, and the size in pixels for each cell given by cellWidth and cellHeight.
245     *
246     * @param gridWidth  in grid cells
247     * @param gridHeight in grid cells
248     * @param cellWidth  in pixels
249     * @param cellHeight in pixels
250     * @param tcf        A TextCellFactory that you already constructed
251     */
252    public SquidLayers(int gridWidth, int gridHeight, int cellWidth, int cellHeight, TextCellFactory tcf) {
253        this(gridWidth, gridHeight, cellWidth, cellHeight, tcf,
254                DefaultResources.getSCC(), DefaultResources.getSCC());
255    }
256    /**
257     * Create a new SquidLayers widget with a default font (it will be square if cellWidth and cellHeight are equal, or
258     * narrow otherwise), the given number of cells for gridWidth
259     * and gridHeight, and the size in pixels for each cell given by cellWidth and cellHeight.
260     *
261     * @param gridWidth  in grid cells
262     * @param gridHeight in grid cells
263     * @param cellWidth  in pixels
264     * @param cellHeight in pixels
265     * @param bgColorCenter a SquidColorCenter (possibly with a filter) to use for the background
266     * @param fgColorCenter a SquidColorCenter (possibly with a filter) to use for the foreground
267     */
268    public SquidLayers(int gridWidth, int gridHeight, int cellWidth, int cellHeight,
269                       SquidColorCenter bgColorCenter, SquidColorCenter fgColorCenter) {
270        initPalettes();
271        width = gridWidth;
272        height = gridHeight;
273
274        this.cellWidth = cellWidth;
275        this.cellHeight = cellHeight;
276
277        lightnesses = new int[width][height];
278        values = new boolean[width][height];
279        for (int x = 0; x < width; x++) {
280            for (int y = 0; y < height; y++) {
281                lightnesses[x][y] = 256;
282            }
283        }
284
285        textFactory = new TextCellFactory();
286        if (cellHeight == cellWidth) {
287            textFactory = textFactory.defaultSquareFont();
288        } else {
289            textFactory = textFactory.defaultNarrowFont();
290        }
291        textFactory = textFactory.width(cellWidth).height(cellHeight).initBySize();
292        backgroundPanel = new SquidPanel(gridWidth, gridHeight, textFactory, bgColorCenter);
293        foregroundPanel = new SquidPanel(gridWidth, gridHeight, textFactory, fgColorCenter);
294
295        animationDuration = foregroundPanel.DEFAULT_ANIMATION_DURATION;
296
297        extraPanels = new ArrayList<>();
298
299        addActorAt(0, backgroundPanel);
300        addActorAt(2, foregroundPanel);
301
302        setSize(backgroundPanel.getWidth(), backgroundPanel.getHeight());
303    }
304
305    /**
306     * Create a new SquidLayers widget with the given path to a BitmapFont file, the given number of cells for gridWidth
307     * and gridHeight, and the size in pixels for each cell given by cellWidth and cellHeight.
308     *
309     * @param gridWidth  in grid cells
310     * @param gridHeight in grid cells
311     * @param cellWidth  in pixels
312     * @param cellHeight in pixels
313     * @param fontpath   A path to a BitmapFont that can be on the classpath (in SquidLib) or in the assets folder.
314     * @param bgColorCenter a SquidColorCenter (possibly with a filter) to use for the background
315     * @param fgColorCenter a SquidColorCenter (possibly with a filter) to use for the foreground
316     */
317    public SquidLayers(int gridWidth, int gridHeight, int cellWidth, int cellHeight, String fontpath,
318                       SquidColorCenter bgColorCenter, SquidColorCenter fgColorCenter) {
319        this(gridWidth, gridHeight, cellWidth, cellHeight, new TextCellFactory().font(fontpath), bgColorCenter, fgColorCenter);
320    }
321    /**
322     * Create a new SquidLayers widget with the given BitmapFont (already constructed), the given number of cells for
323     * gridWidth and gridHeight, and the size in pixels for each cell given by cellWidth and cellHeight.
324     *
325     * @param gridWidth  in grid cells
326     * @param gridHeight in grid cells
327     * @param cellWidth  in pixels
328     * @param cellHeight in pixels
329     * @param bitmapFont A BitmapFont that you already constructed
330     * @param bgColorCenter a SquidColorCenter (possibly with a filter) to use for the background
331     * @param fgColorCenter a SquidColorCenter (possibly with a filter) to use for the foreground
332     */
333    public SquidLayers(int gridWidth, int gridHeight, int cellWidth, int cellHeight, BitmapFont bitmapFont,
334                       SquidColorCenter bgColorCenter, SquidColorCenter fgColorCenter) {
335        this(gridWidth, gridHeight, cellWidth, cellHeight, new TextCellFactory().font(bitmapFont), bgColorCenter, fgColorCenter);
336    }
337    /**
338     * Create a new SquidLayers widget with the given TextCellFactory, the given number of cells for gridWidth
339     * and gridHeight, the size in pixels for each cell given by cellWidth and cellHeight, and the given
340     * SquidColorCenters for background and foreground. Consider using the overloads that take either a path
341     * to a .fnt font file or a BitmapFont for simplicity.
342     *
343     * @param gridWidth  in grid cells
344     * @param gridHeight in grid cells
345     * @param cellWidth  in pixels
346     * @param cellHeight in pixels
347     * @param tcf   A TextCellFactory that will be (re-)initialized here with the given cellHeight and cellWidth.
348     * @param bgColorCenter a SquidColorCenter (possibly with a filter) to use for the background
349     * @param fgColorCenter a SquidColorCenter (possibly with a filter) to use for the foreground
350     */
351    public SquidLayers(int gridWidth, int gridHeight, int cellWidth, int cellHeight, TextCellFactory tcf,
352                       SquidColorCenter bgColorCenter, SquidColorCenter fgColorCenter) {
353        initPalettes();
354
355        width = gridWidth;
356        height = gridHeight;
357
358        this.cellWidth = cellWidth;
359        this.cellHeight = cellHeight;
360
361        lightnesses = new int[width][height];
362        values = new boolean[width][height];
363        for (int x = 0; x < width; x++) {
364            for (int y = 0; y < height; y++) {
365                lightnesses[x][y] = 256;
366            }
367        }
368
369        textFactory = tcf.width(cellWidth).height(cellHeight).initBySize();
370
371        backgroundPanel = new SquidPanel(gridWidth, gridHeight, textFactory, bgColorCenter);
372        foregroundPanel = new SquidPanel(gridWidth, gridHeight, textFactory, fgColorCenter);
373
374        animationDuration = foregroundPanel.DEFAULT_ANIMATION_DURATION;
375
376        extraPanels = new ArrayList<>();
377
378        addActorAt(0, backgroundPanel);
379        addActorAt(2, foregroundPanel);
380
381        setSize(backgroundPanel.getWidth(), backgroundPanel.getHeight());
382    }
383
384    private void initPalettes() {
385        palette = new ArrayList<>(256);
386        Collections.addAll(palette, SColor.LIMITED_PALETTE);
387        /*
388        palette.add(SColor.PURE_DARK_GRAY);
389        palette.add(SColor.CREAM);
390        palette.add(SColor.FLATTERY_BROWN);
391        palette.add(SColor.SILVER_GREY);
392        palette.add(SColor.RUST);
393        palette.add(SColor.PALE_CORNFLOWER_BLUE);
394        palette.add(SColor.INTERNATIONAL_ORANGE);
395
396        palette.add(SColor.WHITE);
397        palette.add(SColor.LIGHT_GRAY);
398        palette.add(SColor.DARK_GRAY);
399
400        palette.add(SColor.RED_INCENSE);
401        palette.add(SColor.RED);
402        palette.add(SColor.COCHINEAL_RED);
403
404        palette.add(SColor.PEACH_ORANGE);
405        palette.add(SColor.ORANGE_PEEL);
406        palette.add(SColor.TANGERINE);
407
408        palette.add(SColor.LEMON_CHIFFON);
409        palette.add(SColor.CORN);
410        palette.add(SColor.GOLDEN_YELLOW);
411
412        palette.add(SColor.TEA_GREEN);
413        palette.add(SColor.LIME_GREEN);
414        palette.add(SColor.GREEN_BAMBOO);
415
416        palette.add(SColor.CYAN);
417        palette.add(SColor.OCEAN_BLUE);
418        palette.add(SColor.MIDORI);
419
420        palette.add(SColor.COLUMBIA_BLUE);
421        palette.add(SColor.ROYAL_BLUE);
422        palette.add(SColor.PERSIAN_BLUE);
423
424        palette.add(SColor.LAVENDER_BLUE);
425        palette.add(SColor.DARK_VIOLET);
426        palette.add(SColor.INDIGO);
427
428        palette.add(SColor.CARNATION_PINK);
429        palette.add(SColor.HOT_MAGENTA);
430        palette.add(SColor.LIGHT_MAROON);
431
432        palette.add(SColor.TAN);
433        palette.add(SColor.DARK_TAN);
434        palette.add(SColor.PALE_BROWN);
435
436        palette.add(SColor.STEAMED_CHESTNUT);
437        palette.add(SColor.DARK_CHESTNUT);
438        palette.add(SColor.SAPPANWOOD_INCENSE);
439
440         */
441    }
442
443    /**
444     * Add an extra layer on top of the foreground layer. Use putInto methods to specify the layer when adding a char (0
445     * is background, 1 is unused, 2 is foreground, and the first call to this method creates layer 3).
446     *
447     * @return this for chaining
448     */
449    public SquidLayers addExtraLayer() {
450        SquidPanel sp = new SquidPanel(width, height, textFactory);
451        addActor(sp);
452        extraPanels.add(sp);
453        return this;
454    }
455
456    /**
457     * Adds a color to the end of the default palette, then returns that palette.
458     * 
459     * The default palette's entries can be seen in the documentation for SquidLayers.getPalette() .
460     *
461     * @param color an Color to add to the palette at the end
462     * @return the extended palette.
463     */
464    public ArrayList<Color> extendPalette(Color color) {
465        palette.add(color);
466        return palette;
467    }
468
469    /**
470     * Changes a color at the specified index in the default palette, then returns that palette.
471     * 
472     * If the index is greater than or equal to the number of colors in the palette, does nothing.
473     * 
474     * The default palette's entries can be seen in the documentation for SquidLayers.getPalette() .
475     *
476     * @param index must be at least 0 and less than the length of palette (starts at length 40).
477     * @param color the Color to put at the given index
478     * @return the altered palette
479     */
480    public ArrayList<Color> alterPalette(int index, Color color) {
481        if (index >= 0 && index < palette.size())
482            palette.set(index, color);
483
484        return palette;
485    }
486
487    /**
488     * Sets the size of the text in the given layer  (but not the size of the cells) to the given width and height in
489     * pixels (which may be stretched by viewports later on, if your program uses them).
490     * @param layer the layer to affect; 0 is background, 1 is unused, 2 is foreground, 3 and higher are extra panels
491     * @param wide the width of a glyph in pixels
492     * @param high the height of a glyph in pixels
493     * @return this for chaining
494     */
495    public SquidLayers setTextSize(int layer, int wide, int high)
496    {
497        SquidPanel p = backgroundPanel;
498        switch (layer) {
499            case 0:
500                break;
501            case 1:
502                break;
503            case 2:
504                p = foregroundPanel;
505                break;
506            default:
507                p = extraPanels.get(layer - 3);
508        }
509        p.setTextSize(wide, high);
510        return this;
511    }
512
513    /**
514     * Sets the size of the text in all layers (but not the size of the cells) to the given width and height in pixels
515     * (which may be stretched by viewports later on, if your program uses them).
516     * @param wide the width of a glyph in pixels
517     * @param high the height of a glyph in pixels
518     * @return this for chaining
519     */
520    public SquidLayers setTextSize(int wide, int high)
521    {
522        textFactory.tweakHeight(high).tweakWidth(wide).initBySize();
523        setTextSize(0, wide, high);
524        setTextSize(2, wide, high);
525        for (int i = 0; i < extraPanels.size(); i++) {
526            setTextSize(i + 3, wide, high);
527        }
528        return this;
529    }
530
531
532    /**
533     * Place a char c into the foreground at position x, y, with the default color.
534     *
535     * @param x in grid cells.
536     * @param y in grid cells.
537     * @param c a character to be drawn in the foreground
538     */
539    public SquidLayers put(int x, int y, char c) {
540        foregroundPanel.put(x, y, c);
541        values[x][y] = true;
542        return this;
543    }
544
545    /**
546     * Place a char c into the foreground, with a foreground color specified by an index into the default palette.
547     *
548     * @param x               in grid cells.
549     * @param y               in grid cells.
550     * @param c               a character to be drawn in the foreground
551     * @param foregroundIndex int index into the default palette for the char being drawn
552     */
553    public SquidLayers put(int x, int y, char c, int foregroundIndex) {
554        foregroundPanel.put(x, y, c, foregroundIndex, palette);
555        values[x][y] = true;
556        return this;
557    }
558
559    /**
560     * Place a char c into the foreground, with a foreground color specified by an index into the default palette.
561     *
562     * @param x               in grid cells.
563     * @param y               in grid cells.
564     * @param c               a character to be drawn in the foreground
565     * @param foreground    Color for the char being drawn
566     */
567    public SquidLayers put(int x, int y, char c, Color foreground) {
568        foregroundPanel.put(x, y, c, foreground);
569        values[x][y] = true;
570        return this;
571    }
572
573    /**
574     * Place a char c into the foreground, with a foreground color specified by an index into the default palette, and a
575     * background color specified in the same way.
576     *
577     * @param x               in grid cells.
578     * @param y               in grid cells.
579     * @param c               a character to be drawn in the foreground
580     * @param foregroundIndex int index into the default palette for the char being drawn
581     * @param backgroundIndex int index into the default palette for the background
582     */
583    public SquidLayers put(int x, int y, char c, int foregroundIndex, int backgroundIndex) {
584        foregroundPanel.put(x, y, c, foregroundIndex, palette);
585        backgroundPanel.put(x, y, backgroundIndex, palette);
586        values[x][y] = true;
587        return this;
588    }
589    /**
590     * Place a char c into the foreground, with a foreground color specified by an index into the default palette, and a
591     * background color specified in the same way.
592     *
593     * @param x               in grid cells.
594     * @param y               in grid cells.
595     * @param c               a character to be drawn in the foreground
596     * @param foreground    Color for the char being drawn
597     * @param background    Color for the background
598     */
599    public SquidLayers put(int x, int y, char c, Color foreground, Color background) {
600        foregroundPanel.put(x, y, c, foreground);
601        backgroundPanel.put(x, y, background);
602        values[x][y] = true;
603        return this;
604    }
605
606    /**
607     * Place a char c into the foreground, with a foreground color specified by an index into the default palette, a
608     * background color specified in the same way, and a lightness variation for the background (0 is no change, 100 is
609     * very bright, -100 is very dark, anything past -150 or 150 will make the background almost fully black or white).
610     *
611     * @param x                   in grid cells.
612     * @param y                   in grid cells.
613     * @param c                   a character to be drawn in the foreground
614     * @param foregroundIndex     int index into the default palette for the char being drawn
615     * @param backgroundIndex     int index into the default palette for the background
616     * @param backgroundLightness int between -255 and 255 , lower numbers are darker, higher lighter.
617     */
618    public SquidLayers put(int x, int y, char c, int foregroundIndex, int backgroundIndex, int backgroundLightness) {
619        backgroundLightness = clamp(backgroundLightness, -255, 255);
620        foregroundPanel.put(x, y, c, foregroundIndex, palette);
621        values[x][y] = true;
622        lightnesses[x][y] = 256 + clamp(backgroundLightness, -255, 255);
623        backgroundPanel.put(x, y, palette.get(backgroundIndex), lightnesses[x][y] / 512f);
624        return this;
625    }
626    /**
627     * Place a char c into the foreground, with a foreground color specified by an index into alternatePalette, a
628     * background color specified in the same way, and a lightness variation for the background (0 is no change, 100 is
629     * very bright, -100 is very dark, anything past -150 or 150 will make the background almost fully black or white).
630     *
631     * @param x                   in grid cells.
632     * @param y                   in grid cells.
633     * @param c                   a character to be drawn in the foreground
634     * @param alternatePalette    an alternate Color ArrayList for both foreground and background
635     * @param foregroundIndex     int index into alternatePalette for the char being drawn
636     * @param backgroundIndex     int index into alternatePalette for the background
637     * @param backgroundLightness int between -255 and 255 , lower numbers are darker, higher lighter.
638     */
639    public SquidLayers put(int x, int y, char c, ArrayList<Color> alternatePalette, int foregroundIndex, int backgroundIndex, int backgroundLightness) {
640        foregroundPanel.put(x, y, c, foregroundIndex, alternatePalette);
641        values[x][y] = true;
642        lightnesses[x][y] = 256 + clamp(backgroundLightness, -255, 255);
643
644        backgroundPanel.put(x, y, alternatePalette.get(backgroundIndex), lightnesses[x][y] / 512f);
645        return this;
646    }
647
648    /**
649     * Place a char c into the foreground, with a foreground and background libGDX Color and a lightness variation for
650     * the background (0 is no change, 255 will nearly double the brightness (capping at white), -255 will reduce the
651     * color to nearly black (for most colors, all the way to black), and values in between will be proportional..
652     *
653     * @param x                   in grid cells.
654     * @param y                   in grid cells.
655     * @param c                   a character to be drawn in the foreground
656     * @param foreground            Color for the char being drawn
657     * @param background            Color for the background
658     * @param backgroundLightness int between -255 and 255 , lower numbers are darker, higher lighter.
659     */
660    public SquidLayers put(int x, int y, char c, Color foreground, Color background, int backgroundLightness) {
661        foregroundPanel.put(x, y, c, foreground);
662        values[x][y] = true;
663        lightnesses[x][y] = 256 + clamp(backgroundLightness, -255, 255);
664
665        backgroundPanel.put(x, y, background, lightnesses[x][y] / 512f);
666        return this;
667    }
668
669    /**
670     * Place a char c into the foreground, with a foreground color specified by an index into alternatePalette, a
671     * background color specified in the same way, and a lightness variation for the background (0 is no change, 100 is
672     * very bright, -100 is very dark, anything past -150 or 150 will make the background almost fully black or white).
673     *
674     * @param x                   in grid cells.
675     * @param y                   in grid cells.
676     * @param c                   a character to be drawn in the foreground
677     * @param foregroundIndex     int index into alternatePalette for the char being drawn
678     * @param fgPalette           an alternate Color ArrayList for the foreground; can be null to use the default.
679     * @param backgroundIndex     int index into alternatePalette for the background
680     * @param bgPalette           an alternate Color ArrayList for the background; can be null to use the default.
681     * @param backgroundLightness int between -255 and 255 , lower numbers are darker, higher lighter.
682     */
683    public SquidLayers put(int x, int y, char c, int foregroundIndex, ArrayList<Color> fgPalette, int backgroundIndex, ArrayList<Color> bgPalette, int backgroundLightness) {
684        if (fgPalette == null) fgPalette = palette;
685        if (bgPalette == null) bgPalette = palette;
686        foregroundPanel.put(x, y, c, foregroundIndex, fgPalette);
687        values[x][y] = true;
688        lightnesses[x][y] = 256 + clamp(backgroundLightness, -255, 255);
689
690        backgroundPanel.put(x, y, bgPalette.get(backgroundIndex), lightnesses[x][y] / 512f);
691        return this;
692    }
693
694
695    public SquidLayers put(int x, int y, char[][] c) {
696        foregroundPanel.put(x, y, c);
697        for (int i = x; i < c.length && i < width; i++) {
698            for (int j = y; j < c[i].length && j < height; j++) {
699                values[i][j] = true;
700            }
701        }
702        return this;
703    }
704
705    public SquidLayers put(int x, int y, char[][] c, int[][] foregroundIndex) {
706        foregroundPanel.put(x, y, c, foregroundIndex, palette);
707        for (int i = x; i < c.length && i < width; i++) {
708            for (int j = y; j < c[i].length && j < height; j++) {
709                values[i][j] = true;
710            }
711        }
712        return this;
713    }
714
715    public SquidLayers put(int x, int y, char c[][], int[][] foregroundIndex, int[][] backgroundIndex) {
716        foregroundPanel.put(x, y, c, foregroundIndex, palette);
717        for (int i = x; i < c.length && i < width; i++) {
718            for (int j = y; j < c[i].length && j < height; j++) {
719                values[i][j] = true;
720            }
721        }
722        backgroundPanel.put(x, y, backgroundIndex, palette);
723        return this;
724    }
725
726    /**
727     * Place a char[][] c into the foreground, with a foreground color specified by an index into alternatePalette, a
728     * background color specified in the same way, and a lightness variation for the background (0 is no change, 100 is
729     * very bright, -100 is very dark, anything past -150 or 150 will make the background almost fully black or white).
730     *
731     * @param x                   in grid cells.
732     * @param y                   in grid cells.
733     * @param c                   char[][] to be drawn in the foreground starting from x, y
734     * @param foregroundIndex     int[][] of indices into the default palette for the char being drawn
735     * @param backgroundIndex     int[][] of indices into the default palette for the background
736     * @param backgroundLightness int[][] with elements between -255 and 255 , lower darker, higher lighter.
737     */
738    public SquidLayers put(int x, int y, char[][] c, int[][] foregroundIndex, int[][] backgroundIndex, int[][] backgroundLightness) {
739        foregroundPanel.put(x, y, c, foregroundIndex, palette);
740        for (int i = x; i < width && i-x < backgroundLightness.length; i++) {
741            for (int j = y; j < height && j - y < backgroundLightness[i].length; j++) {
742                lightnesses[i][j] = 256 + clamp(backgroundLightness[i-x][j-y], -255, 255);
743                values[i][j] = true;
744                backgroundPanel.put(i, j, palette.get(backgroundIndex[i-x][j-y]), lightnesses[i][j] / 512f);
745
746            }
747        }
748        return this;
749    }
750
751    /**
752     * Place a char c into the foreground, with a foreground color specified by an index into alternatePalette, a
753     * background color specified in the same way, and a lightness variation for the background (0 is no change, 100 is
754     * very bright, -100 is very dark, anything past -150 or 150 will make the background almost fully black or white).
755     *
756     * @param x                   in grid cells.
757     * @param y                   in grid cells.
758     * @param c                   char[][] to be drawn in the foreground starting from x, y
759     * @param alternatePalette    an alternate Color ArrayList for both foreground and background
760     * @param foregroundIndex     int[][] of indices into alternatePalette for the char being drawn
761     * @param backgroundIndex     int[][] of indices into alternatePalette for the background
762     * @param backgroundLightness int[][] with elements between -255 and 255 , lower darker, higher lighter.
763     */
764    public SquidLayers put(int x, int y, char[][] c, ArrayList<Color> alternatePalette, int[][] foregroundIndex, int[][] backgroundIndex, int[][] backgroundLightness) {
765
766        if (alternatePalette == null) alternatePalette = palette;
767        foregroundPanel.put(x, y, c, foregroundIndex, alternatePalette);
768        for (int i = x; i < width && i - x < backgroundLightness.length; i++) {
769            for (int j = y; j < height && j - y < backgroundLightness[i].length; j++) {
770                lightnesses[i][j] = 256 + clamp(backgroundLightness[i-x][j-y], -255, 255);
771                values[i][j] = true;
772                backgroundPanel.put(i, j, alternatePalette.get(backgroundIndex[i-x][j-y]), lightnesses[i][j] / 512f);
773
774            }
775        }
776        return this;
777    }
778    /**
779     * Place a char c into the foreground, with a foreground color specified by an index into alternatePalette, a
780     * background color specified in the same way, and a lightness variation for the background (0 is no change, 100 is
781     * very bright, -100 is very dark, anything past -150 or 150 will make the background almost fully black or white).
782     *
783     * @param x                   in grid cells.
784     * @param y                   in grid cells.
785     * @param c                   char[][] to be drawn in the foreground starting from x, y
786     * @param foregrounds     int[][] of indices into alternatePalette for the char being drawn
787     * @param backgrounds     int[][] of indices into alternatePalette for the background
788     * @param backgroundLightness int[][] with elements between -255 and 255 , lower darker, higher lighter.
789     */
790    public SquidLayers put(int x, int y, char[][] c, Color[][] foregrounds, Color[][] backgrounds, int[][] backgroundLightness) {
791
792        foregroundPanel.put(x, y, c, foregrounds);
793        for (int i = x; i < width && i - x < backgroundLightness.length; i++) {
794            for (int j = y; j < height && j - y < backgroundLightness[i].length; j++) {
795                lightnesses[i][j] = 256 + clamp(backgroundLightness[i-x][j-y], -255, 255);
796                values[i][j] = true;
797                backgroundPanel.put(i, j, backgrounds[i-x][j-y], lightnesses[i][j] / 512f);
798            }
799        }
800        return this;
801    }
802
803    /**
804     * Place a char c into the foreground, with a foreground color specified by an index into alternatePalette, a
805     * background color specified in the same way, and a lightness variation for the background (0 is no change, 100 is
806     * very bright, -100 is very dark, anything past -150 or 150 will make the background almost fully black or white).
807     *
808     * @param x                   in grid cells.
809     * @param y                   in grid cells.
810     * @param c                   char[][] to be drawn in the foreground starting from x, y
811     * @param foregroundIndex     int[][] of indices into fgPalette for the char being drawn
812     * @param fgPalette           an alternate Color ArrayList for the foreground; can be null to use the default.
813     * @param backgroundIndex     int[][] of indices into bgPalette for the background
814     * @param bgPalette           an alternate Color ArrayList for the background; can be null to use the default.
815     * @param backgroundLightness int[][] with elements between -255 and 255 , lower darker, higher lighter.
816     */
817    public SquidLayers put(int x, int y, char[][] c, int[][] foregroundIndex, ArrayList<Color> fgPalette, int[][] backgroundIndex, ArrayList<Color> bgPalette, int[][] backgroundLightness) {
818        if (fgPalette == null) fgPalette = palette;
819        if (bgPalette == null) bgPalette = palette;
820        foregroundPanel.put(x, y, c, foregroundIndex, fgPalette);
821        for (int i = x; i < width && i - x < backgroundLightness.length; i++) {
822            for (int j = y; j < height && j - y < backgroundLightness[i].length; j++) {
823                lightnesses[i][j] = 256 + clamp(backgroundLightness[i-x][j-y], -255, 255);
824                values[i][j] = true;
825                backgroundPanel.put(i, j, bgPalette.get(backgroundIndex[i-x][j-y]), lightnesses[i-x][j-y] / 512f);
826
827            }
828        }
829        return this;
830    }
831
832    /**
833     * Place a char c into the specified layer, with a color specified by an index into alternatePalette.
834     *
835     * @param layer 0 or 1 for background, 2 for foreground, 3 or higher for extra layers added on.
836     * @param x     in grid cells.
837     * @param y     in grid cells.
838     * @param c     char to be drawn in the foreground at x, y
839     */
840    public SquidLayers putInto(int layer, int x, int y, char c) {
841        SquidPanel p = backgroundPanel;
842        switch (layer) {
843            case 0:
844                break;
845            case 1:
846                break;
847            case 2:
848                p = foregroundPanel;
849                break;
850            default:
851                p = extraPanels.get(layer - 3);
852        }
853        p.put(x, y, c);
854        values[x][y] = true;
855        return this;
856    }
857
858    /**
859     * Place a char c into the specified layer, with a color specified by an index into the default palette.
860     *
861     * @param layer      0 or 1 for background, 2 for foreground, 3 or higher for extra layers added on.
862     * @param x          in grid cells.
863     * @param y          in grid cells.
864     * @param c          char to be drawn in the foreground at x, y
865     * @param colorIndex int index into alternatePalette for the char being drawn
866     */
867    public SquidLayers putInto(int layer, int x, int y, char c, int colorIndex) {
868        SquidPanel p = backgroundPanel;
869        switch (layer) {
870            case 0:
871                break;
872            case 1:
873                break;
874            case 2:
875                p = foregroundPanel;
876                break;
877            default:
878                p = extraPanels.get(layer - 3);
879        }
880        p.put(x, y, c, colorIndex, palette);
881        values[x][y] = true;
882        return this;
883    }
884
885    /**
886     * Place a char c into the specified layer, with a color specified by an index into alternatePalette.
887     *
888     * @param layer            0 or 1 for background, 2 for foreground, 3 or higher for extra layers added on.
889     * @param x                in grid cells.
890     * @param y                in grid cells.
891     * @param c                char to be drawn in the foreground at x, y
892     * @param alternatePalette an alternate Color ArrayList for both foreground and background
893     * @param colorIndex       int index into alternatePalette for the char being drawn
894     */
895    public SquidLayers putInto(int layer, int x, int y, char c, ArrayList<Color> alternatePalette, int colorIndex) {
896        SquidPanel p = backgroundPanel;
897        switch (layer) {
898            case 0:
899                break;
900            case 1:
901                break;
902            case 2:
903                p = foregroundPanel;
904                break;
905            default:
906                p = extraPanels.get(layer - 3);
907        }
908        if (alternatePalette == null) alternatePalette = palette;
909        p.put(x, y, c, colorIndex, alternatePalette);
910        values[x][y] = true;
911        return this;
912    }
913
914    /**
915     * Place a char c into the foreground, with a foreground color specified by an index into the default palette.
916     *
917     * @param layer   the layer to draw into
918     * @param x       in grid cells.
919     * @param y       in grid cells.
920     * @param c       a character to be drawn in the specified layer
921     * @param color   Color for the char being drawn
922     */
923    public SquidLayers putInto(int layer, int x, int y, char c, Color color) {
924        SquidPanel p = backgroundPanel;
925        switch (layer) {
926            case 0:
927                break;
928            case 1:
929                break;
930            case 2:
931                p = foregroundPanel;
932                break;
933            default:
934                p = extraPanels.get(layer - 3);
935        }
936        p.put(x, y, c, color);
937        values[x][y] = true;
938        return this;
939    }
940    /**
941     * Place a char c[][] into the specified layer, with a color specified by an index into alternatePalette.
942     *
943     * @param layer 0 or 1 for background, 2 for foreground, 3 or higher for extra layers added on.
944     * @param x     in grid cells.
945     * @param y     in grid cells.
946     * @param c     char[][] to be drawn in the foreground starting from x, y
947     */
948    public SquidLayers putInto(int layer, int x, int y, char[][] c) {
949        SquidPanel p = backgroundPanel;
950        switch (layer) {
951            case 0:
952                break;
953            case 1:
954                break;
955            case 2:
956                p = foregroundPanel;
957                break;
958            default:
959                p = extraPanels.get(layer - 3);
960        }
961        p.put(x, y, c);
962        for (int i = x; i < c.length && i < width; i++) {
963            for (int j = y; j < c[i].length && j < height; j++) {
964                values[i][j] = true;
965            }
966        }
967        return this;
968    }
969
970    /**
971     * Place a char c[][] into the specified layer, with a color specified by an index into the default palette.
972     *
973     * @param layer      0 or 1 for background, 2 for foreground, 3 or higher for extra layers added on.
974     * @param x          in grid cells.
975     * @param y          in grid cells.
976     * @param c          char[][] to be drawn in the foreground starting from x, y
977     * @param colorIndex int[][] of indices into alternatePalette for the char being drawn
978     */
979    public SquidLayers putInto(int layer, int x, int y, char[][] c, int[][] colorIndex) {
980        SquidPanel p = backgroundPanel;
981        switch (layer) {
982            case 0:
983                break;
984            case 1:
985                break;
986            case 2:
987                p = foregroundPanel;
988                break;
989            default:
990                p = extraPanels.get(layer - 3);
991        }
992        p.put(x, y, c, colorIndex, palette);
993        for (int i = x; i < c.length && i < width; i++) {
994            for (int j = y; j < c[i].length && j < height; j++) {
995                values[i][j] = true;
996            }
997        }
998        return this;
999    }
1000
1001    /**
1002     * Place a char c[][] into the specified layer, with a color specified by an index into alternatePalette.
1003     *
1004     * @param layer            0 or 1 for background, 2 for foreground, 3 or higher for extra layers added on.
1005     * @param x                in grid cells.
1006     * @param y                in grid cells.
1007     * @param c                char[][] to be drawn in the foreground starting from x, y
1008     * @param alternatePalette an alternate Color ArrayList for both foreground and background
1009     * @param colorIndex       int[][] of indices into alternatePalette for the char being drawn
1010     */
1011    public SquidLayers putInto(int layer, int x, int y, char[][] c, ArrayList<Color> alternatePalette, int[][] colorIndex) {
1012        SquidPanel p = backgroundPanel;
1013        switch (layer) {
1014            case 0:
1015                break;
1016            case 1:
1017                break;
1018            case 2:
1019                p = foregroundPanel;
1020                break;
1021            default:
1022                p = extraPanels.get(layer - 3);
1023        }
1024        if (alternatePalette == null) alternatePalette = palette;
1025        p.put(x, y, c, colorIndex, alternatePalette);
1026        for (int i = x; i < c.length && i < width; i++) {
1027            for (int j = y; j < c[i].length && j < height; j++) {
1028                values[i][j] = true;
1029            }
1030        }
1031        return this;
1032    }
1033
1034    /**
1035     * Place a char c[][] into the specified layer, with a color specified by an index into alternatePalette.
1036     *
1037     * @param layer            0 or 1 for background, 2 for foreground, 3 or higher for extra layers added on.
1038     * @param x                in grid cells.
1039     * @param y                in grid cells.
1040     * @param c                char[][] to be drawn in the foreground starting from x, y
1041     * @param colors          int[][] of indices into alternatePalette for the char being drawn
1042     */
1043    public SquidLayers putInto(int layer, int x, int y, char[][] c, Color[][] colors) {
1044        SquidPanel p = backgroundPanel;
1045        switch (layer) {
1046            case 0:
1047                break;
1048            case 1:
1049                break;
1050            case 2:
1051                p = foregroundPanel;
1052                break;
1053            default:
1054                p = extraPanels.get(layer - 3);
1055        }
1056        p.put(x, y, c, colors);
1057        for (int i = x; i < c.length && i < width; i++) {
1058            for (int j = y; j < c[i].length && j < height; j++) {
1059                values[i][j] = true;
1060            }
1061        }
1062        return this;
1063    }
1064
1065    /**
1066     * Put a string at the given x, y position, using the default color.
1067     *
1068     * @param x in grid cells.
1069     * @param y in grid cells.
1070     * @param s the string to print
1071     * @return this, for chaining
1072     */
1073    public SquidLayers putString(int x, int y, String s) {
1074        foregroundPanel.put(x, y, s);
1075        return this;
1076    }
1077
1078    /**
1079     * Put a string at the given x, y position, with the given index for foreground color that gets looked up in the
1080     * default palette.
1081     *
1082     * @param x               in grid cells.
1083     * @param y               in grid cells.
1084     * @param s               the string to print
1085     * @param foregroundIndex the indexed color to use
1086     * @return this, for chaining
1087     */
1088    public SquidLayers putString(int x, int y, String s, int foregroundIndex) {
1089        foregroundPanel.put(x, y, s, palette.get(foregroundIndex));
1090        return this;
1091    }
1092
1093    /**
1094     * Put a string at the given x, y position, with the given indices for foreground and background color that look up
1095     * their index in the default palette.
1096     *
1097     * @param x               in grid cells.
1098     * @param y               in grid cells.
1099     * @param s               the string to print
1100     * @param foregroundIndex the indexed color to use
1101     * @param backgroundIndex the indexed color to use
1102     * @return this, for chaining
1103     */
1104    public SquidLayers putString(int x, int y, String s, int foregroundIndex, int backgroundIndex) {
1105        foregroundPanel.put(x, y, s, palette.get(foregroundIndex));
1106        for (int i = x; i < s.length() && i < width; i++) {
1107            backgroundPanel.put(i, y, palette.get(backgroundIndex));
1108        }
1109        return this;
1110    }
1111
1112    /**
1113     * Put a string at the given x, y position, with the given indices for foreground and background color that look up
1114     * their index in alternatePalette.
1115     *
1116     * @param x                in grid cells.
1117     * @param y                in grid cells.
1118     * @param s                the string to print
1119     * @param alternatePalette the colors this can use, where the indices are used instead of individual colors
1120     * @param foregroundIndex the indexed color to use
1121     * @param backgroundIndex the indexed color to use
1122     * @return this, for chaining
1123     */
1124    public SquidLayers putString(int x, int y, String s, ArrayList<Color> alternatePalette, int foregroundIndex, int backgroundIndex) {
1125        foregroundPanel.put(x, y, s, alternatePalette.get(foregroundIndex));
1126        for (int i = x; i < s.length() && i < width; i++) {
1127            backgroundPanel.put(i, y, alternatePalette.get(backgroundIndex));
1128        }
1129        return this;
1130    }
1131    /**
1132     * Put a string at the given x, y position, with the given indices for foreground and background color that look up
1133     * their index in alternatePalette.
1134     *
1135     * @param x                in grid cells.
1136     * @param y                in grid cells.
1137     * @param s                the string to print
1138     * @param foreground      the Color of the string's chars
1139     * @param background      the Color of the background of the string
1140     * @return this, for chaining
1141     */
1142    public SquidLayers putString(int x, int y, String s, Color foreground, Color background) {
1143        foregroundPanel.put(x, y, s, foreground);
1144        for (int i = x; i < s.length() && i < width; i++) {
1145            backgroundPanel.put(i, y, background);
1146        }
1147        return this;
1148    }
1149
1150    /**
1151     * A utility method that draws a 1-cell-wide black box around the text you request (as s) and replaces the contents
1152     * of anything that was below or adjacent to the string's new position. Useful for message boxes.
1153     *
1154     * @param x in grid cells.
1155     * @param y in grid cells.
1156     * @param s the string to print inside the box
1157     * @return this, for chaining
1158     */
1159    public SquidLayers putBoxedString(int x, int y, String s) {
1160        if (y > 0 && y + 1 < height && x > 0 && x + 1 < width) {
1161            for (int j = y - 1; j < y + 2 && j < height; j++) {
1162                for (int i = x - 1; i < s.length() + x + 2 && i < width; i++) {
1163                    foregroundPanel.put(i, j, ' ');
1164                    lightnesses[i][j] = -255;
1165
1166                    backgroundPanel.put(i, j, backgroundPanel.getAt(i, j),
1167                            palette.get(9), 0f / 512f);
1168                }
1169            }
1170        }
1171        foregroundPanel.put(x, y, s, palette.get(1));
1172
1173        return this;
1174    }
1175
1176    /**
1177     * Change the lightness for the background of the cell at x, y (0 is no change, 100 is
1178     * very bright, -100 is very dark, anything past -150 or 150 will make the background almost fully black or white).
1179     *
1180     * @param x                   in grid cells.
1181     * @param y                   in grid cells.
1182     * @param lightness int between -255 and 255 , lower numbers are darker, higher lighter.
1183     */
1184    public SquidLayers highlight(int x, int y, int lightness) {
1185        lightnesses[x][y] = 256 + clamp(lightness, -255, 255);
1186
1187        backgroundPanel.put(x, y, backgroundPanel.getAt(x, y),
1188                backgroundPanel.getColorAt(x, y), lightnesses[x][y] / 512f);
1189        return this;
1190    }
1191    /**
1192     * Change the lightness for the background of the cell at x, y (0 is no change, 100 is
1193     * very bright, -100 is very dark, anything past -150 or 150 will make the background almost fully black or white).
1194     *
1195     * @param x                   in grid cells.
1196     * @param y                   in grid cells.
1197     * @param lightness int[][] with elements between -255 and 255 , lower numbers are darker, higher lighter.
1198     */
1199    public SquidLayers highlight(int x, int y, int[][] lightness) {
1200        for (int i = 0; i < lightness.length && x + i < width; i++) {
1201            for (int j = 0; j < lightness[i].length && y + j < height; j++) {
1202                lightnesses[x+i][y+j] = 256 + clamp(lightness[i][j], -255, 255);;
1203                backgroundPanel.put(x, y, backgroundPanel.getAt(x, y),
1204                        backgroundPanel.getColorAt(x, y), lightnesses[i][j] / 512f);
1205            }
1206        }
1207        return this;
1208    }
1209    /**
1210     * Very basic check to see if something was rendered at the x,y cell requested. (usually this only checks the
1211     * foreground) If blank, false, otherwise true.
1212     *
1213     * @param x in grid cells.
1214     * @param y in grid cells.
1215     * @return true if something was rendered in the foreground at the given x,y position
1216     */
1217    public boolean hasValue(int x, int y) {
1218        return values[x][y];
1219    }
1220
1221    /**
1222     * Clear one cell at position x, y of  its foreground contents.
1223     * 
1224     * You may be looking for the erase() method, which erases all panels and all cells.
1225     *
1226     * @param x in grid cells
1227     * @param y in grid cells
1228     * @return this for chaining
1229     */
1230    public SquidLayers clear(int x, int y) {
1231        foregroundPanel.clear(x, y);
1232        values[x][y] = false;
1233        return this;
1234    }
1235
1236    public SquidLayers eraseLayer(int layer)
1237    {
1238        SquidPanel p = foregroundPanel;
1239        switch (layer) {
1240            case 0:
1241                p = backgroundPanel;
1242                break;
1243            case 1:
1244                break;
1245            case 2:
1246                break;
1247            default:
1248                p = extraPanels.get(layer - 3);
1249        }
1250        p.erase();
1251        return this;
1252    }
1253    /**
1254     * Erase everything visible in all cells or all layers.  This is not at all expensive to do compared to the
1255     * pre-SquidLib-3.0.0 version of this method that used Swing and took a long time to erase.
1256     *
1257     * @return this, for chaining
1258     */
1259    public SquidLayers erase() {
1260        foregroundPanel.erase();
1261        backgroundPanel.erase();
1262        for (SquidPanel sp : extraPanels) {
1263            sp.erase();
1264        }
1265        for (int i = 0; i < width; i++) {
1266            for (int j = 0; j < height; j++) {
1267                values[i][j] = false;
1268            }
1269        }
1270        return this;
1271    }
1272
1273    public SquidLayers bump(int x, int y, int layer, Direction dir, float duration) {
1274        SquidPanel p = foregroundPanel;
1275        switch (layer) {
1276            case 0:
1277                p = backgroundPanel;
1278                break;
1279            case 1:
1280                break;
1281            case 2:
1282                break;
1283            default:
1284                p = extraPanels.get(layer - 3);
1285        }
1286        if (duration < 0)
1287            duration = animationDuration;
1288        p.bump(x, y, dir, duration);
1289        return this;
1290    }
1291    public SquidLayers bump(AnimatedEntity ae, int layer, Direction dir, float duration) {
1292        SquidPanel p = foregroundPanel;
1293        switch (layer) {
1294            case 0:
1295                p = backgroundPanel;
1296                break;
1297            case 1:
1298                break;
1299            case 2:
1300                break;
1301            default:
1302                p = extraPanels.get(layer - 3);
1303        }
1304        if (duration < 0)
1305            duration = animationDuration;
1306        p.bump(ae, dir, duration);
1307        return this;
1308    }
1309
1310    public SquidLayers bump(int x, int y, Direction dir) {
1311        return bump(x, y, 2, dir, -1);
1312    }
1313    public SquidLayers bump(AnimatedEntity ae, Direction dir) {
1314        return bump(ae, 2, dir, -1);
1315    }
1316
1317    public SquidLayers slide(AnimatedEntity ae, int endX, int endY, int layer, float duration) {
1318        SquidPanel p = foregroundPanel;
1319        switch (layer) {
1320            case 0:
1321                p = backgroundPanel;
1322                break;
1323            case 1:
1324                break;
1325            case 2:
1326                break;
1327            default:
1328                p = extraPanels.get(layer - 3);
1329        }
1330        if (duration < 0)
1331            duration = animationDuration;
1332        p.slide(ae, endX, endY, duration);
1333        return this;
1334    }
1335    public SquidLayers slide(int x, int y, int endX, int endY, int layer, float duration) {
1336        SquidPanel p = foregroundPanel;
1337        switch (layer) {
1338            case 0:
1339                p = backgroundPanel;
1340                break;
1341            case 1:
1342                break;
1343            case 2:
1344                break;
1345            default:
1346                p = extraPanels.get(layer - 3);
1347        }
1348        if (duration < 0)
1349            duration = animationDuration;
1350        p.slide(x, y, endX, endY, duration);
1351        return this;
1352    }
1353
1354    public SquidLayers slide(int x, int y, int endX, int endY) {
1355        return slide(x, y, endX, endY, 2, -1);
1356    }
1357    public SquidLayers slide(AnimatedEntity ae, int endX, int endY) {
1358        return slide(ae, endX, endY, 2, -1);
1359    }
1360
1361    public SquidLayers wiggle(int x, int y, int layer, float duration) {
1362        SquidPanel p = foregroundPanel;
1363        switch (layer) {
1364            case 0:
1365                p = backgroundPanel;
1366                break;
1367            case 1:
1368                break;
1369            case 2:
1370                break;
1371            default:
1372                p = extraPanels.get(layer - 3);
1373        }
1374        if (duration < 0)
1375            duration = animationDuration;
1376        p.wiggle(x, y, duration);
1377        return this;
1378    }
1379    public SquidLayers wiggle(AnimatedEntity ae, int layer, float duration) {
1380        SquidPanel p = foregroundPanel;
1381        switch (layer) {
1382            case 0:
1383                p = backgroundPanel;
1384                break;
1385            case 1:
1386                break;
1387            case 2:
1388                break;
1389            default:
1390                p = extraPanels.get(layer - 3);
1391        }
1392        if (duration < 0)
1393            duration = animationDuration;
1394        p.wiggle(ae, duration);
1395        return this;
1396    }
1397
1398    public SquidLayers wiggle(int x, int y) {
1399        return wiggle(x, y, 2, -1);
1400    }
1401    public SquidLayers wiggle(AnimatedEntity ae) {
1402        return wiggle(ae, 2, -1);
1403    }
1404    public SquidLayers tint(int x, int y, Color color, int layer, float duration) {
1405        SquidPanel p = foregroundPanel;
1406        switch (layer) {
1407            case 0:
1408                p = backgroundPanel;
1409                break;
1410            case 1:
1411                break;
1412            case 2:
1413                break;
1414            default:
1415                p = extraPanels.get(layer - 3);
1416        }
1417        if (duration < 0)
1418            duration = animationDuration;
1419        p.tint(x, y, color, duration);
1420        return this;
1421    }
1422    public SquidLayers tint(AnimatedEntity ae, Color color, int layer, float duration) {
1423        SquidPanel p = foregroundPanel;
1424        switch (layer) {
1425            case 0:
1426                p = backgroundPanel;
1427                break;
1428            case 1:
1429                break;
1430            case 2:
1431                break;
1432            default:
1433                p = extraPanels.get(layer - 3);
1434        }
1435        if (duration < 0)
1436            duration = animationDuration;
1437        p.tint(ae, color, duration);
1438        return this;
1439    }
1440
1441    public SquidLayers tint(int x, int y, Color color) {
1442        return tint(x, y, color, 2, -1);
1443    }
1444    public SquidLayers tint(AnimatedEntity ae, Color color) {
1445        return tint(ae, color, 2, -1);
1446    }
1447
1448    public boolean hasActiveAnimations() {
1449        if (foregroundPanel.hasActiveAnimations())
1450            return true;
1451        if (backgroundPanel.hasActiveAnimations())
1452            return true;
1453        for (SquidPanel panel : extraPanels) {
1454            if (panel.hasActiveAnimations())
1455                return true;
1456        }
1457        return false;
1458    }
1459
1460    public AnimatedEntity animateActor(int x, int y, char c, Color color, int layer) {
1461        SquidPanel p = foregroundPanel;
1462        switch (layer) {
1463            case 0:
1464                p = backgroundPanel;
1465                break;
1466            case 1:
1467                break;
1468            case 2:
1469                break;
1470            default:
1471                p = extraPanels.get(layer - 3);
1472        }
1473        return p.animateActor(x, y, c, color);
1474    }
1475
1476    public AnimatedEntity animateActor(int x, int y, char c, Color color) {
1477        return foregroundPanel.animateActor(x, y, c, color);
1478    }
1479    public AnimatedEntity animateActor(int x, int y, char c, Color color, boolean doubleWidth) {
1480        return foregroundPanel.animateActor(x, y, doubleWidth, c, color);
1481    }
1482    public AnimatedEntity animateActor(int x, int y, char c, Collection<Color> colors, boolean doubleWidth) {
1483        return foregroundPanel.animateActor(x, y, doubleWidth, String.valueOf(c), colors);
1484    }
1485    public AnimatedEntity animateActor(int x, int y, char c, Collection<Color> colors, float loopTime, boolean doubleWidth) {
1486        return foregroundPanel.animateActor(x, y, doubleWidth, String.valueOf(c), colors, loopTime);
1487    }
1488
1489    public AnimatedEntity animateActor(int x, int y, char c, int index, ArrayList<Color> palette, int layer) {
1490        return animateActor(x, y, c, palette.get(index), layer);
1491    }
1492    public AnimatedEntity animateActor(int x, int y, char c, int index, ArrayList<Color> palette) {
1493        return animateActor(x, y, c, palette.get(index));
1494    }
1495
1496    public AnimatedEntity animateActor(int x, int y, char c, int index, int layer) {
1497        return animateActor(x, y, c, palette.get(index), layer);
1498    }
1499    public AnimatedEntity animateActor(int x, int y, char c, int index) {
1500        return animateActor(x, y, c, palette.get(index));
1501    }
1502    public AnimatedEntity animateActor(int x, int y, char c, int index, boolean doubleWidth) {
1503        return animateActor(x, y, c, palette.get(index), doubleWidth);
1504    }
1505
1506    public AnimatedEntity animateActor(int x, int y, String s, Color color, int layer) {
1507        SquidPanel p = foregroundPanel;
1508        switch (layer) {
1509            case 0:
1510                p = backgroundPanel;
1511                break;
1512            case 1:
1513                break;
1514            case 2:
1515                break;
1516            default:
1517                p = extraPanels.get(layer - 3);
1518        }
1519        return p.animateActor(x, y, s, color);
1520    }
1521    public AnimatedEntity animateActor(int x, int y, String s, Color color, int layer, boolean doubleWidth) {
1522        SquidPanel p = foregroundPanel;
1523        switch (layer) {
1524            case 0:
1525                p = backgroundPanel;
1526                break;
1527            case 1:
1528                break;
1529            case 2:
1530                break;
1531            default:
1532                p = extraPanels.get(layer - 3);
1533        }
1534        return p.animateActor(x, y, doubleWidth, s, color);
1535    }
1536    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, Color color, int layer) {
1537        SquidPanel p = foregroundPanel;
1538        switch (layer) {
1539            case 0:
1540                p = backgroundPanel;
1541                break;
1542            case 1:
1543                break;
1544            case 2:
1545                break;
1546            default:
1547                p = extraPanels.get(layer - 3);
1548        }
1549        return p.animateActor(x, y, tr, color);
1550    }
1551    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, Color color, int layer, boolean doubleWidth, boolean stretch) {
1552        SquidPanel p = foregroundPanel;
1553        switch (layer) {
1554            case 0:
1555                p = backgroundPanel;
1556                break;
1557            case 1:
1558                break;
1559            case 2:
1560                break;
1561            default:
1562                p = extraPanels.get(layer - 3);
1563        }
1564        return p.animateActor(x, y, doubleWidth, stretch, tr, color);
1565    }
1566
1567    public AnimatedEntity animateActor(int x, int y, String s, Color color) {
1568        return foregroundPanel.animateActor(x, y, s, color);
1569    }
1570    public AnimatedEntity animateActor(int x, int y, String s, Color color, boolean doubleWidth) {
1571        return foregroundPanel.animateActor(x, y, doubleWidth, s, color);
1572    }
1573
1574    public AnimatedEntity animateActor(int x, int y, String s, int index, ArrayList<Color> palette, int layer) {
1575        return animateActor(x, y, s, palette.get(index), layer);
1576    }
1577    public AnimatedEntity animateActor(int x, int y, String s, int index, ArrayList<Color> palette) {
1578        return animateActor(x, y, s, palette.get(index));
1579    }
1580
1581    public AnimatedEntity animateActor(int x, int y, String s, int index, int layer) {
1582        return animateActor(x, y, s, palette.get(index), layer);
1583    }
1584    public AnimatedEntity animateActor(int x, int y, String s, int index) {
1585        return animateActor(x, y, s, palette.get(index));
1586    }
1587    public AnimatedEntity animateActor(int x, int y, String s, int index, boolean doubleWidth) {
1588        return animateActor(x, y, s, palette.get(index), doubleWidth);
1589    }
1590
1591    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, Color color) {
1592        return foregroundPanel.animateActor(x, y, tr, color);
1593    }
1594    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, Color color, boolean doubleWidth) {
1595        return foregroundPanel.animateActor(x, y, doubleWidth, tr, color);
1596    }
1597    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, Color color, boolean doubleWidth, boolean stretch) {
1598        return foregroundPanel.animateActor(x, y, doubleWidth, stretch, tr, color);
1599    }
1600
1601    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, int index, ArrayList<Color> palette, int layer) {
1602        return animateActor(x, y, tr, palette.get(index), layer);
1603    }
1604    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, int index, ArrayList<Color> palette, int layer, boolean doubleWidth) {
1605        return animateActor(x, y, tr, palette.get(index), layer, doubleWidth, true);
1606    }
1607    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, int index, ArrayList<Color> palette, int layer, boolean doubleWidth, boolean stretch) {
1608        return animateActor(x, y, tr, palette.get(index), layer, doubleWidth, stretch);
1609    }
1610    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, int index, ArrayList<Color> palette) {
1611        return animateActor(x, y, tr, palette.get(index));
1612    }
1613    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, int index, int layer) {
1614        return animateActor(x, y, tr, palette.get(index), layer);
1615    }
1616    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, int index) {
1617        return animateActor(x, y, tr, palette.get(index));
1618    }
1619    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, int index, boolean doubleWidth) {
1620        return animateActor(x, y, tr, palette.get(index), doubleWidth);
1621    }
1622    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, int index, boolean doubleWidth, boolean stretch) {
1623        return animateActor(x, y, tr, palette.get(index), doubleWidth, stretch);
1624    }
1625    public AnimatedEntity animateActor(int x, int y, TextureRegion tr) {
1626        return animateActor(x, y, tr, Color.WHITE);
1627    }
1628    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, boolean doubleWidth) {
1629        return animateActor(x, y, tr, Color.WHITE, doubleWidth);
1630    }
1631    public AnimatedEntity animateActor(int x, int y, TextureRegion tr, boolean doubleWidth, boolean stretch) {
1632        return animateActor(x, y, tr, Color.WHITE, doubleWidth, stretch);
1633    }
1634
1635    public LinkedHashSet<AnimatedEntity> getAnimatedEntities(int layer) {
1636        SquidPanel p = foregroundPanel;
1637        switch (layer) {
1638            case 0:
1639                p = backgroundPanel;
1640                break;
1641            case 1:
1642                break;
1643            case 2:
1644                break;
1645            default:
1646                p = extraPanels.get(layer - 3);
1647        }
1648        return p.getAnimatedEntities();
1649    }
1650
1651    public LinkedHashSet<AnimatedEntity> getAnimatedEntities() {
1652        return foregroundPanel.getAnimatedEntities();
1653    }
1654
1655    public AnimatedEntity getAnimatedEntityByCell(int x, int y, int layer) {
1656        SquidPanel p = foregroundPanel;
1657        switch (layer) {
1658            case 0:
1659                p = backgroundPanel;
1660                break;
1661            case 1:
1662                break;
1663            case 2:
1664                break;
1665            default:
1666                p = extraPanels.get(layer - 3);
1667        }
1668        return p.getAnimatedEntityByCell(x, y);
1669    }
1670    public void removeAnimatedEntity(AnimatedEntity ae, int layer)
1671    {
1672        SquidPanel p = foregroundPanel;
1673        switch (layer) {
1674            case 0:
1675                p = backgroundPanel;
1676                break;
1677            case 1:
1678                break;
1679            case 2:
1680                break;
1681            default:
1682                p = extraPanels.get(layer - 3);
1683        }
1684        p.removeAnimatedEntity(ae);
1685    }
1686    public void removeAnimatedEntity(AnimatedEntity ae)
1687    {
1688        foregroundPanel.removeAnimatedEntity(ae);
1689    }
1690
1691    public AnimatedEntity getAnimatedEntityByCell(int x, int y) {
1692        return foregroundPanel.getAnimatedEntityByCell(x, y);
1693    }
1694
1695    public void removeAnimatedEntityByCell(int x, int y, int layer) {
1696        SquidPanel p = foregroundPanel;
1697        switch (layer) {
1698            case 0:
1699                p = backgroundPanel;
1700                break;
1701            case 1:
1702                break;
1703            case 2:
1704                break;
1705            default:
1706                p = extraPanels.get(layer - 3);
1707        }
1708        p.removeAnimatedEntity(getAnimatedEntityByCell(x, y, layer));
1709    }
1710    public void removeAnimatedEntityByCell(int x, int y) {
1711        foregroundPanel.removeAnimatedEntity(getAnimatedEntityByCell(x, y));
1712    }
1713
1714    @Override
1715    public void draw(Batch batch, float parentAlpha) {
1716        //textFactory.configureShader(batch);
1717        super.draw(batch, parentAlpha);
1718    }
1719
1720    public void drawActor(Batch batch, float parentAlpha, AnimatedEntity ae, int layer)
1721    {
1722        SquidPanel p = foregroundPanel;
1723        switch (layer) {
1724            case 0:
1725                p = backgroundPanel;
1726                break;
1727            case 1:
1728                break;
1729            case 2:
1730                break;
1731            default:
1732                p = extraPanels.get(layer - 3);
1733        }
1734        p.drawActor(batch, parentAlpha, ae);
1735    }
1736    public void drawActor(Batch batch, float parentAlpha, AnimatedEntity ae)
1737    {
1738        foregroundPanel.drawActor(batch, parentAlpha, ae);
1739    }
1740    public void setLightingColor(Color lightingColor)
1741    {
1742        backgroundPanel.setLightingColor(lightingColor);
1743    }
1744    public Color getLightingColor()
1745    {
1746        return backgroundPanel.getLightingColor();
1747    }
1748
1749    private int clamp(int x, int min, int max)
1750    {
1751        return Math.min(Math.max(min, x), max);
1752    }
1753
1754
1755    /**
1756     * Sets the position of the actor's bottom left corner.
1757     *
1758     * @param x
1759     * @param y
1760     */
1761    @Override
1762    public void setPosition(float x, float y) {
1763        super.setPosition(x, y);
1764        setBounds(x, y, getWidth(), getHeight());
1765        foregroundPanel.setPosition(x, y);
1766        backgroundPanel.setPosition(x, y);
1767        for(SquidPanel panel : extraPanels)
1768        {
1769            panel.setPosition(x, y);
1770        }
1771    }
1772
1773    public SquidPanel getLayer(int layer)
1774    {
1775        SquidPanel p = foregroundPanel;
1776        switch (layer) {
1777            case 0:
1778                p = backgroundPanel;
1779                break;
1780            case 1:
1781                break;
1782            case 2:
1783                break;
1784            default:
1785                p = extraPanels.get(layer - 3);
1786        }
1787        return p;
1788    }
1789    public SquidPanel getForegroundLayer()
1790    {
1791        return foregroundPanel;
1792    }
1793    public SquidPanel getBackgroundLayer()
1794    {
1795        return backgroundPanel;
1796    }
1797
1798
1799    /**
1800     * Sets the IColorCenter used by the foreground layer.
1801     *
1802     * @param scc an IColorCenter<Color>; commonly a SquidColorCenter with an optional filter
1803     */
1804    public void setFGColorCenter(IColorCenter<Color> scc) {
1805        foregroundPanel.setColorCenter(scc);
1806    }
1807    /**
1808     * Sets the IColorCenter used by the background layer.
1809     *
1810     * @param scc an IColorCenter<Color>; commonly a SquidColorCenter with an optional filter
1811     */
1812    public void setBGColorCenter(IColorCenter<Color> scc) {
1813        backgroundPanel.setColorCenter(scc);
1814    }
1815    public void setOffsets(float x, float y)
1816    {
1817        foregroundPanel.setOffsets(x, y);
1818        backgroundPanel.setOffsets(x, y);
1819        for(SquidPanel p : extraPanels)
1820            p.setOffsets(x, y);
1821    }
1822}