Skip to content

Commit 448e5eb

Browse files
committed
feat: improve HUD configuration with more settings, implement persistence for themes
1 parent a7d06d4 commit 448e5eb

14 files changed

Lines changed: 601 additions & 111 deletions

File tree

minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import dev.deftu.omnicore.api.client.commands.OmniClientCommandSource;
3636
import dev.deftu.omnicore.api.client.commands.OmniClientCommands;
3737
import dev.deftu.omnicore.api.client.input.OmniKeys;
38+
import dev.deftu.omnicore.api.client.render.OmniResolution;
3839
import dev.deftu.omnicore.api.client.screen.OmniScreens;
3940
import dev.deftu.omnicore.api.loader.ModInfo;
4041
import dev.deftu.omnicore.api.loader.OmniLoader;
@@ -54,6 +55,7 @@
5455
import org.polyfrost.oneconfig.api.hud.v1.HudManager;
5556
import org.polyfrost.oneconfig.api.hud.v1.events.HudEditorToggleEvent;
5657
import org.polyfrost.oneconfig.internal.ui.compose.impls.HudEditorUIScreen;
58+
import org.polyfrost.oneconfig.internal.ui.hud.LegacyHudRenderer;
5759
import org.polyfrost.oneconfig.api.hypixel.v1.HypixelUtils;
5860
import org.polyfrost.oneconfig.api.platform.v1.Platform;
5961
import org.polyfrost.oneconfig.api.ui.v1.internal.BlurHandler;
@@ -186,9 +188,15 @@ private static void registerEventHandlers() {
186188
EventManager.register(InitializationEvent.class, e -> HudManager.INSTANCE.initialize());
187189
EventManager.register(HudRenderEvent.class, e -> {
188190
if (!SkiaCtx.INSTANCE.isReady()) return;
191+
float sw = OmniClient.getWindow().getScreenWidth();
192+
float sh = OmniClient.getWindow().getScreenHeight();
193+
float scale = (float) OmniResolution.getScaleFactor();
194+
HudManager.guiScreenWidth = sw / scale;
195+
HudManager.guiScreenHeight = sh / scale;
196+
LegacyHudRenderer.INSTANCE.renderLive(e.ctx);
189197
SkiaCtx.INSTANCE.queueHudDraw(() -> {
190198
var ctx = new RenderContext(SkiaCtx.INSTANCE.getCanvas());
191-
HudManager.INSTANCE.render(ctx, OmniClient.getWindow().getScreenWidth(), OmniClient.getWindow().getScreenHeight());
199+
HudManager.INSTANCE.render(ctx, sw, sh);
192200
});
193201
SkiaCtx.INSTANCE.drawNow();
194202
});
@@ -205,6 +213,7 @@ private static void registerEventHandlers() {
205213
ConfigManager.initialize();
206214
ConfigRegistry.INSTANCE.loadFrom(ConfigManager.active(), ConfigSource.OC);
207215
org.polyfrost.oneconfig.internal.ui.hud.BuiltinHudRegistrar.register();
216+
org.polyfrost.oneconfig.internal.ui.themes.ThemeRegistry.INSTANCE.loadFromConfig();
208217
});
209218
// //#if MC < 1.13
210219
// // this is cringe but is better than the alternative of checking every frame in a mixin (that's how vanilla does it lol)
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* This file is part of OneConfig.
3+
* OneConfig - Next Generation Config Library for Minecraft: Java Edition
4+
* Copyright (C) 2021~2024 Polyfrost.
5+
* <https://polyfrost.org> <https://github.com/Polyfrost/>
6+
*
7+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8+
*
9+
* OneConfig is licensed under the terms of version 3 of the GNU Lesser
10+
* General Public License as published by the Free Software Foundation, AND
11+
* under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
12+
* either version 1.0 of the Additional Terms, or (at your option) any later
13+
* version.
14+
*
15+
* This program is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18+
* Lesser General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU Lesser General Public
21+
* License. If not, see <https://www.gnu.org/licenses/>. You should
22+
* have also received a copy of the Additional Terms Applicable
23+
* to OneConfig, as published by Polyfrost. If not, see
24+
* <https://polyfrost.org/legal/oneconfig/additional-terms>
25+
*/
26+
27+
package org.polyfrost.oneconfig.test;
28+
29+
import dev.deftu.omnicore.api.client.render.OmniRenderingContext;
30+
import kotlin.Pair;
31+
import net.minecraft.client.Minecraft;
32+
import net.minecraft.client.gui.GuiGraphics;
33+
import net.minecraft.world.item.ItemStack;
34+
import net.minecraft.world.item.Items;
35+
import org.jetbrains.annotations.NotNull;
36+
import org.polyfrost.oneconfig.api.hud.v1.LegacyHud;
37+
38+
public class TestLegacyHud_Test extends LegacyHud {
39+
private static final float W = 20f;
40+
private static final float H = 20f;
41+
42+
private ItemStack stack;
43+
44+
public TestLegacyHud_Test() {
45+
super("test-legacy-hud", "Item HUD", Category.Companion.getINFO());
46+
}
47+
48+
@Override
49+
public float getWidth() {
50+
return W;
51+
}
52+
53+
@Override
54+
public float getHeight() {
55+
return H;
56+
}
57+
58+
@Override
59+
public boolean update() {
60+
return false;
61+
}
62+
63+
@Override
64+
public void render(@NotNull OmniRenderingContext mcCtx) {
65+
GuiGraphics graphics = mcCtx.graphics();
66+
if (graphics == null) return;
67+
68+
if (stack == null) stack = new ItemStack(Items.DIAMOND_SWORD);
69+
70+
graphics.fill(0, 0, (int) W, (int) H, 0x80000000);
71+
72+
graphics.renderItem(stack, 2, 2);
73+
}
74+
75+
@NotNull
76+
@Override
77+
public Pair<Float, Float> defaultPosition() {
78+
return new Pair<>(10f, 120f);
79+
}
80+
}

