1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.gui.animation;
|
---|
3 |
|
---|
4 | import java.awt.Color;
|
---|
5 | import java.awt.Graphics;
|
---|
6 | import java.awt.Point;
|
---|
7 | import java.awt.Polygon;
|
---|
8 | import java.util.Random;
|
---|
9 |
|
---|
10 | /**
|
---|
11 | * A star displayed when {@link ChristmasExtension} is active. Copied from Icedtea-Web.
|
---|
12 | * @author Jiri Vanek (Red Hat)
|
---|
13 | * @see <a href="http://icedtea.classpath.org/hg/icedtea-web/rev/87d3081ab573">Initial commit</a>
|
---|
14 | * @since 14581
|
---|
15 | */
|
---|
16 | class Star {
|
---|
17 | private static final Random seed = new Random();
|
---|
18 |
|
---|
19 | static final int averageStarWidth = 10; // stars will be 5-15
|
---|
20 | static final int averageFallSpeed = 4; // 2-6
|
---|
21 | static final int averageRotationSpeed = 2; // 1-3
|
---|
22 |
|
---|
23 | private static final Color WATER_LIVE_COLOR = new Color(80, 131, 160);
|
---|
24 |
|
---|
25 | private final int w;
|
---|
26 | private final int h;
|
---|
27 |
|
---|
28 | private int radiusX;
|
---|
29 | private int radiusY;
|
---|
30 | private int maxRadiusX;
|
---|
31 | private int maxRadiusY;
|
---|
32 | private final Point center = new Point();
|
---|
33 | private final int fallSpeed;
|
---|
34 | private final boolean orientation;
|
---|
35 | private final int[] originalColor = new int[3];
|
---|
36 | private final int[] color = new int[originalColor.length];
|
---|
37 | private int direction;
|
---|
38 | private final boolean haveEight;
|
---|
39 |
|
---|
40 | Star(int w, int h) {
|
---|
41 | this.w = w;
|
---|
42 | this.h = h;
|
---|
43 | createRadiuses();
|
---|
44 | haveEight = seed.nextBoolean();
|
---|
45 | center.x = seed.nextInt(w + 1);
|
---|
46 | center.y = seed.nextInt(h + 1);
|
---|
47 | fallSpeed = averageFallSpeed / 2 + seed.nextInt(averageFallSpeed / 2);
|
---|
48 | orientation = seed.nextBoolean();
|
---|
49 | direction = -(averageRotationSpeed / 2 + seed.nextInt(averageRotationSpeed / 2));
|
---|
50 | if (seed.nextInt(4) == 0) {
|
---|
51 | originalColor[0] = Color.yellow.getRed();
|
---|
52 | originalColor[1] = Color.yellow.getGreen();
|
---|
53 | originalColor[2] = Color.yellow.getBlue();
|
---|
54 | } else {
|
---|
55 | originalColor[0] = WATER_LIVE_COLOR.getRed();
|
---|
56 | originalColor[1] = WATER_LIVE_COLOR.getGreen();
|
---|
57 | originalColor[2] = WATER_LIVE_COLOR.getBlue();
|
---|
58 | }
|
---|
59 | }
|
---|
60 |
|
---|
61 | void paint(Graphics g) {
|
---|
62 | Color c = g.getColor();
|
---|
63 | g.setColor(new Color(color[0], color[1], color[2]));
|
---|
64 | Polygon p = createPolygon();
|
---|
65 | if (haveEight) {
|
---|
66 | int min1 = Math.min(radiusX, radiusY);
|
---|
67 | int min2 = min1 / 2;
|
---|
68 | g.fillRect(center.x - min2, center.y - min2, min1, min1);
|
---|
69 | }
|
---|
70 | g.fillPolygon(p);
|
---|
71 | g.setColor(c);
|
---|
72 | }
|
---|
73 |
|
---|
74 | void animate() {
|
---|
75 | center.y += fallSpeed;
|
---|
76 | if (orientation) {
|
---|
77 | radiusX += direction;
|
---|
78 | if (radiusX <= -direction) {
|
---|
79 | direction = -direction;
|
---|
80 | radiusX = direction;
|
---|
81 | }
|
---|
82 | if (radiusX >= maxRadiusX) {
|
---|
83 | direction = -direction;
|
---|
84 | radiusX = maxRadiusX;
|
---|
85 | }
|
---|
86 | interpolateColors(radiusX, maxRadiusX);
|
---|
87 | } else {
|
---|
88 | radiusY += direction;
|
---|
89 | if (radiusY <= -direction) {
|
---|
90 | direction = -direction;
|
---|
91 | radiusY = direction;
|
---|
92 | }
|
---|
93 | if (radiusY >= maxRadiusY) {
|
---|
94 | direction = -direction;
|
---|
95 | radiusY = maxRadiusY;
|
---|
96 | }
|
---|
97 | interpolateColors(radiusY, maxRadiusY);
|
---|
98 | }
|
---|
99 | if (center.y > h + radiusX * 2 || center.y > h + radiusY * 2) {
|
---|
100 | createRadiuses();
|
---|
101 | center.x = seed.nextInt(w + 1);
|
---|
102 | center.y = -radiusY * 2;
|
---|
103 | }
|
---|
104 | }
|
---|
105 |
|
---|
106 | private static int createRadius() {
|
---|
107 | return averageStarWidth / 2 + seed.nextInt(averageStarWidth);
|
---|
108 | }
|
---|
109 |
|
---|
110 | private Polygon createPolygon() {
|
---|
111 | int min = Math.min(radiusX, radiusY) / 3;
|
---|
112 | Polygon p = new Polygon();
|
---|
113 | p.addPoint(center.x - radiusX, center.y);
|
---|
114 | p.addPoint(center.x - min, center.y - min);
|
---|
115 | p.addPoint(center.x, center.y - radiusY);
|
---|
116 | p.addPoint(center.x + min, center.y - min);
|
---|
117 | p.addPoint(center.x + radiusX, center.y);
|
---|
118 | p.addPoint(center.x + min, center.y + min);
|
---|
119 | p.addPoint(center.x, center.y + radiusY);
|
---|
120 | p.addPoint(center.x - min, center.y + min);
|
---|
121 | return p;
|
---|
122 | }
|
---|
123 |
|
---|
124 | private void interpolateColors(int is, int max) {
|
---|
125 | for (int i = 0; i < originalColor.length; i++) {
|
---|
126 | int fadeMin;
|
---|
127 | if (center.y < 0) {
|
---|
128 | fadeMin = 0;
|
---|
129 | } else if (center.y > h) {
|
---|
130 | fadeMin = 255;
|
---|
131 | } else {
|
---|
132 | fadeMin = (int) interpol(h, center.y, 255, 0); // from white to black
|
---|
133 | }
|
---|
134 | int fadeMax;
|
---|
135 | if (center.y < 0) {
|
---|
136 | fadeMax = 0;
|
---|
137 | } else if (center.y > h) {
|
---|
138 | fadeMax = originalColor[i];
|
---|
139 | } else {
|
---|
140 | fadeMax = (int) interpol(h, center.y, originalColor[i], 0); // from color to black
|
---|
141 | }
|
---|
142 | color[i] = (int) interpol(max, is, fadeMin, fadeMax);
|
---|
143 | }
|
---|
144 | }
|
---|
145 |
|
---|
146 | private void createRadiuses() {
|
---|
147 | radiusX = createRadius();
|
---|
148 | radiusY = radiusX;
|
---|
149 | switch (seed.nextInt(3)) {
|
---|
150 | case 0:
|
---|
151 | radiusX = radiusX + (2 * radiusX) / 3;
|
---|
152 | break;
|
---|
153 | case 1:
|
---|
154 | radiusY = radiusY + (2 * radiusY) / 3;
|
---|
155 | break;
|
---|
156 | default:
|
---|
157 | break;
|
---|
158 | }
|
---|
159 | maxRadiusX = radiusX;
|
---|
160 | maxRadiusY = radiusY;
|
---|
161 | }
|
---|
162 |
|
---|
163 | /**
|
---|
164 | * Interpolation is root ratio is r= (currentSize / origSize)
|
---|
165 | * then value to-from is interpolated from to to from according to ratio
|
---|
166 | *
|
---|
167 | * @param origSize original size
|
---|
168 | * @param currentSize current size
|
---|
169 | * @param from starting value
|
---|
170 | * @param to ending value
|
---|
171 | * @return interpolated value
|
---|
172 | */
|
---|
173 | static double interpol(double origSize, double currentSize, double from, double to) {
|
---|
174 | return (currentSize / origSize) * (to - from) + from;
|
---|
175 | }
|
---|
176 | }
|
---|