-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
338 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
158 changes: 158 additions & 0 deletions
158
src/main/java/com/goby56/wakes/config/gui/ColorPicker.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
package com.goby56.wakes.config.gui; | ||
|
||
import com.goby56.wakes.config.WakesConfigScreen; | ||
import com.goby56.wakes.render.enums.WakeColor; | ||
import com.mojang.blaze3d.systems.RenderSystem; | ||
import net.minecraft.client.font.TextRenderer; | ||
import net.minecraft.client.gui.DrawContext; | ||
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; | ||
import net.minecraft.client.gui.widget.ClickableWidget; | ||
import net.minecraft.client.gui.widget.SliderWidget; | ||
import net.minecraft.client.gui.widget.TextFieldWidget; | ||
import net.minecraft.client.render.*; | ||
import net.minecraft.text.Text; | ||
import net.minecraft.util.Identifier; | ||
import org.joml.Matrix4f; | ||
import org.joml.Vector2f; | ||
import org.joml.Vector2i; | ||
|
||
import java.awt.*; | ||
import java.util.function.Function; | ||
|
||
public class ColorPicker extends ClickableWidget { | ||
private static final Identifier BACKGROUND_TEXTURE = Identifier.ofVanilla("widget/button"); | ||
private static final Identifier FRAME_TEXTURE = Identifier.ofVanilla("widget/slot_frame"); | ||
|
||
private final WakesConfigScreen screenContext; | ||
private final TextFieldWidget hexInput; | ||
private final GradientSlider hueSlider; | ||
private final GradientSlider alphaSlider; | ||
private final Vector2i colorPickerPos; | ||
private final Vector2i colorPickerDim; | ||
private PickListener listener; | ||
|
||
public interface PickListener { | ||
void onPickedColor(WakeColor color); | ||
} | ||
|
||
|
||
public ColorPicker(WakesConfigScreen screenContext, int x, int y, int width, int height) { | ||
super(x, y, width, height, Text.of("")); | ||
this.screenContext = screenContext; | ||
|
||
var topLeft = globalSpace(new Vector2f(0f, 0f)); | ||
var bottomRight = globalSpace(new Vector2f(1f, 2f / 3f)); | ||
this.colorPickerPos = topLeft; | ||
this.colorPickerDim = bottomRight.sub(bottomRight); | ||
|
||
this.hexInput = new HexInputField(new Vector2f(0f, 5f / 6f), new Vector2f(1f / 3f, 1f), this::globalSpace, screenContext.textRenderer); | ||
this.hueSlider = new GradientSlider(new Vector2f(0f, 2f / 3f), new Vector2f(1f, 5f / 6f), this::globalSpace); | ||
this.alphaSlider = new GradientSlider(new Vector2f(1f / 3f, 5f / 6f), new Vector2f(1f, 1f), this::globalSpace); | ||
|
||
screenContext.addWidget(this); | ||
screenContext.addWidget(hueSlider); | ||
screenContext.addWidget(alphaSlider); | ||
} | ||
|
||
public void toggleActive() { | ||
boolean active = !this.active; | ||
this.active = active; | ||
this.hexInput.active = active; | ||
this.hueSlider.active = active; | ||
this.alphaSlider.active = active; | ||
} | ||
|
||
public void registerListener(PickListener listener) { | ||
this.listener = listener; | ||
} | ||
|
||
private Vector2f relativeSpace(Vector2i globalSpace) { | ||
return new Vector2f((float) (globalSpace.x - getX()) / width, (float) (globalSpace.y - getY()) / width); | ||
} | ||
|
||
private Vector2i globalSpace(Vector2f relativeSpace) { | ||
return new Vector2i((int) (relativeSpace.x * width + getX()), (int) (relativeSpace.y * height + getY())); | ||
} | ||
|
||
@Override | ||
public void onClick(double mouseX, double mouseY) { | ||
System.out.printf("%f, %f\n", (mouseX - getX()) / width, (mouseY - getY()) / height); | ||
super.onClick(mouseX, mouseY); | ||
} | ||
|
||
@Override | ||
protected void onDrag(double mouseX, double mouseY, double deltaX, double deltaY) { | ||
super.onDrag(mouseX, mouseY, deltaX, deltaY); | ||
} | ||
|
||
@Override | ||
protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { | ||
if (!active) return; | ||
int x = getX(); | ||
int y = getY(); | ||
|
||
context.drawGuiTexture(BACKGROUND_TEXTURE, x, y, width, height); | ||
|
||
drawColorPicker(context, colorPickerPos.x, colorPickerPos.y, colorPickerDim.x, colorPickerDim.y); | ||
} | ||
|
||
private void drawColorPicker(DrawContext context, int x, int y, int w, int h) { | ||
// Color picker | ||
context.drawGuiTexture(FRAME_TEXTURE, x - 3, y - 3, w + 6, h + 6); | ||
RenderSystem.setShader(GameRenderer::getPositionColorProgram); | ||
BufferBuilder buffer = Tessellator.getInstance().begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); | ||
Matrix4f matrix = context.getMatrices().peek().getPositionMatrix(); | ||
buffer.vertex(matrix, x, y, 5).color(Color.HSBtoRGB(1, 0, 1)); | ||
buffer.vertex(matrix, x, y + h, 5).color(Color.HSBtoRGB(1, 0, 0)); | ||
buffer.vertex(matrix, x + w, y + h, 5).color(Color.HSBtoRGB(1, 1, 0)); | ||
buffer.vertex(matrix, x + w, y, 5).color(Color.HSBtoRGB(1, 1, 1)); | ||
BufferRenderer.drawWithGlobalProgram(buffer.end()); | ||
} | ||
|
||
@Override | ||
protected void appendClickableNarrations(NarrationMessageBuilder builder) { | ||
|
||
} | ||
|
||
private class HexInputField extends TextFieldWidget { | ||
|
||
public HexInputField(Vector2f topLeft, Vector2f bottomRight, Function<Vector2f, Vector2i> globalSpaceConverter, TextRenderer textRenderer) { | ||
super(textRenderer, 0, 0, 0, 0, Text.of("")); | ||
Vector2i globalPos = globalSpaceConverter.apply(topLeft); | ||
Vector2i dimensions = globalSpaceConverter.apply(bottomRight).sub(globalPos); | ||
this.setX(globalPos.x); | ||
this.setY(globalPos.y); | ||
this.setWidth(dimensions.x); | ||
this.setHeight(dimensions.y); | ||
} | ||
} | ||
|
||
private class GradientSlider extends SliderWidget { | ||
|
||
|
||
public GradientSlider(Vector2f topLeft, Vector2f bottomRight, Function<Vector2f, Vector2i> globalSpaceConverter) { | ||
super(0, 0, 0, 0, Text.of(""), 1f); | ||
Vector2i globalPos = globalSpaceConverter.apply(topLeft); | ||
Vector2i dimensions = globalSpaceConverter.apply(bottomRight).sub(globalPos); | ||
this.setX(globalPos.x); | ||
this.setY(globalPos.y); | ||
this.setWidth(dimensions.x); | ||
this.setHeight(dimensions.y); | ||
} | ||
|
||
@Override | ||
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { | ||
super.renderWidget(context, mouseX, mouseY, delta); | ||
} | ||
|
||
@Override | ||
protected void updateMessage() { | ||
|
||
} | ||
|
||
@Override | ||
protected void applyValue() { | ||
|
||
} | ||
} | ||
} |
131 changes: 111 additions & 20 deletions
131
src/main/java/com/goby56/wakes/config/gui/GradientSlider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,148 @@ | ||
package com.goby56.wakes.config.gui; | ||
|
||
import com.goby56.wakes.WakesClient; | ||
import com.goby56.wakes.config.WakesConfigScreen; | ||
import com.goby56.wakes.render.enums.WakeColor; | ||
import com.mojang.blaze3d.systems.RenderSystem; | ||
import net.minecraft.client.MinecraftClient; | ||
import net.minecraft.client.gui.DrawContext; | ||
import net.minecraft.client.gui.screen.Screen; | ||
import net.minecraft.client.gui.widget.SliderWidget; | ||
import net.minecraft.text.Text; | ||
import net.minecraft.util.math.MathHelper; | ||
|
||
import java.util.ArrayList; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.Collections; | ||
|
||
public class GradientSlider extends SliderWidget { | ||
private ArrayList<Float> values; | ||
private final WakesConfigScreen screenContext; | ||
private ArrayList<SliderHandle> handles; | ||
private final ColorPicker colorPicker; | ||
private Integer activeSection = null; | ||
|
||
public GradientSlider(int x, int y, int width, int height, Text text, ArrayList<Float> values) { | ||
public GradientSlider(WakesConfigScreen screenContext, int x, int y, int width, int height, Text text, ArrayList<Float> normalizedValues) { | ||
super(x, y, width, height, text, 0f); | ||
this.values = values; | ||
this.screenContext = screenContext; | ||
this.handles = new ArrayList<>(); | ||
for (float val : normalizedValues) { | ||
this.handles.add(new SliderHandle(val)); | ||
} | ||
this.colorPicker = new ColorPicker(screenContext, 10, height / 2 - 100 / 2, 100, 100); | ||
colorPicker.registerListener(this::onColorPicked); | ||
} | ||
|
||
private void unfocusHandles() { | ||
for (SliderHandle handle : handles) { | ||
handle.focused = false; | ||
} | ||
} | ||
|
||
@Override | ||
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { | ||
MinecraftClient minecraftClient = MinecraftClient.getInstance(); | ||
RenderSystem.enableBlend(); | ||
RenderSystem.defaultBlendFunc(); | ||
RenderSystem.enableDepthTest(); | ||
|
||
context.drawGuiTexture(this.getTexture(), this.getX(), this.getY(), this.getWidth(), this.getHeight()); | ||
context.setShaderColor(1.0F, 1.0F, 1.0F, 0.3f); | ||
|
||
values = new ArrayList<>(List.of(0f, 0.1f, 0.5f, 0.7f, 1f)); | ||
for (int i = 1; i < values.size(); i++) { | ||
float value = values.get(i - 1); | ||
float diff = values.get(i) - value; | ||
int x = this.getX() + (int)(value * (double)(this.width - 8)); | ||
int y = this.getY(); | ||
context.fill(x, y + 1, (int) (x + (diff * (this.width - 8))) + 8, y + this.height - 1, WakesClient.CONFIG_INSTANCE.wakeColors.get(i - 1).argb); | ||
context.drawGuiTexture(this.getHandleTexture(), x, y, 8, this.getHeight()); | ||
this.hovered = context.scissorContains(mouseX, mouseY) && mouseX >= this.getX() && mouseY >= this.getY() && mouseX < this.getX() + this.width && mouseY < this.getY() + this.height; | ||
int n = handles.size(); | ||
int y = this.getY(); | ||
|
||
int prevX = this.getX(); | ||
for (int i = 0; i < n; i++) { | ||
float value = handles.get(i).value; | ||
|
||
int currX = this.getX() + (int)(value * (double)(this.width)); | ||
|
||
context.fill(prevX, y, currX, y + this.height, WakesClient.CONFIG_INSTANCE.wakeColors.get(i).argb); | ||
|
||
prevX = currX; | ||
} | ||
context.fill(prevX, y, this.getX() + this.width, y + this.height, WakesClient.CONFIG_INSTANCE.wakeColors.get(n).argb); | ||
|
||
float hoveredVal = valueFromMousePos(mouseX); | ||
boolean correctY = mouseY >= getY() && mouseY < getY() + height; | ||
for (SliderHandle handle : handles) { | ||
boolean isHovered = handle.inProximity(hoveredVal, width, 8) && correctY; | ||
context.drawGuiTexture(handle.getHandleTexture(isHovered), this.getX() + (int)(handle.value * (double)(this.width - 4)), this.getY(), 8, this.getHeight()); | ||
} | ||
context.drawGuiTexture(this.getHandleTexture(), this.getX() + (int)(this.value * (double)(this.width - 8)), this.getY(), 8, this.getHeight()); | ||
context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); | ||
int i = this.active ? 16777215 : 10526880; | ||
this.drawScrollableText(context, minecraftClient.textRenderer, 2, i | MathHelper.ceil(this.alpha * 255.0F) << 24); | ||
} | ||
|
||
@Override | ||
public void onClick(double mouseX, double mouseY) { | ||
float value = valueFromMousePos(mouseX); | ||
SliderHandle handle = closestHandle(value); | ||
unfocusHandles(); | ||
if (handle.inProximity(value, width, 8)) { | ||
// Mouse on handle | ||
handle.focused = true; | ||
} else { | ||
activeSection = getActiveSection(value); | ||
colorPicker.toggleActive(); | ||
// Do color picker | ||
} | ||
} | ||
|
||
@Override | ||
public void onRelease(double mouseX, double mouseY) { | ||
unfocusHandles(); | ||
super.onRelease(mouseX, mouseY); | ||
} | ||
|
||
@Override | ||
protected void onDrag(double mouseX, double mouseY, double deltaX, double deltaY) { | ||
Collections.sort(handles); | ||
|
||
float value = valueFromMousePos(mouseX); | ||
for (SliderHandle handle : handles) { | ||
if (handle.focused) { | ||
if (handle.setValue(value)) { | ||
this.applyValue(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private void onColorPicked(WakeColor color) { | ||
if (this.activeSection != null) { | ||
WakesClient.CONFIG_INSTANCE.wakeColors.set(this.activeSection, color); | ||
} | ||
} | ||
|
||
private float valueFromMousePos(double mouseX) { | ||
return (float) ((mouseX - (double)(this.getX() + 4)) / (double)(this.width - 8)); | ||
} | ||
|
||
private SliderHandle closestHandle(float value) { | ||
float min = 1f; | ||
SliderHandle closest = null; | ||
for (SliderHandle handle : handles) { | ||
float d = Math.abs(handle.value - value); | ||
if (d < min) { | ||
closest = handle; | ||
min = d; | ||
} | ||
} | ||
return closest; | ||
} | ||
|
||
private int getActiveSection(float value) { | ||
for (int i = 0; i < handles.size(); i++) { | ||
if (handles.get(i).value <= value) { | ||
return i+1; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
@Override | ||
protected void updateMessage() { | ||
this.setMessage(Text.of(String.valueOf(this.value))); | ||
} | ||
|
||
@Override | ||
protected void applyValue() { | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.