diff --git a/fml/src/main/java/cpw/mods/fml/client/FMLConfigGuiFactory.java b/fml/src/main/java/cpw/mods/fml/client/FMLConfigGuiFactory.java index 0203d7b56..84964aa10 100644 --- a/fml/src/main/java/cpw/mods/fml/client/FMLConfigGuiFactory.java +++ b/fml/src/main/java/cpw/mods/fml/client/FMLConfigGuiFactory.java @@ -10,6 +10,7 @@ import com.google.common.collect.ImmutableSet; import cpw.mods.fml.client.config.ConfigGuiType; import cpw.mods.fml.client.config.DummyConfigElement; import cpw.mods.fml.client.config.GuiConfig; +import cpw.mods.fml.client.config.GuiConfigEntries.NumberSliderEntry; import cpw.mods.fml.client.config.IConfigElement; import cpw.mods.fml.client.config.DummyConfigElement.DummyCategoryElement; import cpw.mods.fml.client.config.DummyConfigElement.DummyListElement; @@ -74,8 +75,10 @@ public class FMLConfigGuiFactory implements IModGuiFactory // Numbers category numbersList.add((new DummyConfigElement("basicInteger", 42, ConfigGuiType.INTEGER, "fml.config.sample.basicInteger"))); numbersList.add((new DummyConfigElement("boundedInteger", 42, ConfigGuiType.INTEGER, "fml.config.sample.boundedInteger", -1, 256))); + numbersList.add((new DummyConfigElement("sliderInteger", 42, ConfigGuiType.INTEGER, "fml.config.sample.sliderInteger", -1, 256)).setCustomListEntryClass(NumberSliderEntry.class)); numbersList.add(new DummyConfigElement("basicDouble", 42.4242D, ConfigGuiType.DOUBLE, "fml.config.sample.basicDouble")); numbersList.add(new DummyConfigElement("boundedDouble", 42.4242D, ConfigGuiType.DOUBLE, "fml.config.sample.boundedDouble", -1.0D, 256.256D)); + numbersList.add(new DummyConfigElement("sliderDouble", 42.4242D, ConfigGuiType.DOUBLE, "fml.config.sample.sliderDouble", -1.0D, 256.256D).setCustomListEntryClass(NumberSliderEntry.class)); list.add(new DummyCategoryElement("numbers", "fml.config.sample.ctgy.numbers", numbersList)); diff --git a/fml/src/main/java/cpw/mods/fml/client/config/GuiConfig.java b/fml/src/main/java/cpw/mods/fml/client/config/GuiConfig.java index f7665766d..b7e522788 100644 --- a/fml/src/main/java/cpw/mods/fml/client/config/GuiConfig.java +++ b/fml/src/main/java/cpw/mods/fml/client/config/GuiConfig.java @@ -82,11 +82,11 @@ public class GuiConfig extends GuiScreen * * @param parentScreen the parent GuiScreen object * @param configElements a List of IConfigProperty objects - * @param areAllPropsHotLoadable send true if every property on this screen is able to be modified on the fly while a world is running * @param modID the mod ID for the mod whose config settings will be edited * @param configID an identifier that will be passed to the OnConfigChanged and PostConfigChanged events. Setting this value will force * the save action to be called when the Done button is pressed on this screen if any configElements were changed. * @param allRequireWorldRestart send true if all configElements on this screen require a world restart + * @param allRequireMcRestart send true if all configElements on this screen require MC to be restarted * @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being * edited. */ @@ -102,9 +102,9 @@ public class GuiConfig extends GuiScreen * * @param parentScreen the parent GuiScreen object * @param configElements a List of IConfigProperty objects - * @param areAllPropsHotLoadable send true if every property on this screen is able to be modified on the fly while a world is running * @param modID the mod ID for the mod whose config settings will be edited * @param allRequireWorldRestart send true if all configElements on this screen require a world restart + * @param allRequireMcRestart send true if all configElements on this screen require MC to be restarted * @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being * edited. */ @@ -122,6 +122,7 @@ public class GuiConfig extends GuiScreen * @param configElements a List of IConfigProperty objects * @param modID the mod ID for the mod whose config settings will be edited * @param allRequireWorldRestart send true if all configElements on this screen require a world restart + * @param allRequireMcRestart send true if all configElements on this screen require MC to be restarted * @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being * edited. * @param titleLine2 the desired title second line for this screen. Typically this is used to send the category name of the category @@ -144,6 +145,7 @@ public class GuiConfig extends GuiScreen * @param modID the mod ID for the mod whose config settings will be edited * @param configID an identifier that will be passed to the OnConfigChanged and PostConfigChanged events * @param allRequireWorldRestart send true if all configElements on this screen require a world restart + * @param allRequireMcRestart send true if all configElements on this screen require MC to be restarted * @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being * edited. * @param titleLine2 the desired title second line for this screen. Typically this is used to send the category name of the category diff --git a/fml/src/main/java/cpw/mods/fml/client/config/GuiConfigEntries.java b/fml/src/main/java/cpw/mods/fml/client/config/GuiConfigEntries.java index 12bc9f391..e5f22c540 100644 --- a/fml/src/main/java/cpw/mods/fml/client/config/GuiConfigEntries.java +++ b/fml/src/main/java/cpw/mods/fml/client/config/GuiConfigEntries.java @@ -778,6 +778,104 @@ public class GuiConfigEntries extends GuiListExtended } } + /** + * NumberSliderEntry + * + * Provides a slider for numeric properties. + */ + public static class NumberSliderEntry extends ButtonEntry + { + protected final double beforeValue; + + public NumberSliderEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement configElement) + { + super(owningScreen, owningEntryList, configElement, new GuiSlider(0, owningEntryList.controlX, 0, owningEntryList.controlWidth, 18, + "", "", Double.valueOf(configElement.getMinValue().toString()), Double.valueOf(configElement.getMaxValue().toString()), + Double.valueOf(configElement.get().toString()), configElement.getType() == ConfigGuiType.DOUBLE, true)); + + if (configElement.getType() == ConfigGuiType.INTEGER) + this.beforeValue = Integer.valueOf(configElement.get().toString()); + else + this.beforeValue = Double.valueOf(configElement.get().toString()); + } + + @Override + public void updateValueButtonText() + { + ((GuiSlider) this.btnValue).updateSlider(); + } + + @Override + public void valueButtonPressed(int slotIndex) {} + + @Override + public boolean isDefault() + { + if (configElement.getType() == ConfigGuiType.INTEGER) + return (int) ((GuiSlider) this.btnValue).getValue() == Integer.valueOf(configElement.getDefault().toString()); + else + return ((GuiSlider) this.btnValue).getValue() == Double.valueOf(configElement.getDefault().toString()); + } + + @Override + public void setToDefault() + { + if (this.enabled()) + { + ((GuiSlider) this.btnValue).setValue(Double.valueOf(configElement.getDefault().toString())); + ((GuiSlider) this.btnValue).updateSlider(); + } + } + + @Override + public boolean isChanged() + { + if (configElement.getType() == ConfigGuiType.INTEGER) + return (int) ((GuiSlider) this.btnValue).getValue() != (int) beforeValue; + else + return ((GuiSlider) this.btnValue).getValue() != beforeValue; + } + + @Override + public void undoChanges() + { + if (this.enabled()) + { + ((GuiSlider) this.btnValue).setValue(beforeValue); + ((GuiSlider) this.btnValue).updateSlider(); + } + } + + @Override + public boolean saveConfigElement() + { + if (this.enabled() && this.isChanged()) + { + if (configElement.getType() == ConfigGuiType.INTEGER) + configElement.set((int) ((GuiSlider) this.btnValue).getValue()); + else + configElement.set(((GuiSlider) this.btnValue).getValue()); + return configElement.requiresMcRestart(); + } + return false; + } + + @Override + public Object getCurrentValue() + { + if (configElement.getType() == ConfigGuiType.INTEGER) + return (int) ((GuiSlider) this.btnValue).getValue(); + else + return ((GuiSlider) this.btnValue).getValue(); + } + + @Override + public Object[] getCurrentValues() + { + return new Object[] { getCurrentValue() }; + } + } + /** * ButtonEntry * @@ -788,10 +886,15 @@ public class GuiConfigEntries extends GuiListExtended protected final GuiButtonExt btnValue; public ButtonEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement configElement) + { + this(owningScreen, owningEntryList, configElement, new GuiButtonExt(0, owningEntryList.controlX, 0, owningEntryList.controlWidth, 18, + configElement.get() != null ? I18n.format(String.valueOf(configElement.get())) : "")); + } + + public ButtonEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement configElement, GuiButtonExt button) { super(owningScreen, owningEntryList, configElement); - this.btnValue = new GuiButtonExt(0, this.owningEntryList.controlX, 0, this.owningEntryList.controlWidth, 18, - configElement.get() != null ? I18n.format(String.valueOf(configElement.get())) : ""); + this.btnValue = button; } /** diff --git a/fml/src/main/java/cpw/mods/fml/client/config/GuiSlider.java b/fml/src/main/java/cpw/mods/fml/client/config/GuiSlider.java new file mode 100644 index 000000000..3a85f8f50 --- /dev/null +++ b/fml/src/main/java/cpw/mods/fml/client/config/GuiSlider.java @@ -0,0 +1,201 @@ +package cpw.mods.fml.client.config; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; + +import org.lwjgl.opengl.GL11; + +/** + * This class is blatantly stolen from iChunUtils with permission. + * + * @author iChun + */ +public class GuiSlider extends GuiButtonExt +{ + /** The value of this slider control. */ + public double sliderValue = 1.0F; + + public String dispString = ""; + + /** Is this slider control being dragged. */ + public boolean dragging = false; + public boolean showDecimal = true; + + public double minValue = 0.0D; + public double maxValue = 5.0D; + public int precision = 1; + + public ISlider parent = null; + + public String suffix = ""; + + public boolean drawString = true; + + public GuiSlider(int id, int xPos, int yPos, int width, int height, String prefix, String suf, double minVal, double maxVal, double currentVal, boolean showDec, boolean drawStr) + { + this(id, xPos, yPos, width, height, prefix, suf, minVal, maxVal, currentVal, showDec, drawStr, null); + } + + public GuiSlider(int id, int xPos, int yPos, int width, int height, String prefix, String suf, double minVal, double maxVal, double currentVal, boolean showDec, boolean drawStr, ISlider par) + { + super(id, xPos, yPos, width, height, prefix); + minValue = minVal; + maxValue = maxVal; + sliderValue = (currentVal - minValue) / (maxValue - minValue); + dispString = prefix; + parent = par; + suffix = suf; + showDecimal = showDec; + String val; + + if (showDecimal) + { + val = Double.toString(sliderValue * (maxValue - minValue) + minValue); + precision = Math.min(val.substring(val.indexOf(".") + 1).length(), 4); + } + else + { + val = Integer.toString((int)Math.round(sliderValue * (maxValue - minValue) + minValue)); + precision = 0; + } + + displayString = dispString + val + suffix; + + drawString = drawStr; + if(!drawString) + { + displayString = ""; + } + } + + public GuiSlider(int id, int xPos, int yPos, String displayStr, double minVal, double maxVal, double currentVal, ISlider par) + { + this(id, xPos, yPos, 150, 20, displayStr, "", minVal, maxVal, currentVal, true, true, par); + } + + /** + * Returns 0 if the button is disabled, 1 if the mouse is NOT hovering over this button and 2 if it IS hovering over + * this button. + */ + public int getHoverState(boolean par1) + { + return 0; + } + + /** + * Fired when the mouse button is dragged. Equivalent of MouseListener.mouseDragged(MouseEvent e). + */ + protected void mouseDragged(Minecraft par1Minecraft, int par2, int par3) + { + if (this.visible) + { + if (this.dragging) + { + this.sliderValue = (par2 - (this.xPosition + 4)) / (float)(this.width - 8); + updateSlider(); + } + + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + this.drawTexturedModalRect(this.xPosition + (int)(this.sliderValue * (float)(this.width - 8)), this.yPosition, 0, 66, 4, 20); + this.drawTexturedModalRect(this.xPosition + (int)(this.sliderValue * (float)(this.width - 8)) + 4, this.yPosition, 196, 66, 4, 20); + } + } + + /** + * Returns true if the mouse has been pressed on this control. Equivalent of MouseListener.mousePressed(MouseEvent + * e). + */ + public boolean mousePressed(Minecraft par1Minecraft, int par2, int par3) + { + if (super.mousePressed(par1Minecraft, par2, par3)) + { + this.sliderValue = (float)(par2 - (this.xPosition + 4)) / (float)(this.width - 8); + updateSlider(); + this.dragging = true; + return true; + } + else + { + return false; + } + } + + public void updateSlider() + { + if (this.sliderValue < 0.0F) + { + this.sliderValue = 0.0F; + } + + if (this.sliderValue > 1.0F) + { + this.sliderValue = 1.0F; + } + + String val; + + if (showDecimal) + { + val = Double.toString(sliderValue * (maxValue - minValue) + minValue); + + if (val.substring(val.indexOf(".") + 1).length() > precision) + { + val = val.substring(0, val.indexOf(".") + precision + 1); + + if (val.endsWith(".")) + { + val = val.substring(0, val.indexOf(".") + precision); + } + } + else + { + while (val.substring(val.indexOf(".") + 1).length() < precision) + { + val = val + "0"; + } + } + } + else + { + val = Integer.toString((int)Math.round(sliderValue * (maxValue - minValue) + minValue)); + } + + if(drawString) + { + displayString = dispString + val + suffix; + } + + if (parent != null) + { + parent.onChangeSliderValue(this); + } + } + + /** + * Fired when the mouse button is released. Equivalent of MouseListener.mouseReleased(MouseEvent e). + */ + public void mouseReleased(int par1, int par2) + { + this.dragging = false; + } + + public int getValueInt() + { + return (int)Math.round(sliderValue * (maxValue - minValue) + minValue); + } + + public double getValue() + { + return sliderValue * (maxValue - minValue) + minValue; + } + + public void setValue(double d) + { + this.sliderValue = (d - minValue) / (maxValue - minValue); + } + + public static interface ISlider + { + void onChangeSliderValue(GuiSlider slider); + } +} diff --git a/fml/src/main/resources/assets/fml/lang/en_US.lang b/fml/src/main/resources/assets/fml/lang/en_US.lang index 2274c1800..09a4eb17e 100644 --- a/fml/src/main/resources/assets/fml/lang/en_US.lang +++ b/fml/src/main/resources/assets/fml/lang/en_US.lang @@ -52,6 +52,10 @@ fml.config.sample.modIDSelector.tooltip=A special property that allows the user fml.config.sample.modIDSelector=Mod ID Selector fml.config.sample.patternString.tooltip=A string property that is validated using a Pattern object. fml.config.sample.patternString=Pattern Validated String +fml.config.sample.sliderDouble.tooltip=A double property with defined bounds using a slider control. +fml.config.sample.sliderDouble=Slider Double +fml.config.sample.sliderInteger.tooltip=An integer property with defined bounds using a slider control. +fml.config.sample.sliderInteger=Slider Integer fml.config.sample.stringList.tooltip=A basic string list with no validation. fml.config.sample.stringList=Basic String List fml.config.sample.stringListFixed.tooltip=A string list that has a fixed length of 7.