forked from MinecraftForge/MinecraftForge
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add modern implementation of the Slider widget and deprecate the old …
…one (MinecraftForge#8496)
- Loading branch information
1 parent
eed24f0
commit f0b90dc
Showing
2 changed files
with
225 additions
and
0 deletions.
There are no files selected for viewing
220 changes: 220 additions & 0 deletions
220
src/main/java/net/minecraftforge/client/gui/widget/ForgeSlider.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,220 @@ | ||
/* | ||
* Minecraft Forge - Forge Development LLC | ||
* SPDX-License-Identifier: LGPL-2.1-only | ||
*/ | ||
|
||
package net.minecraftforge.client.gui.widget; | ||
|
||
import net.minecraft.client.gui.components.AbstractSliderButton; | ||
import net.minecraft.network.chat.Component; | ||
import net.minecraft.network.chat.TextComponent; | ||
import net.minecraft.util.Mth; | ||
import org.lwjgl.glfw.GLFW; | ||
|
||
import java.text.DecimalFormat; | ||
|
||
/** | ||
* Slider widget implementation which allows inputting values in a certain range with optional step size. | ||
*/ | ||
public class ForgeSlider extends AbstractSliderButton | ||
{ | ||
protected Component prefix; | ||
protected Component suffix; | ||
|
||
protected double minValue; | ||
protected double maxValue; | ||
|
||
/** Allows input of discontinuous values with a certain step */ | ||
protected double stepSize; | ||
|
||
protected boolean drawString; | ||
|
||
private final DecimalFormat format; | ||
|
||
/** | ||
* @param x x position of upper left corner | ||
* @param y y position of upper left corner | ||
* @param width Width of the widget | ||
* @param height Height of the widget | ||
* @param prefix {@link Component} displayed before the value string | ||
* @param suffix {@link Component} displayed after the value string | ||
* @param minValue Minimum (left) value of slider | ||
* @param maxValue Maximum (right) value of slider | ||
* @param currentValue Starting value when widget is first displayed | ||
* @param stepSize Size of step used. Precision will automatically be calculated based on this value if this value is not 0. | ||
* @param precision Only used when {@code stepSize} is 0. Limited to a maximum of 4 (inclusive). | ||
* @param drawString Should text be displayed on the widget | ||
*/ | ||
public ForgeSlider(int x, int y, int width, int height, Component prefix, Component suffix, double minValue, double maxValue, double currentValue, double stepSize, int precision, boolean drawString) | ||
{ | ||
super(x, y, width, height, TextComponent.EMPTY, 0D); | ||
this.prefix = prefix; | ||
this.suffix = suffix; | ||
this.minValue = minValue; | ||
this.maxValue = maxValue; | ||
this.stepSize = Math.abs(stepSize); | ||
this.value = this.snapToNearest((currentValue - minValue) / (maxValue - minValue)); | ||
this.drawString = drawString; | ||
|
||
if (stepSize == 0D) | ||
{ | ||
precision = Math.min(precision, 4); | ||
|
||
StringBuilder builder = new StringBuilder("0"); | ||
|
||
if (precision > 0) | ||
builder.append('.'); | ||
|
||
while (precision-- > 0) | ||
builder.append('0'); | ||
|
||
this.format = new DecimalFormat(builder.toString()); | ||
} | ||
else if (Mth.equal(this.stepSize, Math.floor(this.stepSize))) | ||
{ | ||
this.format = new DecimalFormat("0"); | ||
} | ||
else | ||
{ | ||
this.format = new DecimalFormat(Double.toString(this.stepSize).replaceAll("\\d", "0")); | ||
} | ||
|
||
this.updateMessage(); | ||
} | ||
|
||
/** | ||
* Overload with {@code stepSize} set to 1, useful for sliders with whole number values. | ||
*/ | ||
public ForgeSlider(int x, int y, int width, int height, Component prefix, Component suffix, double minValue, double maxValue, double currentValue, boolean drawString) | ||
{ | ||
this(x, y, width, height, prefix, suffix, minValue, maxValue, currentValue, 1D, 0, drawString); | ||
} | ||
|
||
/** | ||
* @return Current slider value as a double | ||
*/ | ||
public double getValue() | ||
{ | ||
return this.value * (maxValue - minValue) + minValue; | ||
} | ||
|
||
/** | ||
* @return Current slider value as an long | ||
*/ | ||
public long getValueLong() | ||
{ | ||
return Math.round(this.getValue()); | ||
} | ||
|
||
/** | ||
* @return Current slider value as an int | ||
*/ | ||
public int getValueInt() | ||
{ | ||
return (int) this.getValueLong(); | ||
} | ||
|
||
/** | ||
* @param value The new slider value | ||
*/ | ||
public void setValue(double value) | ||
{ | ||
this.value = this.snapToNearest((value - this.minValue) / (this.maxValue - this.minValue)); | ||
this.updateMessage(); | ||
} | ||
|
||
public String getValueString() | ||
{ | ||
return this.format.format(this.getValue()); | ||
} | ||
|
||
@Override | ||
public void onClick(double mouseX, double mouseY) | ||
{ | ||
this.setValueFromMouse(mouseX); | ||
} | ||
|
||
@Override | ||
protected void onDrag(double mouseX, double mouseY, double dragX, double dragY) | ||
{ | ||
super.onDrag(mouseX, mouseY, dragX, dragY); | ||
this.setValueFromMouse(mouseX); | ||
} | ||
|
||
@Override | ||
public boolean keyPressed(int keyCode, int scanCode, int modifiers) | ||
{ | ||
boolean flag = keyCode == GLFW.GLFW_KEY_LEFT; | ||
if (flag || keyCode == GLFW.GLFW_KEY_RIGHT) | ||
{ | ||
if (this.minValue > this.maxValue) | ||
flag = !flag; | ||
float f = flag ? -1F : 1F; | ||
if (stepSize <= 0D) | ||
this.setSliderValue(this.value + (f / (this.width - 8))); | ||
else | ||
this.setValue(this.getValue() + f * this.stepSize); | ||
} | ||
|
||
return false; | ||
} | ||
|
||
private void setValueFromMouse(double mouseX) | ||
{ | ||
this.setSliderValue((mouseX - (this.x + 4)) / (this.width - 8)); | ||
} | ||
|
||
/** | ||
* @param value Percentage of slider range | ||
*/ | ||
private void setSliderValue(double value) | ||
{ | ||
double oldValue = this.value; | ||
this.value = this.snapToNearest(value); | ||
if (!Mth.equal(oldValue, this.value)) | ||
this.applyValue(); | ||
|
||
this.updateMessage(); | ||
} | ||
|
||
/** | ||
* Snaps the value, so that the displayed value is the nearest multiple of {@code stepSize}. | ||
* If {@code stepSize} is 0, no snapping occurs. | ||
*/ | ||
private double snapToNearest(double value) | ||
{ | ||
if(stepSize <= 0D) | ||
return Mth.clamp(value, 0D, 1D); | ||
|
||
value = Mth.lerp(Mth.clamp(value, 0D, 1D), this.minValue, this.maxValue); | ||
|
||
value = (stepSize * Math.round(value / stepSize)); | ||
|
||
if (this.minValue > this.maxValue) | ||
{ | ||
value = Mth.clamp(value, this.maxValue, this.minValue); | ||
} | ||
else | ||
{ | ||
value = Mth.clamp(value, this.minValue, this.maxValue); | ||
} | ||
|
||
return Mth.map(value, this.minValue, this.maxValue, 0D, 1D); | ||
} | ||
|
||
@Override | ||
protected void updateMessage() | ||
{ | ||
if (this.drawString) | ||
{ | ||
this.setMessage(new TextComponent("").append(prefix).append(this.getValueString()).append(suffix)); | ||
} | ||
else | ||
{ | ||
this.setMessage(TextComponent.EMPTY); | ||
} | ||
} | ||
|
||
@Override | ||
protected void applyValue() {} | ||
} |
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