@Nonnull
public static String createRgbGradient(@Nonnull String text, @Nonnull ChatColor start, @Nonnull ChatColor end) {
return createGradient(text, start, end, true);
}
@Nonnull
public static String create16ColorsGradient(@Nonnull String text, @Nonnull ChatColor start, @Nonnull ChatColor end) {
return createGradient(text, start, end, false);
}
@Nonnull
private static String createGradient(@Nonnull String text, @Nonnull ChatColor start, @Nonnull ChatColor end, boolean useRGB) {
char[] chars = text.toCharArray();
int length = chars.length;
StringBuilder result = new StringBuilder();
for (int i = 0; i < length; i++) {
ChatColor color = getGradientColor(start, end, ((double) i) / length);
if (!useRGB) {
color = nearestNamedTo(color);
}
result.append(color).append(chars[i]);
}
return result.toString();
}
@Nonnull
private static ChatColor getGradientColor(@Nonnull ChatColor start, @Nonnull ChatColor end, double percent) {
Color s = start.getColor();
Color e = end.getColor();
return ChatColor.of(new Color(
(int) (s.getRed() + ((e.getRed() - s.getRed()) * percent)),
(int) (s.getGreen() + ((e.getGreen() - s.getGreen()) * percent)),
(int) (s.getBlue() + ((e.getBlue() - s.getBlue()) * percent))
));
}
private static final ChatColor[] NAMED_COLORS = new ChatColor[]{
ChatColor.BLACK, ChatColor.DARK_BLUE, ChatColor.DARK_GREEN, ChatColor.DARK_AQUA,
ChatColor.DARK_RED, ChatColor.DARK_PURPLE, ChatColor.GOLD, ChatColor.GRAY,
ChatColor.DARK_GRAY, ChatColor.BLUE, ChatColor.GREEN, ChatColor.AQUA,
ChatColor.RED, ChatColor.LIGHT_PURPLE, ChatColor.YELLOW, ChatColor.WHITE
};
@Nonnull
private static ChatColor nearestNamedTo(@Nonnull ChatColor any) {
float matchedDistance = Float.MAX_VALUE;
ChatColor match = NAMED_COLORS[0];
int i = 0;
for (int length = NAMED_COLORS.length; i < length; ++i) {
ChatColor potential = NAMED_COLORS[i];
float distance = distance(any.getColor(), potential.getColor());
if (distance < matchedDistance) {
match = potential;
matchedDistance = distance;
}
if (distance == 0.0F) {
break;
}
}
return match;
}
private static float distance(@Nonnull Color first, @Nonnull Color second) {
float[] selfHVS = Color.RGBtoHSB(first.getRed(), first.getGreen(), first.getBlue(), null);
float[] otherHVS = Color.RGBtoHSB(second.getRed(), second.getGreen(), second.getBlue(), null);
float hueDistance = 3.0F * Math.min(Math.abs(selfHVS[0] - otherHVS[0]), 1.0F - Math.abs(selfHVS[0] - otherHVS[0]));
float saturationDiff = selfHVS[1] - otherHVS[1];
float valueDiff = selfHVS[2] - otherHVS[2];
return (hueDistance * hueDistance) + (saturationDiff * saturationDiff) + (valueDiff * valueDiff);
}