Skip to content

Commit c73f682

Browse files
committed
HUD: Added context menu to add and remove hud elements and also change settings
1 parent d4cb76c commit c73f682

File tree

3 files changed

+141
-72
lines changed

3 files changed

+141
-72
lines changed

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,9 @@ import imgui.ImGui.closeCurrentPopup
4242
import imgui.flag.ImGuiCol
4343
import imgui.flag.ImGuiStyleVar
4444
import imgui.flag.ImGuiWindowFlags
45-
import imgui.type.ImString
4645
import net.fabricmc.loader.api.FabricLoader
47-
import net.minecraft.client.Keyboard
4846
import net.minecraft.util.Util
4947
import net.minecraft.world.GameMode
50-
import java.nio.file.Path
5148
import java.util.Locale
5249

5350
object MenuBar {

src/main/kotlin/com/lambda/gui/components/HudGuiLayout.kt

Lines changed: 102 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package com.lambda.gui.components
2020
import com.lambda.core.Loadable
2121
import com.lambda.event.events.GuiEvent
2222
import com.lambda.event.listener.SafeListener.Companion.listen
23+
import com.lambda.gui.components.ModuleEntry.Companion.buildModuleSettingsContext
2324
import com.lambda.gui.dsl.ImGuiBuilder
2425
import com.lambda.gui.dsl.ImGuiBuilder.buildLayout
2526
import com.lambda.gui.snap.Guide
@@ -69,9 +70,20 @@ object HudGuiLayout : Loadable {
6970

7071
init {
7172
listen<GuiEvent.NewFrame> {
72-
if (ClickGui.isEnabled && !isShownInGUI) return@listen
73-
7473
buildLayout {
74+
if (ClickGui.isEnabled && !isShownInGUI) {
75+
popupContextVoid("##hud-background") {
76+
menuItem(if (isShownInGUI) "Hide HUD" else "Show HUD") {
77+
isShownInGUI = !isShownInGUI
78+
}
79+
separator()
80+
menu("HUD Settings") {
81+
buildModuleSettingsContext(GuiSettings)
82+
}
83+
}
84+
return@buildLayout
85+
}
86+
7587
val vp = ImGui.getMainViewport()
7688
SnapManager.beginFrame(vp.sizeX, vp.sizeY, io.fontGlobalScale)
7789

@@ -93,59 +105,104 @@ object HudGuiLayout : Loadable {
93105

94106
notShown.forEach { SnapManager.unregisterElement(it.name) }
95107

96-
val canDrag = ClickGui.isEnabled && !isLocked
97-
if (canDrag) {
108+
registerContextMenu(notShown)
109+
110+
if (ClickGui.isEnabled && !isLocked) {
98111
if (activeDragHudName == null && mousePressedThisFrame) { tryBeginDrag(huds) }
99112
if (activeDragHudName != null && mouseDown) updateDragAndSnapping()
100113
if (activeDragHudName != null) drawDragGrid()
101114
}
102115

103116
huds.forEach { hud ->
104-
val override = pendingPositions[hud.name]
105-
if (override != null) {
106-
ImGui.setNextWindowPos(override.first, override.second)
107-
}
117+
registerHudElement(hud)
118+
}
119+
}
120+
}
121+
}
108122

109-
val bg = hud.backgroundColor
110-
val hasBg = bg.alpha > 0
111-
val baseFlags = if (hasBg) {
112-
DEFAULT_HUD_FLAGS and ImGuiWindowFlags.NoBackground.inv()
113-
} else DEFAULT_HUD_FLAGS
114-
val hudFlags = if (!ClickGui.isEnabled || isLocked) {
115-
baseFlags or ImGuiWindowFlags.NoMove
116-
} else baseFlags
117-
118-
val pushedColor = if (hasBg) {
119-
val packed = ImColor.rgba(bg.red, bg.green, bg.blue, bg.alpha)
120-
ImGui.pushStyleColor(imgui.flag.ImGuiCol.WindowBg, packed)
121-
true
122-
} else {
123-
false
124-
}
123+
private fun ImGuiBuilder.registerHudElement(hud: HudModule) {
124+
val override = pendingPositions[hud.name]
125+
if (override != null) {
126+
ImGui.setNextWindowPos(override.first, override.second)
127+
}
125128

126-
val outlineWidth = if (hud.outline) hud.outlineWidth else 0f
127-
withStyleVar(ImGuiStyleVar.WindowBorderSize, outlineWidth) {
128-
window("##${hud.name}", flags = hudFlags) {
129-
val vis = snapOverlays[hud.name]
130-
if (vis != null) {
131-
SnapManager.drawSnapLines(
132-
foregroundDrawList,
133-
vis.snapX, vis.kindX,
134-
vis.snapY, vis.kindY
135-
)
136-
}
137-
with(hud) { buildLayout() }
138-
if (canDrag) {
139-
drawHudCornerArcs(foregroundDrawList, windowPos.x, windowPos.y, windowSize.x, windowSize.y)
140-
}
141-
val rect = RectF(windowPos.x, windowPos.y, windowSize.x, windowSize.y)
142-
SnapManager.registerElement(hud.name, rect)
143-
lastBounds[hud.name] = rect
144-
}
129+
val bg = hud.backgroundColor
130+
val hasBg = bg.alpha > 0
131+
val baseFlags = if (hasBg) {
132+
DEFAULT_HUD_FLAGS and ImGuiWindowFlags.NoBackground.inv()
133+
} else DEFAULT_HUD_FLAGS
134+
val hudFlags = if (!ClickGui.isEnabled || isLocked) {
135+
baseFlags or ImGuiWindowFlags.NoMove
136+
} else baseFlags
137+
138+
val pushedColor = if (hasBg) {
139+
val packed = ImColor.rgba(bg.red, bg.green, bg.blue, bg.alpha)
140+
ImGui.pushStyleColor(imgui.flag.ImGuiCol.WindowBg, packed)
141+
true
142+
} else {
143+
false
144+
}
145+
146+
val outlineWidth = if (hud.outline) hud.outlineWidth else 0f
147+
withStyleVar(ImGuiStyleVar.WindowBorderSize, outlineWidth) {
148+
window("##${hud.name}", flags = hudFlags) {
149+
val vis = snapOverlays[hud.name]
150+
if (vis != null) {
151+
SnapManager.drawSnapLines(
152+
foregroundDrawList,
153+
vis.snapX, vis.kindX,
154+
vis.snapY, vis.kindY
155+
)
156+
}
157+
with(hud) { buildLayout() }
158+
159+
popupContextWindow("##ctx-${hud.name}") {
160+
menuItem("Remove HUD Element") {
161+
hud.disable()
162+
SnapManager.unregisterElement(hud.name)
145163
}
164+
separator()
165+
buildModuleSettingsContext(hud)
166+
}
146167

147-
if (pushedColor) {
148-
ImGui.popStyleColor()
168+
if (ClickGui.isEnabled && !isLocked) {
169+
drawHudCornerArcs(foregroundDrawList, windowPos.x, windowPos.y, windowSize.x, windowSize.y)
170+
}
171+
val rect = RectF(windowPos.x, windowPos.y, windowSize.x, windowSize.y)
172+
SnapManager.registerElement(hud.name, rect)
173+
lastBounds[hud.name] = rect
174+
}
175+
}
176+
177+
if (pushedColor) {
178+
ImGui.popStyleColor()
179+
}
180+
}
181+
182+
private fun ImGuiBuilder.registerContextMenu(notShown: List<HudModule>) {
183+
popupContextVoid("##hud-background") {
184+
menuItem(if (isLocked) "Unlock HUD" else "Lock HUD") {
185+
isLocked = !isLocked
186+
}
187+
menuItem(if (isShownInGUI) "Hide HUD" else "Show HUD") {
188+
isShownInGUI = !isShownInGUI
189+
}
190+
separator()
191+
menu("HUD Settings") {
192+
buildModuleSettingsContext(GuiSettings)
193+
}
194+
separator()
195+
if (notShown.isEmpty()) {
196+
textDisabled("No hidden HUD elements")
197+
} else {
198+
text("Add HUD Element:")
199+
separator()
200+
notShown.sortedBy { it.name.lowercase() }.forEach { hud ->
201+
menuItem("+ ${hud.name}") {
202+
val mx = io.mousePos.x
203+
val my = io.mousePos.y
204+
hud.enable()
205+
pendingPositions[hud.name] = mx to my
149206
}
150207
}
151208
}

src/main/kotlin/com/lambda/gui/components/ModuleEntry.kt

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ class ModuleEntry(val module: Module): Layout {
3636

3737
ImGui.setNextWindowSizeConstraints(0f, 0f, Float.MAX_VALUE, io.displaySize.y * 0.5f)
3838
popupContextItem("##ctx-${module.name}") {
39+
buildModuleSettingsContext(module)
40+
}
41+
}
42+
43+
companion object {
44+
/**
45+
* Builds the settings context popup content for a given module.
46+
*/
47+
fun ImGuiBuilder.buildModuleSettingsContext(module: Module) {
3948
group {
4049
with(module.keybindSetting) { buildLayout() }
4150
sameLine()
@@ -45,35 +54,41 @@ class ModuleEntry(val module: Module): Layout {
4554
lambdaTooltip("Resets all settings for this module to their default values")
4655
}
4756
separator()
48-
group {
49-
val visibleSettings = module.settings.filter { it.visibility() } - module.keybindSetting
50-
val (grouped, ungrouped) = visibleSettings.partition { it.groups.isNotEmpty() }
51-
52-
ungrouped.forEach { with(it) { buildLayout() } }
53-
renderGroup(grouped, emptyList())
54-
}
57+
val visibleSettings = module.settings.filter { it.visibility() } - module.keybindSetting
58+
val (grouped, ungrouped) = visibleSettings.partition { it.groups.isNotEmpty() }
59+
ungrouped.forEach { with(it) { buildLayout() } }
60+
renderGroup(grouped, emptyList(), module)
5561
}
56-
}
5762

58-
private fun ImGuiBuilder.renderGroup(settings: List<AbstractSetting<*>>, parentPath: List<NamedEnum>) {
59-
settings.filter { it.groups.contains(parentPath) }.forEach { with(it) { buildLayout() } }
63+
private fun ImGuiBuilder.renderGroup(
64+
settings: List<AbstractSetting<*>>,
65+
parentPath: List<NamedEnum>,
66+
module: Module
67+
) {
68+
settings.filter { it.groups.contains(parentPath) }.forEach { with(it) { buildLayout() } }
6069

61-
val subGroupSettings = settings.filter { s -> s.groups.any { it.size > parentPath.size && it.subList(0, parentPath.size) == parentPath } }
62-
val subTabs = subGroupSettings
63-
.flatMap { s ->
64-
s.groups.mapNotNull { path -> if (path.size > parentPath.size && path.subList(0, parentPath.size) == parentPath) path[parentPath.size] else null }
65-
}.distinct()
70+
val subGroupSettings = settings.filter { s ->
71+
s.groups.any { it.size > parentPath.size && it.subList(0, parentPath.size) == parentPath }
72+
}
73+
val subTabs = subGroupSettings
74+
.flatMap { s ->
75+
s.groups.mapNotNull { path ->
76+
if (path.size > parentPath.size && path.subList(0, parentPath.size) == parentPath)
77+
path[parentPath.size] else null
78+
}
79+
}.distinct()
6680

67-
if (subTabs.isNotEmpty()) {
68-
val id = "##${module.name}-tabs-${parentPath.joinToString("-") { it.displayName }}"
69-
tabBar(id, ImGuiTabBarFlags.FittingPolicyResizeDown) {
70-
subTabs.forEach { tab ->
71-
tabItem(tab.displayName) {
72-
val newParentPath = parentPath + tab
73-
val settingsForSubGroup = subGroupSettings.filter { s ->
74-
s.groups.any { it.size >= newParentPath.size && it.subList(0, newParentPath.size) == newParentPath }
81+
if (subTabs.isNotEmpty()) {
82+
val id = "##${module.name}-tabs-${parentPath.joinToString("-") { it.displayName }}"
83+
tabBar(id, ImGuiTabBarFlags.FittingPolicyResizeDown) {
84+
subTabs.forEach { tab ->
85+
tabItem(tab.displayName) {
86+
val newParentPath = parentPath + tab
87+
val settingsForSubGroup = subGroupSettings.filter { s ->
88+
s.groups.any { it.size >= newParentPath.size && it.subList(0, newParentPath.size) == newParentPath }
89+
}
90+
renderGroup(settingsForSubGroup, newParentPath, module)
7591
}
76-
renderGroup(settingsForSubGroup, newParentPath)
7792
}
7893
}
7994
}

0 commit comments

Comments
 (0)