minecraft/src/main/java/org/polyfrost/oneconfig/test/TestMod_Test.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public static void initialize() {
4343
config.preload();
4444
}
4545
ConfigRegistry.INSTANCE.registerTree(config.getTree(), ConfigSource.OC);
46+
47+
HudManager.INSTANCE.register(new TestLegacyHud_Test(), "test_mod");
4648
});
4749
}
4850
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.polyfrost.oneconfig.internal.ui.hud
2+
3+
import androidx.compose.runtime.snapshots.Snapshot
4+
import dev.deftu.omnicore.api.client.render.OmniRenderingContext
5+
import org.polyfrost.oneconfig.api.hud.v1.HudManager
6+
import org.polyfrost.oneconfig.api.hud.v1.LegacyHud
7+
8+
object LegacyHudRenderer {
9+
fun renderLive(eventCtx: OmniRenderingContext) {
10+
if (!eventCtx.areGraphicsAvailable) return
11+
for (hud in HudManager.activeInstances) {
12+
if (hud !is LegacyHud || hud.hidden) continue
13+
hud.update()
14+
val hudScale = hud.effectiveScale
15+
Snapshot.withMutableSnapshot {
16+
hud.renderedW = hud.width * hudScale
17+
hud.renderedH = hud.height * hudScale
18+
}
19+
//#if MC >= 1.21.8
20+
//$$ val graphics = eventCtx.graphics ?: continue
21+
//$$ val pose = graphics.pose()
22+
//$$ pose.pushMatrix()
23+
//$$ pose.translate(hud.x, hud.y)
24+
//$$ if (hudScale != 1f) pose.scale(hudScale, hudScale)
25+
//$$ hud.render(eventCtx)
26+
//$$ pose.popMatrix()
27+
//#else
28+
val graphics = eventCtx.graphics ?: continue
29+
val pose = graphics.pose()
30+
pose.pushPose()
31+
pose.translate(hud.x.toDouble(), hud.y.toDouble(), 0.0)
32+
if (hudScale != 1f) pose.scale(hudScale, hudScale, 1f)
33+
hud.render(eventCtx)
34+
graphics.flush()
35+
pose.popPose()
36+
//#endif
37+
}
38+
}
39+
}

