Skip to content

Commit d213385

Browse files
ItsEmpalineargraph
authored andcommitted
fix: chroma colour not properly adding alpha, and translated chroma colour into kotlin
1 parent f1d979b commit d213385

File tree

1 file changed

+162
-175
lines changed

1 file changed

+162
-175
lines changed
Lines changed: 162 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1,223 +1,210 @@
1-
/*
2-
* Copyright (C) 2023 NotEnoughUpdates contributors
3-
*
4-
* This file is part of MoulConfig.
5-
*
6-
* MoulConfig is free software: you can redistribute it
7-
* and/or modify it under the terms of the GNU Lesser General Public
8-
* License as published by the Free Software Foundation, either
9-
* version 3 of the License, or (at your option) any later version.
10-
*
11-
* MoulConfig is distributed in the hope that it will be useful,
12-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14-
* Lesser General Public License for more details.
15-
*
16-
* You should have received a copy of the GNU Lesser General Public License
17-
* along with MoulConfig. If not, see <https://www.gnu.org/licenses/>.
18-
*
19-
*/
20-
21-
package io.github.notenoughupdates.moulconfig;
22-
23-
import com.google.gson.annotations.Expose;
24-
import lombok.AllArgsConstructor;
25-
import lombok.Data;
26-
27-
import java.awt.*;
28-
29-
@Data
30-
@AllArgsConstructor
31-
public class ChromaColour {
32-
/**
33-
* Hue in a range from 0 to 1. For a chroma colour this is added to the time as an offset.
34-
*/
35-
@Expose
36-
float hue;
37-
/**
38-
* Saturation in a range from 0 to 1
39-
*/
40-
@Expose
41-
float saturation;
42-
/**
43-
* Brightness in a range from 0 to 1
44-
*/
45-
@Expose
46-
float brightness;
47-
/**
48-
* If set to 0, this indicates a static colour. If set to a value above 0, indicates the amount of milliseconds that pass until the same colour is met again.
49-
* This value may be saved lossy.
50-
*/
51-
@Expose
52-
int timeForFullRotationInMillis;
53-
/**
54-
* Alpha in a range from 0 to 255 (with 255 being fully opaque).
55-
*/
56-
@Expose
57-
int alpha;
1+
package io.github.notenoughupdates.moulconfig
2+
3+
import com.google.gson.annotations.Expose
4+
import java.awt.Color
5+
6+
@Suppress("DeprecatedCallableAddReplaceWith", "DEPRECATION")
7+
data class ChromaColour(
8+
/**
9+
* Hue in a range from 0 to 1. For a chroma colour this is added to the time as an offset.
10+
*/
11+
@Expose
12+
var hue: Float,
13+
/**
14+
* Saturation in a range from 0 to 1
15+
*/
16+
@Expose
17+
var saturation: Float,
18+
/**
19+
* Brightness in a range from 0 to 1
20+
*/
21+
@Expose
22+
var brightness: Float,
23+
/**
24+
* If set to 0, this indicates a static colour. If set to a value above 0, indicates the amount of milliseconds that pass until the same colour is met again.
25+
* This value may be saved lossy.
26+
*/
27+
@Expose
28+
var timeForFullRotationInMillis: Int,
29+
/**
30+
* Alpha in a range from 0 to 255 (with 255 being fully opaque).
31+
*/
32+
@Expose
33+
var alpha: Int,
34+
) {
35+
private val cachedRGB: Int = (Color.HSBtoRGB(hue, saturation, brightness) and 0x00FFFFFF) or (alpha shl 24)
5836

5937
/**
6038
* @param offset offset the colour by a hue amount.
6139
* @return the colour, at the current time if this is a chrome colour
6240
*/
63-
public Color getEffectiveColour(float offset) {
64-
double effectiveHue;
65-
if (timeForFullRotationInMillis > 0) {
66-
effectiveHue = System.currentTimeMillis() / (double) timeForFullRotationInMillis;
41+
fun getEffectiveColourRGB(offset: Float): Int {
42+
var effectiveHue = if (timeForFullRotationInMillis > 0) {
43+
System.currentTimeMillis() / timeForFullRotationInMillis.toDouble()
6744
} else {
68-
effectiveHue = hue;
45+
hue.toDouble()
6946
}
70-
effectiveHue += offset;
71-
return new Color(Color.HSBtoRGB((float) (effectiveHue % 1), saturation, brightness) | (alpha << 24), true);
47+
effectiveHue += offset.toDouble()
48+
return (Color.HSBtoRGB((effectiveHue % 1).toFloat(), saturation, brightness) and 0x00FFFFFF) or (alpha shl 24)
7249
}
50+
/**
51+
* @param offset offset the colour by a hue amount.
52+
* @return the colour, at the current time if this is a chrome colour
53+
*/
54+
fun getEffectiveColour(offset: Float): Color = Color(getEffectiveColourRGB(offset), true)
7355

7456
/**
75-
* Unlike {@link #getEffectiveColour(float)}, this offset does not change anything if not using an animated colour.
57+
* Unlike [getEffectiveColourRGB], this offset does not change anything if not using an animated colour.
7658
*
7759
* @param offset offset the colour by a time amount in milliseconds.
7860
* @return the colour, at the current time if this is a chrome colour
7961
*/
80-
public Color getEffectiveColourWithTimeOffset(int offset) {
81-
double effectiveHue;
82-
if (timeForFullRotationInMillis > 0) {
83-
effectiveHue = (System.currentTimeMillis() + offset) / (double) timeForFullRotationInMillis;
84-
} else {
85-
effectiveHue = hue;
86-
}
87-
return new Color(Color.HSBtoRGB((float) (effectiveHue % 1), saturation, brightness) | (alpha << 24), true);
88-
62+
fun getEffectiveColourWithTimeOffsetRGB(offset: Int): Int {
63+
if (timeForFullRotationInMillis == 0) return cachedRGB
64+
val effectiveHue = (System.currentTimeMillis() + offset) / timeForFullRotationInMillis.toDouble()
65+
return (Color.HSBtoRGB((effectiveHue % 1).toFloat(), saturation, brightness) and 0x00FFFFFF) or (alpha shl 24)
8966
}
9067

68+
/**
69+
* Unlike [getEffectiveColour], this offset does not change anything if not using an animated colour.
70+
*
71+
* @param offset offset the colour by a time amount in milliseconds.
72+
* @return the colour, at the current time if this is a chrome colour
73+
*/
74+
fun getEffectiveColourWithTimeOffset(offset: Int): Color = Color(getEffectiveColourWithTimeOffsetRGB(offset), true)
9175

9276
/**
9377
* @return the colour, at the current time if this is a chrome colour
9478
*/
95-
public Color getEffectiveColour() {
96-
return getEffectiveColour(0);
97-
}
79+
fun getEffectiveColourRGB(): Int = getEffectiveColourWithTimeOffsetRGB(0)
9880

99-
@Deprecated
100-
public String toLegacyString() {
101-
int timeInSeconds = timeForFullRotationInMillis / 1000;
102-
int namedSpeed =
103-
timeInSeconds == 0 ? 0 : (int) (255 - (timeInSeconds - MIN_CHROMA_SECS) * 254F / (MAX_CHROMA_SECS - MIN_CHROMA_SECS));
104-
return special(namedSpeed, alpha, Color.HSBtoRGB(hue, saturation, brightness));
81+
/**
82+
* @return the colour, at the current time if this is a chrome colour
83+
*/
84+
fun getEffectiveColour(): Color = getEffectiveColourWithTimeOffset(0)
85+
86+
@Deprecated("")
87+
fun toLegacyString(): String {
88+
val timeInSeconds = timeForFullRotationInMillis / 1000
89+
val namedSpeed =
90+
if (timeInSeconds == 0) 0 else (255 - (timeInSeconds - MIN_CHROMA_SECS) * 254f / (MAX_CHROMA_SECS - MIN_CHROMA_SECS)).toInt()
91+
val red = cachedRGB shr 16 and 0xFF
92+
val green = cachedRGB shr 8 and 0xFF
93+
val blue = cachedRGB and 0xFF
94+
return special(namedSpeed, alpha, red, green, blue)
10595
}
10696

107-
@Deprecated
108-
public static String special(int chromaSpeed, int alpha, int rgb) {
109-
return special(chromaSpeed, alpha, (rgb & 0xFF0000) >> 16, (rgb & 0x00FF00) >> 8, (rgb & 0x0000FF));
110-
}
97+
companion object {
11198

112-
private static final int RADIX = 10;
113-
114-
@Deprecated
115-
public static String special(int chromaSpeed, int alpha, int r, int g, int b) {
116-
StringBuilder sb = new StringBuilder();
117-
sb.append(Integer.toString(chromaSpeed, RADIX)).append(":");
118-
sb.append(Integer.toString(alpha, RADIX)).append(":");
119-
sb.append(Integer.toString(r, RADIX)).append(":");
120-
sb.append(Integer.toString(g, RADIX)).append(":");
121-
sb.append(Integer.toString(b, RADIX));
122-
return sb.toString();
123-
}
99+
@JvmStatic
100+
@Deprecated("")
101+
fun special(chromaSpeed: Int, alpha: Int, rgb: Int): String {
102+
return special(chromaSpeed, alpha, rgb shr 16 and 0xFF, rgb shr 8 and 0xFF, rgb and 0xFF)
103+
}
124104

125-
private static int[] decompose(String csv) {
126-
String[] split = csv.split(":");
105+
private const val RADIX: Int = 10
106+
107+
@JvmStatic
108+
@Deprecated("")
109+
fun special(chromaSpeed: Int, alpha: Int, r: Int, g: Int, b: Int): String {
110+
val sb = StringBuilder()
111+
sb.append(chromaSpeed.toString(RADIX)).append(":")
112+
sb.append(alpha.toString(RADIX)).append(":")
113+
sb.append(r.toString(RADIX)).append(":")
114+
sb.append(g.toString(RADIX)).append(":")
115+
sb.append(b.toString(RADIX))
116+
return sb.toString()
117+
}
118+
119+
@JvmStatic
120+
private fun decompose(csv: String): IntArray {
121+
val split = csv.split(":")
127122

128-
int[] arr = new int[split.length];
123+
val arr = IntArray(split.size)
129124

130-
for (int i = 0; i < split.length; i++) {
131-
try {
132-
arr[i] = Integer.parseInt(split[split.length - 1 - i], RADIX);
133-
} catch (NumberFormatException e) {
134-
e.printStackTrace();
125+
for (i in split.indices) {
126+
try {
127+
arr[i] = split[split.size - 1 - i].toInt(RADIX)
128+
} catch (e: NumberFormatException) {
129+
e.printStackTrace()
130+
}
135131
}
132+
return arr
136133
}
137-
return arr;
138-
}
139134

140-
@Deprecated
141-
public static int specialToSimpleRGB(String special) {
142-
int[] d = decompose(special);
143-
int r = d[2];
144-
int g = d[1];
145-
int b = d[0];
146-
int a = d[3];
147-
int chr = d[4];
135+
@JvmStatic
136+
@Deprecated("")
137+
fun specialToSimpleRGB(special: String): Int {
138+
val (b, g, r, a) = decompose(special)
148139

149-
return (a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF);
150-
}
140+
return (a and 0xFF) shl 24 or ((r and 0xFF) shl 16) or ((g and 0xFF) shl 8) or (b and 0xFF)
141+
}
151142

152-
@Deprecated
153-
public static int getSpeed(String special) {
154-
return decompose(special)[4];
155-
}
143+
@JvmStatic
144+
@Deprecated("")
145+
fun getSpeed(special: String): Int = decompose(special)[4]
156146

157-
@Deprecated
158-
public static float getSecondsForSpeed(int speed) {
159-
return (255 - speed) / 254f * (MAX_CHROMA_SECS - MIN_CHROMA_SECS) + MIN_CHROMA_SECS;
160-
}
147+
private const val MIN_CHROMA_SECS: Int = 1
148+
private const val MAX_CHROMA_SECS: Int = 60
161149

162-
private static final int MIN_CHROMA_SECS = 1;
163-
private static final int MAX_CHROMA_SECS = 60;
150+
@JvmStatic
151+
@Deprecated("")
152+
fun getSecondsForSpeed(speed: Int): Float = (255 - speed) / 254f * (MAX_CHROMA_SECS - MIN_CHROMA_SECS) + MIN_CHROMA_SECS
164153

154+
@JvmStatic
155+
@Deprecated("")
156+
fun specialToChromaRGB(special: String): Int {
157+
val (b, g, r, a, chr) = decompose(special)
165158

166-
@Deprecated
167-
public static int specialToChromaRGB(String special) {
168-
int[] d = decompose(special);
169-
int chr = d[4];
170-
int a = d[3];
171-
int r = d[2];
172-
int g = d[1];
173-
int b = d[0];
159+
val hsv = Color.RGBtoHSB(r, g, b, null)
174160

175-
float[] hsv = Color.RGBtoHSB(r, g, b, null);
161+
if (chr > 0) {
162+
val seconds = getSecondsForSpeed(chr)
163+
hsv[0] += (((System.currentTimeMillis().toDouble()) / 1000.0 / seconds) % 1).toFloat()
164+
hsv[0] %= 1f
165+
if (hsv[0] < 0) hsv[0] += 1f
166+
}
176167

177-
if (chr > 0) {
178-
float seconds = getSecondsForSpeed(chr);
179-
hsv[0] += (((double) System.currentTimeMillis()) / 1000.0 / seconds) % 1;
180-
hsv[0] %= 1;
181-
if (hsv[0] < 0) hsv[0] += 1;
168+
return (a and 0xFF) shl 24 or (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) and 0x00FFFFFF)
182169
}
183170

184-
return (a & 0xFF) << 24 | (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0x00FFFFFF);
185-
}
186-
187-
@Deprecated
188-
public static int rotateHue(int argb, int degrees) {
189-
int a = (argb >> 24) & 0xFF;
190-
int r = (argb >> 16) & 0xFF;
191-
int g = (argb >> 8) & 0xFF;
192-
int b = (argb) & 0xFF;
171+
@JvmStatic
172+
@Deprecated("")
173+
fun rotateHue(argb: Int, degrees: Int): Int {
174+
val a = (argb shr 24) and 0xFF
175+
val r = (argb shr 16) and 0xFF
176+
val g = (argb shr 8) and 0xFF
177+
val b = (argb) and 0xFF
193178

194-
float[] hsv = Color.RGBtoHSB(r, g, b, null);
179+
val hsv = Color.RGBtoHSB(r, g, b, null)
195180

196-
hsv[0] += degrees / 360f;
197-
hsv[0] %= 1;
181+
hsv[0] += degrees / 360f
182+
hsv[0] %= 1f
198183

199-
return (a & 0xFF) << 24 | (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0x00FFFFFF);
200-
}
184+
return (a and 0xFF) shl 24 or (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) and 0x00FFFFFF)
185+
}
201186

202-
@Deprecated
203-
public static ChromaColour forLegacyString(String stringRepresentation) {
204-
int[] d = decompose(stringRepresentation);
205-
assert d.length == 5;
206-
207-
int chr = d[4];
208-
int a = d[3];
209-
int r = d[2];
210-
int g = d[1];
211-
int b = d[0];
212-
return fromRGB(r, g, b, chr > 0 ? (int) (getSecondsForSpeed(chr) * 1000) : 0, a);
213-
}
187+
@JvmStatic
188+
@Deprecated("")
189+
fun forLegacyString(stringRepresentation: String): ChromaColour {
190+
val d = decompose(stringRepresentation)
191+
assert(d.size == 5)
192+
193+
val chr = d[4]
194+
val a = d[3]
195+
val r = d[2]
196+
val g = d[1]
197+
val b = d[0]
198+
return fromRGB(r, g, b, if (chr > 0) (getSecondsForSpeed(chr) * 1000).toInt() else 0, a)
199+
}
214200

215-
public static ChromaColour fromStaticRGB(int r, int g, int b, int a) {
216-
return fromRGB(r, g, b, 0, a);
217-
}
201+
@JvmStatic
202+
fun fromStaticRGB(r: Int, g: Int, b: Int, a: Int): ChromaColour = fromRGB(r, g, b, 0, a)
218203

219-
public static ChromaColour fromRGB(int r, int g, int b, int chromaSpeedMillis, int a) {
220-
float[] floats = Color.RGBtoHSB(r, g, b, null);
221-
return new ChromaColour(floats[0], floats[1], floats[2], chromaSpeedMillis, a);
204+
@JvmStatic
205+
fun fromRGB(r: Int, g: Int, b: Int, chromaSpeedMillis: Int, a: Int): ChromaColour {
206+
val floats = Color.RGBtoHSB(r, g, b, null)
207+
return ChromaColour(floats[0], floats[1], floats[2], chromaSpeedMillis, a)
208+
}
222209
}
223210
}

0 commit comments

Comments
 (0)