Skip to content

Commit 46df050

Browse files
committed
Merge branch '1.21.5' into feature/packetmine-rewrite
2 parents 3253c5c + 9846eb1 commit 46df050

File tree

13 files changed

+192
-86
lines changed

13 files changed

+192
-86
lines changed

src/main/kotlin/com/lambda/config/AbstractSetting.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ import kotlin.reflect.KProperty
9494
* @property visibility A function that determines whether the setting is visible.
9595
*/
9696
abstract class AbstractSetting<T : Any>(
97-
private val defaultValue: T,
97+
internal val defaultValue: T,
9898
val type: Type,
9999
val description: String,
100100
val visibility: () -> Boolean,
@@ -169,7 +169,7 @@ abstract class AbstractSetting<T : Any>(
169169
val valueString = value().value()
170170
val parsed = try {
171171
JsonParser.parseString("\"$valueString\"")
172-
} catch (e: Exception) {
172+
} catch (_: Exception) {
173173
return@executeWithResult failure("$valueString is not a valid JSON string.")
174174
}
175175
val config = Configuration.configurableBySetting(this@AbstractSetting) ?: return@executeWithResult failure("No config found for $name.")

src/main/kotlin/com/lambda/config/settings/FunctionSetting.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import com.lambda.gui.dsl.ImGuiBuilder
2525

2626
open class FunctionSetting<T>(
2727
override val name: String,
28-
private val defaultValue: () -> T,
28+
defaultValue: () -> T,
2929
description: String,
3030
visibility: () -> Boolean,
3131
) : AbstractSetting<() -> T>(

src/main/kotlin/com/lambda/config/settings/NumericSetting.kt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ package com.lambda.config.settings
1919

2020
import com.google.gson.reflect.TypeToken
2121
import com.lambda.config.AbstractSetting
22+
import com.lambda.gui.dsl.ImGuiBuilder
23+
import imgui.ImGui
24+
import imgui.ImGui.calcTextSize
25+
import imgui.ImGui.dummy
26+
import imgui.ImGui.textUnformatted
27+
import imgui.flag.ImGuiCol
28+
import imgui.flag.ImGuiHoveredFlags
2229
import java.text.NumberFormat
2330
import java.util.*
2431
import kotlin.reflect.KProperty
@@ -46,4 +53,48 @@ abstract class NumericSetting<T>(
4653
override operator fun setValue(thisRef: Any?, property: KProperty<*>, valueIn: T) {
4754
value = valueIn.coerceIn(range)
4855
}
56+
57+
/**
58+
* Subclasses must implement this to provide their specific slider widget.
59+
*/
60+
protected abstract fun ImGuiBuilder.buildSlider()
61+
62+
override fun ImGuiBuilder.buildLayout() {
63+
val showReset = isModified
64+
val resetButtonText = "R"
65+
val valueString = this@NumericSetting.toString()
66+
67+
buildSlider()
68+
69+
if (description.isNotBlank()) {
70+
lambdaTooltip(description)
71+
}
72+
73+
val itemRectMin = ImGui.getItemRectMin()
74+
val itemRectMax = ImGui.getItemRectMax()
75+
val textHeight = ImGui.getTextLineHeight()
76+
val textY = itemRectMin.y + (itemRectMax.y - itemRectMin.y - textHeight) / 2.0f
77+
val labelWidth = calcTextSize(name).x
78+
val valueWidth = calcTextSize(valueString).x
79+
80+
val labelEndPosX = itemRectMin.x + style.framePadding.x * 2 + labelWidth
81+
val valueStartPosX = itemRectMax.x - style.framePadding.x * 2 - valueWidth
82+
83+
windowDrawList.addText(itemRectMin.x + style.framePadding.x * 2, textY, ImGui.getColorU32(ImGuiCol.Text), name)
84+
if (labelEndPosX < valueStartPosX) {
85+
windowDrawList.addText(valueStartPosX, textY, ImGui.getColorU32(ImGuiCol.Text), valueString)
86+
}
87+
88+
sameLine(0.0f, style.itemSpacing.x)
89+
if (showReset) {
90+
button("$resetButtonText##$name") {
91+
reset()
92+
}
93+
onItemHover {
94+
tooltip { text("Reset to default") }
95+
}
96+
} else {
97+
dummy(calcTextSize(resetButtonText).x + style.framePadding.x * 2.0f, ImGui.getFrameHeight())
98+
}
99+
}
49100
}

src/main/kotlin/com/lambda/config/settings/StringSetting.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import net.minecraft.command.CommandRegistryAccess
3333
*/
3434
class StringSetting(
3535
override val name: String,
36-
val defaultValue: String,
36+
defaultValue: String,
3737
val multiline: Boolean = false,
3838
val flags: Int = ImGuiInputTextFlags.None,
3939
description: String,

src/main/kotlin/com/lambda/config/settings/numeric/DoubleSetting.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,15 @@ class DoubleSetting(
4646
unit,
4747
visibility
4848
) {
49-
override fun ImGuiBuilder.buildLayout() {
50-
text(name)
51-
52-
sameLine()
53-
helpMarker(description)
49+
private var valueIndex: Int
50+
get() = ((value - range.start) / step).toInt()
51+
set(index) {
52+
value = (range.start + index * step).coerceIn(range)
53+
}
5454

55-
inputDouble("##$name", ::value)
55+
override fun ImGuiBuilder.buildSlider() {
56+
val maxIndex = ((range.endInclusive - range.start) / step).toInt()
57+
slider("##$name", ::valueIndex, 0, maxIndex, "")
5658
}
5759

5860
override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) {

src/main/kotlin/com/lambda/config/settings/numeric/FloatSetting.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,15 @@ class FloatSetting(
4545
unit,
4646
visibility
4747
) {
48-
override fun ImGuiBuilder.buildLayout() {
49-
text(name)
50-
51-
sameLine()
52-
helpMarker(description)
48+
private var valueIndex: Int
49+
get() = ((value - range.start) / step).toInt()
50+
set(index) {
51+
value = (range.start + index * step).coerceIn(range)
52+
}
5353

54-
inputFloat("##$name", ::value)
54+
override fun ImGuiBuilder.buildSlider() {
55+
val maxIndex = ((range.endInclusive - range.start) / step).toInt()
56+
slider("##$name", ::valueIndex, 0, maxIndex, "")
5557
}
5658

5759
override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) {

src/main/kotlin/com/lambda/config/settings/numeric/IntegerSetting.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,8 @@ class IntegerSetting(
4545
unit,
4646
visibility
4747
) {
48-
override fun ImGuiBuilder.buildLayout() {
49-
text(name)
50-
51-
sameLine()
52-
helpMarker(description)
53-
54-
slider("##$name", ::value, range.start, range.endInclusive, "%d$unit")
48+
override fun ImGuiBuilder.buildSlider() {
49+
slider("##$name", ::value, range.start, range.endInclusive, "")
5550
}
5651

5752
override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) {

src/main/kotlin/com/lambda/config/settings/numeric/LongSetting.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,15 @@ class LongSetting(
4545
unit,
4646
visibility
4747
) {
48-
var intValue = value.toInt()
49-
50-
override fun ImGuiBuilder.buildLayout() {
51-
text(name)
52-
53-
sameLine()
54-
helpMarker(description)
48+
private var valueIndex: Int
49+
get() = ((value - range.start) / step).toInt()
50+
set(index) {
51+
value = (range.start + index * step).coerceIn(range)
52+
}
5553

56-
inputInt("##$name", ::intValue) { value = it.toLong() }
54+
override fun ImGuiBuilder.buildSlider() {
55+
val maxIndex = ((range.endInclusive - range.start) / step).toInt()
56+
slider("##$name", ::valueIndex, 0, maxIndex, "")
5757
}
5858

5959
override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) {

src/main/kotlin/com/lambda/gui/LambdaScreen.kt

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717

1818
package com.lambda.gui
1919

20+
import com.lambda.config.Configuration
2021
import com.lambda.module.ModuleRegistry
2122
import com.lambda.module.modules.client.ClickGui
2223
import com.lambda.module.tag.ModuleTag
24+
import com.lambda.threading.runSafe
25+
import com.lambda.util.Communication.info
2326
import imgui.ImGui
2427
import imgui.flag.ImGuiWindowFlags.AlwaysAutoResize
2528
import net.minecraft.client.gui.DrawContext
@@ -42,10 +45,29 @@ object LambdaScreen : Screen(Text.of("Lambda GUI")) {
4245
}
4346
}
4447

45-
// ToDo
4648
mainMenuBar {
49+
menu("File") {
50+
menuItem("Save Configs", "Ctrl+S") {
51+
Configuration.configurations.forEach { config ->
52+
config.trySave(true)
53+
}
54+
runSafe {
55+
info("Saved ${Configuration.configurations.size} configuration files.")
56+
}
57+
}
58+
menuItem("Load Configs", "Ctrl+L") {
59+
Configuration.configurations.forEach { config ->
60+
config.tryLoad()
61+
}
62+
runSafe {
63+
info("Loaded ${Configuration.configurations.size} configuration files.")
64+
}
65+
}
66+
}
4767
menu("HUD") {
48-
menuItem("ClickGUI", "Ctrl+Alt+C") {}
68+
menuItem("Open Editor", "Ctrl+Alt+C") {
69+
ImGui.showStyleEditor()
70+
}
4971
}
5072
}
5173
ImGui.showDemoWindow()

src/main/kotlin/com/lambda/gui/dsl/ImGuiBuilder.kt

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,6 @@ object ImGuiBuilder {
132132
val isWindowAppearing: Boolean get() = ImGui.isWindowAppearing()
133133
val isWindowCollapsed: Boolean get() = ImGui.isWindowCollapsed()
134134

135-
/**
136-
* Returns whether the current window is focused.
137-
*/
138-
val isWindowFocused: Boolean get() = ImGui.isWindowFocused()
139-
fun isWindowFocused(flags: Int = ImGuiWindowFlags.None) = ImGui.isWindowHovered(flags)
140-
141-
/**
142-
* Returns whether the current window is hovered and not blocked by a popup/modal
143-
*/
144-
val isWindowHovered: Boolean get() = ImGui.isWindowHovered()
145-
fun isWindowHovered(flags: Int = ImGuiWindowFlags.None) = ImGui.isWindowHovered(flags)
146-
147135
/**
148136
* Returns the current window position in screen space
149137
*
@@ -167,41 +155,71 @@ object ImGuiBuilder {
167155
val windowViewport: ImGuiViewport get() = ImGui.getWindowViewport()
168156

169157
/**
170-
* Returns whether the last item hovered and usable (not blocked by a popup, etc.).
158+
* Returns whether any item hovered and usable (not blocked by a popup, etc.).
171159
*/
172-
val isItemHovered: Boolean get() = ImGui.isItemHovered()
173-
fun isItemHovered(flags: Int = ImGuiHoveredFlags.None) = ImGui.isItemHovered(flags)
160+
val isAnyItemHovered: Boolean get() = ImGui.isAnyItemHovered()
174161

175162
/**
176163
* Returns whether:
177-
* - A button is being held
178-
* - A text field being is edited
179-
* - The last item is being held and allows interaction
164+
* - Any button is being held
165+
* - Any text field is being edited
166+
* - Any item is being held and allows interaction
180167
*/
181-
val isItemActive: Boolean get() = ImGui.isItemActive()
168+
val isAnyItemActive: Boolean get() = ImGui.isAnyItemActive()
182169

183170
/**
184-
* Returns whether the last item is focused via keyboard/gamepad navigation
171+
* Returns whether any item is focused via keyboard/gamepad navigation
185172
*/
186-
val isItemFocused: Boolean get() = ImGui.isItemFocused()
173+
val isAnyItemFocused: Boolean get() = ImGui.isAnyItemFocused()
187174

188175
/**
189-
* Returns whether any item hovered and usable (not blocked by a popup, etc.).
176+
* Executes the specified block if the current window is hovered, based on the provided flags.
177+
*
178+
* @param flags Optional flags to control the behavior of the hover state. The default value is `ImGuiWindowFlags.None`.
179+
* @param block A lambda block of code to be executed when the window is hovered.
190180
*/
191-
val isAnyItemHovered: Boolean get() = ImGui.isAnyItemHovered()
181+
@ImGuiDsl
182+
fun onWindowFocus(flags: Int = ImGuiWindowFlags.None, block: ProcedureBlock) =
183+
if (ImGui.isWindowHovered(flags)) block() else Unit
192184

193185
/**
194-
* Returns whether:
195-
* - Any button is being held
196-
* - Any text field is being edited
197-
* - Any item is being held and allows interaction
186+
* Executes a given block of code when the current ImGui window is being hovered.
187+
*
188+
* @param flags Optional flag settings for specifying conditions under which the window hover is detected.
189+
* Defaults to `ImGuiWindowFlags.None`.
190+
* @param block The block of code to execute when the hover condition is met.
198191
*/
199-
val isAnyItemActive: Boolean get() = ImGui.isAnyItemActive()
192+
@ImGuiDsl
193+
fun onWindowHover(flags: Int = ImGuiWindowFlags.None, block: ProcedureBlock) =
194+
if (ImGui.isWindowHovered(flags)) block() else Unit
200195

201196
/**
202-
* Returns whether any item is focused via keyboard/gamepad navigation
197+
* Executes the given block of code if the current ImGui item is hovered.
198+
*
199+
* @param flags Customization flags for determining hover behavior. Defaults to `ImGuiHoveredFlags.None`.
200+
* @param block The block of code to execute when the item is hovered.
203201
*/
204-
val isAnyItemFocused: Boolean get() = ImGui.isAnyItemFocused()
202+
@ImGuiDsl
203+
fun onItemHover(flags: Int = ImGuiHoveredFlags.None, block: ProcedureBlock) =
204+
if (ImGui.isItemHovered(flags)) block() else Unit
205+
206+
/**
207+
* Executes the provided block of code if the current item is active in the ImGui context.
208+
*
209+
* @param block The block of code to be executed when the item is active.
210+
*/
211+
@ImGuiDsl
212+
fun onItemActive(block: ProcedureBlock) =
213+
if (ImGui.isItemActive()) block() else Unit
214+
215+
/**
216+
* Executes the given [block] when the currently active item in the ImGui interface gains focus.
217+
*
218+
* @param block The block of code to execute if the current item is focused.
219+
*/
220+
@ImGuiDsl
221+
fun onItemFocus(block: ProcedureBlock) =
222+
if (ImGui.isItemFocused()) block() else Unit
205223

206224
/**
207225
* Returns whether the last hovered item is clicked on
@@ -210,8 +228,9 @@ object ImGuiBuilder {
210228
*
211229
* this is NOT equivalent to the behavior of e.g. Button(). Read comments in function definition.
212230
*/
213-
val isItemClicked: Boolean get() = ImGui.isItemClicked()
214-
fun isItemClicked(button: Int = ImGuiMouseButton.Right) = ImGui.isItemClicked(button)
231+
@ImGuiDsl
232+
fun onItemClick(button: Int = ImGuiMouseButton.Right, block: ProcedureBlock) =
233+
if (ImGui.isItemClicked(button)) block() else Unit
215234

216235
/**
217236
* Returns whether:
@@ -353,7 +372,7 @@ object ImGuiBuilder {
353372
@ImGuiDsl
354373
fun textCopyable(text: String) {
355374
text(text)
356-
if (isItemHovered()) {
375+
onItemHover {
357376
if (isMouseClicked(ImGuiMouseButton.Left)) {
358377
setClipboardText(text)
359378
}
@@ -1401,6 +1420,22 @@ object ImGuiBuilder {
14011420
endTooltip()
14021421
}
14031422

1423+
/**
1424+
* Displays a tooltip with the specified description when the current ImGui item is hovered.
1425+
*
1426+
* @param description The text content to display in the tooltip.
1427+
*/
1428+
@ImGuiDsl
1429+
fun lambdaTooltip(description: String) {
1430+
onItemHover {
1431+
tooltip {
1432+
withTextWrapPos(fontSize * 35f) {
1433+
textUnformatted(description)
1434+
}
1435+
}
1436+
}
1437+
}
1438+
14041439
/**
14051440
* Creates a help marker with a tooltip.
14061441
*
@@ -1409,11 +1444,11 @@ object ImGuiBuilder {
14091444
@ImGuiDsl
14101445
fun helpMarker(description: String, text: String = "(?)") {
14111446
textDisabled(text)
1412-
if (isItemHovered()) {
1447+
onItemHover {
14131448
tooltip {
1414-
pushTextWrapPos(fontSize * 35f)
1415-
textUnformatted(description)
1416-
popTextWrapPos()
1449+
withTextWrapPos(fontSize * 35f) {
1450+
textUnformatted(description)
1451+
}
14171452
}
14181453
}
14191454
}

0 commit comments

Comments
 (0)