/* This file is part of Eternity II Editor. * * Eternity II Editor is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Eternity II Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Eternity II Editor. If not, see <http://www.gnu.org/licenses/>. * * Eternity II Editor project is hosted on SourceForge: * http://sourceforge.net/projects/eternityii/ * and maintained by Yannick Kirschhoffer <alcibiade@alcibiade.org> */ package org.alcibiade.eternity.editor.model; import java.awt.Color; import java.awt.GradientPaint; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.Dimension2D; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import java.util.Arrays; import java.util.List; public enum Pattern implements Comparable<Pattern>, Serializable { // "Empty" pattern a.k.a. default pattern PAT_00(0, PatternColor.COL_GRAY, PatternColor.COL_GRAY, PatternShape.SHAPE_NONE), // Original patterns // 1-8 PAT_01(1, PatternColor.COL_ORANGE, PatternColor.COL_LIGHTBLUE, PatternShape.SHAPE_ROUNDCROSS), PAT_02( 2, PatternColor.COL_DARKBLUE, PatternColor.COL_YELLOW, PatternShape.SHAPE_FLOWER), PAT_03( 3, PatternColor.COL_PINK, PatternColor.COL_LIGHTBLUE, PatternShape.SHAPE_HOLLOWCROSS), PAT_04( 4, PatternColor.COL_GREEN, PatternColor.COL_DARKBLUE, PatternShape.SHAPE_BOULON), PAT_05( 5, PatternColor.COL_BROWN, PatternColor.COL_ORANGE, PatternShape.SHAPE_ROUNDCASTLE), PAT_06( 6, PatternColor.COL_PINK, PatternColor.COL_YELLOW, PatternShape.SHAPE_CROSSBALLS), PAT_07( 7, PatternColor.COL_DARKPURPLE, PatternColor.COL_LIGHTBLUE, PatternShape.SHAPE_LYS), PAT_08( 8, PatternColor.COL_YELLOW, PatternColor.COL_LIGHTBLUE, PatternShape.SHAPE_STAR), // 9-22 PAT_09(9, PatternColor.COL_DARKPURPLE, PatternColor.COL_YELLOW, PatternShape.SHAPE_TOXIC), PAT_10( 10, PatternColor.COL_GREEN, PatternColor.COL_PINK, PatternShape.SHAPE_CROSSBALLS), PAT_11( 11, PatternColor.COL_DARKPURPLE, PatternColor.COL_GREEN, PatternShape.SHAPE_TOXIC), PAT_12( 12, PatternColor.COL_GREEN, PatternColor.COL_ORANGE, PatternShape.SHAPE_LYS), PAT_13( 13, PatternColor.COL_DARKPURPLE, PatternColor.COL_YELLOW, PatternShape.SHAPE_STAR), PAT_14( 14, PatternColor.COL_LIGHTBLUE, PatternColor.COL_PINK, PatternShape.SHAPE_CASTLE), PAT_15( 15, PatternColor.COL_YELLOW, PatternColor.COL_GREEN, PatternShape.SHAPE_SQUARE), PAT_16( 16, PatternColor.COL_LIGHTBLUE, PatternColor.COL_PINK, PatternShape.SHAPE_LYS), PAT_17( 17, PatternColor.COL_YELLOW, PatternColor.COL_DARKBLUE, PatternShape.SHAPE_CASTLE), PAT_18( 18, PatternColor.COL_ORANGE, PatternColor.COL_DARKPURPLE, PatternShape.SHAPE_STAR), PAT_19( 19, PatternColor.COL_DARKBLUE, PatternColor.COL_ORANGE, PatternShape.SHAPE_CROSSBALLS), PAT_20( 20, PatternColor.COL_DARKBLUE, PatternColor.COL_LIGHTBLUE, PatternShape.SHAPE_SQUARE), PAT_21( 21, PatternColor.COL_PINK, PatternColor.COL_YELLOW, PatternShape.SHAPE_CASTLE), PAT_22( 22, PatternColor.COL_DARKBLUE, PatternColor.COL_PINK, PatternShape.SHAPE_TOXIC), // Extra patterns PAT_23(23, PatternColor.COL_MAGENTA, PatternColor.COL_LIGHTBLUE, PatternShape.SHAPE_TOXIC), PAT_24( 24, PatternColor.COL_GREEN, PatternColor.COL_ORANGE, PatternShape.SHAPE_SQUARE), PAT_25( 25, PatternColor.COL_LIGHTBLUE, PatternColor.COL_PINK, PatternShape.SHAPE_SQUARE), PAT_26( 26, PatternColor.COL_YELLOW, PatternColor.COL_GREEN, PatternShape.SHAPE_FLOWER), PAT_27( 27, PatternColor.COL_MAGENTA, PatternColor.COL_LIGHTBLUE, PatternShape.SHAPE_LYS), PAT_28( 28, PatternColor.COL_PURPLE, PatternColor.COL_YELLOW, PatternShape.SHAPE_CASTLE), PAT_29( 29, PatternColor.COL_GREEN, PatternColor.COL_LIGHTBLUE, PatternShape.SHAPE_STAR), PAT_30( 30, PatternColor.COL_YELLOW, PatternColor.COL_LIGHTBLUE, PatternShape.SHAPE_BOULON), // End of new 1.1 batch PAT_31(31, PatternColor.COL_MAGENTA, PatternColor.COL_GREEN, PatternShape.SHAPE_BOULON), PAT_32( 32, PatternColor.COL_MAGENTA, PatternColor.COL_GREEN, PatternShape.SHAPE_HOLLOWCROSS), PAT_33( 33, PatternColor.COL_PURPLE, PatternColor.COL_MAGENTA, PatternShape.SHAPE_ROUNDCROSS), PAT_34( 34, PatternColor.COL_DARKPURPLE, PatternColor.COL_ORANGE, PatternShape.SHAPE_CROSSBALLS), PAT_35( 35, PatternColor.COL_ORANGE, PatternColor.COL_GREEN, PatternShape.SHAPE_LYS), PAT_36( 36, PatternColor.COL_LIGHTBLUE, PatternColor.COL_DARKBLUE, PatternShape.SHAPE_STAR), PAT_37( 37, PatternColor.COL_PURPLE, PatternColor.COL_GREEN, PatternShape.SHAPE_CASTLE), PAT_38( 38, PatternColor.COL_YELLOW, PatternColor.COL_PURPLE, PatternShape.SHAPE_HOLLOWCROSS), PAT_39( 39, PatternColor.COL_GREEN, PatternColor.COL_YELLOW, PatternShape.SHAPE_STAR); private int patternCode; private PatternColor patternBg; private PatternColor patternFg; private PatternShape patternShape; private Pattern(int code, PatternColor bg, PatternColor fg, PatternShape shape) { patternCode = code; patternBg = bg; patternFg = fg; patternShape = shape; } public int getCode() { return patternCode; } public PatternColor getPatternBg() { return patternBg; } public PatternColor getPatternFg() { return patternFg; } public PatternShape getPatternShape() { return patternShape; } public String getCodeString() { String result = null; if (patternCode < 10) { result = " " + patternCode; } else { result = Integer.toString(patternCode); } return result; } public void paint(Graphics2D g2d, Dimension2D size) { double w = size.getWidth(); double h = size.getHeight(); Color bg = patternBg.getColor(); if (patternBg != PatternColor.COL_GRAY) { bg = bg.darker(); } GradientPaint grad_back = new GradientPaint(new Point2D.Double(0, 0), patternBg.getColor() .brighter(), new Point2D.Double(0, h), bg); g2d.setPaint(grad_back); GeneralPath globalshape = new GeneralPath(); globalshape.moveTo(0, (float) h / 2); globalshape.lineTo((float) w / 2, 0); globalshape.lineTo((float) w, (float) h / 2); globalshape.lineTo((float) w / 2, (float) h); Shape previous_clip = g2d.getClip(); g2d.fill(globalshape); g2d.clip(globalshape); double cx = w / 2.; double cy = h / 2.; double minsize = Math.min(w, h); if (patternShape == PatternShape.SHAPE_NONE) { // Nothing to do } else if (patternShape == PatternShape.SHAPE_ROUNDCROSS) { double rad_ext = minsize * 0.60; g2d.setColor(patternFg.getColor()); g2d.fill(new Ellipse2D.Double(cx - rad_ext / 2, cy - rad_ext / 2, rad_ext, rad_ext)); double rad_in = minsize * 0.28; double rad_out = minsize * 0.22; g2d.setPaint(grad_back); g2d.fill(new Ellipse2D.Double(cx - rad_out - rad_in / 2, cy - rad_out - rad_in / 2, rad_in, rad_in)); g2d.fill(new Ellipse2D.Double(cx - rad_out - rad_in / 2, cy + rad_out - rad_in / 2, rad_in, rad_in)); g2d.fill(new Ellipse2D.Double(cx + rad_out - rad_in / 2, cy - rad_out - rad_in / 2, rad_in, rad_in)); g2d.fill(new Ellipse2D.Double(cx + rad_out - rad_in / 2, cy + rad_out - rad_in / 2, rad_in, rad_in)); } else if (patternShape == PatternShape.SHAPE_HOLLOWCROSS) { double rad_ext = minsize * 0.60; g2d.setColor(patternFg.getColor()); g2d.fill(new Rectangle2D.Double(cx - rad_ext / 2, cy - rad_ext / 2, rad_ext, rad_ext)); double rad_in = minsize * 0.40; double rad_out = rad_ext * 0.52; g2d.setPaint(grad_back); g2d.fill(new Ellipse2D.Double(cx - rad_out - rad_in / 2, cy - rad_out - rad_in / 2, rad_in, rad_in)); g2d.fill(new Ellipse2D.Double(cx - rad_out - rad_in / 2, cy + rad_out - rad_in / 2, rad_in, rad_in)); g2d.fill(new Ellipse2D.Double(cx + rad_out - rad_in / 2, cy - rad_out - rad_in / 2, rad_in, rad_in)); g2d.fill(new Ellipse2D.Double(cx + rad_out - rad_in / 2, cy + rad_out - rad_in / 2, rad_in, rad_in)); double rad_hole = minsize * 0.15; GeneralPath inside = new GeneralPath(); inside.moveTo((float) (cx), (float) (cy - rad_hole)); inside.lineTo((float) (cx + rad_hole), (float) (cy)); inside.lineTo((float) (cx), (float) (cy + rad_hole)); inside.lineTo((float) (cx - rad_hole), (float) (cy)); g2d.fill(inside); } else if (patternShape == PatternShape.SHAPE_BOULON) { double p1 = minsize * 0.4; double p2 = p1 * 0.66; double p3 = p1 * 0.33; GeneralPath boulon = new GeneralPath(); boulon.moveTo((float) (cx - p2), (float) (cy)); boulon.lineTo((float) (cx - p2), (float) (cy - p3)); boulon.lineTo((float) (cx - p3), (float) (cy - p2)); boulon.lineTo((float) (cx), (float) (cy - p2)); boulon.lineTo((float) (cx + p3), (float) (cy - p2)); boulon.lineTo((float) (cx + p2), (float) (cy - p3)); boulon.lineTo((float) (cx + p2), (float) (cy)); boulon.lineTo((float) (cx + p2), (float) (cy + p3)); boulon.lineTo((float) (cx + p3), (float) (cy + p2)); boulon.lineTo((float) (cx), (float) (cy + p2)); boulon.lineTo((float) (cx - p3), (float) (cy + p2)); boulon.lineTo((float) (cx - p2), (float) (cy + p3)); g2d.setColor(patternFg.getColor()); g2d.fill(boulon); double rad_in = minsize * 0.27; g2d.setPaint(grad_back); g2d.fill(new Ellipse2D.Double(cx - rad_in / 2, cy - rad_in / 2, rad_in, rad_in)); } else if (patternShape == PatternShape.SHAPE_FLOWER) { double rad = minsize / 7; g2d.setColor(patternFg.getColor()); g2d.fill(new Ellipse2D.Double(cx - 2 * rad, cy - 1 * rad, 2 * rad, 2 * rad)); g2d.fill(new Ellipse2D.Double(cx - 1 * rad, cy - 2 * rad, 2 * rad, 2 * rad)); g2d.fill(new Ellipse2D.Double(cx + 0 * rad, cy - 1 * rad, 2 * rad, 2 * rad)); g2d.fill(new Ellipse2D.Double(cx - 1 * rad, cy + 0 * rad, 2 * rad, 2 * rad)); rad *= 0.9; g2d.setPaint(grad_back); g2d.fill(new Ellipse2D.Double(cx - rad, cy - rad, 2 * rad, 2 * rad)); } else if (patternShape == PatternShape.SHAPE_LYS) { double p1 = minsize * 0.35; double p2 = p1 * 0.66; double p3 = p1 * 0.33; double p4 = p1 * 0.20; g2d.setColor(patternFg.getColor()); GeneralPath lys = new GeneralPath(); lys.moveTo((float) (cx - p1), (float) (cy)); lys.lineTo((float) (cx - p2), (float) (cy - p3)); lys.lineTo((float) (cx - p4), (float) (cy - p4)); lys.lineTo((float) (cx - p3), (float) (cy - p2)); lys.lineTo((float) (cx), (float) (cy - p1)); lys.lineTo((float) (cx + p3), (float) (cy - p2)); lys.lineTo((float) (cx + p4), (float) (cy - p4)); lys.lineTo((float) (cx + p2), (float) (cy - p3)); lys.lineTo((float) (cx + p1), (float) (cy)); lys.lineTo((float) (cx + p2), (float) (cy + p3)); lys.lineTo((float) (cx + p4), (float) (cy + p4)); lys.lineTo((float) (cx + p3), (float) (cy + p2)); lys.lineTo((float) (cx), (float) (cy + p1)); lys.lineTo((float) (cx - p3), (float) (cy + p2)); lys.lineTo((float) (cx - p4), (float) (cy + p4)); lys.lineTo((float) (cx - p2), (float) (cy + p3)); g2d.setColor(patternFg.getColor()); g2d.fill(lys); } else if (patternShape == PatternShape.SHAPE_ROUNDCASTLE) { double p1 = minsize * 0.23; double p2 = p1 * 0.90; // Main circle radius double p3 = p1 * 0.45; // External circles radius double p4 = p1 * 0.90; // Inner star major radius double p5 = p1 * 0.30; // Inner star minor radius g2d.setColor(patternFg.getColor()); g2d.fill(new Ellipse2D.Double(cx - p2, cy - p2, 2 * p2, 2 * p2)); g2d.fill(new Ellipse2D.Double(cx - p1 - p3, cy - p3, 2 * p3, 2 * p3)); g2d.fill(new Ellipse2D.Double(cx - p3, cy - p1 - p3, 2 * p3, 2 * p3)); g2d.fill(new Ellipse2D.Double(cx + p1 - p3, cy - p3, 2 * p3, 2 * p3)); g2d.fill(new Ellipse2D.Double(cx - p3, cy + p1 - p3, 2 * p3, 2 * p3)); GeneralPath innerStar = new GeneralPath(); innerStar.moveTo((float) (cx), (float) (cy - p4)); innerStar.lineTo((float) (cx + p5), (float) (cy - p5)); innerStar.lineTo((float) (cx + p4), (float) (cy)); innerStar.lineTo((float) (cx + p5), (float) (cy + p5)); innerStar.lineTo((float) (cx), (float) (cy + p4)); innerStar.lineTo((float) (cx - p5), (float) (cy + p5)); innerStar.lineTo((float) (cx - p4), (float) (cy)); innerStar.lineTo((float) (cx - p5), (float) (cy - p5)); innerStar.lineTo((float) (cx), (float) (cy - p4)); g2d.setColor(patternBg.getColor()); g2d.fill(innerStar); } else if (patternShape == PatternShape.SHAPE_CROSSBALLS) { double p1 = minsize * 0.23; double p2 = p1 * 0.30; double p3 = p1 * 0.45; g2d.setColor(patternFg.getColor()); g2d.fill(new Rectangle2D.Double(cx - p1, cy - p2, 2 * p1, 2 * p2)); g2d.fill(new Rectangle2D.Double(cx - p2, cy - p1, 2 * p2, 2 * p1)); g2d.fill(new Ellipse2D.Double(cx - p1 - p3, cy - p3, 2 * p3, 2 * p3)); g2d.fill(new Ellipse2D.Double(cx - p3, cy - p1 - p3, 2 * p3, 2 * p3)); g2d.fill(new Ellipse2D.Double(cx + p1 - p3, cy - p3, 2 * p3, 2 * p3)); g2d.fill(new Ellipse2D.Double(cx - p3, cy + p1 - p3, 2 * p3, 2 * p3)); } else if (patternShape == PatternShape.SHAPE_CASTLE) { double p1 = minsize * 0.35; double p2 = p1 * 0.66; double p3 = p1 * 0.33; double p4 = p1 * 0.15; GeneralPath castle = new GeneralPath(); castle.moveTo((float) (cx - p1), (float) (cy)); castle.lineTo((float) (cx - p2), (float) (cy - p3)); castle.lineTo((float) (cx - p2 + p4), (float) (cy - p3 + p4)); castle.lineTo((float) (cx - p3 + p4), (float) (cy - p2 + p4)); castle.lineTo((float) (cx - p3), (float) (cy - p2)); castle.lineTo((float) (cx), (float) (cy - p1)); castle.lineTo((float) (cx + p3), (float) (cy - p2)); castle.lineTo((float) (cx + p3 - p4), (float) (cy - p2 + p4)); castle.lineTo((float) (cx + p2 - p4), (float) (cy - p3 + p4)); castle.lineTo((float) (cx + p2), (float) (cy - p3)); castle.lineTo((float) (cx + p1), (float) (cy)); castle.lineTo((float) (cx + p2), (float) (cy + p3)); castle.lineTo((float) (cx + p2 - p4), (float) (cy + p3 - p4)); castle.lineTo((float) (cx + p3 - p4), (float) (cy + p2 - p4)); castle.lineTo((float) (cx + p3), (float) (cy + p2)); castle.lineTo((float) (cx), (float) (cy + p1)); castle.lineTo((float) (cx - p3), (float) (cy + p2)); castle.lineTo((float) (cx - p3 + p4), (float) (cy + p2 - p4)); castle.lineTo((float) (cx - p2 + p4), (float) (cy + p3 - p4)); castle.lineTo((float) (cx - p2), (float) (cy + p3)); g2d.setColor(patternFg.getColor()); g2d.fill(castle); g2d.setColor(patternFg.getColor().darker()); g2d.draw(castle); } else if (patternShape == PatternShape.SHAPE_SQUARE) { double p1 = minsize * 0.35; double p2 = p1 * 0.50; GeneralPath square_ext = new GeneralPath(); square_ext.moveTo((float) (cx - p1), (float) (cy)); square_ext.lineTo((float) (cx), (float) (cy - p1)); square_ext.lineTo((float) (cx + p1), (float) (cy)); square_ext.lineTo((float) (cx), (float) (cy + p1)); g2d.setColor(patternFg.getColor()); g2d.fill(square_ext); g2d.setColor(patternFg.getColor().darker()); g2d.draw(square_ext); GeneralPath square_int = new GeneralPath(); square_int.moveTo((float) (cx - p2), (float) (cy)); square_int.lineTo((float) (cx), (float) (cy - p2)); square_int.lineTo((float) (cx + p2), (float) (cy)); square_int.lineTo((float) (cx), (float) (cy + p2)); g2d.setColor(patternBg.getColor()); g2d.fill(square_int); g2d.setColor(patternBg.getColor().darker()); g2d.draw(square_int); } else if (patternShape == PatternShape.SHAPE_TOXIC) { double p1 = minsize * 0.30; double p2 = p1 * 0.30; double p3 = p2 * 1.10; Ellipse2D circle_ext = new Ellipse2D.Double(cx - p1, cy - p1, 2 * p1, 2 * p1); g2d.setColor(patternFg.getColor()); g2d.fill(circle_ext); g2d.setColor(patternFg.getColor().darker()); g2d.draw(circle_ext); GeneralPath cross_int = new GeneralPath(); cross_int.moveTo((float) (cx - p2), (float) (cy)); cross_int.lineTo((float) (cx - p2 - p3), (float) (cy - p3)); cross_int.lineTo((float) (cx - p3), (float) (cy - p2 - p3)); cross_int.lineTo((float) (cx), (float) (cy - p2)); cross_int.lineTo((float) (cx + p3), (float) (cy - p2 - p3)); cross_int.lineTo((float) (cx + p2 + p3), (float) (cy - p3)); cross_int.lineTo((float) (cx + p2), (float) (cy)); cross_int.lineTo((float) (cx + p2 + p3), (float) (cy + p3)); cross_int.lineTo((float) (cx + p3), (float) (cy + p2 + p3)); cross_int.lineTo((float) (cx), (float) (cy + p2)); cross_int.lineTo((float) (cx - p3), (float) (cy + p2 + p3)); cross_int.lineTo((float) (cx - p2 - p3), (float) (cy + p3)); g2d.setColor(patternBg.getColor()); g2d.fill(cross_int); g2d.setColor(patternBg.getColor().darker()); g2d.draw(cross_int); } else if (patternShape == PatternShape.SHAPE_STAR) { double rad1 = minsize * 0.3; double rad2 = rad1 * 0.5; g2d.setColor(patternFg.getColor()); GeneralPath star = new GeneralPath(); star.moveTo((float) (cx - rad1), (float) (cy)); for (int a = 0; a <= 360; a += 30) { double rad; if (a % 60 == 0) { rad = rad1; } else { rad = rad2; } double arad = Math.PI * 2. * a / 360.; star.lineTo((float) (cx + rad * Math.cos(arad)), (float) (cy + rad * Math.sin(arad))); } g2d.fill(star); } g2d.setClip(previous_clip); } public static List<Pattern> getAllPatterns() { return Arrays.asList(values()); } public static List<Pattern> getNonDefaultPatterns() { List<Pattern> allPatterns = getAllPatterns(); return allPatterns.subList(1, allPatterns.size()); } public static Pattern getDefaultPattern() { return PAT_00; } public static Pattern getPatternByCode(int patternCode) { Pattern result = null; for (Pattern pattern : getAllPatterns()) { if (pattern.getCode() == patternCode) { result = pattern; } } return result; } @Override public String toString() { return String.format("Pat%02d", patternCode); } }