Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,41 +1,42 @@
package gregtech.api.items.metaitem.stats;

import net.minecraft.item.ItemStack;
import gregtech.client.utils.ToolChargeBarRenderer;

import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable;
import net.minecraft.item.ItemStack;

import java.awt.*;
import org.jetbrains.annotations.NotNull;

public interface IItemDurabilityManager extends IItemComponent {

/** The durability remaining on this item (double from 0 to 1). */
double getDurabilityForDisplay(ItemStack itemStack);
double getDurabilityForDisplay(@NotNull ItemStack itemStack);

/** The first and last colors of a gradient. Default to Green durability gradient (null Pair). */
@Nullable
default Pair<Color, Color> getDurabilityColorsForDisplay(ItemStack itemStack) {
return null;
/**
* The left and right gradient bounds as two ARGB encoded integers packed into a long.<br/>
* See {@link gregtech.api.util.ColorUtil#packTwoARGB(int, int)} on how to make the long in the proper format.
*/
default long getDurabilityColorsForDisplay(@NotNull ItemStack itemStack) {
return ToolChargeBarRenderer.defaultGradient;
}

/** Whether to show the durability as red when at the last 1/4th durability. Default true */
default boolean doDamagedStateColors(ItemStack itemStack) {
default boolean doDamagedStateColors(@NotNull ItemStack itemStack) {
return true;
}

/**
* Whether to show the durability bar when {@link IItemDurabilityManager#getDurabilityForDisplay(ItemStack)} is 0.
* Default true
*/
default boolean showEmptyBar(ItemStack itemStack) {
default boolean showEmptyBar(@NotNull ItemStack itemStack) {
return true;
}

/**
* Whether to show the durability bar when {@link IItemDurabilityManager#getDurabilityForDisplay(ItemStack)} is 1.
* Default true
*/
default boolean showFullBar(ItemStack itemStack) {
default boolean showFullBar(@NotNull ItemStack itemStack) {
return true;
}
}
162 changes: 162 additions & 0 deletions src/main/java/gregtech/api/util/ColorUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package gregtech.api.util;

import org.jetbrains.annotations.Range;

public class ColorUtil {

/**
* Combine three R, G, and B values into an (A)RGB encoded integer. <br/>
* Alpha channel will be {@code 0}
*/
public static int combineRGBNoAlpha(@Range(from = 0, to = 255) int r, @Range(from = 0, to = 255) int g,
@Range(from = 0, to = 255) int b) {
return (r << 16) | (g << 8) | b;
}

/**
* Combine three R, G, and B values into an (A)RGB encoded integer. <br/>
* Alpha channel will be {@code 0xFF}/{@code 255}
*/
public static int combineRGBFullAlpha(@Range(from = 0, to = 255) int r, @Range(from = 0, to = 255) int g,
@Range(from = 0, to = 255) int b) {
return 0xFF000000 | (r << 16) | (g << 8) | b;
}

/**
* Combine A, R, G, and B values into an ARGB encoded integer.
*/
public static int combineARGB(@Range(from = 0, to = 255) int a, @Range(from = 0, to = 255) int r,
@Range(from = 0, to = 255) int g, @Range(from = 0, to = 255) int b) {
return (a << 24) | (r << 16) | (g << 8) | b;
}

/**
* Pack two ARGB encoded integers into a single {@code long} with the left integer taking the 32 most significant
* bits and the right the 32 least significant bits.
*/
public static long packTwoARGB(int left, int right) {
return ((long) left << 32) | right;
}

/**
* Get the left ARGB encoded integer from a long produced from {@link #packTwoARGB(int, int)}.
*/
public static int getLeftARGB(long doublePackedARGB) {
return (int) (doublePackedARGB >>> 32);
}

/**
* Get the right ARGB encoded integer from a long produced from {@link #packTwoARGB(int, int)}.
*/
public static int getRightARGB(long doublePackedARGB) {
return (int) doublePackedARGB;
}

/**
* Get an array of the red, blue, and green channels as floats from 0 to 1. <br/>
* Index {@code 0} = {@code Red} <br/>
* Index {@code 1} = {@code Green} <br/>
* Index {@code 2} = {@code Blue} <br/>
* See {@link #getARGBFloats(int)} for getting the alpha channel.
*/
public static float[] getRGBFloats(int rgb) {
return new float[] {
ARGBHelper.RED.isolateAndShiftAsFloat(rgb),
ARGBHelper.GREEN.isolateAndShiftAsFloat(rgb),
ARGBHelper.BLUE.isolateAndShiftAsFloat(rgb)
};
}

/**
* Get an array of the alpha, red, blue, and green channels as floats from 0 to 1. <br/>
* Index {@code 0} = {@code Alpha} <br/>
* Index {@code 1} = {@code Red} <br/>
* Index {@code 2} = {@code Green} <br/>
* Index {@code 3} = {@code Blue} <br/>
* See {@link #getRGBFloats(int)} for ignoring the alpha channel.
*/
public static float[] getARGBFloats(int argb) {
return new float[] {
ARGBHelper.ALPHA.isolateAndShiftAsFloat(argb),
ARGBHelper.RED.isolateAndShiftAsFloat(argb),
ARGBHelper.GREEN.isolateAndShiftAsFloat(argb),
ARGBHelper.BLUE.isolateAndShiftAsFloat(argb)
};
}

/**
* A helper enum designed to help with changing or getting specific color channels from an ARGB encoded integer.
*/
public enum ARGBHelper {

ALPHA(0xFF000000, 24),
RED(0xFF0000, 16),
GREEN(0xFF00, 8),
BLUE(0xFF, 0);

public final int overlay;
public final int invertedOverlay;
public final int shift;

ARGBHelper(int overlay, int shift) {
this.overlay = overlay;
this.invertedOverlay = ~overlay;
this.shift = shift;
}

/**
* Isolate this channel as an integer from 0 to 255. <br/>
* Example: {@code GREEN.isolateAndShift(0xDEADBEEF)} will return {@code 0xBE} or {@code 190}.
*/
public final @Range(from = 0, to = 0xFF) int isolateAndShift(int value) {
return (value >> shift) & 0xFF;
}

/**
* Isolate this channel as a float from 0 to 1. <br/>
* Example: {@code GREEN.isolateAndShift(0xDEADBEEF)} will return {@code 0xBE / 255} or {@code 0.74509805}.
*/
public final float isolateAndShiftAsFloat(int value) {
return ((value >> shift) & 0xFF) / 255.0F;
}

/**
* Remove the other two colors from the integer encoded ARGB and set the alpha to 255. <br/>
* Will always return {@code 0xFF000000} if called on {@link #ALPHA}. <br/>
* Unlike {@link #isolateAndShift(int)}, this will not be between 0 and 255. <br/>
* Example: {@code GREEN.isolateWithFullAlpha(0xDEADBEEF)} will return {@code 0xFF00BE00} or {@code -16728576}.
*/
public final int isolateWithFullAlpha(int value) {
return (value & overlay) | ALPHA.overlay;
}

/**
* Set the value of this channel in an integer encoded ARGB value.
*/
public final int replace(int originalARGB, @Range(from = 0, to = 0xFF) int value) {
return (originalARGB & invertedOverlay) | (value << shift);
}

/**
* The same as {@link #replace(int, int)} but will behave as if {@code originalARGB} was {@code 0}.
*/
public final int get(@Range(from = 0, to = 0xFF) int value) {
return value << shift;
}

/**
* Add a value to this channel's value. Can overflow in this channel, but will not affect the other channels.
*/
public final int add(int originalARGB, @Range(from = 0, to = 0xFF) int value) {
return replace(originalARGB, (isolateAndShift(originalARGB) + value) & 0xFF);
}

/**
* Subtract a value from this channel's value. Can underflow in this channel, but will not affect the other
* channels.
*/
public final int subtract(int originalARGB, @Range(from = 0, to = 0xFF) int value) {
return replace(originalARGB, (isolateAndShift(originalARGB) - value) & 0xFF);
}
}
}
77 changes: 32 additions & 45 deletions src/main/java/gregtech/api/util/GradientUtil.java
Original file line number Diff line number Diff line change
@@ -1,53 +1,40 @@
package gregtech.api.util;

import org.apache.commons.lang3.tuple.Pair;

import java.awt.*;

public class GradientUtil {

private GradientUtil() {}

public static Pair<Color, Color> getGradient(Color rgb, int luminanceDifference) {
public static long getGradient(int rgb, int luminanceDifference) {
float[] hsl = RGBtoHSL(rgb);
float[] upshade = new float[3];
float[] downshade = new float[3];
System.arraycopy(hsl, 0, upshade, 0, 3);
System.arraycopy(hsl, 0, downshade, 0, 3);
upshade[2] = upshade[2] + luminanceDifference;
if (upshade[2] > 100.0F) upshade[2] = 100.0F;
downshade[2] = downshade[2] - luminanceDifference;
if (downshade[2] < 0.0F) downshade[2] = 0.0F;
Color upshadeRgb = toRGB(upshade);
Color downshadeRgb = toRGB(downshade);
return Pair.of(downshadeRgb, upshadeRgb);
}
float[] upShade = new float[3];
float[] downShade = new float[3];

System.arraycopy(hsl, 0, upShade, 0, 3);
System.arraycopy(hsl, 0, downShade, 0, 3);

upShade[2] = Math.min(upShade[2] + luminanceDifference, 100.0F);
downShade[2] = Math.max(downShade[2] - luminanceDifference, 0.0F);

public static Pair<Color, Color> getGradient(int rgb, int luminanceDifference) {
return getGradient(new Color(rgb), luminanceDifference);
return ColorUtil.packTwoARGB(toRGB(downShade), toRGB(upShade));
}

public static float[] RGBtoHSL(Color rgbColor) {
// Get RGB values in the range 0 - 1
float[] rgb = rgbColor.getRGBColorComponents(null);
float r = rgb[0];
float g = rgb[1];
float b = rgb[2];
public static float[] RGBtoHSL(int rgb) {
float red = ColorUtil.ARGBHelper.RED.isolateAndShiftAsFloat(rgb);
float green = ColorUtil.ARGBHelper.GREEN.isolateAndShiftAsFloat(rgb);
float blue = ColorUtil.ARGBHelper.BLUE.isolateAndShiftAsFloat(rgb);

// Minimum and Maximum RGB values are used in the HSL calculations
float min = Math.min(r, Math.min(g, b));
float max = Math.max(r, Math.max(g, b));
float min = Math.min(red, Math.min(green, blue));
float max = Math.max(red, Math.max(green, blue));

// Calculate the Hue
float h = 0;
if (max == min) {
h = 0;
} else if (max == r) {
h = ((60 * (g - b) / (max - min)) + 360) % 360;
} else if (max == g) {
h = (60 * (b - r) / (max - min)) + 120;
} else if (max == b) {
h = (60 * (r - g) / (max - min)) + 240;
} else if (max == red) {
h = ((60 * (green - blue) / (max - min)) + 360) % 360;
} else if (max == green) {
h = (60 * (blue - red) / (max - min)) + 120;
} else if (max == blue) {
h = (60 * (red - green) / (max - min)) + 240;
}

// Calculate the Luminance
Expand All @@ -66,11 +53,11 @@ public static float[] RGBtoHSL(Color rgbColor) {
return new float[] { h, s * 100, l * 100 };
}

public static Color toRGB(float[] hsv) {
return toRGB(hsv[0], hsv[1], hsv[2]);
public static int toRGB(float[] hsl) {
return toRGB(hsl[0], hsl[1], hsl[2]);
}

public static Color toRGB(float h, float s, float l) {
public static int toRGB(float h, float s, float l) {
// Formula needs all values between 0 - 1
h = h % 360.0F;
h /= 360.0F;
Expand All @@ -86,15 +73,15 @@ public static Color toRGB(float h, float s, float l) {

float p = 2 * l - q;

float r = Math.max(0, hueToRGB(p, q, h + (1.0F / 3.0F)));
float g = Math.max(0, hueToRGB(p, q, h));
float b = Math.max(0, hueToRGB(p, q, h - (1.0F / 3.0F)));
float red = Math.max(0, hueToRGB(p, q, h + (1.0F / 3.0F)));
float green = Math.max(0, hueToRGB(p, q, h));
float blue = Math.max(0, hueToRGB(p, q, h - (1.0F / 3.0F)));

r = Math.min(r, 1.0F);
g = Math.min(g, 1.0F);
b = Math.min(b, 1.0F);
red = Math.min(red, 1.0F);
green = Math.min(green, 1.0F);
blue = Math.min(blue, 1.0F);

return new Color(r, g, b);
return ColorUtil.combineRGBFullAlpha((int) red * 255, (int) green * 255, (int) blue * 255);
}

private static float hueToRGB(float p, float q, float h) {
Expand Down
Loading
Loading