minecraft/versions/26.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/services/CinnabarVulkanService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class CinnabarVulkanService private constructor(
8888
companion object {
8989
private val LOG = LoggerFactory.getLogger(CinnabarVulkanService::class.java)
9090

91-
private fun hgFormatToVkFormat(name: String): Int = when (name) {
91+
fun hgFormatToVkFormat(name: String): Int= when (name) {
9292
"RGBA8_UNORM" -> VK_FORMAT_R8G8B8A8_UNORM
9393
"RGBA8_SRGB" -> VK_FORMAT_R8G8B8A8_SRGB
9494
"BGRA8_UNORM" -> VK_FORMAT_B8G8R8A8_UNORM

modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/Hud.kt

Lines changed: 155 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ enum class Font {
5050
Poppins;
5151
}
5252

53+
enum class Section {
54+
TopLeft, TopCenter, TopRight,
55+
CenterLeft, Center, CenterRight,
56+
BottomLeft, BottomCenter, BottomRight
57+
}
58+
59+
private const val GRID_SIZE = 3
60+
5361
@Suppress("EqualsOrHashCode", "UnstableApiUsage")
5462
abstract class Hud(id: String, title: String, val category: Category) : Cloneable, Config(id, null, title, null) {
5563
private var _staticWidth: MutableState<Boolean> = mutableStateOf(false)
@@ -67,18 +75,103 @@ abstract class Hud(id: String, title: String, val category: Category) : Cloneabl
6775
var toggleKey: Int = -1
6876
var showKey: Int = -1
6977

70-
private var _x: MutableState<Float> = mutableStateOf(0f)
71-
var x: Float get() = _x.value; set(v) { _x.value = v }
78+
private var _section: MutableState<Section> = mutableStateOf(Section.TopLeft)
79+
var section: Section get() = _section.value; set(v) { _section.value = v }
7280

73-
private var _y: MutableState<Float> = mutableStateOf(0f)
74-
var y: Float get() = _y.value; set(v) { _y.value = v }
81+
private var _relativeX: MutableState<Float> = mutableStateOf(0f)
82+
var relativeX: Float get() = _relativeX.value; set(v) { _relativeX.value = v }
83+
84+
private var _relativeY: MutableState<Float> = mutableStateOf(0f)
85+
var relativeY: Float get() = _relativeY.value; set(v) { _relativeY.value = v }
7586

7687
private var _renderedW: MutableState<Float> = mutableStateOf(0f)
7788
var renderedW: Float get() = _renderedW.value; set(v) { _renderedW.value = v }
7889

7990
private var _renderedH: MutableState<Float> = mutableStateOf(0f)
8091
var renderedH: Float get() = _renderedH.value; set(v) { _renderedH.value = v }
8192

93+
val scaledWidth: Float get() {
94+
val w = if (staticWidth) staticW else renderedW
95+
return if (w > 0f) w else 1f
96+
}
97+
98+
val scaledHeight: Float get() {
99+
val h = if (staticWidth) staticH else renderedH
100+
return if (h > 0f) h else 1f
101+
}
102+
103+
var x: Float
104+
get() {
105+
val sw = HudManager.guiScreenWidth
106+
val secPos = (sw / GRID_SIZE * relativeX).toInt()
107+
return when (section) {
108+
Section.TopLeft, Section.CenterLeft, Section.BottomLeft -> secPos.toFloat()
109+
Section.TopCenter, Section.Center, Section.BottomCenter -> (sw - scaledWidth) / 2f + secPos
110+
Section.TopRight, Section.CenterRight, Section.BottomRight -> sw - scaledWidth - secPos
111+
}
112+
}
113+
set(v) { updateRelativeX(v) }
114+
115+
var y: Float
116+
get() {
117+
val sh = HudManager.guiScreenHeight
118+
val secPos = (sh / GRID_SIZE * relativeY).toInt()
119+
return when (section) {
120+
Section.TopLeft, Section.TopCenter, Section.TopRight -> secPos.toFloat()
121+
Section.CenterLeft, Section.Center, Section.CenterRight -> (sh - scaledHeight) / 2f + secPos
122+
Section.BottomLeft, Section.BottomCenter, Section.BottomRight -> sh - scaledHeight - secPos
123+
}
124+
}
125+
set(v) { updateRelativeY(v) }
126+
127+
private fun updateRelativeX(absX: Float) {
128+
val sw = HudManager.guiScreenWidth
129+
val gridW = sw / GRID_SIZE
130+
relativeX = when (section) {
131+
Section.TopLeft, Section.CenterLeft, Section.BottomLeft -> absX / gridW
132+
Section.TopCenter, Section.Center, Section.BottomCenter -> (absX - (sw - scaledWidth) / 2f) / gridW
133+
else -> (sw - scaledWidth - absX) / gridW
134+
}.coerceIn(-1f, 2f)
135+
}
136+
137+
private fun updateRelativeY(absY: Float) {
138+
val sh = HudManager.guiScreenHeight
139+
val gridH = sh / GRID_SIZE
140+
relativeY = when (section) {
141+
Section.TopLeft, Section.TopCenter, Section.TopRight -> absY / gridH
142+
Section.CenterLeft, Section.Center, Section.CenterRight -> (absY - (sh - scaledHeight) / 2f) / gridH
143+
else -> (sh - scaledHeight - absY) / gridH
144+
}.coerceIn(-1f, 2f)
145+
}
146+
147+
fun setAbsolutePosition(absX: Float, absY: Float) {
148+
val sw = HudManager.guiScreenWidth
149+
val sh = HudManager.guiScreenHeight
150+
val gridW = sw / GRID_SIZE
151+
val gridH = sh / GRID_SIZE
152+
153+
section = when {
154+
absX < gridW -> when {
155+
absY > 2 * gridH -> Section.BottomLeft
156+
absY > gridH -> Section.CenterLeft
157+
else -> Section.TopLeft
158+
}
159+
absX < 2 * gridW -> when {
160+
absY > 2 * gridH -> Section.BottomCenter
161+
absY > gridH -> Section.Center
162+
else -> Section.TopCenter
163+
}
164+
else -> when {
165+
absY > 2 * gridH -> Section.BottomRight
166+
absY > gridH -> Section.CenterRight
167+
else -> Section.TopRight
168+
}
169+
}
170+
171+
updateRelativeX(absX)
172+
updateRelativeY(absY)
173+
}
174+
82175
var hidden: Boolean = false
83176

84177
private var _alignment: MutableState<PolyAlign> = mutableStateOf(PolyAlign.TopLeft)
@@ -123,6 +216,38 @@ abstract class Hud(id: String, title: String, val category: Category) : Cloneabl
123216
private var _textAlign: MutableState<Int> = mutableStateOf(1)
124217
var textAlign: Int get() = _textAlign.value; set(v) { _textAlign.value = v }
125218

219+
private var _useGuiScale: MutableState<Boolean> = mutableStateOf(true)
220+
var useGuiScale: Boolean get() = _useGuiScale.value; set(v) { _useGuiScale.value = v }
221+
222+
private var _customScale: MutableState<Float> = mutableStateOf(1f)
223+
var customScale: Float get() = _customScale.value; set(v) { _customScale.value = v }
224+
225+
val effectiveScale: Float get() = if (useGuiScale) 1f else customScale
226+
227+
private var _showBackground: MutableState<Boolean> = mutableStateOf(true)
228+
var showBackground: Boolean get() = _showBackground.value; set(v) { _showBackground.value = v }
229+
230+
private var _bgColor: MutableState<Int> = mutableStateOf(0x80000000.toInt())
231+
var bgColor: Int get() = _bgColor.value; set(v) { _bgColor.value = v }
232+
233+
private var _bgRadius: MutableState<Float> = mutableStateOf(4f)
234+
var bgRadius: Float get() = _bgRadius.value; set(v) { _bgRadius.value = v }
235+
236+
private var _textColor: MutableState<Int> = mutableStateOf(0xFFFFFFFF.toInt())
237+
var textColor: Int get() = _textColor.value; set(v) { _textColor.value = v }
238+
239+
private var _showShadow: MutableState<Boolean> = mutableStateOf(false)
240+
var showShadow: Boolean get() = _showShadow.value; set(v) { _showShadow.value = v }
241+
242+
private var _shadowColor: MutableState<Int> = mutableStateOf(0x40000000)
243+
var shadowColor: Int get() = _shadowColor.value; set(v) { _shadowColor.value = v }
244+
245+
private var _shadowOffsetX: MutableState<Float> = mutableStateOf(2f)
246+
var shadowOffsetX: Float get() = _shadowOffsetX.value; set(v) { _shadowOffsetX.value = v }
247+
248+
private var _shadowOffsetY: MutableState<Float> = mutableStateOf(2f)
249+
var shadowOffsetY: Float get() = _shadowOffsetY.value; set(v) { _shadowOffsetY.value = v }
250+
126251
override fun addToInitQueue() {}
127252

128253
val isReal get() = tree != null
@@ -156,8 +281,9 @@ abstract class Hud(id: String, title: String, val category: Category) : Cloneabl
156281
tree.addMetadata("category", category)
157282
tree.addMetadata("hidden", true)
158283
var hidden = { Property.Display.HIDDEN }
159-
tree["x"] = ktProperty(out::x).apply { addDisplayCondition(hidden) }
160-
tree["y"] = ktProperty(out::y).apply { addDisplayCondition(hidden) }
284+
tree["section"] = ktProperty(out::section).apply { addDisplayCondition(hidden) }
285+
tree["relativeX"] = ktProperty(out::relativeX).apply { addDisplayCondition(hidden) }
286+
tree["relativeY"] = ktProperty(out::relativeY).apply { addDisplayCondition(hidden) }
161287
tree["toggleKey"] = ktProperty(out::toggleKey).apply { addDisplayCondition(hidden) }
162288
tree["showKey"] = ktProperty(out::showKey).apply { addDisplayCondition(hidden) }
163289
tree["alignment"] = ktProperty(out::alignment).apply { addDisplayCondition(hidden) }
@@ -175,6 +301,16 @@ abstract class Hud(id: String, title: String, val category: Category) : Cloneabl
175301
tree["textItalic"] = ktProperty(out::textItalic).apply { addDisplayCondition(hidden) }
176302
tree["textUnderline"] = ktProperty(out::textUnderline).apply { addDisplayCondition(hidden) }
177303
tree["textAlign"] = ktProperty(out::textAlign).apply { addDisplayCondition(hidden) }
304+
tree["useGuiScale"] = ktProperty(out::useGuiScale).apply { addDisplayCondition(hidden) }
305+
tree["customScale"] = ktProperty(out::customScale).apply { addDisplayCondition(hidden) }
306+
tree["showBackground"] = ktProperty(out::showBackground).apply { addDisplayCondition(hidden) }
307+
tree["bgColor"] = ktProperty(out::bgColor).apply { addDisplayCondition(hidden) }
308+
tree["bgRadius"] = ktProperty(out::bgRadius).apply { addDisplayCondition(hidden) }
309+
tree["textColor"] = ktProperty(out::textColor).apply { addDisplayCondition(hidden) }
310+
tree["showShadow"] = ktProperty(out::showShadow).apply { addDisplayCondition(hidden) }
311+
tree["shadowColor"] = ktProperty(out::shadowColor).apply { addDisplayCondition(hidden) }
312+
tree["shadowOffsetX"] = ktProperty(out::shadowOffsetX).apply { addDisplayCondition(hidden) }
313+
tree["shadowOffsetY"] = ktProperty(out::shadowOffsetY).apply { addDisplayCondition(hidden) }
178314
addToSerialized(tree)
179315
tree["hudClass"] = simple(value = out::class.java.name).apply {
180316
addDisplayCondition { Property.Display.HIDDEN }
@@ -216,8 +352,9 @@ abstract class Hud(id: String, title: String, val category: Category) : Cloneabl
216352
showKey = -1
217353
toggleKey = -1
218354
_staticWidth = mutableStateOf(this@Hud.staticWidth)
219-
_x = mutableStateOf(this@Hud.x)
220-
_y = mutableStateOf(this@Hud.y)
355+
_section = mutableStateOf(this@Hud.section)
356+
_relativeX = mutableStateOf(this@Hud.relativeX)
357+
_relativeY = mutableStateOf(this@Hud.relativeY)
221358
_renderedW = mutableStateOf(0f)
222359
_renderedH = mutableStateOf(0f)
223360
_alignment = mutableStateOf(this@Hud.alignment)
@@ -234,6 +371,16 @@ abstract class Hud(id: String, title: String, val category: Category) : Cloneabl
234371
_textItalic = mutableStateOf(this@Hud.textItalic)
235372
_textUnderline = mutableStateOf(this@Hud.textUnderline)
236373
_textAlign = mutableStateOf(this@Hud.textAlign)
374+
_useGuiScale = mutableStateOf(this@Hud.useGuiScale)
375+
_customScale = mutableStateOf(this@Hud.customScale)
376+
_showBackground = mutableStateOf(this@Hud.showBackground)
377+
_bgColor = mutableStateOf(this@Hud.bgColor)
378+
_bgRadius = mutableStateOf(this@Hud.bgRadius)
379+
_textColor = mutableStateOf(this@Hud.textColor)
380+
_showShadow = mutableStateOf(this@Hud.showShadow)
381+
_shadowColor = mutableStateOf(this@Hud.shadowColor)
382+
_shadowOffsetX = mutableStateOf(this@Hud.shadowOffsetX)
383+
_shadowOffsetY = mutableStateOf(this@Hud.shadowOffsetY)
237384
}
238385

239386
class Category(val name: String, val id: Byte) {

0 commit comments

Comments
 (0)