From dc2b265de4e18c2809b797783d69c1fc43d214e8 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Sun, 30 Nov 2025 15:21:56 +0000 Subject: [PATCH 01/47] Revert "revert gl renderer thing" This reverts commit 896a95769a476388fea779c25439f3ac4c7b0dd3. --- .../ui/v1/internal/wrappers/PolyUIScreen.java | 67 +++++++------------ 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java index 56da7a8f5..f43950880 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java @@ -26,25 +26,20 @@ package org.polyfrost.oneconfig.api.ui.v1.internal.wrappers; -import dev.deftu.omnicore.api.client.framebuffer.ManagedFramebuffer; -import dev.deftu.omnicore.api.client.framebuffer.OmniFramebuffer; import dev.deftu.omnicore.api.client.input.KeyboardModifiers; import dev.deftu.omnicore.api.client.input.OmniKey; import dev.deftu.omnicore.api.client.input.OmniKeys; import dev.deftu.omnicore.api.client.input.OmniMouseButton; import dev.deftu.omnicore.api.client.render.OmniRenderingContext; -import dev.deftu.omnicore.api.client.render.OmniResolution; import dev.deftu.omnicore.api.client.screen.KeyPressEvent; import dev.deftu.omnicore.api.client.screen.OmniScreen; import dev.deftu.textile.Text; -import dev.deftu.omnicore.api.client.textures.OmniTextureFormat; -import dev.deftu.omnicore.api.color.OmniColors; -import kotlin.Unit; import net.minecraft.client.Minecraft; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; +import org.lwjgl.BufferUtils; import org.polyfrost.oneconfig.api.platform.v1.Platform; import org.polyfrost.oneconfig.api.ui.v1.Notifications; import org.polyfrost.oneconfig.api.ui.v1.UIManager; @@ -53,8 +48,11 @@ import org.polyfrost.polyui.component.Drawable; import org.polyfrost.polyui.data.Cursor; +import java.nio.Buffer; +import java.nio.IntBuffer; import java.util.function.Consumer; +import static org.lwjgl.opengl.GL11.*; import static org.polyfrost.oneconfig.api.ui.v1.keybind.KeybindManager.translateKey; @SuppressWarnings("unused") @@ -64,11 +62,16 @@ public class PolyUIScreen extends OmniScreen implements BlurScreen { @NotNull public final PolyUI polyUI; - private OmniFramebuffer framebuffer; - private final float designedWidth, designedHeight, initialWidth, initialHeight; private final boolean pauses, blurs; private final Consumer close; + private final IntBuffer VIEWPORT = BufferUtils.createIntBuffer( + //#if MC >= 1.13 + //$$ 4 + //#else + 16 + //#endif + ); //#if MC < 1.13 private int mx, my; @@ -118,42 +121,28 @@ public void onRender(@NotNull OmniRenderingContext ctx, int mouseX, int mouseY, } //#endif - if (framebuffer == null || polyUI == UIManager.INSTANCE.getDefaultInstance()) { + if (polyUI == UIManager.INSTANCE.getDefaultInstance()) { return; } - Drawable master = polyUI.getMaster(); - try { - framebuffer.clearColor(0f, 0f, 0f, 0f); // Clear to transparent black - if (framebuffer instanceof ManagedFramebuffer) { - ((ManagedFramebuffer) framebuffer).clearDepthStencil(1.0, 0); - } - - framebuffer.usingToRender((matrixStack, w, h) -> { - matrixStack.runReplacingGlobalState(polyUI::render); - return Unit.INSTANCE; - }); + ((Buffer) VIEWPORT).clear(); + //#if MC >= 1.13 + //$$ glGetIntegerv(GL_VIEWPORT, VIEWPORT); + //#else + glGetInteger(GL_VIEWPORT, VIEWPORT); + //#endif + int w = (int) polyUI.getMaster().getWidth(); + int h = (int) polyUI.getMaster().getHeight(); + int x = Platform.screen().windowWidth() / 2 - w / 2; + int y = Platform.screen().windowHeight() / 2 - h / 2; + glViewport(x, y, w, h); + polyUI.render(); + glViewport(VIEWPORT.get(), VIEWPORT.get(), VIEWPORT.get(), VIEWPORT.get()); } catch (Exception e) { polyUI.getRenderer().endFrame(); death(e); } - - float ratio = Platform.screen().pixelRatio(); - float scalingFactor = 1f / (float) OmniResolution.getScaleFactor(); - - float scaledX = (Platform.screen().viewportWidth() / 2f - master.getWidth() * ratio / 2f) * scalingFactor; - float scaledY = (Platform.screen().viewportHeight() / 2f - master.getHeight() * ratio / 2f) * scalingFactor; - float scaledWidth = master.getWidth() * scalingFactor * ratio; - float scaledHeight = master.getHeight() * scalingFactor * ratio; - - framebuffer.drawColorTexture( - UIManager.INSTANCE.getRenderPipeline(), - ctx.pose(), - scaledX, scaledY, - scaledWidth, scaledHeight, - OmniColors.WHITE - ); } @Override @@ -283,11 +272,6 @@ public void onScreenClose() { } protected final void adjustResolution(float w, float h, boolean force) { - if (this.framebuffer == null) { - int width = Platform.screen().viewportWidth(); - int height = Platform.screen().viewportHeight(); - this.framebuffer = new ManagedFramebuffer(width, height, OmniTextureFormat.RGBA8, OmniTextureFormat.DEPTH24_STENCIL8); - } // asm: normally, a polyui instance is as big as its window and that is it. // however, inside minecraft, the actual content is smaller than the window size, so resizing it directly would just fuck it up. @@ -307,7 +291,6 @@ protected final void adjustResolution(float w, float h, boolean force) { // framebuffer should you know probably be the correct larger size because.. well yeah of course it does // didn't anyone think of that? polyUI.resize(initialWidth * sx, initialHeight * sy, force); - framebuffer.resize((int) (polyUI.getMaster().getWidth() * ratio), (int) (polyUI.getMaster().getHeight() * ratio)); polyUI.getWindow().setPixelRatio(ratio); } catch (Exception e) { death(e); From 7ed6a9d74bd975be8c279d82c3d6e93cab606e45 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Sun, 30 Nov 2025 15:22:02 +0000 Subject: [PATCH 02/47] Reapply "it works!" This reverts commit 93a2d59035feb3c81dd912009de19d8965766549. --- .../api/ui/v1/internal/wrappers/PolyUIScreen.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java index f43950880..bc589927a 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java @@ -126,6 +126,10 @@ public void onRender(@NotNull OmniRenderingContext ctx, int mouseX, int mouseY, } try { + // asm: we need to bind the main framebuffer on 1.21.5+ because for some reason mc unbinds it right before... whatever + //#if MC >= 1.21.5 + //$$ kotlin.jvm.functions.Function0 unbind = dev.deftu.omnicore.api.client.framebuffer.OmniFramebuffers.getMain().bind(); + //#endif ((Buffer) VIEWPORT).clear(); //#if MC >= 1.13 //$$ glGetIntegerv(GL_VIEWPORT, VIEWPORT); @@ -139,6 +143,9 @@ public void onRender(@NotNull OmniRenderingContext ctx, int mouseX, int mouseY, glViewport(x, y, w, h); polyUI.render(); glViewport(VIEWPORT.get(), VIEWPORT.get(), VIEWPORT.get(), VIEWPORT.get()); + //#if MC >= 1.21.5 + //$$ unbind.invoke(); + //#endif } catch (Exception e) { polyUI.getRenderer().endFrame(); death(e); From c3d4efa7f57e2021daac8974c3b277bc30e29140 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Sun, 30 Nov 2025 21:30:09 +0000 Subject: [PATCH 03/47] polyui state v2 + GLRenderer fixes --- gradle/libs.versions.toml | 2 +- .../api/ui/v1/internal/UIManagerImpl.java | 4 +- .../ui/v1/internal/wrappers/PolyUIScreen.java | 9 +- .../oneconfig/api/config/v1/Visualizer.kt | 251 +++++++++--------- .../config/v1/internal/ConfigVisualizer.kt | 21 +- .../oneconfig/api/config/v1/Property.java | 29 +- .../oneconfig/api/event/v1/EventManager.java | 2 +- .../oneconfig/api/hud/v1/internal/hudpages.kt | 186 +++++++------ .../oneconfig/internal/ui/OneConfigUI.kt | 63 +++-- .../api/ui/v1/internal/GLRendererImpl.kt | 7 +- 10 files changed, 305 insertions(+), 269 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 56b81b393..2255ec277 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kotlinx-coroutines = "1.10.2" kotlinx-atomicfu = "0.29.0" fabric-language-kotlin = "1.13.5+kotlin.2.2.10" google-ksp = "2.2.10-2.0.2" -polyui = "1.15.2" +polyui = "2.0.4" annotations = "24.1.0" hypixel-modapi = "1.0.1" hypixel-data = "0.2.0" # Dep of hypixel-modapi diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java index 439d14db7..d4aa2029d 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java @@ -127,8 +127,8 @@ public UIManagerImpl() throws Throwable { tinyFD = Lwjgl3Manager.getIsolated(TinyFdApi.class, LWJGL_IMPL_PACKAGE + "TinyFdImpl"); //#endif - renderer = new NVGRendererImpl(isGl3, nanoVg, nanoSvg, stb); -// renderer = new GLRendererImpl(nanoSvg, stb); +// renderer = new NVGRendererImpl(isGl3, nanoVg, nanoSvg, stb); + renderer = new GLRendererImpl(nanoSvg, stb); } catch (Exception e) { throw new RuntimeException("Failed to get valid rendering implementation", e); } diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java index bc589927a..287c7b36a 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java @@ -136,10 +136,11 @@ public void onRender(@NotNull OmniRenderingContext ctx, int mouseX, int mouseY, //#else glGetInteger(GL_VIEWPORT, VIEWPORT); //#endif - int w = (int) polyUI.getMaster().getWidth(); - int h = (int) polyUI.getMaster().getHeight(); - int x = Platform.screen().windowWidth() / 2 - w / 2; - int y = Platform.screen().windowHeight() / 2 - h / 2; + float factor = Platform.screen().pixelRatio(); + int w = (int) (polyUI.getMaster().getWidth() * factor); + int h = (int) (polyUI.getMaster().getHeight() * factor); + int x = Platform.screen().viewportWidth() / 2 - w / 2; + int y = Platform.screen().viewportHeight() / 2 - h / 2; glViewport(x, y, w, h); polyUI.render(); glViewport(VIEWPORT.get(), VIEWPORT.get(), VIEWPORT.get(), VIEWPORT.get()); diff --git a/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/Visualizer.kt b/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/Visualizer.kt index fb75c589f..6a7e613ae 100644 --- a/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/Visualizer.kt +++ b/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/Visualizer.kt @@ -33,7 +33,6 @@ import org.polyfrost.polyui.color.asMutable import org.polyfrost.polyui.component.Drawable import org.polyfrost.polyui.component.extensions.* import org.polyfrost.polyui.component.impl.* -import org.polyfrost.polyui.event.Event import org.polyfrost.polyui.event.State import org.polyfrost.polyui.input.PolyBind import org.polyfrost.polyui.unit.Align @@ -41,15 +40,80 @@ import org.polyfrost.polyui.unit.Align.Wrap import org.polyfrost.polyui.unit.Vec2 import org.polyfrost.polyui.utils.image import org.polyfrost.polyui.utils.mapToArray +import org.polyfrost.polyui.utils.setNumber +import org.polyfrost.polyui.utils.toString +import java.lang.ref.WeakReference import java.util.function.Predicate import kotlin.math.roundToInt /** * Visualizers are procedures that take a property, and return a drawable that represents it. */ +@Suppress("UNCHECKED_CAST") fun interface Visualizer { fun visualize(prop: Property<*>): Drawable + fun Property.toState(): State { + val state = State(getAs()) + var dodge = false + + val stateRef = WeakReference(state) + var callback: Predicate? = null + callback = Predicate { + if (!dodge) { + dodge = true + val ret = stateRef.get()?.set(it) ?: run { + removeCallback(callback!!) + false + } + dodge = false + ret + } else false + } + addCallback(callback) + + state.weaklyListen(this) { + if (!dodge) { + dodge = true + setAs(it) + dodge = false + } + } + return state + } + + fun Property>.toEnumState(): State { + val state = State(get()?.ordinal ?: 0) + var dodge = false + + val stateRef = WeakReference(state) + var callback: Predicate>? = null + callback = Predicate> { + if (!dodge) { + val st = stateRef.get() + if (st == null) { + removeCallback(callback!!) + false + } else { + dodge = true + val ret = st.set(it.ordinal) + dodge = false + ret + } + } else false + } + addCallback(callback) + + state.weaklyListen(this) { + if (!dodge) { + dodge = true + setAs(this.type.enumConstants[it] as Enum<*>) + dodge = false + } + } + return state + } + class ButtonVisualizer : Visualizer { override fun visualize(prop: Property<*>): Drawable { val text = prop.getMetadata("text")?.strv() @@ -68,49 +132,39 @@ fun interface Visualizer { if (p !is PolyColor.Mutable) { prop.setAsReferential(p.asMutable()) } - val state = State(prop.getAs()) + prop as Property + val state = prop.toState() val out = Block(color = state.value, size = Vec2(58f, 32f)).withBorder(3f, color = { page.border20 }) out.onClick { ColorPicker(state, polyUI, attachedDrawable = out); true } - prop.addCallback { - state.value = (it as PolyColor).asMutable() - false - } return out } } class DropdownVisualizer : Visualizer { override fun visualize(prop: Property<*>): Drawable { - val options: Array = prop.getMetadata("options") ?: emptyArray() - if (prop.type.isEnum || prop.type.superclass?.isEnum == true) { - require(options.isEmpty()) { "Dropdowns should not have options when used with enums (offender=${prop.id})" } + val options = prop.getMetadata>("options") + return if (prop.type.isEnum || prop.type.superclass?.isEnum == true) { + require(options.isNullOrEmpty()) { "Dropdowns should not have options when used with enums (offender=${prop.id})" } val constants = if (prop.type.isEnum) prop.type.enumConstants else prop.type.superclass.enumConstants - val index = constants.indexOf(prop.get()) - val s = Dropdown( + prop as Property> + Dropdown( optPadding = 24f, - initial = index, + state = prop.toEnumState(), entries = constants.mapToArray { it as Enum<*> null to (it::class.java.fields[0].get(it) as? String ?: it.name) }, - ).onChange { i: Int -> - prop.setAs(constants[i]) - false - } - // todo setback not supported currently on dropdowns - return s + ) } else { require(prop.type == Int::class.java) { "Dropdowns can only be used with enums or integers (offender=${prop.id}, type=${prop.type})" } + require(options != null) { "Dropdown integer properties must have options specified in their metadata (offender=${prop.id})" } require(options.size >= 2) { "Dropdowns must have at least two options (offender=${prop.id})" } - val s = Dropdown( + prop as Property + Dropdown( optPadding = 24f, - initial = prop.getAs(), + state = prop.toState(), entries = options.mapToArray { null to it }, - ).onChange { i: Int -> - prop.setAs(i) - false - } - return s + ) } } } @@ -169,76 +223,48 @@ fun interface Visualizer { val unit = prop.getMetadata("unit") val min = prop.getMetadata("min") ?: 0f val max = prop.getMetadata("max") ?: 100f - val integral = prop.type == Int::class.java || prop.type == Long::class.java - val placeholder = prop.getMetadata("placeholder") ?: if (integral) "${min.toInt()}-${max.toInt()}" else "$min-$max" - var dodge = false + val placeholder = prop.getMetadata("placeholder") ?: "${min.toString(dps = 2)}-${max.toString(dps = 2)}" + prop as Property + val state = prop.toState() val s = BoxedTextInput( placeholder = placeholder, image = "assets/oneconfig/ico/text.svg".image(), size = Vec2(200f, 32f), - initialValue = prop.getAs().toString(), + value = state, post = unit - ).apply { - (this[1][0] as TextInput).numeric(min, max, integral).on(Event.Change.Number) { - dodge = true - prop.setAs(if (integral) it.amount.toInt() else it.amount.toFloat()) - } - } - prop.addCallback { - if (!dodge) (s[1][0] as TextInput).text = it.toString() - dodge = false - false - } + ) + s.getTextFromBoxedTextInput().numeric(min, max, state) return s } } class RadioVisualizer : Visualizer { override fun visualize(prop: Property<*>): Drawable { - val options: Array = prop.getMetadata("options") ?: emptyArray() - var dodge = false + val options: Array? = prop.getMetadata("options") if (prop.type.isEnum) { val values = prop.type.enumConstants var field = prop.type::class.java.fields.firstOrNull() if (field?.type == String::class.java) field = null - require(options.isEmpty()) { "Radio button ${prop.id} cannot have options when used with enums" } - val r = - Radiobutton( + require(options.isNullOrEmpty()) { "Radio button ${prop.id} cannot have options when used with enums" } + prop as Property> + return Radiobutton( entries = values.mapToArray { it as Enum<*> null to (field?.get(it) as? String ?: it.name) }, - initial = values.indexOf(prop.get()), + state = prop.toEnumState(), optionLateralPadding = 20f, - ).onChange { amount: Int -> - dodge = true - prop.setAs(values[amount]) - false - } - prop.addCallback { - if (!dodge) r.setRadiobuttonEntry(values.indexOf(it as Enum<*>)) - dodge = false - false - } - return r + ) } else { require(prop.type == Int::class.java) { "Radio buttons ${prop.id} can only be used with enum or integer types (type=${prop.type}" } + require(options != null) { "Radio button ${prop.id} integer properties must have options specified in their metadata" } require(options.size >= 2) { "Radio button ${prop.id} must have at least two options" } - val r = Radiobutton( + prop as Property + return Radiobutton( entries = options.mapToArray { null to it }, - initial = prop.getAs(), + state = prop.toState(), optionLateralPadding = 20f, - ).onChange { amount: Int -> - dodge = true - prop.setAs(amount) - false - } - prop.addCallback { - if (!dodge) r.setRadiobuttonEntry(it as Int) - dodge = false - false - } - return r + ) } } } @@ -249,75 +275,44 @@ fun interface Visualizer { val max = prop.getMetadata("max") ?: 100f val stepAmount = prop.getMetadata("step") ?: 0f val nsteps = if (stepAmount > 0f) ((max - min) / stepAmount).roundToInt() else 0 - var dodge = false - val value = prop.getAs().toFloat() - if (value.isNaN() || value.isInfinite()) { - println("Warning: Slider property ${prop.id} has invalid value $value, resetting to $min") - } + prop as Property + val state = prop.toState() - val initialValue = value.coerceIn(min, max) - // todo stepped - val s = - Slider( + val f = state.value.toFloat() + if (f.isNaN() || f.isInfinite()) { + println("Warning: Slider property ${prop.id} has invalid value $f, resetting to $min") + state.setNumber(min) + } else state.setNumber(f.coerceIn(min, max)) + + return Slider( min = min, max = max, length = 200f, steps = nsteps, - initialValue = initialValue, - integral = prop.type == Int::class.java || prop.type == Long::class.java, - ).onChange { amount: Float -> - dodge = true - if (prop.type == Int::class.java) prop.setAs(amount.toInt()) else prop.setAs(amount) - false - } - prop.addCallback { - if (!dodge) s.setSliderValue((it as Number).toFloat(), min, max, false) - dodge = false - false - } - return s + state = state + ) } } class SwitchVisualizer : Visualizer { override fun visualize(prop: Property<*>): Drawable { - val state = prop.getAs() - var dodge = false + prop as Property val s = Switch( lateralStretch = 2f, size = 21f, - state = state, - ).onChange { new: Boolean -> - dodge = true - prop.setAs(new) - false - } - prop.addCallback { - if (!dodge) s.toggle(it as Boolean) - dodge = false - false - } + state = prop.toState(), + ) return s } } class CheckboxVisualizer : Visualizer { override fun visualize(prop: Property<*>): Drawable { - val state = prop.getAs() - var dodge = false + prop as Property val s = Checkbox( size = 24f, - state = state, - ).onChange { new: Boolean -> - dodge = true - prop.setAs(new) - false - } - prop.addCallback { - if (!dodge) s.toggle(it as Boolean) - dodge = false - false - } + state = prop.toState(), + ) return s } } @@ -328,31 +323,23 @@ fun interface Visualizer { val regexString = prop.getMetadata("regex") val regex = regexString?.let { Regex(it) } val validate = prop.getMetadata>("validate") - var dodge = false + prop as Property + val state = prop.toState() val s = BoxedTextInput( image = "assets/oneconfig/ico/text.svg".image(), placeholder = placeholder, //size = Vec2(200f, 32f), - initialValue = prop.getAs(), - ).onChange { text: String -> + value = state, + ).onChange(state) { text: String -> if (validate != null && !validate.test(text)) { - shake() - return@onChange true + shake(); return@onChange true } if (regex != null && !regex.matches(text)) { - shake() - return@onChange true + shake(); return@onChange true } - dodge = true - prop.setAs(text) false } if (regexString != null) s.addHoverInfo(Text("Must match regex: $regexString")) - prop.addCallback { - if (!dodge) (s[1][0] as TextInput).text = it as String - dodge = false - false - } return s } } diff --git a/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt b/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt index 3ccb5836a..3beca1711 100644 --- a/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt +++ b/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt @@ -38,6 +38,7 @@ import org.polyfrost.polyui.component.extensions.* import org.polyfrost.polyui.component.impl.* import org.polyfrost.polyui.data.PolyImage import org.polyfrost.polyui.event.Event +import org.polyfrost.polyui.event.State import org.polyfrost.polyui.operations.Resize import org.polyfrost.polyui.operations.Rotate import org.polyfrost.polyui.unit.* @@ -261,43 +262,43 @@ open class ConfigVisualizer { wrapForAccordion(vis.visualize(node), node.title ?: return@map null, node.description).addHideHandler(node).addResetMenu(root, node).linkTo(node) } - var open = true + var open = State(true) val e: Property<*>? = tree.getProp("enabled") val toWrap: Drawable var enabled: Property? = null var contentHeight = -1f // asm: signature as it prevents re-wrapping of function val openInsn: Drawable.(Any?) -> Unit = { - open = !open + open.value = !open.value val arrow = if (enabled != null) this[1][1] else this[1] val anim = Animations.Default.create(0.6.seconds) - Rotate(arrow, if (!open) PI else 0.0, false, anim).add() + Rotate(arrow, if (!open.value) PI else 0.0, false, anim).add() val content = parent[1] if (contentHeight == -1f) contentHeight = content.height - Resize(parent, width = 0f, height = if (open) -contentHeight else contentHeight, add = true, animation = anim).add() - Resize(content, width = 0f, height = if (open) -contentHeight else contentHeight, add = true, animation = anim).add() + Resize(parent, width = 0f, height = if (open.value) -contentHeight else contentHeight, add = true, animation = anim).add() + Resize(content, width = 0f, height = if (open.value) -contentHeight else contentHeight, add = true, animation = anim).add() // won't ever open properly unless it renders at least once (tee hee) :) - if (!open) { + if (!open.value) { content.height = 1f content.renders = true } } if (e != null && e.type == Boolean::class.java && e.getVisualizer() == null) { - open = e.getAs() + open.value = e.getAs() toWrap = Group( Switch( lateralStretch = 2f, size = 21f, state = open - ).onToggle { + ).onChange(open) { enabled?.setAs(it) - if (open != it) (parent.parent as Drawable).openInsn(null) + if (open.value != it) (parent.parent as Drawable).openInsn(null) }, Image("polyui/chevron-down.svg").also { it.rotation = PI } ) // lmao - open = !open + open.value = !open.value @Suppress("UNCHECKED_CAST") // reason: #already-type-checked enabled = e as Property } else { diff --git a/modules/config/src/main/java/org/polyfrost/oneconfig/api/config/v1/Property.java b/modules/config/src/main/java/org/polyfrost/oneconfig/api/config/v1/Property.java index 3de52aedc..9b1be0b0e 100644 --- a/modules/config/src/main/java/org/polyfrost/oneconfig/api/config/v1/Property.java +++ b/modules/config/src/main/java/org/polyfrost/oneconfig/api/config/v1/Property.java @@ -179,6 +179,13 @@ public final Property addCallback(@NotNull Collection> callbacks return this; } + public final boolean removeCallback(@NotNull Predicate callback) { + if (callbacks != null) { + return callbacks.remove(callback); + } + return false; + } + @Override @SuppressWarnings({"unchecked", "rawtypes"}) public void overwrite(Node with, boolean preserveMissingOptions) { @@ -204,9 +211,9 @@ protected final void clearCallbacks() { *
* The value (and callbacks) are only set/called if the value is different from the previous value (using {@link Objects#equals(Object)}). */ - public final void set(@Nullable T value) { - if (Objects.equals(this.get(), value)) return; - setReferential(value); + public final boolean set(@Nullable T value) { + if (Objects.equals(this.get(), value)) return false; + return setReferential(value); } /** @@ -215,7 +222,7 @@ public final void set(@Nullable T value) { * Unlike {@link #set(Object)}, this will always set the value, regardless of if it is the same as the previous value. * Use this method with caution. */ - public void setReferential(@Nullable T value) { + public boolean setReferential(@Nullable T value) { if (callbacks != null) { T prev = get(); set0(value); @@ -224,13 +231,14 @@ public void setReferential(@Nullable T value) { if (p.test(value)) { LOGGER.info("property {} set cancelled by {}", this.getID(), p); set0(prev); - return; + return true; } } catch (Throwable t) { LOGGER.error("failed to call cancellable callback {} on property {}", p, this.getID(), t); } } } else set0(value); + return false; } protected abstract void set0(@Nullable T value); @@ -260,8 +268,8 @@ public final V getAs() { * This method is unsafe, and will throw a {@link ClassCastException} if the value is not of the correct type. */ @SuppressWarnings("unchecked") - public final void setAs(V value) { - set((T) WrappingUtils.richCast(value, type)); + public final boolean setAs(V value) { + return set((T) WrappingUtils.richCast(value, type)); } /** @@ -271,8 +279,8 @@ public final void setAs(V value) { * Use this method with caution. */ @SuppressWarnings("unchecked") - public final void setAsReferential(V value) { - setReferential((T) WrappingUtils.richCast(value, type)); + public final boolean setAsReferential(V value) { + return setReferential((T) WrappingUtils.richCast(value, type)); } /** @@ -440,7 +448,8 @@ static final class Dummy extends Property { @Override @Deprecated - public void setReferential(@Nullable Void value) { + public boolean setReferential(@Nullable Void value) { + return false; } @Override diff --git a/modules/events/src/main/java/org/polyfrost/oneconfig/api/event/v1/EventManager.java b/modules/events/src/main/java/org/polyfrost/oneconfig/api/event/v1/EventManager.java index 0a155bdce..03d830cbd 100644 --- a/modules/events/src/main/java/org/polyfrost/oneconfig/api/event/v1/EventManager.java +++ b/modules/events/src/main/java/org/polyfrost/oneconfig/api/event/v1/EventManager.java @@ -218,7 +218,7 @@ public void post(E event) { //noinspection StringConcatenationArgumentToLogCall LOGGER.error("Failed to invoke event handler for " + event.getClass().getName(), throwable); if (OmniLoader.isDevelopment()) { - throw new EventException("Event handler " + handler.getEventClass().getName() + " for " + handler.getEventClass().getName() + " failed", throwable); + throw new EventException("Event handler " + handler.getClass().getName() + " for " + handler.getEventClass().getName() + " failed", throwable); } if (handler.onError()) { LOGGER.error("removing {} registered to {} as it has failed too many times ({})", handler, event.getClass().getName(), EventHandler.ERROR_THRESHOLD); diff --git a/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/internal/hudpages.kt b/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/internal/hudpages.kt index 4372526b1..23e33cd20 100644 --- a/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/internal/hudpages.kt +++ b/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/internal/hudpages.kt @@ -49,7 +49,6 @@ import org.polyfrost.polyui.unit.seconds import org.polyfrost.polyui.utils.image import kotlin.experimental.or import kotlin.math.PI -import kotlin.math.roundToInt val alignC = Align(main = Align.Content.Center, cross = Align.Content.Center, line = Align.Line.Center) val alignNoPad = Align(pad = Vec2.ZERO) @@ -141,11 +140,13 @@ private fun HudButton(text: String): Block { } fun HudSettingsPage(hud: Hud<*>): Drawable { + val state = State(0) return Group( Radiobutton( "assets/oneconfig/ico/cog.svg".image() to "oneconfig.hudeditor.settings.title", "assets/oneconfig/ico/paintbrush.svg".image() to "oneconfig.hudeditor.designer.title", - ).onInit { color = polyUI.colors.component.bgDeselected }.onChange { index: Int -> + state = state + ).onInit { color = polyUI.colors.component.bgDeselected }.onChange(state) { index: Int -> if (index == 0) { parent[1] = HudVisualizer.get(hud.tree) } else { @@ -163,37 +164,53 @@ private fun makeHudDesigner(hud: Hud<*>): Drawable { val theHud = hud.get() val bg = hud.getBackground() val receiver = bg ?: theHud + + val padState = State(receiver.alignment.padBetween.x).listen { + receiver.alignment = receiver.alignment.copy(padBetween = Vec2(it, it)) + receiver.recalculate(false) + false + } + val radiusState = State((receiver as? Block)?.radii?.getOrNull(0) ?: 0f).listen { + (receiver as? Block)?.radius(it) + receiver.recalculate(false) + false + } + + val xPadState = State(receiver.padding.x).listen { + receiver.padding = receiver.padding.copy(x = it) + receiver.recalculate(false) + false + } + val yPadState = State(receiver.padding.y).listen { + receiver.padding = receiver.padding.copy(y = it) + receiver.recalculate(false) + false + } + val wPadState = State(receiver.padding.w).listen { + receiver.padding = receiver.padding.copy(w = it) + receiver.recalculate(false) + false + } + val hPadState = State(receiver.padding.h).listen { + receiver.padding = receiver.padding.copy(h = it) + receiver.recalculate(false) + false + } + + val staticWidth = State(false) + return Group( Text("oneconfig.hudeditor.general.title", fontSize = 16f).setFont { medium }, subheading("oneconfig.hudeditor.padding.title", "oneconfig.hudeditor.padding.info"), interactiveAlignment(receiver), Group( - DraggingNumericTextInput(icon = "assets/oneconfig/ico/align.svg".image(), suffix = "px", max = 30f, size = Vec2(120f, 32f)).also { - it[0].onChange { value: Float -> - receiver.alignment = receiver.alignment.copy(padBetween = Vec2(value, value)) - receiver.recalculate(false) - false - } - }.titled("oneconfig.hudeditor.padding.between"), - DraggingNumericTextInput(icon = "assets/oneconfig/ico/maximise.svg".image(), suffix = "px", max = 10f, size = Vec2(120f, 32f)).also { - it[0].onChange { value: Float -> - (receiver as? Block)?.radius(value) - false - } - }.titled("oneconfig.hudeditor.corner.radius"), + DraggingNumericTextInput(icon = "assets/oneconfig/ico/align.svg".image(), suffix = "px", max = 30f, size = Vec2(120f, 32f), state = padState).titled("oneconfig.hudeditor.padding.between"), + DraggingNumericTextInput(icon = "assets/oneconfig/ico/maximise.svg".image(), suffix = "px", max = 10f, size = Vec2(120f, 32f), state = radiusState).titled("oneconfig.hudeditor.corner.radius"), Group( - DraggingNumericTextInput(icon = "assets/oneconfig/ico/align.svg".image(), suffix = "px", initialValue = receiver.padding.x, max = 30f, size = Vec2(68f, 32f)).onChange { value: Float -> - receiver.padding = receiver.padding.copy(x = value) - }, - DraggingNumericTextInput(icon = "assets/oneconfig/ico/align.svg".image(), suffix = "px", initialValue = receiver.padding.y, max = 30f, size = Vec2(68f, 32f)).onChange { value: Float -> - receiver.padding = receiver.padding.copy(y = value) - }.also { it[0].rotation = PI / 2 }, - DraggingNumericTextInput(icon = "assets/oneconfig/ico/align.svg".image(), suffix = "px", initialValue = receiver.padding.w, max = 30f, size = Vec2(68f, 32f)).onChange { value: Float -> - receiver.padding = receiver.padding.copy(w = value) - }.also { it[0].rotation = PI }, - DraggingNumericTextInput(icon = "assets/oneconfig/ico/align.svg".image(), suffix = "px", initialValue = receiver.padding.h, max = 30f, size = Vec2(68f, 32f)).onChange { value: Float -> - receiver.padding = receiver.padding.copy(h = value) - }.also { it[0].rotation = PI * 1.5 }, + DraggingNumericTextInput(icon = "assets/oneconfig/ico/align.svg".image(), suffix = "px", state = xPadState, max = 30f, size = Vec2(68f, 32f)), + DraggingNumericTextInput(icon = "assets/oneconfig/ico/align.svg".image(), suffix = "px", state = yPadState, max = 30f, size = Vec2(68f, 32f)).also { it[0].rotation = PI / 2 }, + DraggingNumericTextInput(icon = "assets/oneconfig/ico/align.svg".image(), suffix = "px", state = wPadState, max = 30f, size = Vec2(68f, 32f)).also { it[0].rotation = PI }, + DraggingNumericTextInput(icon = "assets/oneconfig/ico/align.svg".image(), suffix = "px", state = hPadState, max = 30f, size = Vec2(68f, 32f)).also { it[0].rotation = PI * 1.5 }, alignment = Align(main = Align.Content.SpaceBetween, wrap = Align.Wrap.NEVER, padEdges = Vec2.ZERO), size = Vec2(308f, 32f) ).titled("oneconfig.hudeditor.padding.edges"),//.padded(16f, 12f, 0f, 0f), @@ -201,15 +218,15 @@ private fun makeHudDesigner(hud: Hud<*>): Drawable { size = Vec2(320f, 126f), ), Group( - Checkbox(size = 18f).onToggle { + Checkbox(size = 18f, state = staticWidth).onChange(staticWidth) { hud.staticWidth = it val siblings = siblings siblings[2].isEnabled = !it siblings[3].isEnabled = !it }, Text("oneconfig.hudeditor.staticwidth"), - DraggingNumericTextInput(pre = "oneconfig.width", suffix = "px", initialValue = receiver.width.roundToInt().toFloat(), max = 1000f, size = Vec2(128f, 32f)), - DraggingNumericTextInput(pre = "oneconfig.height", suffix = "px", initialValue = receiver.height.roundToInt().toFloat(), max = 1000f, size = Vec2(128f, 32f)), + DraggingNumericTextInput(pre = "oneconfig.width", suffix = "px", state = State.of(receiver::width), max = 1000f, size = Vec2(128f, 32f)), + DraggingNumericTextInput(pre = "oneconfig.height", suffix = "px", state = State.of(receiver::height), max = 1000f, size = Vec2(128f, 32f)), alignment = Align(padBetween = Vec2(12f, 6f)) ), *(if (bg != null) colorOptions(bg) else arrayOf()), @@ -316,68 +333,81 @@ fun interactiveAlignment(recv: Drawable): Block { fun textOptions(text: Text): Drawable { var prevWeight: Font.Weight = Font.Weight.Regular + var example: Text? = null + + val fontState = State(0).listen { + text.font = when (it) { + 1 -> PolyUI.monospaceFont + 2 -> mcFont.get(text.fontWeight, text.italic) + else -> text.polyUI.fonts.get(text.fontWeight, text.italic) + } + text._parent?.recalculate(false) + example?.run { + font = text.font + parent.recalculate() + } + false + } + val fontSize = State(text.fontSize).listen { + text.fontSize = it + text._parent?.recalculate(false) + example?.run { + fontSize = text.fontSize + parent.recalculate() + } + false + } + + val fontWeight = State(text.fontWeight.value / 100 - 1).listen { + text.fontWeight = Font.byWeight((it + 1) * 100) + text._parent?.recalculate(false) + example?.run { + fontWeight = text.fontWeight + parent.recalculate() + } + false + } + + val boldState = State(text.fontWeight.value > 500).listen { + if (it) { + prevWeight = text.fontWeight + text.fontWeight = when (text.fontWeight) { + Font.Weight.Thin, Font.Weight.ExtraLight, Font.Weight.Light -> Font.Weight.SemiBold + Font.Weight.Regular -> Font.Weight.Bold + Font.Weight.Medium -> Font.Weight.ExtraBold + else -> text.fontWeight + } + } else { + text.fontWeight = prevWeight + } + false + } + return Group( subheading("oneconfig.hudeditor.text.title", "oneconfig.hudeditor.text.info"), Block( - Text("oneconfig.hudeditor.text.example", fontSize = 16f), + Text("oneconfig.hudeditor.text.example", fontSize = 16f).also { example = it }, size = Vec2(476f, 58f), alignment = alignC, ).withBorder(), Dropdown( - "Poppins", "JetBrains Mono", "Minecraft" - ).onChange { it: Int -> - text.font = when (it) { - 1 -> PolyUI.monospaceFont - 2 -> mcFont.get(text.fontWeight, text.italic) - else -> polyUI.fonts.get(text.fontWeight, text.italic) - } - text._parent?.recalculate(false) - val ex = (parent.parent[1][0] as? Text) ?: return@onChange false - ex.font = text.font - ex.parent.recalculate() - false - }.titled("oneconfig.hudeditor.text.font"), - DraggingNumericTextInput("assets/oneconfig/ico/text-input.svg".image(), initialValue = text.fontSize.roundToInt().toFloat(), min = 1f, size = Vec2(72f, 0f), suffix = "px").also { - it[0].onChange { value: Float -> - text.fontSize = value - text._parent?.recalculate(false) - val ex = (parent.parent.parent[1][0] as? Text) ?: return@onChange false - ex.fontSize = text.fontSize - ex.parent.recalculate() - false - } - }.titled("oneconfig.hudeditor.text.size"), + "Poppins", "JetBrains Mono", "Minecraft", + state = fontState + ).titled("oneconfig.hudeditor.text.font"), + DraggingNumericTextInput("assets/oneconfig/ico/text-input.svg".image(), state = fontSize, min = 1f, size = Vec2(72f, 0f), suffix = "px").titled("oneconfig.hudeditor.text.size"), Dropdown( "oneconfig.fweight.100", "oneconfig.fweight.200", "oneconfig.fweight.300", "oneconfig.fweight.400", "oneconfig.fweight.500", - ).onChange { it: Int -> - text.fontWeight = Font.byWeight((it + 1) * 100) - text._parent?.recalculate(false) - val ex = (parent.parent[1][0] as? Text) ?: return@onChange false - ex.fontWeight = text.fontWeight - ex.parent.recalculate() - false - }.titled("oneconfig.hudeditor.text.weight"), + state = fontWeight, + ).titled("oneconfig.hudeditor.text.weight"), Group( - Block(Image("assets/oneconfig/ico/bold.svg"), alignment = alignNoPad).radius(2f).toggleable(text.fontWeight.value > 500).onToggle { - if (it) { - prevWeight = text.fontWeight - text.fontWeight = when (text.fontWeight) { - Font.Weight.Thin, Font.Weight.ExtraLight, Font.Weight.Light -> Font.Weight.SemiBold - Font.Weight.Regular -> Font.Weight.Bold - Font.Weight.Medium -> Font.Weight.ExtraBold - else -> text.fontWeight - } - } else { - text.fontWeight = prevWeight - } - }, - Block(Image("assets/oneconfig/ico/italic.svg"), alignment = alignNoPad).radius(2f).toggleable(text.italic).onToggle { text.italic = it }, - Block(Image("assets/oneconfig/ico/underline.svg"), alignment = alignNoPad).radius(2f).toggleable(text.underline).onToggle { text.underline = it }, - Block(Image("assets/oneconfig/ico/strikethrough.svg"), alignment = alignNoPad).radius(2f).toggleable(text.strikethrough).onToggle { text.strikethrough = it }, + Block(Image("assets/oneconfig/ico/bold.svg"), alignment = alignNoPad).radius(2f).toggleable(boldState), + Block(Image("assets/oneconfig/ico/italic.svg"), alignment = alignNoPad).radius(2f).toggleable(State.of(text::italic)), + Block(Image("assets/oneconfig/ico/underline.svg"), alignment = alignNoPad).radius(2f).toggleable(State.of(text::underline)), + Block(Image("assets/oneconfig/ico/strikethrough.svg"), alignment = alignNoPad).radius(2f).toggleable(State.of(text::strikethrough)), ).titled("oneconfig.hudeditor.text.effects"), *colorOptions(text), size = Vec2(476f, 0f), diff --git a/modules/internal/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/OneConfigUI.kt b/modules/internal/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/OneConfigUI.kt index f54945347..f33e66275 100644 --- a/modules/internal/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/OneConfigUI.kt +++ b/modules/internal/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/OneConfigUI.kt @@ -25,6 +25,7 @@ */ @file:JvmName("OneConfigUI") +@file:Suppress("FunctionName") package org.polyfrost.oneconfig.internal.ui @@ -55,6 +56,7 @@ import org.polyfrost.polyui.data.Cursor import org.polyfrost.polyui.data.Font import org.polyfrost.polyui.data.PolyImage import org.polyfrost.polyui.event.Event +import org.polyfrost.polyui.event.State import org.polyfrost.polyui.operations.Move import org.polyfrost.polyui.operations.Recolor import org.polyfrost.polyui.unit.Align @@ -132,6 +134,32 @@ object OneConfigUI { } if (!OmniLoader.isDevelopment) builder.pauses() + val searchState = State("").listen { text: String -> + if (text.length > 2) { + if(current?.name != "oneconfig.search") { + val search = Group(children = ConfigVisualizer.INSTANCE.getMatching(text).toTypedArray(), visibleSize = Vec2(1130f, 635f)).named("oneconfig.search") + if (search.children.isNullOrEmpty()) search.addChild(searchNoneFound, recalculate = false) + openPage(search, SetAnimation.Fade) + } else { + val search = current as Group + search.children?.clear() + ConfigVisualizer.INSTANCE.getMatching(text).fastEach { + search.addChild(it, recalculate = false) + } + if (search.children.isNullOrEmpty()) search.addChild(searchNoneFound, recalculate = false) + // search.at = search.screenAt + search.recalculate(false) + search.resetScroll() + search.visibleSize = Vec2(1130f, 635f).rescaleToPolyUIInstance(search.polyUI) + search.clipChildren() + } + } else { + openPage(ModsPage(collectTrees()), SetAnimation.Fade) + } + + false + } + val (polyUI, win) = builder.makeAndOpenWithRef( Block( Block( @@ -210,31 +238,8 @@ object OneConfigUI { TextInput( placeholder = "oneconfig.search.placeholder", visibleSize = Vec2(210f, 12f), - ).onChange { text: String -> - if (text.length > 2) { - if(current?.name != "oneconfig.search") { - val search = Group(children = ConfigVisualizer.INSTANCE.getMatching(text).toTypedArray(), visibleSize = Vec2(1130f, 635f)).named("oneconfig.search") - if (search.children.isNullOrEmpty()) search.addChild(searchNoneFound, recalculate = false) - openPage(search, SetAnimation.Fade) - } else { - val search = current as Group - search.children?.clear() - ConfigVisualizer.INSTANCE.getMatching(text).fastEach { - search.addChild(it, recalculate = false) - } - if (search.children.isNullOrEmpty()) search.addChild(searchNoneFound, recalculate = false) - // search.at = search.screenAt - search.recalculate(false) - search.resetScroll() - search.visibleSize = Vec2(1130f, 635f).rescaleToPolyUIInstance(polyUI) - search.clipChildren() - } - } else { - openPage(ModsPage(collectTrees()), SetAnimation.Fade) - } - - false - }, + text = searchState, + ), size = Vec2(256f, 32f), alignment = Align(pad = Vec2(10f, 8f)), ).withBorder(1f) { page.border5 }.named("SearchField").onRightClick { @@ -293,9 +298,11 @@ object OneConfigUI { prevArrow?.disable(false) } current = page - val translated = ui.polyUI.translator.translate(page.name) - val title = ui[1][0][0][2] as Text - title._text = translated + // todo expose _theText or do this in a better way +// val translated = ui.polyUI.translator.translate(page.name) +// val title = ui[1][0][0][2] as Text +// @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "UnstableApiUsage") +// title._theText = translated val prev = ui[1][1] ui[1].set(prev, page, animation) } diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 2e1571a83..f42e6e333 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -597,7 +597,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (count >= MAX_BATCH) { flush() } - val glyph = fAtlas.get(c) + val glyph = fAtlas.get(c) ?: continue buffer.put(penX + glyph.xOff * scaleFactor).put(penY + glyph.yOff * scaleFactor) .put(glyph.width * scaleFactor).put(glyph.height * scaleFactor) buffer.put(EMPTY_ROW) // zero radii @@ -1006,7 +1006,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re // var height = 0f val scaleFactor = fontSize / this.renderedSize for (c in text) { - width += get(c).xAdvance * scaleFactor + val g = get(c) ?: continue + width += g.xAdvance * scaleFactor // height = maxOf(height, g.height + g.offsetY) } return Vec2.of(width, fontSize) @@ -1014,7 +1015,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re @Suppress("DEPRECATION") @kotlin.internal.InlineOnly - inline fun get(char: Char) = glyphs[(char.toInt() - 32) /* .coerceIn(0, glyphs.size - 1) */] + inline fun get(char: Char) = if (char.toInt() in 32..32+95) glyphs[(char.toInt() - 32)] else null } @kotlin.internal.InlineOnly From 7ef695f2943ac71726d5c2b3e11c1ca8182beadf Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Mon, 1 Dec 2025 12:08:39 +0000 Subject: [PATCH 04/47] getting there! --- gradle/libs.versions.toml | 2 +- .../api/ui/v1/internal/UIManagerImpl.java | 11 ++++-- .../oneconfig/internal/OneConfig.java | 18 +++++++-- .../oneconfig/api/ui/v1/UIManager.java | 13 +++++-- .../oneconfig/api/ui/v1/api/RendererExt.java | 5 +++ .../oneconfig/api/ui/v1/api/StbApi.java | 10 ++--- .../api/ui/v1/internal/GLRendererImpl.kt | 38 ++++++++++--------- .../oneconfig/api/ui/v1/internal/StbImpl.kt | 10 ++--- 8 files changed, 67 insertions(+), 40 deletions(-) create mode 100644 modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/RendererExt.java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2255ec277..3b391217d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kotlinx-coroutines = "1.10.2" kotlinx-atomicfu = "0.29.0" fabric-language-kotlin = "1.13.5+kotlin.2.2.10" google-ksp = "2.2.10-2.0.2" -polyui = "2.0.4" +polyui = "2.0.5" annotations = "24.1.0" hypixel-modapi = "1.0.1" hypixel-data = "0.2.0" # Dep of hypixel-modapi diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java index d4aa2029d..eaa539c46 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java @@ -47,11 +47,9 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.polyfrost.oneconfig.api.ClassHasOverwrites; -import org.polyfrost.oneconfig.api.ui.v1.api.NanoSvgApi; -import org.polyfrost.oneconfig.api.ui.v1.api.NanoVgApi; -import org.polyfrost.oneconfig.api.ui.v1.api.StbApi; -import org.polyfrost.oneconfig.api.ui.v1.api.TinyFdApi; +import org.polyfrost.oneconfig.api.ui.v1.api.*; import org.polyfrost.oneconfig.api.ui.v1.UIManager; import org.polyfrost.oneconfig.api.ui.v1.internal.wrappers.MCWindow; import org.polyfrost.oneconfig.api.ui.v1.internal.wrappers.PolyUIScreen; @@ -134,6 +132,11 @@ public UIManagerImpl() throws Throwable { } } + @Override + public @Nullable RendererExt getRendererExt() { + return (renderer instanceof RendererExt ? (RendererExt) renderer : null); + } + @Override public Renderer getRenderer() { return renderer; diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java index 2b91497f8..e8d04780e 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java @@ -53,6 +53,7 @@ import org.polyfrost.oneconfig.api.hypixel.v1.HypixelUtils; import org.polyfrost.oneconfig.api.platform.v1.Platform; import org.polyfrost.oneconfig.api.ui.v1.UIManager; +import org.polyfrost.oneconfig.api.ui.v1.api.RendererExt; import org.polyfrost.oneconfig.api.ui.v1.internal.BlurHandler; import org.polyfrost.oneconfig.api.ui.v1.keybind.OCKeybindHelper; import org.polyfrost.oneconfig.internal.ui.OneConfigUI; @@ -132,8 +133,8 @@ private void init() { if (Boolean.getBoolean("oneconfig.test")) { try { TestMod_Test.initialize(); - } catch (Throwable ignored) { - ignored.printStackTrace(); + } catch (Throwable e) { + e.printStackTrace(); } } @@ -155,7 +156,7 @@ private void init() { LOGGER.info("OneConfig initialization took {}ms", (System.nanoTime() - t1) / 1_000_000.0); } - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({"unchecked", "rawtypes", "UnstableApiUsage"}) private static void registerCommands() { ClientCommandInternals.initialize(); // //#if MC > 1.16 @@ -201,7 +202,16 @@ private static void registerCommands() { return ctx.getSource().replyChat("OK"); }) ) - .build(); + .then(OmniClientCommands.literal("dumpAtlas") + .executes((ctx) -> { + RendererExt ext = UIManager.INSTANCE.getRendererExt(); + if (ext == null) { + return ctx.getSource().replyChat("RendererExt is not available on this platform."); + } + ext.dumpAtlas(); + return ctx.getSource().replyChat("OK"); + }) + ).build(); OmniClientCommands.register(node); OmniClientCommands.register(OmniClientCommands.literal("ocfg").executes(executor).redirect(node)); } diff --git a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java index 265ddf2aa..77f941472 100644 --- a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java +++ b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java @@ -47,10 +47,10 @@ import org.polyfrost.oneconfig.api.event.v1.EventDelay; import org.polyfrost.oneconfig.api.event.v1.EventManager; import org.polyfrost.oneconfig.api.event.v1.events.HudRenderEvent; -import org.polyfrost.oneconfig.api.event.v1.events.RenderEvent; import org.polyfrost.oneconfig.api.event.v1.events.ResizeEvent; import org.polyfrost.oneconfig.api.event.v1.events.WorldEvent; import org.polyfrost.oneconfig.api.platform.v1.Platform; +import org.polyfrost.oneconfig.api.ui.v1.api.RendererExt; import org.polyfrost.oneconfig.api.ui.v1.api.TinyFdApi; import org.polyfrost.polyui.PolyUI; import org.polyfrost.polyui.Settings; @@ -76,6 +76,12 @@ public interface UIManager { */ Renderer getRenderer(); + /** + * Return the renderer extension instance. This interface specifies additional (debug) operations for the renderer. + */ + @Nullable + RendererExt getRendererExt(); + /** * Return the TinyFD implementation instance. This interface specifies operations for opening native * file dialogs, and showing notifications. @@ -157,9 +163,8 @@ default PolyUI createDefault() { }); }; - EventManager.register(RenderEvent.Post.class, event -> { - renderer.accept(event.ctx); - }); + // todo temporary reversion: on RenderEvent it just renders nothing (see #592, #579) + EventManager.register(HudRenderEvent.class, event -> renderer.accept(event.ctx)); EventManager.register(ResizeEvent.class, event -> { float ratio = Platform.screen().pixelRatio(); diff --git a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/RendererExt.java b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/RendererExt.java new file mode 100644 index 000000000..f4812bc91 --- /dev/null +++ b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/RendererExt.java @@ -0,0 +1,5 @@ +package org.polyfrost.oneconfig.api.ui.v1.api; + +public interface RendererExt { + void dumpAtlas(); +} diff --git a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java index 838d65894..29443a217 100644 --- a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java +++ b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java @@ -12,15 +12,15 @@ public interface StbApi { void image_write_png(String filename, int w, int h, int comp, ByteBuffer data, int strideInBytes); - long createFontInfo(); + long font_CreateFontInfo(); - long createPackRange(); + long font_CreatePackRange(); - long createPackedCharArray(int capacity); + long font_CreatePackedCharArray(int capacity); - long createPackContext(); + long font_CreatePackContext(); - boolean initFont(long info, ByteBuffer data); + boolean font_InitFont(long info, ByteBuffer data); float font_ScaleForMappingEmToPixels(long info, float pixels); diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index f42e6e333..e4b778841 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -9,6 +9,7 @@ import org.lwjgl.opengl.GL14.* import org.lwjgl.opengl.GL15.* import org.lwjgl.opengl.GL20.* import org.polyfrost.oneconfig.api.ui.v1.api.NanoSvgApi +import org.polyfrost.oneconfig.api.ui.v1.api.RendererExt import org.polyfrost.oneconfig.api.ui.v1.api.StbApi import org.polyfrost.polyui.PolyUI import org.polyfrost.polyui.color.Color @@ -42,10 +43,9 @@ private val EMPTY_ROW = floatArrayOf(0f, 0f, 0f, 0f) private val NO_UV = floatArrayOf(-1f, -1f, 1f, 1f) @Suppress("UnstableApiUsage", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") -class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Renderer { +class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Renderer, RendererExt { private val buffer = BufferUtils.createFloatBuffer(MAX_BATCH * STRIDE) - private val transformBuffer = BufferUtils.createFloatBuffer(9) private val scissorStack = IntArray(MAX_UI_DEPTH * 4) private val transformStack = ArrayList(MAX_UI_DEPTH) private val fonts = HashMap() @@ -81,11 +81,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re 0f, 1f, 0f, 0f, 0f, 1f ) - set(value) { - field = value - transformBuffer.clear() - transformBuffer.put(value).flip() - } private var viewportWidth = 0f private var viewportHeight = 0f private var pixelRatio = 1f @@ -284,8 +279,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re @Suppress("SameParameterValue") - private fun glUniformMatrix3fv(location: Int, transpose: Boolean, buf: FloatBuffer) { - ShaderInternals.uniformMatrix3(location, transpose, buf) + private fun glUniformMatrix3fv(location: Int, transpose: Boolean, array: FloatArray) { + ShaderInternals.uniformMatrix3(location, transpose, array) } override fun init() { @@ -387,7 +382,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val prevProg = glGetInteger(GL_CURRENT_PROGRAM) glUseProgram(program) glUniform2f(uWindow, width, height) - glUniformMatrix3fv(uTransform, false, transformBuffer) + glUniformMatrix3fv(uTransform, false, transform) glUseProgram(prevProg) glDisable(GL_SCISSOR_TEST) viewportWidth = width * pixelRatio @@ -430,7 +425,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glUseProgram(program) if (popFlushNeeded) { - glUniformMatrix3fv(uTransform, false, transformBuffer) + glUniformMatrix3fv(uTransform, false, transform) popFlushNeeded = false } @@ -851,19 +846,25 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } } + private var i = 0 fun dumpTexture(texId: Int = atlas) { val buf = BufferUtils.createByteBuffer(ATLAS_SIZE * ATLAS_SIZE * 4) glBindTexture(GL_TEXTURE_2D, texId) glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf) glBindTexture(GL_TEXTURE_2D, 0) stb.image_write_png( - "debug_texture$texId.png", + "debug_texture$texId($i).png", ATLAS_SIZE, ATLAS_SIZE, 4, buf, ATLAS_SIZE * 4 ) + i++ + } + + override fun dumpAtlas() { + dumpTexture(atlas) } override fun cleanup() { @@ -891,8 +892,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val lineGap: Float init { - val fontInfo = stb.createFontInfo() - if (!stb.initFont(fontInfo, data)) { + val stb = stb + val fontInfo = stb.font_CreateFontInfo() + if (!stb.font_InitFont(fontInfo, data)) { throw IllegalStateException("Failed to initialize font") } val scale = stb.font_ScaleForMappingEmToPixels(fontInfo, renderedSize) @@ -906,15 +908,15 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re descent = des[0] * scale lineGap = gap[0] * scale - val range = stb.createPackRange() + val range = stb.font_CreatePackRange() stb.font_RangeSetFontSize(range, renderedSize) stb.font_RangeSetFirstUnicodeCodepointInRange(range, 32) stb.font_RangeSetNumChars(range, 95) - val packed = stb.createPackedCharArray(95) + val packed = stb.font_CreatePackedCharArray(95) stb.font_RangeSetChardata(range, packed) val bitMap = BufferUtils.createByteBuffer(FONT_MAX_BITMAP_W * FONT_MAX_BITMAP_H) - val pack = stb.createPackContext() + val pack = stb.font_CreatePackContext() if (!stb.font_PackBegin(pack, bitMap, FONT_MAX_BITMAP_W, FONT_MAX_BITMAP_H, 0, 1, 0L)) { throw IllegalStateException("Failed to initialize font packer") } @@ -974,6 +976,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re stb.free(packed) stb.free(range) +// dumpAtlas() + val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) glBindTexture(GL_TEXTURE_2D, atlas) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt index a37379759..a3a698224 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt @@ -27,15 +27,15 @@ class StbImpl : StbApi { STBImageWrite.stbi_write_png(filename, w, h, comp, data, strideInBytes) } - override fun createFontInfo() = STBTTFontinfo.malloc().address() + override fun font_CreateFontInfo() = STBTTFontinfo.malloc().address() - override fun createPackRange() = STBTTPackRange.malloc().address() + override fun font_CreatePackRange() = STBTTPackRange.malloc().address() - override fun createPackedCharArray(capacity: Int) = STBTTPackedchar.malloc(capacity).address() + override fun font_CreatePackedCharArray(capacity: Int) = STBTTPackedchar.malloc(capacity).address() - override fun createPackContext() = STBTTPackContext.malloc().address() + override fun font_CreatePackContext() = STBTTPackContext.malloc().address() - override fun initFont(info: Long, data: ByteBuffer) = nstbtt_InitFont(info, MemoryUtil.memAddress(data), 0) != 0 + override fun font_InitFont(info: Long, data: ByteBuffer) = nstbtt_InitFont(info, MemoryUtil.memAddress(data), 0) != 0 override fun font_ScaleForMappingEmToPixels(info: Long, pixels: Float) = nstbtt_ScaleForMappingEmToPixels(info, pixels) From 80316fc46e8a351adbab6c92096251b5743ae77b Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Mon, 1 Dec 2025 21:20:40 +0000 Subject: [PATCH 05/47] fixed GLRenderer yay --- .../api/ui/v1/internal/GLRendererImpl.kt | 84 +++++++++++-------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index e4b778841..f03f80c6f 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -86,6 +86,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private var pixelRatio = 1f private var alphaCap = 1f private var popFlushNeeded = false + private val init get() = program != 0 private var slotX = 0 private var slotY = 0 @@ -284,6 +285,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } override fun init() { + if (init) return // check if instancing extension is available require(GlCapabilities.isGl21Available) { "At least OpenGL 2.1 is required" } if (!GlCapabilities.isGl33Available) { // asm: skip check, both are core past 3.3 @@ -398,6 +400,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private fun flush() { if (count == 0) return buffer.flip() + val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) val prevProg = glGetInteger(GL_CURRENT_PROGRAM) val prevBuf = glGetInteger(GL_ARRAY_BUFFER_BINDING) @@ -459,6 +462,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (prevDepth) glEnable(GL_DEPTH_TEST) if (prevCull) glEnable(GL_CULL_FACE) glUseProgram(prevProg) + glActiveTexture(prevActive) glBindTexture(GL_TEXTURE_2D, prevTex) glBindBuffer(GL_ARRAY_BUFFER, prevBuf) if (GlCapabilities.isGl3Available) org.lwjgl.opengl.GL30.glBindVertexArray(prevVao) @@ -598,7 +602,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re buffer.put(EMPTY_ROW) // zero radii buffer.put(r).put(g).put(b).put(a) buffer.put(EMPTY_ROW) // color1 unused - buffer.put(glyph.u).put(glyph.v).put(glyph.uw).put(glyph.vh) + buffer.put(glyph, 0, 4) buffer.put(-1f) // thickness = -1 for text penX += glyph.xAdvance * scaleFactor count += 1 @@ -796,18 +800,23 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re h[0] / ATLAS_SIZE.toFloat() ) - val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - glBindTexture(GL_TEXTURE_2D, atlas) - glPixelStorei(GL_UNPACK_ALIGNMENT, 1) - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) - glTexSubImage2D(GL_TEXTURE_2D, 0, slotX, slotY, w[0], h[0], GL_RGBA, GL_UNSIGNED_BYTE, d) - when (mipmapMode) { - 1 -> org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D) - 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) + synchronized(this) { + val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) + val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) + glActiveTexture(GL_TEXTURE0) + glBindTexture(GL_TEXTURE_2D, atlas) + glPixelStorei(GL_UNPACK_ALIGNMENT, 1) + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) + glTexSubImage2D(GL_TEXTURE_2D, 0, slotX, slotY, w[0], h[0], GL_RGBA, GL_UNSIGNED_BYTE, d) + when (mipmapMode) { + 1 -> org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D) + 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) + } + glBindTexture(GL_TEXTURE_2D, prevTex) + glActiveTexture(prevActive) } - glBindTexture(GL_TEXTURE_2D, prevTex) if (image.type == PolyImage.Type.Raster) stb.image_free(d) slotX += w[0] @@ -976,30 +985,33 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re stb.free(packed) stb.free(range) -// dumpAtlas() - - val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - glBindTexture(GL_TEXTURE_2D, atlas) - glPixelStorei(GL_UNPACK_ALIGNMENT, 1) - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) - // can't write to the alpha channel in GL3 core! lol haha - glTexSubImage2D( - GL_TEXTURE_2D, - 0, - sx, - sy, - FONT_MAX_BITMAP_W, - FONT_MAX_BITMAP_H, - GL_RED, - GL_UNSIGNED_BYTE, - bitMap - ) - glBindTexture(GL_TEXTURE_2D, prevTex) - when (mipmapMode) { - 1 -> org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D) - 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) + synchronized(this@GLRendererImpl) { + val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) + val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) + glActiveTexture(GL_TEXTURE0) + glBindTexture(GL_TEXTURE_2D, atlas) + glPixelStorei(GL_UNPACK_ALIGNMENT, 1) + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) + // can't write to the alpha channel in GL3 core! lol haha + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + sx, + sy, + FONT_MAX_BITMAP_W, + FONT_MAX_BITMAP_H, + GL_RED, + GL_UNSIGNED_BYTE, + bitMap + ) + when (mipmapMode) { + 1 -> org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D) + 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) + } + glBindTexture(GL_TEXTURE_2D, prevTex) + glActiveTexture(prevActive) } slotX += totalSizeX atlasRowHeight = maxOf(atlasRowHeight, totalSizeY) From 0bebd02e4e0b507ffa91a333ca7b0853849a3f02 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:04:12 +0000 Subject: [PATCH 06/47] port fixes --- .../api/ui/v1/internal/GLRendererImpl.kt | 184 ++++++++++-------- 1 file changed, 99 insertions(+), 85 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index f03f80c6f..07e411d52 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -1,3 +1,5 @@ +@file:Suppress("UnstableApiUsage", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + package org.polyfrost.oneconfig.api.ui.v1.internal import dev.deftu.omnicore.api.client.render.GlCapabilities @@ -41,14 +43,36 @@ private const val MAX_BATCH = 1024 private val EMPTY_ROW = floatArrayOf(0f, 0f, 0f, 0f) private val NO_UV = floatArrayOf(-1f, -1f, 1f, 1f) +private val IDENTITY = floatArrayOf( + 1f, 0f, 0f, + 0f, 1f, 0f, + 0f, 0f, 1f +) + +private fun FloatArray.isIdentity(): Boolean { + return this[0] == 1f && this[1] == 0f && this[2] == 0f && + this[3] == 0f && this[4] == 1f && this[5] == 0f && + this[6] == 0f && this[7] == 0f && this[8] == 1f +} + +@kotlin.internal.InlineOnly +private inline fun FloatArray.set(other: FloatArray) { + System.arraycopy(other, 0, this, 0, 9) +} + +@kotlin.internal.InlineOnly +private inline fun FloatArray.setThenClear(other: FloatArray) { + System.arraycopy(other, 0, this, 0, 9) + System.arraycopy(IDENTITY, 0, other, 0, 9) +} -@Suppress("UnstableApiUsage", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Renderer, RendererExt { private val buffer = BufferUtils.createFloatBuffer(MAX_BATCH * STRIDE) private val scissorStack = IntArray(MAX_UI_DEPTH * 4) - private val transformStack = ArrayList(MAX_UI_DEPTH) + private val transformStack = Array(MAX_UI_DEPTH) { FloatArray(9) } private val fonts = HashMap() + private val init get() = program != 0 // lateinit private var mipmapMode = 0 @@ -75,6 +99,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re // Current batch state private var count = 0 private var curTex = 0 + private var transformDepth = 0 private var curScissor = 0 private var transform = floatArrayOf( 1f, 0f, 0f, @@ -86,7 +111,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private var pixelRatio = 1f private var alphaCap = 1f private var popFlushNeeded = false - private val init get() = program != 0 private var slotX = 0 private var slotY = 0 @@ -128,14 +152,19 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re float rRight = mix(r.z, r.y, py); // bottom-right / top-right float radius = mix(rLeft, rRight, px); - vec2 d = abs(p) - b + vec2(radius); - vec2 dClamped = max(d, vec2(0.0)); - return length(dClamped) - radius + min(max(d.x, d.y), 0.0); + vec2 q = abs(p) - (b - vec2(radius)); + return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius; } float hollowRoundedBoxSDF(vec2 p, vec2 b, vec4 r, float thickness) { - float dist = roundedBoxSDF(p, b, r); - return abs(dist) - thickness * 0.5; + float outer = roundedBoxSDF(p, b + vec2(0.2), r); + float inner = roundedBoxSDF(p, b - vec2(thickness), max(r - vec4(thickness), 0.0)); + return max(outer, -inner); + } + + float roundBoxSDF(vec2 p, vec2 halfSize, float radius) { + vec2 q = abs(p) - (halfSize - vec2(radius)); + return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius; } void main() { @@ -152,20 +181,19 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re col = (vThickness == -1.0) ? vec4(col.rgb, col.a * texColor.r) : col * texColor; } else if (vThickness == -2.0) { // linear gradient, vUV as start and vUV2 as end - vec2 dir = normalize(vUV2 - vUV); - float t = dot((p + halfSize) - vUV, dir) / length(vUV2 - vUV); - t = clamp(t, 0.0, 1.0); + vec2 dir = vUV2 - vUV; + float len = length(dir); + float t = clamp(dot((p + halfSize) - vUV, dir / len) / len, 0.0, 1.0); col = mix(vColor0, vColor1, t); } else if (vThickness == -3.0) { // radial gradient, vUV as center and vUV2.x as radius float dist = length(p + halfSize - vUV); - float t = (dist - vUV2.x) / (vUV2.y - vUV2.x); - t = clamp(t, 0.0, 1.0); + float t = clamp((dist - vUV2.x) / (vUV2.y - vUV2.x), 0.0, 1.0); col = mix(vColor0, vColor1, t); } else if (vThickness == -4.0) { // box gradient, vUV.x as radius and vUV.y as feather - float dist = roundedBoxSDF(p, halfSize - vec2(vUV.x), vec4(vUV.x)); - float t = clamp(dist / vUV.y, 0.0, 1.0); + float dist = roundBoxSDF(p, halfSize, vUV.x); + float t = clamp((dist + vUV.y * 0.5) / vUV.y, 0.0, 1.0); col = mix(vColor0, vColor1, t); } @@ -380,7 +408,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re alphaCap = 1f count = 0 buffer.clear() - loadIdentity() + transform.set(IDENTITY) + transformDepth = 0 val prevProg = glGetInteger(GL_CURRENT_PROGRAM) glUseProgram(program) glUniform2f(uWindow, width, height) @@ -596,7 +625,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (count >= MAX_BATCH) { flush() } - val glyph = fAtlas.get(c) ?: continue + val glyph = fAtlas.get(c) buffer.put(penX + glyph.xOff * scaleFactor).put(penY + glyph.yOff * scaleFactor) .put(glyph.width * scaleFactor).put(glyph.height * scaleFactor) buffer.put(EMPTY_ROW) // zero radii @@ -697,15 +726,17 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re override fun push() { if (transform.isIdentity()) return - transformStack.add(transform.copyOf()) + transformStack[transformDepth++].set(transform) } override fun pop() { if (transform.isIdentity()) return flush() - if (transformStack.isEmpty()) { - loadIdentity() - } else transform = transformStack.removeLast() + if (transformDepth == 0) { + transform.set(IDENTITY) + } else { + transform.setThenClear(transformStack[--transformDepth]) + } popFlushNeeded = true } @@ -763,20 +794,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re popFlushNeeded = true } - private fun FloatArray.isIdentity(): Boolean { - return this[0] == 1f && this[1] == 0f && this[2] == 0f && - this[3] == 0f && this[4] == 1f && this[5] == 0f && - this[6] == 0f && this[7] == 0f && this[8] == 1f - } - - private fun loadIdentity() { - val transform = transform - transform[0] = 1f; transform[1] = 0f; transform[2] = 0f - transform[3] = 0f; transform[4] = 1f; transform[5] = 0f - transform[6] = 0f; transform[7] = 0f; transform[8] = 1f - this.transform = transform - } - override fun initImage(image: PolyImage, size: Vec2) { if (image.initialized) return val w = IntArray(1) @@ -800,27 +817,26 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re h[0] / ATLAS_SIZE.toFloat() ) - synchronized(this) { - val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) - val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - glActiveTexture(GL_TEXTURE0) - glBindTexture(GL_TEXTURE_2D, atlas) - glPixelStorei(GL_UNPACK_ALIGNMENT, 1) - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) - glTexSubImage2D(GL_TEXTURE_2D, 0, slotX, slotY, w[0], h[0], GL_RGBA, GL_UNSIGNED_BYTE, d) - when (mipmapMode) { - 1 -> org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D) - 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) - } - glBindTexture(GL_TEXTURE_2D, prevTex) - glActiveTexture(prevActive) + val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) + val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) + glActiveTexture(GL_TEXTURE0) + glBindTexture(GL_TEXTURE_2D, atlas) + glPixelStorei(GL_UNPACK_ALIGNMENT, 1) + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) + glTexSubImage2D(GL_TEXTURE_2D, 0, slotX, slotY, w[0], h[0], GL_RGBA, GL_UNSIGNED_BYTE, d) + when (mipmapMode) { + 1 -> org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D) + 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) } + glBindTexture(GL_TEXTURE_2D, prevTex) + glActiveTexture(prevActive) + if (image.type == PolyImage.Type.Raster) stb.image_free(d) - slotX += w[0] - if (h[0] > atlasRowHeight) atlasRowHeight = h[0] + slotX += w[0] + 1 + if (h[0] + 1 > atlasRowHeight) atlasRowHeight = h[0] + 1 image.reportInit() } @@ -882,7 +898,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (quadVbo != 0) glDeleteBuffers(quadVbo) if (instancedVbo != 0) glDeleteBuffers(instancedVbo) if (atlas != 0) glDeleteTextures(atlas) - transformStack.clear() fonts.clear() buffer.clear() } @@ -985,36 +1000,35 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re stb.free(packed) stb.free(range) - synchronized(this@GLRendererImpl) { - val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) - val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - glActiveTexture(GL_TEXTURE0) - glBindTexture(GL_TEXTURE_2D, atlas) - glPixelStorei(GL_UNPACK_ALIGNMENT, 1) - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) - // can't write to the alpha channel in GL3 core! lol haha - glTexSubImage2D( - GL_TEXTURE_2D, - 0, - sx, - sy, - FONT_MAX_BITMAP_W, - FONT_MAX_BITMAP_H, - GL_RED, - GL_UNSIGNED_BYTE, - bitMap - ) - when (mipmapMode) { - 1 -> org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D) - 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) - } - glBindTexture(GL_TEXTURE_2D, prevTex) - glActiveTexture(prevActive) + val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) + val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) + glActiveTexture(GL_TEXTURE0) + glBindTexture(GL_TEXTURE_2D, atlas) + glPixelStorei(GL_UNPACK_ALIGNMENT, 1) + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) + // can't write to the alpha channel in GL3 core! lol haha + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + sx, + sy, + FONT_MAX_BITMAP_W, + FONT_MAX_BITMAP_H, + GL_RED, + GL_UNSIGNED_BYTE, + bitMap + ) + when (mipmapMode) { + 1 -> org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D) + 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) } - slotX += totalSizeX - atlasRowHeight = maxOf(atlasRowHeight, totalSizeY) + glBindTexture(GL_TEXTURE_2D, prevTex) + glActiveTexture(prevActive) + + slotX += totalSizeX + 1 + atlasRowHeight = maxOf(atlasRowHeight, totalSizeY + 1) } fun measure(text: String, fontSize: Float): Vec2 { @@ -1022,7 +1036,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re // var height = 0f val scaleFactor = fontSize / this.renderedSize for (c in text) { - val g = get(c) ?: continue + val g = get(c) width += g.xAdvance * scaleFactor // height = maxOf(height, g.height + g.offsetY) } @@ -1031,7 +1045,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re @Suppress("DEPRECATION") @kotlin.internal.InlineOnly - inline fun get(char: Char) = if (char.toInt() in 32..32+95) glyphs[(char.toInt() - 32)] else null + inline fun get(char: Char) = if (char.toInt() in 32..32 + 95) glyphs[(char.toInt() - 32)] else glyphs['?'.toInt()] } @kotlin.internal.InlineOnly From 34824546ea84c2a6109297a53b875269779ca016 Mon Sep 17 00:00:00 2001 From: Wyvest Date: Thu, 4 Dec 2025 05:29:29 -0500 Subject: [PATCH 07/47] Fix 1.8 errors --- .../api/ui/v1/internal/GLRendererImpl.kt | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 07e411d52..cbfea5e2e 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -7,6 +7,7 @@ import dev.deftu.omnicore.internal.client.render.shader.ShaderInternals import org.apache.logging.log4j.LogManager import org.lwjgl.BufferUtils import org.lwjgl.opengl.GL11.* +import org.lwjgl.opengl.GL13 import org.lwjgl.opengl.GL14.* import org.lwjgl.opengl.GL15.* import org.lwjgl.opengl.GL20.* @@ -24,6 +25,7 @@ import org.polyfrost.polyui.unit.Vec4 import org.polyfrost.polyui.utils.toDirectByteBuffer import org.polyfrost.polyui.utils.toDirectByteBufferNT import java.nio.ByteBuffer +import java.nio.ByteOrder import java.nio.FloatBuffer import kotlin.math.cos import kotlin.math.roundToInt @@ -309,7 +311,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re @Suppress("SameParameterValue") private fun glUniformMatrix3fv(location: Int, transpose: Boolean, array: FloatArray) { - ShaderInternals.uniformMatrix3(location, transpose, array) + val buffer = ByteBuffer.allocateDirect(array.size * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(array) + buffer.flip() + ShaderInternals.uniformMatrix3(location, transpose, buffer) } override fun init() { @@ -461,7 +465,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re popFlushNeeded = false } - glActiveTexture(GL_TEXTURE0) + @Suppress("RemoveRedundantQualifierName") + GL13.glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, curTex) // Quad attrib @@ -491,7 +496,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (prevDepth) glEnable(GL_DEPTH_TEST) if (prevCull) glEnable(GL_CULL_FACE) glUseProgram(prevProg) - glActiveTexture(prevActive) + @Suppress("RemoveRedundantQualifierName") + GL13.glActiveTexture(prevActive) glBindTexture(GL_TEXTURE_2D, prevTex) glBindBuffer(GL_ARRAY_BUFFER, prevBuf) if (GlCapabilities.isGl3Available) org.lwjgl.opengl.GL30.glBindVertexArray(prevVao) @@ -819,7 +825,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - glActiveTexture(GL_TEXTURE0) + @Suppress("RemoveRedundantQualifierName") + GL13.glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, atlas) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) @@ -831,7 +838,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) } glBindTexture(GL_TEXTURE_2D, prevTex) - glActiveTexture(prevActive) + @Suppress("RemoveRedundantQualifierName") + GL13.glActiveTexture(prevActive) if (image.type == PolyImage.Type.Raster) stb.image_free(d) @@ -1002,7 +1010,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - glActiveTexture(GL_TEXTURE0) + @Suppress("RemoveRedundantQualifierName") + GL13.glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, atlas) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) @@ -1025,7 +1034,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) } glBindTexture(GL_TEXTURE_2D, prevTex) - glActiveTexture(prevActive) + @Suppress("RemoveRedundantQualifierName") + GL13.glActiveTexture(prevActive) slotX += totalSizeX + 1 atlasRowHeight = maxOf(atlasRowHeight, totalSizeY + 1) From a1865d9f2e368fa8c99b58e4b0ceb503c9cd0db5 Mon Sep 17 00:00:00 2001 From: Wyvest Date: Thu, 4 Dec 2025 05:37:45 -0500 Subject: [PATCH 08/47] Disable blur everywhere --- .../oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java index 287c7b36a..9fc70937b 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java @@ -85,7 +85,7 @@ public PolyUIScreen(@NotNull PolyUI polyUI, float designedWidth, float designedH this.designedHeight = designedHeight; this.initialWidth = polyUI.getMaster().getWidth(); this.initialHeight = polyUI.getMaster().getHeight(); - this.blurs = blurs; + this.blurs = false; //todo fix blur this.pauses = pauses; this.close = onClose; //#if MC <= 1.12.2 @@ -239,7 +239,7 @@ public boolean isPausingScreen() { @Override public boolean hasBackgroundBlur() { - return blurs; + return false; } From 4c4c05206bd81395c5f821d2a3179bcf07c66080 Mon Sep 17 00:00:00 2001 From: Wyvest Date: Thu, 4 Dec 2025 06:04:35 -0500 Subject: [PATCH 09/47] bump textile and apiDump --- gradle/libs.versions.toml | 2 +- modules/config-impl/api/config-impl.api | 33 +++++++++++++++++++++++++ modules/config/api/config.api | 9 ++++--- modules/ui/api/ui.api | 15 +++++++---- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3b391217d..f1ad67825 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,7 @@ copycat = "0.1.3" copycat-image-awt = "0.1.1" # Per version -textile = "1.0.0-beta.8" +textile = "1.0.0-beta.9" omnicore = "1.0.0-beta.38" lwjgl = "3.3.3" # All downloaded by the isolated-lwjgl3-loader diff --git a/modules/config-impl/api/config-impl.api b/modules/config-impl/api/config-impl.api index 91e6cc320..9d0db0d00 100644 --- a/modules/config-impl/api/config-impl.api +++ b/modules/config-impl/api/config-impl.api @@ -102,74 +102,107 @@ protected final class org/polyfrost/oneconfig/api/config/v1/KtConfig$Provider : } public abstract interface class org/polyfrost/oneconfig/api/config/v1/Visualizer { + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public abstract fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$ButtonVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$CheckboxVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$ColorVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } +public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$DefaultImpls { + public static fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Visualizer;Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public static fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Visualizer;Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; +} + public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$DraggableListVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public synthetic fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/impl/Group; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$DropdownVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$InfoVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public synthetic fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/impl/Group; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$KeybindVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$MultiSelectDropdownVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public synthetic fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/impl/Group; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$NumberVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$RadioVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$SliderVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$SwitchVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } public final class org/polyfrost/oneconfig/api/config/v1/Visualizer$TextVisualizer : org/polyfrost/oneconfig/api/config/v1/Visualizer { public fun ()V + public fun toEnumState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; + public fun toState (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/event/State; public fun visualize (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/polyui/component/Drawable; } diff --git a/modules/config/api/config.api b/modules/config/api/config.api index fef4b2884..f543a39f1 100644 --- a/modules/config/api/config.api +++ b/modules/config/api/config.api @@ -72,12 +72,13 @@ public abstract class org/polyfrost/oneconfig/api/config/v1/Property : org/polyf public fun onDisplayChange (Ljava/util/function/Consumer;)V public fun overwrite (Lorg/polyfrost/oneconfig/api/config/v1/Node;Z)V public static fun recast (Lorg/polyfrost/oneconfig/api/config/v1/Property;)Lorg/polyfrost/oneconfig/api/config/v1/Property; + public final fun removeCallback (Ljava/util/function/Predicate;)Z public fun revaluateDisplay ()V - public final fun set (Ljava/lang/Object;)V + public final fun set (Ljava/lang/Object;)Z protected abstract fun set0 (Ljava/lang/Object;)V - public final fun setAs (Ljava/lang/Object;)V - public final fun setAsReferential (Ljava/lang/Object;)V - public fun setReferential (Ljava/lang/Object;)V + public final fun setAs (Ljava/lang/Object;)Z + public final fun setAsReferential (Ljava/lang/Object;)Z + public fun setReferential (Ljava/lang/Object;)Z public final fun toString ()Ljava/lang/String; } diff --git a/modules/ui/api/ui.api b/modules/ui/api/ui.api index 3e5e9ed9f..69e139b94 100644 --- a/modules/ui/api/ui.api +++ b/modules/ui/api/ui.api @@ -43,6 +43,7 @@ public abstract interface class org/polyfrost/oneconfig/api/ui/v1/UIManager { public abstract fun getDefaultInstance ()Lorg/polyfrost/polyui/PolyUI; public abstract fun getRenderPipeline ()Ldev/deftu/omnicore/api/client/render/pipeline/OmniRenderPipeline; public abstract fun getRenderer ()Lorg/polyfrost/polyui/renderer/Renderer; + public abstract fun getRendererExt ()Lorg/polyfrost/oneconfig/api/ui/v1/api/RendererExt; public abstract fun getTinyFD ()Lorg/polyfrost/oneconfig/api/ui/v1/api/TinyFdApi; } @@ -118,13 +119,18 @@ public abstract interface class org/polyfrost/oneconfig/api/ui/v1/api/NanoVgApi$ public abstract fun NVG_ROUND ()I } +public abstract interface class org/polyfrost/oneconfig/api/ui/v1/api/RendererExt { + public abstract fun dumpAtlas ()V +} + public abstract interface class org/polyfrost/oneconfig/api/ui/v1/api/StbApi { - public abstract fun createFontInfo ()J - public abstract fun createPackContext ()J - public abstract fun createPackRange ()J - public abstract fun createPackedCharArray (I)J + public abstract fun font_CreateFontInfo ()J + public abstract fun font_CreatePackContext ()J + public abstract fun font_CreatePackRange ()J + public abstract fun font_CreatePackedCharArray (I)J public abstract fun font_GetFontVMetrics (J[I[I[I)V public abstract fun font_GetPackedGlyph (JI)J + public abstract fun font_InitFont (JLjava/nio/ByteBuffer;)Z public abstract fun font_PackBegin (JLjava/nio/ByteBuffer;IIIIJ)Z public abstract fun font_PackEnd (J)V public abstract fun font_PackFontRange (JLjava/nio/ByteBuffer;IFIIJ)Z @@ -145,7 +151,6 @@ public abstract interface class org/polyfrost/oneconfig/api/ui/v1/api/StbApi { public abstract fun image_free (Ljava/nio/ByteBuffer;)V public abstract fun image_load_from_memory (Ljava/nio/ByteBuffer;[I[I[II)Ljava/nio/ByteBuffer; public abstract fun image_write_png (Ljava/lang/String;IIILjava/nio/ByteBuffer;I)V - public abstract fun initFont (JLjava/nio/ByteBuffer;)Z } public abstract interface class org/polyfrost/oneconfig/api/ui/v1/api/TinyFdApi { From 70e39170c39e553fc44bd102fb602abca34f063e Mon Sep 17 00:00:00 2001 From: Wyvest Date: Thu, 4 Dec 2025 07:11:07 -0500 Subject: [PATCH 10/47] add more disclaimers in TinyFD usage --- .../oneconfig/api/ui/v1/api/TinyFdApi.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/TinyFdApi.java b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/TinyFdApi.java index 06807735d..4a567f30d 100644 --- a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/TinyFdApi.java +++ b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/TinyFdApi.java @@ -53,11 +53,17 @@ public interface TinyFdApi { /** * Open a save file selection prompt. * Same as {@link #openFileSelector(String, String, String[], String)} but says save instead of open. + *

+ * On Linux, TinyFD "allows shell metacharacters in titles, messages, and other input data," meaning that it is vulnerable to command injection. + * **Treat all user input as untrusted and sanitize it before passing it to TinyFD.** */ Path openSaveSelector(@Nullable String title, @Nullable String defaultFilePath, String[] filterPatterns, @Nullable String filterDescription); /** * Open a file selection prompt. + *

+ * On Linux, TinyFD "allows shell metacharacters in titles, messages, and other input data," meaning that it is vulnerable to command injection. + * **Treat all user input as untrusted and sanitize it before passing it to TinyFD.** * * @param title the title of the prompt * @param defaultFilePath the path to the default file to select @@ -71,17 +77,26 @@ public interface TinyFdApi { /** * Open a multi file selection prompt. * Same as {@link #openFileSelector(String, String, String[], String)} but allows the user to select multiple files. + *

+ * On Linux, TinyFD "allows shell metacharacters in titles, messages, and other input data," meaning that it is vulnerable to command injection. + * **Treat all user input as untrusted and sanitize it before passing it to TinyFD.** */ Path[] openMultiFileSelector(@Nullable String title, @Nullable String defaultFilePath, String[] filterPatterns, @Nullable String filterDescription); /** * Open a folder selection prompt. * Same as {@link #openFileSelector(String, String, String[], String)} but allows the user to select a folder. + *

+ * On Linux, TinyFD "allows shell metacharacters in titles, messages, and other input data," meaning that it is vulnerable to command injection. + * **Treat all user input as untrusted and sanitize it before passing it to TinyFD.** */ Path openFolderSelector(@Nullable String title, @Nullable String defaultFolderPath); /** * Shows a message box. + *

+ * On Linux, TinyFD "allows shell metacharacters in titles, messages, and other input data," meaning that it is vulnerable to command injection. + * **Treat all user input as untrusted and sanitize it before passing it to TinyFD.** * * @param message the message. may contain \n and \t * @param dialog the type of message box to show.
One of: {@link #OK_DIALOG}, {@link #OK_CANCEL_DIALOG}, {@link #YES_NO_DIALOG}, {@link #YES_NO_CANCEL_DIALOG} @@ -93,6 +108,9 @@ public interface TinyFdApi { /** * Shows a notification. + *

+ * On Linux, TinyFD "allows shell metacharacters in titles, messages, and other input data," meaning that it is vulnerable to command injection. + * **Treat all user input as untrusted and sanitize it before passing it to TinyFD.** * * @param icon the icon to use. One of: {@link #QUESTION_ICON}, {@link #ERROR_ICON}, {@link #WARNING_ICON}, {@link #INFO_ICON} * @return 0 if the user clicked the "ok" button, 1 for "cancel" From 89304bdb4d4a9e79dd02dd641e514e4a58be7afd Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:28:58 +0000 Subject: [PATCH 11/47] cleanup and improve font rendering --- .../api/ui/v1/internal/GLRendererImpl.kt | 66 ++++++++----------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index cbfea5e2e..5737b2c5d 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -7,7 +7,7 @@ import dev.deftu.omnicore.internal.client.render.shader.ShaderInternals import org.apache.logging.log4j.LogManager import org.lwjgl.BufferUtils import org.lwjgl.opengl.GL11.* -import org.lwjgl.opengl.GL13 +import org.lwjgl.opengl.GL13.* import org.lwjgl.opengl.GL14.* import org.lwjgl.opengl.GL15.* import org.lwjgl.opengl.GL20.* @@ -25,7 +25,6 @@ import org.polyfrost.polyui.unit.Vec4 import org.polyfrost.polyui.utils.toDirectByteBuffer import org.polyfrost.polyui.utils.toDirectByteBufferNT import java.nio.ByteBuffer -import java.nio.ByteOrder import java.nio.FloatBuffer import kotlin.math.cos import kotlin.math.roundToInt @@ -35,10 +34,9 @@ import kotlin.math.tan private val LOGGER = LogManager.getLogger("PolyUI/GLRenderer") private const val MAX_UI_DEPTH = 16 -private const val FONT_MAX_BITMAP_W = 1024 +private const val FONT_MAX_BITMAP_W = 1536 private const val FONT_MAX_BITMAP_H = 512 private const val ATLAS_SIZE = 2048 -private const val FONT_RENDER_SIZE = 24f // 48f scales nicely to 16f, 12f, 32f, etc. private const val ATLAS_SVG_UPSCALE_FACTOR = 2f private const val STRIDE = 4 + 4 + 4 + 4 + 4 + 1 // bounds, radii, color0, color1, UV, thick private const val MAX_BATCH = 1024 @@ -73,7 +71,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private val buffer = BufferUtils.createFloatBuffer(MAX_BATCH * STRIDE) private val scissorStack = IntArray(MAX_UI_DEPTH * 4) private val transformStack = Array(MAX_UI_DEPTH) { FloatArray(9) } - private val fonts = HashMap() + private val transformBuffer = BufferUtils.createFloatBuffer(9) + private val fonts = HashMap() private val init get() = program != 0 // lateinit @@ -103,11 +102,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private var curTex = 0 private var transformDepth = 0 private var curScissor = 0 - private var transform = floatArrayOf( - 1f, 0f, 0f, - 0f, 1f, 0f, - 0f, 0f, 1f - ) + private var transform = IDENTITY.copyOf() private var viewportWidth = 0f private var viewportHeight = 0f private var pixelRatio = 1f @@ -311,9 +306,10 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re @Suppress("SameParameterValue") private fun glUniformMatrix3fv(location: Int, transpose: Boolean, array: FloatArray) { - val buffer = ByteBuffer.allocateDirect(array.size * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(array) - buffer.flip() - ShaderInternals.uniformMatrix3(location, transpose, buffer) + val buf = transformBuffer + buf.clear() + buf.put(array).flip() + ShaderInternals.uniformMatrix3(location, transpose, buf) } override fun init() { @@ -465,8 +461,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re popFlushNeeded = false } - @Suppress("RemoveRedundantQualifierName") - GL13.glActiveTexture(GL_TEXTURE0) + glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, curTex) // Quad attrib @@ -496,8 +491,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (prevDepth) glEnable(GL_DEPTH_TEST) if (prevCull) glEnable(GL_CULL_FACE) glUseProgram(prevProg) - @Suppress("RemoveRedundantQualifierName") - GL13.glActiveTexture(prevActive) + glActiveTexture(prevActive) glBindTexture(GL_TEXTURE_2D, prevTex) glBindBuffer(GL_ARRAY_BUFFER, prevBuf) if (GlCapabilities.isGl3Available) org.lwjgl.opengl.GL30.glBindVertexArray(prevVao) @@ -613,7 +607,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } override fun text(font: Font, x: Float, y: Float, text: String, color: Color, fontSize: Float) { - val fAtlas = getFontAtlas(font) + val fAtlas = getFontAtlas(font, fontSize) if (count >= MAX_BATCH) flush() if (count > 0 && curTex != atlas) flush() curTex = atlas @@ -645,7 +639,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } override fun textBounds(font: Font, text: String, fontSize: Float): Vec2 { - return getFontAtlas(font).measure(text, fontSize) + return getFontAtlas(font, fontSize).measure(text, fontSize) } override fun line(x1: Float, y1: Float, x2: Float, y2: Float, color: Color, width: Float) { @@ -825,8 +819,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - @Suppress("RemoveRedundantQualifierName") - GL13.glActiveTexture(GL_TEXTURE0) + glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, atlas) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) @@ -838,8 +831,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) } glBindTexture(GL_TEXTURE_2D, prevTex) - @Suppress("RemoveRedundantQualifierName") - GL13.glActiveTexture(prevActive) + glActiveTexture(prevActive) if (image.type == PolyImage.Type.Raster) stb.image_free(d) @@ -868,25 +860,29 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } } - private fun getFontAtlas(font: Font): FontAtlas { - return fonts.getOrPut(font) { + private fun getFontAtlas(font: Font, fontSize: Float): FontAtlas { + val renderSize = when(fontSize) { + in 0f..36f -> 24f + else -> 48f + } + return fonts.getOrPut(font.resourcePath.hashCode() + renderSize.toInt()) { val data = font.load { LOGGER.error("Failed to load font: $font", it) - return@getOrPut fonts[PolyUI.defaultFonts.regular] + return@getOrPut fonts[PolyUI.defaultFonts.regular.resourcePath.hashCode() + renderSize.toInt()] ?: throw IllegalStateException("Default font couldn't be loaded") }.toDirectByteBuffer() - FontAtlas(data, FONT_RENDER_SIZE) + FontAtlas(data, renderSize) } } private var i = 0 - fun dumpTexture(texId: Int = atlas) { + override fun dumpAtlas() { val buf = BufferUtils.createByteBuffer(ATLAS_SIZE * ATLAS_SIZE * 4) - glBindTexture(GL_TEXTURE_2D, texId) + glBindTexture(GL_TEXTURE_2D, atlas) glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf) glBindTexture(GL_TEXTURE_2D, 0) stb.image_write_png( - "debug_texture$texId($i).png", + "debug_atlas$i.png", ATLAS_SIZE, ATLAS_SIZE, 4, @@ -896,10 +892,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re i++ } - override fun dumpAtlas() { - dumpTexture(atlas) - } - override fun cleanup() { // dumpAtlas() if (program != 0) glDeleteProgram(program) @@ -1010,8 +1002,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - @Suppress("RemoveRedundantQualifierName") - GL13.glActiveTexture(GL_TEXTURE0) + glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, atlas) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) @@ -1034,8 +1025,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) } glBindTexture(GL_TEXTURE_2D, prevTex) - @Suppress("RemoveRedundantQualifierName") - GL13.glActiveTexture(prevActive) + glActiveTexture(prevActive) slotX += totalSizeX + 1 atlasRowHeight = maxOf(atlasRowHeight, totalSizeY + 1) From ca97ebb8d87c7a6c40f53c36e93f38e9547e8e98 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Sun, 7 Dec 2025 15:47:55 +0000 Subject: [PATCH 12/47] drop shadow, improve font rendering when scale is used --- .../api/ui/v1/internal/GLRendererImpl.kt | 82 ++++++++++++------- 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 5737b2c5d..6dc12e0ff 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -29,6 +29,7 @@ import java.nio.FloatBuffer import kotlin.math.cos import kotlin.math.roundToInt import kotlin.math.sin +import kotlin.math.sqrt import kotlin.math.tan private val LOGGER = LogManager.getLogger("PolyUI/GLRenderer") @@ -101,7 +102,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private var count = 0 private var curTex = 0 private var transformDepth = 0 - private var curScissor = 0 + private var scissorDepth = 0 private var transform = IDENTITY.copyOf() private var viewportWidth = 0f private var viewportHeight = 0f @@ -109,10 +110,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private var alphaCap = 1f private var popFlushNeeded = false + // atlas data private var slotX = 0 private var slotY = 0 - - /** current max height of the currently active row in the atlas. */ private var atlasRowHeight = 0 private val FRAG = """ @@ -149,24 +149,24 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re float rRight = mix(r.z, r.y, py); // bottom-right / top-right float radius = mix(rLeft, rRight, px); - vec2 q = abs(p) - (b - vec2(radius)); + vec2 q = abs(p) - (b - radius); return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius; } float hollowRoundedBoxSDF(vec2 p, vec2 b, vec4 r, float thickness) { - float outer = roundedBoxSDF(p, b + vec2(0.2), r); - float inner = roundedBoxSDF(p, b - vec2(thickness), max(r - vec4(thickness), 0.0)); + float outer = roundedBoxSDF(p, b + 0.2, r + 0.2); + float inner = roundedBoxSDF(p, b - thickness, max(r - thickness, 0.0)); return max(outer, -inner); } float roundBoxSDF(vec2 p, vec2 halfSize, float radius) { - vec2 q = abs(p) - (halfSize - vec2(radius)); + vec2 q = abs(p) - (halfSize - radius); return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius; } void main() { - vec2 center = vRect.xy + 0.5 * vRect.zw; vec2 halfSize = 0.5 * vRect.zw; + vec2 center = vRect.xy + halfSize; vec2 p = vPos - center; float d = (vThickness > 0.0) ? hollowRoundedBoxSDF(p, halfSize, vRadii, vThickness) : roundedBoxSDF(p, halfSize, vRadii); @@ -193,6 +193,10 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re float t = clamp((dist + vUV.y * 0.5) / vUV.y, 0.0, 1.0); col = mix(vColor0, vColor1, t); } + else if (vThickness == -5.0) { // drop shadow, vUV.x as spread and vUV.y as blur + float dShadow = roundBoxSDF(p, halfSize + vUV.x, vRadii.x); + col = vec4(vColor0.rgb, vColor0.a * (1.0 - smoothstep(-vUV.y, vUV.y, dShadow))); + } // Proper antialiasing based on distance field float f = fwidth(d); @@ -404,11 +408,12 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } override fun beginFrame(width: Float, height: Float, pixelRatio: Float) { - curScissor = 0 + scissorDepth = 0 alphaCap = 1f count = 0 buffer.clear() transform.set(IDENTITY) + popFlushNeeded = false transformDepth = 0 val prevProg = glGetInteger(GL_CURRENT_PROGRAM) glUseProgram(program) @@ -608,6 +613,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re override fun text(font: Font, x: Float, y: Float, text: String, color: Color, fontSize: Float) { val fAtlas = getFontAtlas(font, fontSize) + val s = transformScale() + val fAtlasForRendering = if (s == 1f) fAtlas else getFontAtlas(font, fontSize * s) if (count >= MAX_BATCH) flush() if (count > 0 && curTex != atlas) flush() curTex = atlas @@ -631,7 +638,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re buffer.put(EMPTY_ROW) // zero radii buffer.put(r).put(g).put(b).put(a) buffer.put(EMPTY_ROW) // color1 unused - buffer.put(glyph, 0, 4) + buffer.put(if (s == 1f) glyph else fAtlasForRendering.get(c), 0, 4) buffer.put(-1f) // thickness = -1 for text penX += glyph.xAdvance * scaleFactor count += 1 @@ -656,7 +663,14 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re spread: Float, radius: Float ) { - // rect(x, y, width, height, ) + if (count >= MAX_BATCH) flush() + buffer.put(x).put(y).put(width).put(height) + buffer.put(EMPTY_ROW) // zero radii + buffer.put(0f).put(0f).put(0f).put(alphaCap) // black, alpha to alphaCap + buffer.put(EMPTY_ROW) // color1 unused + buffer.put(spread).put(blur).put(0f).put(0f) + buffer.put(-5f) // thickness = -5 for drop shadow + count += 1 } override fun pushScissor(x: Float, y: Float, width: Float, height: Float) { @@ -665,24 +679,24 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val ny = (viewportHeight - (y + height) * pixelRatio).roundToInt() val nw = (width * pixelRatio).roundToInt() val nh = (height * pixelRatio).roundToInt() - scissorStack[curScissor++] = nx - scissorStack[curScissor++] = ny - scissorStack[curScissor++] = nw - scissorStack[curScissor++] = nh + scissorStack[scissorDepth++] = nx + scissorStack[scissorDepth++] = ny + scissorStack[scissorDepth++] = nw + scissorStack[scissorDepth++] = nh glEnable(GL_SCISSOR_TEST) glScissor(nx, ny, nw, nh) } override fun pushScissorIntersecting(x: Float, y: Float, width: Float, height: Float) { - if (curScissor < 4) { + if (scissorDepth < 4) { pushScissor(x, y, width, height) return } flush() - val px = scissorStack[curScissor - 4] - val py = scissorStack[curScissor - 3] - val pw = scissorStack[curScissor - 2] - val ph = scissorStack[curScissor - 1] + val px = scissorStack[scissorDepth - 4] + val py = scissorStack[scissorDepth - 3] + val pw = scissorStack[scissorDepth - 2] + val ph = scissorStack[scissorDepth - 1] val nx = (x * pixelRatio).roundToInt() val ny = (viewportHeight - (y + height) * pixelRatio).roundToInt() @@ -691,10 +705,10 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val iw = maxOf(0, minOf(nx + (width * pixelRatio).roundToInt(), px + pw) - ix) val ih = maxOf(0, minOf(ny + (height * pixelRatio).roundToInt(), py + ph) - iy) - scissorStack[curScissor++] = ix - scissorStack[curScissor++] = iy - scissorStack[curScissor++] = iw - scissorStack[curScissor++] = ih + scissorStack[scissorDepth++] = ix + scissorStack[scissorDepth++] = iy + scissorStack[scissorDepth++] = iw + scissorStack[scissorDepth++] = ih glEnable(GL_SCISSOR_TEST) glScissor(ix, iy, iw, ih) @@ -702,16 +716,16 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re override fun popScissor() { flush() - if (curScissor <= 4) { - curScissor = 0 + if (scissorDepth <= 4) { + scissorDepth = 0 glDisable(GL_SCISSOR_TEST) return } - curScissor -= 4 - val x = scissorStack[curScissor - 4] - val y = scissorStack[curScissor - 3] - val width = scissorStack[curScissor - 2] - val height = scissorStack[curScissor - 1] + scissorDepth -= 4 + val x = scissorStack[scissorDepth - 4] + val y = scissorStack[scissorDepth - 3] + val width = scissorStack[scissorDepth - 2] + val height = scissorStack[scissorDepth - 1] glEnable(GL_SCISSOR_TEST) glScissor(x, y, width, height) } @@ -740,6 +754,12 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re popFlushNeeded = true } + private fun transformScale(): Float { + val sx = sqrt(transform[0] * transform[0] + transform[3] * transform[3]) + val sy = sqrt(transform[1] * transform[1] + transform[4] * transform[4]) + return (sx + sy) * 0.5f + } + override fun translate(x: Float, y: Float) { flush() transform[6] += transform[0] * x + transform[3] * y From 58a5fea535f0ace5dfc8e150c3f2c500fcf52a42 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Sun, 7 Dec 2025 16:13:37 +0000 Subject: [PATCH 13/47] fix keying issues (fixes #591) --- .../oneconfig/api/ui/v1/keybind/KeybindManager.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/keybind/KeybindManager.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/keybind/KeybindManager.kt index 82e7690dc..ad68d505c 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/keybind/KeybindManager.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/keybind/KeybindManager.kt @@ -87,16 +87,17 @@ object KeybindManager { try { if (char.isValid() && inputManager.mods <= 2) { // asm: only allow no mod or shift mod for char input if (down) inputManager.keyTyped(char.code) + return } val mod = when (keyCode) { OmniKeys.KEY_LEFT_SHIFT.code -> KeyModifiers.LSHIFT OmniKeys.KEY_LEFT_CONTROL.code -> if (PolyUI.isOnMac) KeyModifiers.LMETA else KeyModifiers.LPRIMARY -// OmniKeys.KEY_LMENU -> KeyModifiers.LSECONDARY -// OmniKeys.KEY_LMETA -> if (PolyUI.isOnMac) KeyModifiers.LPRIMARY else KeyModifiers.LSECONDARY + OmniKeys.KEY_LEFT_ALT.code -> KeyModifiers.LSECONDARY + OmniKeys.KEY_LEFT_SUPER.code -> if (PolyUI.isOnMac) KeyModifiers.LPRIMARY else KeyModifiers.LSECONDARY OmniKeys.KEY_RIGHT_SHIFT.code -> KeyModifiers.RSHIFT OmniKeys.KEY_RIGHT_CONTROL.code -> if (PolyUI.isOnMac) KeyModifiers.RMETA else KeyModifiers.RPRIMARY -// OmniKeys.KEY_RIGHT_MENU -> KeyModifiers.RSECONDARY -// OmniKeys.KEY_RIGHT_META -> if (PolyUI.isOnMac) KeyModifiers.RPRIMARY else KeyModifiers.RSECONDARY + OmniKeys.KEY_RIGHT_ALT.code -> KeyModifiers.RSECONDARY + OmniKeys.KEY_RIGHT_SUPER.code -> if (PolyUI.isOnMac) KeyModifiers.RPRIMARY else KeyModifiers.RSECONDARY else -> null } From c0f952a84e72a03e1f6fb91f1522c59e7ce80c12 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Mon, 8 Dec 2025 12:31:02 +0000 Subject: [PATCH 14/47] fix crashes and radii issue --- gradle/libs.versions.toml | 2 +- .../api/config/v1/ConfigManager.java | 2 ++ .../serialize/adapter/impl/FontAdapter.java | 26 +++++++++++++++++++ .../oneconfig/api/config/v1/Visualizer.kt | 2 +- .../config/v1/internal/ConfigVisualizer.kt | 5 ++-- .../api/ui/v1/internal/GLRendererImpl.kt | 15 ++++------- 6 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/serialize/adapter/impl/FontAdapter.java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f1ad67825..681e7ec15 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kotlinx-coroutines = "1.10.2" kotlinx-atomicfu = "0.29.0" fabric-language-kotlin = "1.13.5+kotlin.2.2.10" google-ksp = "2.2.10-2.0.2" -polyui = "2.0.5" +polyui = "2.0.6" annotations = "24.1.0" hypixel-modapi = "1.0.1" hypixel-data = "0.2.0" # Dep of hypixel-modapi diff --git a/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/ConfigManager.java b/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/ConfigManager.java index f10fb35c6..8c4e28355 100644 --- a/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/ConfigManager.java +++ b/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/ConfigManager.java @@ -37,6 +37,7 @@ import org.polyfrost.oneconfig.api.config.v1.collect.PropertyCollector; import org.polyfrost.oneconfig.api.config.v1.collect.impl.OneConfigCollector; import org.polyfrost.oneconfig.api.config.v1.serialize.ObjectSerializer; +import org.polyfrost.oneconfig.api.config.v1.serialize.adapter.impl.FontAdapter; import org.polyfrost.oneconfig.api.config.v1.serialize.adapter.impl.PolyColorAdapter; import org.polyfrost.oneconfig.api.config.v1.serialize.adapter.impl.Vec4Adapter; import org.polyfrost.oneconfig.api.config.v1.serialize.impl.FileSerializer; @@ -64,6 +65,7 @@ public final class ConfigManager { static { ObjectSerializer.INSTANCE.registerTypeAdapter(new PolyColorAdapter()); + ObjectSerializer.INSTANCE.registerTypeAdapter(new FontAdapter()); ObjectSerializer.INSTANCE.registerTypeAdapter(new Vec4Adapter()); registerCollector(new OneConfigCollector()); } diff --git a/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/serialize/adapter/impl/FontAdapter.java b/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/serialize/adapter/impl/FontAdapter.java new file mode 100644 index 000000000..dbf637a18 --- /dev/null +++ b/modules/config-impl/src/main/java/org/polyfrost/oneconfig/api/config/v1/serialize/adapter/impl/FontAdapter.java @@ -0,0 +1,26 @@ +package org.polyfrost.oneconfig.api.config.v1.serialize.adapter.impl; + +import org.polyfrost.oneconfig.api.config.v1.serialize.adapter.Adapter; +import org.polyfrost.polyui.data.Font; + +public class FontAdapter extends Adapter { + @Override + public Font deserialize(String in) { + return Font.of(in); + } + + @Override + public String serialize(Font in) { + return in.getResourcePath(); + } + + @Override + public Class getTargetClass() { + return Font.class; + } + + @Override + public Class getOutputClass() { + return String.class; + } +} diff --git a/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/Visualizer.kt b/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/Visualizer.kt index 6a7e613ae..89a4eb6c7 100644 --- a/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/Visualizer.kt +++ b/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/Visualizer.kt @@ -230,7 +230,7 @@ fun interface Visualizer { placeholder = placeholder, image = "assets/oneconfig/ico/text.svg".image(), size = Vec2(200f, 32f), - value = state, + value = state.value.toFloat().toString(dps = 2), post = unit ) s.getTextFromBoxedTextInput().numeric(min, max, state) diff --git a/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt b/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt index 3beca1711..ad6e3d601 100644 --- a/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt +++ b/modules/config-impl/src/main/kotlin/org/polyfrost/oneconfig/api/config/v1/internal/ConfigVisualizer.kt @@ -269,7 +269,6 @@ open class ConfigVisualizer { var contentHeight = -1f // asm: signature as it prevents re-wrapping of function val openInsn: Drawable.(Any?) -> Unit = { - open.value = !open.value val arrow = if (enabled != null) this[1][1] else this[1] val anim = Animations.Default.create(0.6.seconds) Rotate(arrow, if (!open.value) PI else 0.0, false, anim).add() @@ -292,13 +291,13 @@ open class ConfigVisualizer { size = 21f, state = open ).onChange(open) { - enabled?.setAs(it) + enabled?.set(it) if (open.value != it) (parent.parent as Drawable).openInsn(null) }, Image("polyui/chevron-down.svg").also { it.rotation = PI } ) // lmao - open.value = !open.value + //open.value = !open.value @Suppress("UNCHECKED_CAST") // reason: #already-type-checked enabled = e as Property } else { diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 6dc12e0ff..3cdee0b25 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -100,7 +100,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re // Current batch state private var count = 0 - private var curTex = 0 private var transformDepth = 0 private var scissorDepth = 0 private var transform = IDENTITY.copyOf() @@ -145,9 +144,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re float py = step(0.0, p.y); // Select radius per quadrant - float rLeft = mix(r.w, r.x, py); // bottom-left / top-left - float rRight = mix(r.z, r.y, py); // bottom-right / top-right - float radius = mix(rLeft, rRight, px); + float rLeft = mix(r.x, r.w, py); // top-left / bottom-left + float rRight = mix(r.y, r.z, py); // top-right / bottom-right + float radius = mix(rLeft, rRight, px); // left vs right vec2 q = abs(p) - (b - radius); return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius; @@ -467,7 +466,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } glActiveTexture(GL_TEXTURE0) - glBindTexture(GL_TEXTURE_2D, curTex) + glBindTexture(GL_TEXTURE_2D, atlas) // Quad attrib glBindBuffer(GL_ARRAY_BUFFER, quadVbo) @@ -596,8 +595,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re colorMask: Int, topLeftRadius: Float, topRightRadius: Float, bottomLeftRadius: Float, bottomRightRadius: Float ) { if (count >= MAX_BATCH) flush() - if (count > 0 && curTex != atlas) flush() - curTex = atlas buffer.put(x).put(y).put(width).put(height) buffer.put(topLeftRadius).put(topRightRadius).put(bottomRightRadius).put(bottomLeftRadius) @@ -616,8 +613,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val s = transformScale() val fAtlasForRendering = if (s == 1f) fAtlas else getFontAtlas(font, fontSize * s) if (count >= MAX_BATCH) flush() - if (count > 0 && curTex != atlas) flush() - curTex = atlas var penX = x val scaleFactor = fontSize / fAtlas.renderedSize @@ -918,8 +913,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (quadVbo != 0) glDeleteBuffers(quadVbo) if (instancedVbo != 0) glDeleteBuffers(instancedVbo) if (atlas != 0) glDeleteTextures(atlas) + if (vao != 0) org.lwjgl.opengl.GL30C.glDeleteVertexArrays(vao) fonts.clear() - buffer.clear() } override fun delete(font: Font?) {} From fc1dd0f3dcafa51bf5dc87f1d6b5abe6eb0ef7a5 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Mon, 8 Dec 2025 20:16:46 +0000 Subject: [PATCH 15/47] fix scissoring on GLRenderer --- gradle/libs.versions.toml | 2 +- .../v1/internal/ScreenPlatformImpl.java | 25 +++++++++++++++++ .../ui/v1/internal/wrappers/PolyUIScreen.java | 20 +++----------- .../api/ui/v1/internal/GLRendererImpl.kt | 27 +++++++++---------- .../api/platform/v1/ScreenPlatform.java | 11 ++++++++ 5 files changed, 53 insertions(+), 32 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 681e7ec15..6c20262a1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kotlinx-coroutines = "1.10.2" kotlinx-atomicfu = "0.29.0" fabric-language-kotlin = "1.13.5+kotlin.2.2.10" google-ksp = "2.2.10-2.0.2" -polyui = "2.0.6" +polyui = "2.0.7" annotations = "24.1.0" hypixel-modapi = "1.0.1" hypixel-data = "0.2.0" # Dep of hypixel-modapi diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java index 6e6541c62..234a9c28d 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java @@ -29,7 +29,9 @@ import dev.deftu.omnicore.api.client.render.OmniRenderingContext; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.lwjgl.BufferUtils; import org.polyfrost.oneconfig.api.event.v1.EventDelay; import org.polyfrost.oneconfig.api.hud.v1.LegacyHud; import org.polyfrost.oneconfig.api.platform.v1.ScreenPlatform; @@ -38,6 +40,8 @@ import org.polyfrost.polyui.component.Component; import org.polyfrost.polyui.component.Drawable; +import java.nio.Buffer; +import java.nio.IntBuffer; import java.util.List; public class ScreenPlatformImpl implements ScreenPlatform { @@ -45,6 +49,14 @@ public class ScreenPlatformImpl implements ScreenPlatform { // //$$ private final float[] pixelScaleFactor = new float[1]; // //#endif + private final IntBuffer VIEWPORT = BufferUtils.createIntBuffer( + //#if MC >= 1.13 + //$$ 4 + //#else + 16 + //#endif + ); + @Override public int viewportWidth() { //#if MC>=11502 @@ -81,6 +93,19 @@ public int windowHeight() { //#endif } + @Override + public int @NotNull [] glViewport(int @Nullable [] in) { + ((Buffer) VIEWPORT).clear(); + //#if MC >= 1.13 + //$$ org.lwjgl.opengl.GL11.glGetIntegerv(org.lwjgl.opengl.GL11.GL_VIEWPORT, VIEWPORT); + //#else + org.lwjgl.opengl.GL11.glGetInteger(org.lwjgl.opengl.GL11.GL_VIEWPORT, VIEWPORT); + //#endif + int[] out = in != null ? in : new int[4]; + VIEWPORT.get(out, 0, 4); + return out; + } + public void renderLegacyHuds(OmniRenderingContext ctx) { PolyUI defaultInstance = UIManager.INSTANCE.getDefaultInstance(); Drawable master = defaultInstance.getMaster(); diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java index 9fc70937b..b10e04383 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java @@ -39,7 +39,6 @@ import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; -import org.lwjgl.BufferUtils; import org.polyfrost.oneconfig.api.platform.v1.Platform; import org.polyfrost.oneconfig.api.ui.v1.Notifications; import org.polyfrost.oneconfig.api.ui.v1.UIManager; @@ -48,8 +47,6 @@ import org.polyfrost.polyui.component.Drawable; import org.polyfrost.polyui.data.Cursor; -import java.nio.Buffer; -import java.nio.IntBuffer; import java.util.function.Consumer; import static org.lwjgl.opengl.GL11.*; @@ -65,13 +62,7 @@ public class PolyUIScreen extends OmniScreen implements BlurScreen { private final float designedWidth, designedHeight, initialWidth, initialHeight; private final boolean pauses, blurs; private final Consumer close; - private final IntBuffer VIEWPORT = BufferUtils.createIntBuffer( - //#if MC >= 1.13 - //$$ 4 - //#else - 16 - //#endif - ); + private final int[] viewport = new int[4]; //#if MC < 1.13 private int mx, my; @@ -130,12 +121,7 @@ public void onRender(@NotNull OmniRenderingContext ctx, int mouseX, int mouseY, //#if MC >= 1.21.5 //$$ kotlin.jvm.functions.Function0 unbind = dev.deftu.omnicore.api.client.framebuffer.OmniFramebuffers.getMain().bind(); //#endif - ((Buffer) VIEWPORT).clear(); - //#if MC >= 1.13 - //$$ glGetIntegerv(GL_VIEWPORT, VIEWPORT); - //#else - glGetInteger(GL_VIEWPORT, VIEWPORT); - //#endif + Platform.screen().glViewport(viewport); float factor = Platform.screen().pixelRatio(); int w = (int) (polyUI.getMaster().getWidth() * factor); int h = (int) (polyUI.getMaster().getHeight() * factor); @@ -143,7 +129,7 @@ public void onRender(@NotNull OmniRenderingContext ctx, int mouseX, int mouseY, int y = Platform.screen().viewportHeight() / 2 - h / 2; glViewport(x, y, w, h); polyUI.render(); - glViewport(VIEWPORT.get(), VIEWPORT.get(), VIEWPORT.get(), VIEWPORT.get()); + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); //#if MC >= 1.21.5 //$$ unbind.invoke(); //#endif diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 3cdee0b25..2b7a0f424 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -11,6 +11,7 @@ import org.lwjgl.opengl.GL13.* import org.lwjgl.opengl.GL14.* import org.lwjgl.opengl.GL15.* import org.lwjgl.opengl.GL20.* +import org.polyfrost.oneconfig.api.platform.v1.Platform import org.polyfrost.oneconfig.api.ui.v1.api.NanoSvgApi import org.polyfrost.oneconfig.api.ui.v1.api.RendererExt import org.polyfrost.oneconfig.api.ui.v1.api.StbApi @@ -99,12 +100,11 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re // Current batch state + private val viewport = IntArray(4) private var count = 0 private var transformDepth = 0 private var scissorDepth = 0 private var transform = IDENTITY.copyOf() - private var viewportWidth = 0f - private var viewportHeight = 0f private var pixelRatio = 1f private var alphaCap = 1f private var popFlushNeeded = false @@ -420,8 +420,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glUniformMatrix3fv(uTransform, false, transform) glUseProgram(prevProg) glDisable(GL_SCISSOR_TEST) - viewportWidth = width * pixelRatio - viewportHeight = height * pixelRatio + Platform.screen().glViewport(viewport) this.pixelRatio = pixelRatio } @@ -671,7 +670,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re override fun pushScissor(x: Float, y: Float, width: Float, height: Float) { flush() val nx = (x * pixelRatio).roundToInt() - val ny = (viewportHeight - (y + height) * pixelRatio).roundToInt() + val ny = (viewport[3] - (y + height) * pixelRatio).roundToInt() val nw = (width * pixelRatio).roundToInt() val nh = (height * pixelRatio).roundToInt() scissorStack[scissorDepth++] = nx @@ -679,7 +678,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re scissorStack[scissorDepth++] = nw scissorStack[scissorDepth++] = nh glEnable(GL_SCISSOR_TEST) - glScissor(nx, ny, nw, nh) + glScissor(nx + viewport[0], ny + viewport[1], nw, nh) } override fun pushScissorIntersecting(x: Float, y: Float, width: Float, height: Float) { @@ -693,7 +692,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val pw = scissorStack[scissorDepth - 2] val ph = scissorStack[scissorDepth - 1] val nx = (x * pixelRatio).roundToInt() - val ny = (viewportHeight - (y + height) * pixelRatio).roundToInt() + val ny = (viewport[3] - (y + height) * pixelRatio).roundToInt() val ix = maxOf(nx, px) val iy = maxOf(ny, py) @@ -706,7 +705,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re scissorStack[scissorDepth++] = ih glEnable(GL_SCISSOR_TEST) - glScissor(ix, iy, iw, ih) + glScissor(ix + viewport[0], iy + viewport[1], iw, ih) } override fun popScissor() { @@ -717,12 +716,12 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re return } scissorDepth -= 4 - val x = scissorStack[scissorDepth - 4] - val y = scissorStack[scissorDepth - 3] - val width = scissorStack[scissorDepth - 2] - val height = scissorStack[scissorDepth - 1] + val nx = scissorStack[scissorDepth - 4] + val ny = scissorStack[scissorDepth - 3] + val nw = scissorStack[scissorDepth - 2] + val nh = scissorStack[scissorDepth - 1] glEnable(GL_SCISSOR_TEST) - glScissor(x, y, width, height) + glScissor(nx + viewport[0], ny + viewport[1], nw, nh) } override fun globalAlpha(alpha: Float) { @@ -883,7 +882,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re return fonts.getOrPut(font.resourcePath.hashCode() + renderSize.toInt()) { val data = font.load { LOGGER.error("Failed to load font: $font", it) - return@getOrPut fonts[PolyUI.defaultFonts.regular.resourcePath.hashCode() + renderSize.toInt()] + return@getOrPut fonts[PolyUI.defaultFonts.regular.resourcePath.hashCode() + 12f.toInt()] ?: throw IllegalStateException("Default font couldn't be loaded") }.toDirectByteBuffer() FontAtlas(data, renderSize) diff --git a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java index f0c210dff..b48386422 100644 --- a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java +++ b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java @@ -27,6 +27,7 @@ package org.polyfrost.oneconfig.api.platform.v1; import dev.deftu.omnicore.api.client.render.OmniRenderingContext; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface ScreenPlatform { @@ -39,6 +40,16 @@ public interface ScreenPlatform { int windowHeight(); + /** + * Return the result of glGetInteger(GL_VIEWPORT). + * If in is supplied, it will be set to the result and returned. If not, a new array will be created. + */ + int @NotNull [] glViewport(int @Nullable [] in); + + default int @NotNull [] glViewport() { + return glViewport(null); + } + void renderLegacyHuds(OmniRenderingContext ctx); default float pixelRatio() { From d72f971ff7db51d54d519bddf632212cef18898f Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Mon, 8 Dec 2025 20:25:32 +0000 Subject: [PATCH 16/47] dump --- modules/config-impl/api/config-impl.api | 10 ++++++++++ modules/utils/api/utils.api | 2 ++ 2 files changed, 12 insertions(+) diff --git a/modules/config-impl/api/config-impl.api b/modules/config-impl/api/config-impl.api index 9d0db0d00..36c634f34 100644 --- a/modules/config-impl/api/config-impl.api +++ b/modules/config-impl/api/config-impl.api @@ -474,6 +474,16 @@ public final class org/polyfrost/oneconfig/api/config/v1/dsl/Tree_extensionsKt { public static final fun setVisualizer (Lorg/polyfrost/oneconfig/api/config/v1/Property;Ljava/lang/Class;)V } +public class org/polyfrost/oneconfig/api/config/v1/serialize/adapter/impl/FontAdapter : org/polyfrost/oneconfig/api/config/v1/serialize/adapter/Adapter { + public fun ()V + public synthetic fun deserialize (Ljava/lang/Object;)Ljava/lang/Object; + public fun deserialize (Ljava/lang/String;)Lorg/polyfrost/polyui/data/Font; + public fun getOutputClass ()Ljava/lang/Class; + public fun getTargetClass ()Ljava/lang/Class; + public synthetic fun serialize (Ljava/lang/Object;)Ljava/lang/Object; + public fun serialize (Lorg/polyfrost/polyui/data/Font;)Ljava/lang/String; +} + public class org/polyfrost/oneconfig/api/config/v1/serialize/adapter/impl/PolyColorAdapter : org/polyfrost/oneconfig/api/config/v1/serialize/adapter/Adapter { public fun ()V public synthetic fun deserialize (Ljava/lang/Object;)Ljava/lang/Object; diff --git a/modules/utils/api/utils.api b/modules/utils/api/utils.api index 94d93d681..2bc9a2b66 100644 --- a/modules/utils/api/utils.api +++ b/modules/utils/api/utils.api @@ -78,6 +78,8 @@ public abstract interface class org/polyfrost/oneconfig/api/platform/v1/ScreenPl public abstract fun current ()Ljava/lang/Object; public fun display (Ljava/lang/Object;)V public abstract fun display (Ljava/lang/Object;I)V + public fun glViewport ()[I + public abstract fun glViewport ([I)[I public fun pixelRatio ()F public abstract fun renderLegacyHuds (Ldev/deftu/omnicore/api/client/render/OmniRenderingContext;)V public abstract fun viewportHeight ()I From 62b79594bebedda3a24e3b4c229da102538bc4fd Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Tue, 9 Dec 2025 18:02:11 +0000 Subject: [PATCH 17/47] implement MC text with MC renderer, move Platform.screen().glViewport, remove old code from LegacyHud --- .../platform/v1/internal/GLPlatformImpl.java | 31 ++++++++++++- .../v1/internal/ScreenPlatformImpl.java | 45 ------------------- .../api/ui/v1/internal/UIManagerImpl.java | 26 +++++++++-- .../ui/v1/internal/wrappers/PolyUIScreen.java | 2 +- modules/hud/api/hud.api | 4 +- .../oneconfig/api/hud/v1/LegacyHud.kt | 24 +++------- .../oneconfig/api/hud/v1/internal/hudpages.kt | 5 +-- modules/ui/api/ui.api | 3 ++ .../oneconfig/api/ui/v1/UIManager.java | 23 +++++++++- .../api/ui/v1/internal/GLRendererImpl.kt | 18 +++++++- .../api/ui/v1/internal/NVGRendererImpl.kt | 3 +- modules/utils/api/utils.api | 7 ++- .../oneconfig/api/platform/v1/GLPlatform.java | 15 ++++++- .../api/platform/v1/ScreenPlatform.java | 14 ------ 14 files changed, 121 insertions(+), 99 deletions(-) diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java index e2a185d3c..619ae55ac 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java @@ -27,9 +27,17 @@ package org.polyfrost.oneconfig.api.platform.v1.internal; import dev.deftu.omnicore.api.client.render.state.OmniRenderStates; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.BufferUtils; import org.polyfrost.oneconfig.api.platform.v1.GLPlatform; import org.polyfrost.oneconfig.utils.v1.MHUtils; +import java.nio.Buffer; +import java.nio.IntBuffer; + +import static org.lwjgl.opengl.GL11.*; + public class GLPlatformImpl implements GLPlatform { //@formatter:off //#if MC <= 1.12.2 @@ -38,6 +46,14 @@ public class GLPlatformImpl implements GLPlatform { .logIfErr().getOrElse(v -> 0L); //#endif + private final IntBuffer VIEWPORT = BufferUtils.createIntBuffer( + //#if MC >= 1.13 + //$$ 4 + //#else + 16 + //#endif + ); + @Override public long getFunctionAddress(String addr) { //#if MC <= 1.12.2 @@ -53,7 +69,7 @@ public long getFunctionAddress(String addr) { * to match what NanoVG leaves dropped into the OpenGL context. */ @Override - public void updateGameRenderStateAlongsideNanoVG() { + public void syncOpenGLContext() { OmniRenderStates.syncBlend(); OmniRenderStates.syncDepth(); OmniRenderStates.syncCull(); @@ -63,4 +79,17 @@ public void updateGameRenderStateAlongsideNanoVG() { //$$ com.mojang.blaze3d.vertex.BufferUploader.reset(); //#endif } + + @Override + public int @NotNull [] glViewport(int @Nullable [] in) { + ((Buffer) VIEWPORT).clear(); + //#if MC >= 1.13 + //$$ glGetIntegerv(GL_VIEWPORT, VIEWPORT); + //#else + glGetInteger(GL_VIEWPORT, VIEWPORT); + //#endif + int[] out = in != null ? in : new int[4]; + VIEWPORT.get(out, 0, 4); + return out; + } } diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java index 234a9c28d..59f5dbd9f 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java @@ -26,37 +26,17 @@ package org.polyfrost.oneconfig.api.platform.v1.internal; -import dev.deftu.omnicore.api.client.render.OmniRenderingContext; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.lwjgl.BufferUtils; import org.polyfrost.oneconfig.api.event.v1.EventDelay; -import org.polyfrost.oneconfig.api.hud.v1.LegacyHud; import org.polyfrost.oneconfig.api.platform.v1.ScreenPlatform; -import org.polyfrost.oneconfig.api.ui.v1.UIManager; -import org.polyfrost.polyui.PolyUI; -import org.polyfrost.polyui.component.Component; -import org.polyfrost.polyui.component.Drawable; - -import java.nio.Buffer; -import java.nio.IntBuffer; -import java.util.List; public class ScreenPlatformImpl implements ScreenPlatform { // //#if MC > 1.13 // //$$ private final float[] pixelScaleFactor = new float[1]; // //#endif - private final IntBuffer VIEWPORT = BufferUtils.createIntBuffer( - //#if MC >= 1.13 - //$$ 4 - //#else - 16 - //#endif - ); - @Override public int viewportWidth() { //#if MC>=11502 @@ -93,31 +73,6 @@ public int windowHeight() { //#endif } - @Override - public int @NotNull [] glViewport(int @Nullable [] in) { - ((Buffer) VIEWPORT).clear(); - //#if MC >= 1.13 - //$$ org.lwjgl.opengl.GL11.glGetIntegerv(org.lwjgl.opengl.GL11.GL_VIEWPORT, VIEWPORT); - //#else - org.lwjgl.opengl.GL11.glGetInteger(org.lwjgl.opengl.GL11.GL_VIEWPORT, VIEWPORT); - //#endif - int[] out = in != null ? in : new int[4]; - VIEWPORT.get(out, 0, 4); - return out; - } - - public void renderLegacyHuds(OmniRenderingContext ctx) { - PolyUI defaultInstance = UIManager.INSTANCE.getDefaultInstance(); - Drawable master = defaultInstance.getMaster(); - List children = master.getChildren(); - if (children == null || children.isEmpty()) return; - - for (Component child : children) { - if (!(child instanceof LegacyHud.LegacyHudComponent)) continue; - ((LegacyHud.LegacyHudComponent) child).renderLegacy(ctx); - } - } - // todo: https://github.com/Polyfrost/OneConfig/issues/478 // this override was removed to avoid the system receiving incorrect/inaccurate pixel ratio values // while the window was being resized (as it was calculated based on viewport / window size) diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java index eaa539c46..fa45c0621 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/UIManagerImpl.java @@ -41,6 +41,7 @@ import dev.deftu.omnicore.api.client.render.GlCapabilities; import dev.deftu.omnicore.api.client.render.pipeline.OmniRenderPipeline; import dev.deftu.omnicore.api.client.render.pipeline.OmniRenderPipelines; +import dev.deftu.omnicore.api.client.render.OmniRenderingContext; import dev.deftu.omnicore.api.client.render.state.OmniBlendState; import dev.deftu.omnicore.api.client.screen.OmniScreen; import net.minecraft.client.Minecraft; @@ -54,6 +55,7 @@ import org.polyfrost.oneconfig.api.ui.v1.internal.wrappers.MCWindow; import org.polyfrost.oneconfig.api.ui.v1.internal.wrappers.PolyUIScreen; import org.polyfrost.polyui.PolyUI; +import org.polyfrost.polyui.data.Font; import org.polyfrost.polyui.renderer.Renderer; import org.polyfrost.polyui.renderer.Window; @@ -67,15 +69,18 @@ public class UIManagerImpl implements UIManager { private static final String LWJGL_API_PACKAGE = "org.polyfrost.oneconfig.api.ui.v1.api."; private static final String LWJGL_IMPL_PACKAGE = "org.polyfrost.oneconfig.api.ui.v1.internal."; + private static final Font MC_FONT = Font.of("minecraft/assets/fonts/nowhere", null, false, Font.Weight.Regular); + private static final Logger LOGGER = LogManager.getLogger("OneConfig/LWJGL"); private PolyUI ui; private OmniRenderPipeline pipeline; + private OmniRenderingContext ctx; private final Set classLoaderInclude = new HashSet<>(); private final Map> classCache = new HashMap<>(); - private final NanoVgApi nanoVg; +// private final NanoVgApi nanoVg; private final NanoSvgApi nanoSvg; private final StbApi stb; private final TinyFdApi tinyFD; @@ -114,12 +119,12 @@ public UIManagerImpl() throws Throwable { boolean isGl3 = GlCapabilities.isGl3Available(); //#if MC >= 1.16.5 - //$$ nanoVg = new NanoVgImpl(isGl3); +// //$$ nanoVg = new NanoVgImpl(isGl3); //$$ nanoSvg = new NanoSvgImpl(); //$$ stb = new StbImpl(); //$$ tinyFD = new TinyFdImpl(); //#else - nanoVg = Lwjgl3Manager.getIsolated(NanoVgApi.class, LWJGL_IMPL_PACKAGE + "NanoVgImpl", isGl3); +// nanoVg = Lwjgl3Manager.getIsolated(NanoVgApi.class, LWJGL_IMPL_PACKAGE + "NanoVgImpl", isGl3); nanoSvg = Lwjgl3Manager.getIsolated(NanoSvgApi.class, LWJGL_IMPL_PACKAGE + "NanoSvgImpl"); stb = Lwjgl3Manager.getIsolated(StbApi.class, LWJGL_IMPL_PACKAGE + "StbImpl"); tinyFD = Lwjgl3Manager.getIsolated(TinyFdApi.class, LWJGL_IMPL_PACKAGE + "TinyFdImpl"); @@ -173,4 +178,19 @@ public OmniRenderPipeline getRenderPipeline() { return pipeline; } + + @Override + public void __setRenderingContext(OmniRenderingContext renderingContext) { + ctx = renderingContext; + } + + @Override + public OmniRenderingContext getRenderingContext() { + return ctx; + } + + @Override + public Font getMCFont() { + return MC_FONT; + } } diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java index b10e04383..b911666cf 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java @@ -121,7 +121,7 @@ public void onRender(@NotNull OmniRenderingContext ctx, int mouseX, int mouseY, //#if MC >= 1.21.5 //$$ kotlin.jvm.functions.Function0 unbind = dev.deftu.omnicore.api.client.framebuffer.OmniFramebuffers.getMain().bind(); //#endif - Platform.screen().glViewport(viewport); + Platform.gl().glViewport(viewport); float factor = Platform.screen().pixelRatio(); int w = (int) (polyUI.getMaster().getWidth() * factor); int h = (int) (polyUI.getMaster().getHeight() * factor); diff --git a/modules/hud/api/hud.api b/modules/hud/api/hud.api index 4c62331c1..0da2ebebe 100644 --- a/modules/hud/api/hud.api +++ b/modules/hud/api/hud.api @@ -94,8 +94,7 @@ public abstract class org/polyfrost/oneconfig/api/hud/v1/LegacyHud : org/polyfro public static synthetic fun createLegacy-Op45VSw$default (Lorg/polyfrost/oneconfig/api/hud/v1/LegacyHud;[Lorg/polyfrost/polyui/component/Component;Lorg/polyfrost/polyui/unit/Align;JZILjava/lang/Object;)Lorg/polyfrost/oneconfig/api/hud/v1/LegacyHud$LegacyHudComponent; public abstract fun getHeight ()F public abstract fun getWidth ()F - public fun render (Lorg/polyfrost/polyui/renderer/Renderer;Lorg/polyfrost/polyui/component/Drawable;)V - public abstract fun renderLegacy (Ldev/deftu/omnicore/api/client/render/OmniRenderingContext;FFFF)V + public abstract fun renderLegacy (Lorg/polyfrost/polyui/renderer/Renderer;Ldev/deftu/omnicore/api/client/render/OmniRenderingContext;FFFFLorg/polyfrost/polyui/component/Drawable;)V public abstract fun setHeight (F)V public abstract fun setWidth (F)V } @@ -106,7 +105,6 @@ public class org/polyfrost/oneconfig/api/hud/v1/LegacyHud$LegacyHudComponent : o public fun getHeight ()F public fun getWidth ()F protected fun render ()V - public final fun renderLegacy (Ldev/deftu/omnicore/api/client/render/OmniRenderingContext;)V public fun setHeight (F)V public fun setWidth (F)V } diff --git a/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/LegacyHud.kt b/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/LegacyHud.kt index 056bb0456..5a96e9090 100644 --- a/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/LegacyHud.kt +++ b/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/LegacyHud.kt @@ -30,6 +30,7 @@ import dev.deftu.omnicore.api.client.render.OmniRenderingContext import dev.deftu.omnicore.api.client.render.OmniResolution import org.jetbrains.annotations.ApiStatus import org.polyfrost.oneconfig.api.platform.v1.Platform +import org.polyfrost.oneconfig.api.ui.v1.UIManager import org.polyfrost.polyui.component.Component import org.polyfrost.polyui.component.Drawable import org.polyfrost.polyui.renderer.Renderer @@ -38,7 +39,7 @@ import org.polyfrost.polyui.unit.AlignDefault import org.polyfrost.polyui.unit.Vec2 /** - * [Hud] implementation that uses the old rendering system, with a standard [render] method. + * [Hud] implementation that uses the old rendering system. * * **You must** ensure that the [width] and [height] properties accurately reflect the size of the HUD. * Note that they are only queried when the HUD is first created, and when the [update] method returns `true`. @@ -69,18 +70,7 @@ abstract class LegacyHud(id: String, title: String, category: Category) : Hud PolyUI.monospaceFont - 2 -> mcFont.get(text.fontWeight, text.italic) + 2 -> UIManager.INSTANCE.mcFont else -> text.polyUI.fonts.get(text.fontWeight, text.italic) } text._parent?.recalculate(false) diff --git a/modules/ui/api/ui.api b/modules/ui/api/ui.api index 69e139b94..3e8776876 100644 --- a/modules/ui/api/ui.api +++ b/modules/ui/api/ui.api @@ -37,13 +37,16 @@ public final class org/polyfrost/oneconfig/api/ui/v1/OCPolyUIBuilder : org/polyf public abstract interface class org/polyfrost/oneconfig/api/ui/v1/UIManager { public static final field INSTANCE Lorg/polyfrost/oneconfig/api/ui/v1/UIManager; + public abstract fun __setRenderingContext (Ldev/deftu/omnicore/api/client/render/OmniRenderingContext;)V public fun createDefault ()Lorg/polyfrost/polyui/PolyUI; public abstract fun createPolyUIScreen (Lorg/polyfrost/polyui/PolyUI;FFZZLjava/util/function/Consumer;)Ldev/deftu/omnicore/api/client/screen/OmniScreen; public abstract fun createWindow ()Lorg/polyfrost/polyui/renderer/Window; public abstract fun getDefaultInstance ()Lorg/polyfrost/polyui/PolyUI; + public abstract fun getMCFont ()Lorg/polyfrost/polyui/data/Font; public abstract fun getRenderPipeline ()Ldev/deftu/omnicore/api/client/render/pipeline/OmniRenderPipeline; public abstract fun getRenderer ()Lorg/polyfrost/polyui/renderer/Renderer; public abstract fun getRendererExt ()Lorg/polyfrost/oneconfig/api/ui/v1/api/RendererExt; + public abstract fun getRenderingContext ()Ldev/deftu/omnicore/api/client/render/OmniRenderingContext; public abstract fun getTinyFD ()Lorg/polyfrost/oneconfig/api/ui/v1/api/TinyFdApi; } diff --git a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java index 77f941472..e911aa8a7 100644 --- a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java +++ b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java @@ -56,6 +56,7 @@ import org.polyfrost.polyui.Settings; import org.polyfrost.polyui.component.Component; import org.polyfrost.polyui.component.Drawable; +import org.polyfrost.polyui.data.Font; import org.polyfrost.polyui.renderer.Renderer; import org.polyfrost.polyui.renderer.Window; @@ -65,6 +66,7 @@ /** * Abstraction over the LWJGL3 implementation and loading. */ +@SuppressWarnings("DeprecatedIsStillUsed") public interface UIManager { UIManager INSTANCE = ServiceLoader.load( UIManager.class, @@ -113,6 +115,25 @@ public interface UIManager { OmniRenderPipeline getRenderPipeline(); + /** + * Return the current rendering context of the default UI instance. + * This method is internal as, well, you shouldn't have any reason to use it. + *
+ * In fact, if you are using it, please let us know on the GitHub issues page. + */ + @ApiStatus.Internal + OmniRenderingContext getRenderingContext(); + + /** + *

don't use this method!!

+ *
if you do, I don't like you. you will probably break like, everything. + */ + @Deprecated + @ApiStatus.Internal + void __setRenderingContext(OmniRenderingContext renderingContext); + + Font getMCFont(); + /** *

don't use this method!!

*/ @@ -138,8 +159,8 @@ default PolyUI createDefault() { framebuffer.clearDepthStencil(1.0, 0); framebuffer.usingToRender((matrixStack, w, h) -> { ctx.pose().runReplacingGlobalState(() -> { + __setRenderingContext(ctx); polyUI.render(); - Platform.screen().renderLegacyHuds(ctx); }); return Unit.INSTANCE; diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 2b7a0f424..5f1681f59 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -3,6 +3,8 @@ package org.polyfrost.oneconfig.api.ui.v1.internal import dev.deftu.omnicore.api.client.render.GlCapabilities +import dev.deftu.omnicore.api.client.render.OmniTextRenderer +import dev.deftu.omnicore.api.color.OmniColor import dev.deftu.omnicore.internal.client.render.shader.ShaderInternals import org.apache.logging.log4j.LogManager import org.lwjgl.BufferUtils @@ -12,6 +14,7 @@ import org.lwjgl.opengl.GL14.* import org.lwjgl.opengl.GL15.* import org.lwjgl.opengl.GL20.* import org.polyfrost.oneconfig.api.platform.v1.Platform +import org.polyfrost.oneconfig.api.ui.v1.UIManager import org.polyfrost.oneconfig.api.ui.v1.api.NanoSvgApi import org.polyfrost.oneconfig.api.ui.v1.api.RendererExt import org.polyfrost.oneconfig.api.ui.v1.api.StbApi @@ -420,7 +423,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glUniformMatrix3fv(uTransform, false, transform) glUseProgram(prevProg) glDisable(GL_SCISSOR_TEST) - Platform.screen().glViewport(viewport) + Platform.gl().glViewport(viewport) this.pixelRatio = pixelRatio } @@ -608,6 +611,15 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } override fun text(font: Font, x: Float, y: Float, text: String, color: Color, fontSize: Float) { + if (font === UIManager.INSTANCE.mcFont) { + val ctx = UIManager.INSTANCE.renderingContext + // todo hi deftu https://github.com/Deftu/OmniCore/issues/57 +// ctx.pose.push(OmniMatrix3f(transform)) + // asm: can be optimized by https://github.com/Deftu/OmniCore/issues/58 + OmniTextRenderer.render(ctx.pose, text, x, y, OmniColor.argb(color.argb), false) +// ctx.pose.pop() + return + } val fAtlas = getFontAtlas(font, fontSize) val s = transformScale() val fAtlasForRendering = if (s == 1f) fAtlas else getFontAtlas(font, fontSize * s) @@ -640,7 +652,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } override fun textBounds(font: Font, text: String, fontSize: Float): Vec2 { - return getFontAtlas(font, fontSize).measure(text, fontSize) + return if (font === UIManager.INSTANCE.mcFont) { + Vec2(OmniTextRenderer.width(text).toFloat(), OmniTextRenderer.lineHeight.toFloat()) + } else getFontAtlas(font, fontSize).measure(text, fontSize) } override fun line(x1: Float, y1: Float, x2: Float, y2: Float, color: Color, width: Float) { diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NVGRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NVGRendererImpl.kt index 0dacb64c2..52a928dda 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NVGRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NVGRendererImpl.kt @@ -30,7 +30,6 @@ import dev.deftu.omnicore.api.client.render.OmniTextureUnit import dev.deftu.omnicore.api.paddedMinecraftVersion import dev.deftu.omnicore.internal.client.textures.TextureInternals import org.apache.logging.log4j.LogManager -import org.lwjgl.nanovg.NanoVG import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL20 import org.lwjgl.opengl.GL30 @@ -176,7 +175,7 @@ class NVGRendererImpl( GL11.glPopAttrib() } - Platform.gl().updateGameRenderStateAlongsideNanoVG() + Platform.gl().syncOpenGLContext() if (mcVersion >= 1_16_05) { if (prevProgram != -1) { diff --git a/modules/utils/api/utils.api b/modules/utils/api/utils.api index 2bc9a2b66..cdcf7f51e 100644 --- a/modules/utils/api/utils.api +++ b/modules/utils/api/utils.api @@ -53,7 +53,9 @@ public abstract interface class org/polyfrost/oneconfig/api/platform/v1/Compatib public abstract interface class org/polyfrost/oneconfig/api/platform/v1/GLPlatform { public abstract fun getFunctionAddress (Ljava/lang/String;)J - public abstract fun updateGameRenderStateAlongsideNanoVG ()V + public fun glViewport ()[I + public abstract fun glViewport ([I)[I + public abstract fun syncOpenGLContext ()V } public abstract interface class org/polyfrost/oneconfig/api/platform/v1/I18nPlatform { @@ -78,10 +80,7 @@ public abstract interface class org/polyfrost/oneconfig/api/platform/v1/ScreenPl public abstract fun current ()Ljava/lang/Object; public fun display (Ljava/lang/Object;)V public abstract fun display (Ljava/lang/Object;I)V - public fun glViewport ()[I - public abstract fun glViewport ([I)[I public fun pixelRatio ()F - public abstract fun renderLegacyHuds (Ldev/deftu/omnicore/api/client/render/OmniRenderingContext;)V public abstract fun viewportHeight ()I public abstract fun viewportWidth ()I public abstract fun windowHeight ()I diff --git a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java index 7070d6478..f5b168d12 100644 --- a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java +++ b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java @@ -26,6 +26,9 @@ package org.polyfrost.oneconfig.api.platform.v1; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + public interface GLPlatform { /** @@ -36,6 +39,16 @@ public interface GLPlatform { */ long getFunctionAddress(String addr); - void updateGameRenderStateAlongsideNanoVG(); + void syncOpenGLContext(); + + /** + * Return the result of glGetInteger(GL_VIEWPORT). + * If in is supplied, it will be set to the result and returned. If not, a new array will be created. + */ + int @NotNull [] glViewport(int @Nullable [] in); + + default int @NotNull [] glViewport() { + return glViewport(null); + } } diff --git a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java index b48386422..240b8d0eb 100644 --- a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java +++ b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java @@ -26,8 +26,6 @@ package org.polyfrost.oneconfig.api.platform.v1; -import dev.deftu.omnicore.api.client.render.OmniRenderingContext; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface ScreenPlatform { @@ -40,18 +38,6 @@ public interface ScreenPlatform { int windowHeight(); - /** - * Return the result of glGetInteger(GL_VIEWPORT). - * If in is supplied, it will be set to the result and returned. If not, a new array will be created. - */ - int @NotNull [] glViewport(int @Nullable [] in); - - default int @NotNull [] glViewport() { - return glViewport(null); - } - - void renderLegacyHuds(OmniRenderingContext ctx); - default float pixelRatio() { return (float) viewportWidth() / windowWidth(); } From cc412aa9591372342a6320b3921dcb368b9e755f Mon Sep 17 00:00:00 2001 From: Wyvest Date: Wed, 10 Dec 2025 04:42:45 -0500 Subject: [PATCH 18/47] bump to 181 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0b58527de..146a69938 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,4 @@ dgt.minecraft.revision=3 # Project Configuration project.group=org.polyfrost.oneconfig project.name=OneConfig -project.version=1.0.0-alpha.180 +project.version=1.0.0-alpha.181 From 82016023eff49075050c81ed007b7c0327df3156 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Wed, 10 Dec 2025 11:01:05 +0000 Subject: [PATCH 19/47] updates and fixes --- gradle/libs.versions.toml | 2 +- .../api/ui/v1/internal/GLRendererImpl.kt | 164 +++++++++++------- 2 files changed, 101 insertions(+), 65 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6c20262a1..8bf6b1d8d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ copycat-image-awt = "0.1.1" # Per version textile = "1.0.0-beta.9" -omnicore = "1.0.0-beta.38" +omnicore = "1.0.0-beta.39" lwjgl = "3.3.3" # All downloaded by the isolated-lwjgl3-loader # Legacy only diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 5f1681f59..1013211b7 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -4,7 +4,9 @@ package org.polyfrost.oneconfig.api.ui.v1.internal import dev.deftu.omnicore.api.client.render.GlCapabilities import dev.deftu.omnicore.api.client.render.OmniTextRenderer +import dev.deftu.omnicore.api.client.render.stack.OmniPoseStack import dev.deftu.omnicore.api.color.OmniColor +import dev.deftu.omnicore.api.math.OmniMatrix3f import dev.deftu.omnicore.internal.client.render.shader.ShaderInternals import org.apache.logging.log4j.LogManager import org.lwjgl.BufferUtils @@ -30,11 +32,7 @@ import org.polyfrost.polyui.utils.toDirectByteBuffer import org.polyfrost.polyui.utils.toDirectByteBufferNT import java.nio.ByteBuffer import java.nio.FloatBuffer -import kotlin.math.cos -import kotlin.math.roundToInt -import kotlin.math.sin -import kotlin.math.sqrt -import kotlin.math.tan +import kotlin.math.* private val LOGGER = LogManager.getLogger("PolyUI/GLRenderer") @@ -43,7 +41,7 @@ private const val FONT_MAX_BITMAP_W = 1536 private const val FONT_MAX_BITMAP_H = 512 private const val ATLAS_SIZE = 2048 private const val ATLAS_SVG_UPSCALE_FACTOR = 2f -private const val STRIDE = 4 + 4 + 4 + 4 + 4 + 1 // bounds, radii, color0, color1, UV, thick +private const val STRIDE = 4 + 4 + 1 + 1 + 4 + 1 // bounds, radii, color0, color1, UV, thick private const val MAX_BATCH = 1024 private val EMPTY_ROW = floatArrayOf(0f, 0f, 0f, 0f) @@ -109,7 +107,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private var scissorDepth = 0 private var transform = IDENTITY.copyOf() private var pixelRatio = 1f - private var alphaCap = 1f + private var alphaCap = 255 private var popFlushNeeded = false // atlas data @@ -210,19 +208,22 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private val VERT = """ #version $$$ // replaced by compileShader + #extension GL_EXT_gpu_shader4 : enable #if __VERSION__ >= 130 #define ATTRIBUTE in #define VARYING out + #define U_INT uint #else #define ATTRIBUTE attribute #define VARYING varying + #define U_INT unsigned int #endif ATTRIBUTE vec2 aLocal; ATTRIBUTE vec4 iRect; ATTRIBUTE vec4 iRadii; - ATTRIBUTE vec4 iColor0; - ATTRIBUTE vec4 iColor1; + ATTRIBUTE U_INT iColor0; + ATTRIBUTE U_INT iColor1; ATTRIBUTE vec4 iUVRect; ATTRIBUTE float iThickness; @@ -241,6 +242,15 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re VARYING vec2 vUV; VARYING vec2 vUV2; VARYING float vThickness; + + vec4 unpackColor(U_INT c) { + float a = float((c >> 24) & 0xFFu) / 255.0; + float r = float((c >> 16) & 0xFFu) / 255.0; + float g = float((c >> 8) & 0xFFu) / 255.0; + float b = float((c ) & 0xFFu) / 255.0; + + return vec4(r, g, b, a); + } void main() { // Position inside rect @@ -257,8 +267,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re vPos = pos; vRect = iRect; vRadii = iRadii; - vColor0 = iColor0; - vColor1 = iColor1; + vColor0 = unpackColor(iColor0); + vColor1 = unpackColor(iColor1); vUV = uv; // pass through for gradients. vUV2 = iUVRect.zw; @@ -318,6 +328,14 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re ShaderInternals.uniformMatrix3(location, transpose, buf) } + @kotlin.internal.InlineOnly + private inline fun Int.capAlpha(): Int { + val a = (this ushr 24) and 0xFF + val capped = if (a > alphaCap) alphaCap else a + return (capped shl 24) or (this and 0x00FFFFFF) + } + + override fun init() { if (init) return // check if instancing extension is available @@ -340,18 +358,19 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } else { // gl2 check val extensions = glGetString(GL_EXTENSIONS) ?: "" + require("GL_EXT_gpu_shader4" in extensions) { "GL_EXT_gpu_shader4 is not supported and is required" } require("GL_ARB_instanced_arrays" in extensions) { "GL_ARB_instanced_arrays is not supported and is required" } require("GL_ARB_draw_instanced" in extensions) { "GL_ARB_draw_instanced is not supported and is required" } - if ("GL_EXT_framebuffer_object" in extensions) { - LOGGER.info("Using mipmaps as extension GL_EXT_framebuffer_object is available") - mipmapMode = 2 - } +// if ("GL_EXT_framebuffer_object" in extensions) { +// LOGGER.info("Using mipmaps as extension GL_EXT_framebuffer_object is available") +// mipmapMode = 2 +// } } } if (GlCapabilities.isGl3Available) { - LOGGER.info("Using mipmaps and VAOs as OpenGL 3+ is available.") - mipmapMode = 1 +// LOGGER.info("Using mipmaps and VAOs as OpenGL 3+ is available.") +// mipmapMode = 1 // ...ok I guess this is needed vao = org.lwjgl.opengl.GL30.glGenVertexArrays() org.lwjgl.opengl.GL30.glBindVertexArray(vao) @@ -359,8 +378,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re program = linkProgram(compileShader(GL_VERTEX_SHADER, VERT), compileShader(GL_FRAGMENT_SHADER, FRAG)) - if (GlCapabilities.isGl3Available) org.lwjgl.opengl.GL30.glBindVertexArray(0) - val prevBuf = glGetInteger(GL_ARRAY_BUFFER_BINDING) val quadData = BufferUtils.createFloatBuffer(8).put( floatArrayOf( @@ -376,7 +393,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re instancedVbo = glGenBuffers() glBindBuffer(GL_ARRAY_BUFFER, instancedVbo) glBufferData(GL_ARRAY_BUFFER, MAX_BATCH * STRIDE * 4L, GL_STREAM_DRAW) - glBindBuffer(GL_ARRAY_BUFFER, prevBuf) uWindow = glGetUniformLocation(program, "uWindow") uTransform = glGetUniformLocation(program, "uTransform") @@ -388,6 +404,21 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re iUVRect = glGetAttribLocation(program, "iUVRect") iThickness = glGetAttribLocation(program, "iThickness") + if (GlCapabilities.isGl3Available) { + var offset = 0L + offset = enableAttrib(iRect, 4, offset) + offset = enableAttrib(iRadii, 4, offset) + offset = enableAttrib(iColor0, 1, offset, GL_UNSIGNED_INT) + offset = enableAttrib(iColor1, 1, offset, GL_UNSIGNED_INT) + offset = enableAttrib(iUVRect, 4, offset) + enableAttrib(iThickness, 1, offset) + + glBindBuffer(GL_ARRAY_BUFFER, quadVbo) + glEnableVertexAttribArray(aLocal) + glVertexAttribPointer(aLocal, 2, GL_FLOAT, false, 0, 0L) + org.lwjgl.opengl.GL30C.glBindVertexArray(0) + } + val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) atlas = glGenTextures() glBindTexture(GL_TEXTURE_2D, atlas) @@ -402,16 +433,17 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re GL_UNSIGNED_BYTE, null as ByteBuffer? ) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, if (mipmapMode == 0) GL_LINEAR else GL_LINEAR_MIPMAP_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) glBindTexture(GL_TEXTURE_2D, prevTex) + glBindBuffer(GL_ARRAY_BUFFER, prevBuf) } override fun beginFrame(width: Float, height: Float, pixelRatio: Float) { scissorDepth = 0 - alphaCap = 1f + alphaCap = 255 count = 0 buffer.clear() transform.set(IDENTITY) @@ -470,21 +502,24 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, atlas) - // Quad attrib - glBindBuffer(GL_ARRAY_BUFFER, quadVbo) - glEnableVertexAttribArray(aLocal) - glVertexAttribPointer(aLocal, 2, GL_FLOAT, false, 0, 0L) - - // Instance attribs - glBindBuffer(GL_ARRAY_BUFFER, instancedVbo) - - var offset = 0L - offset = enableAttrib(iRect, 4, offset) - offset = enableAttrib(iRadii, 4, offset) - offset = enableAttrib(iColor0, 4, offset) - offset = enableAttrib(iColor1, 4, offset) - offset = enableAttrib(iUVRect, 4, offset) - enableAttrib(iThickness, 1, offset) + // asm: on VAO the state is stored, so we only need to set it up once + if (!GlCapabilities.isGl3Available) { + // Quad attrib + glBindBuffer(GL_ARRAY_BUFFER, quadVbo) + glEnableVertexAttribArray(aLocal) + glVertexAttribPointer(aLocal, 2, GL_FLOAT, false, 0, 0L) + + // Instance attribs + glBindBuffer(GL_ARRAY_BUFFER, instancedVbo) + + var offset = 0L + offset = enableAttrib(iRect, 4, offset) + offset = enableAttrib(iRadii, 4, offset) + offset = enableAttrib(iColor0, 1, offset, GL_UNSIGNED_INT) + offset = enableAttrib(iColor1, 1, offset, GL_UNSIGNED_INT) + offset = enableAttrib(iUVRect, 4, offset) + enableAttrib(iThickness, 1, offset) + } // Draw all instances if (GlCapabilities.isGl31Available) org.lwjgl.opengl.GL31.glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, count) @@ -503,9 +538,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (GlCapabilities.isGl3Available) org.lwjgl.opengl.GL30.glBindVertexArray(prevVao) } - private fun enableAttrib(loc: Int, size: Int, offset: Long): Long { + private fun enableAttrib(loc: Int, size: Int, offset: Long, type: Int = GL_FLOAT): Long { glEnableVertexAttribArray(loc) - glVertexAttribPointer(loc, size, GL_FLOAT, false, STRIDE * 4, offset) + glVertexAttribPointer(loc, size, type, false, STRIDE * 4, offset) // I don't know why core disables the extension functions... but ok! if (GlCapabilities.isGl33Available) org.lwjgl.opengl.GL33.glVertexAttribDivisor(loc, 1) else org.lwjgl.opengl.ARBInstancedArrays.glVertexAttribDivisorARB(loc, 1) @@ -524,10 +559,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (count >= MAX_BATCH) flush() buffer.put(x).put(y).put(width).put(height) buffer.put(topLeftRadius).put(topRightRadius).put(bottomRightRadius).put(bottomLeftRadius) - buffer.put(color.r / 255f).put(color.g / 255f).put(color.b / 255f).put(color.alpha.coerceAtMost(alphaCap)) + buffer.put(java.lang.Float.intBitsToFloat(color.argb.capAlpha())) if (color is PolyColor.Gradient) { - buffer.put(color.color2.r / 255f).put(color.color2.g / 255f).put(color.color2.b / 255f) - .put(color.color2.alpha.coerceAtMost(alphaCap)) + buffer.put(java.lang.Float.intBitsToFloat(color.color2.argb.capAlpha())) when (val type = color.type) { is PolyColor.Gradient.Type.LeftToRight -> { buffer.put(0f).put(height / 2f).put(width).put(height / 2f) @@ -562,7 +596,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } } } else { - buffer.put(EMPTY_ROW) // color1 unused + buffer.put(0f) // color1 unused buffer.put(NO_UV) // -1f UVs to indicate no texture buffer.put(0f) } @@ -585,8 +619,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (count >= MAX_BATCH) flush() buffer.put(x).put(y).put(width).put(height) buffer.put(topLeftRadius).put(topRightRadius).put(bottomRightRadius).put(bottomLeftRadius) - buffer.put(color.r / 255f).put(color.g / 255f).put(color.b / 255f).put(color.alpha.coerceAtMost(alphaCap)) - buffer.put(EMPTY_ROW) // color1 unused + buffer.put(java.lang.Float.intBitsToFloat(color.argb.capAlpha())) + buffer.put(0f) // color1 unused buffer.put(NO_UV) // -1f UVs to indicate no texture buffer.put(lineWidth) count += 1 @@ -600,11 +634,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re buffer.put(x).put(y).put(width).put(height) buffer.put(topLeftRadius).put(topRightRadius).put(bottomRightRadius).put(bottomLeftRadius) - buffer.put((colorMask shr 16 and 0xFF) / 255f) - .put((colorMask shr 8 and 0xFF) / 255f) - .put((colorMask and 0xFF) / 255f) - .put(((colorMask ushr 24 and 0xFF) / 255f).coerceAtMost(alphaCap)) - buffer.put(EMPTY_ROW) // color1 unused + buffer.put(java.lang.Float.intBitsToFloat(colorMask.capAlpha())) + buffer.put(0f) // color1 unused buffer.put(image.uv.x).put(image.uv.y).put(image.uv.w).put(image.uv.h) buffer.put(0f) // thickness = 0 for filled rect count += 1 @@ -614,10 +645,10 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (font === UIManager.INSTANCE.mcFont) { val ctx = UIManager.INSTANCE.renderingContext // todo hi deftu https://github.com/Deftu/OmniCore/issues/57 -// ctx.pose.push(OmniMatrix3f(transform)) + ctx.pose.push(OmniPoseStack.Entry(ctx.pose.current.positionMatrix, OmniMatrix3f.from(transform))) // asm: can be optimized by https://github.com/Deftu/OmniCore/issues/58 OmniTextRenderer.render(ctx.pose, text, x, y, OmniColor.argb(color.argb), false) -// ctx.pose.pop() + ctx.pose.pop() return } val fAtlas = getFontAtlas(font, fontSize) @@ -628,10 +659,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re var penX = x val scaleFactor = fontSize / fAtlas.renderedSize val penY = y + (fAtlas.ascent + fAtlas.descent) * scaleFactor - val r = (color.r / 255f) - val g = (color.g / 255f) - val b = (color.b / 255f) - val a = (color.alpha.coerceAtMost(alphaCap)) + val col = java.lang.Float.intBitsToFloat(color.argb.capAlpha()) val buffer = buffer for (c in text) { @@ -642,8 +670,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re buffer.put(penX + glyph.xOff * scaleFactor).put(penY + glyph.yOff * scaleFactor) .put(glyph.width * scaleFactor).put(glyph.height * scaleFactor) buffer.put(EMPTY_ROW) // zero radii - buffer.put(r).put(g).put(b).put(a) - buffer.put(EMPTY_ROW) // color1 unused + buffer.put(col) + buffer.put(0f) // color1 unused buffer.put(if (s == 1f) glyph else fAtlasForRendering.get(c), 0, 4) buffer.put(-1f) // thickness = -1 for text penX += glyph.xAdvance * scaleFactor @@ -674,8 +702,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (count >= MAX_BATCH) flush() buffer.put(x).put(y).put(width).put(height) buffer.put(EMPTY_ROW) // zero radii - buffer.put(0f).put(0f).put(0f).put(alphaCap) // black, alpha to alphaCap - buffer.put(EMPTY_ROW) // color1 unused + buffer.put(java.lang.Float.intBitsToFloat(alphaCap shl 24)) // black, alpha to alphaCap + buffer.put(0f) // color1 unused buffer.put(spread).put(blur).put(0f).put(0f) buffer.put(-5f) // thickness = -5 for drop shadow count += 1 @@ -739,7 +767,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } override fun globalAlpha(alpha: Float) { - alphaCap = alpha + alphaCap = (alpha * 255f).toInt() } override fun resetGlobalAlpha() = globalAlpha(1f) @@ -763,8 +791,16 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } private fun transformScale(): Float { - val sx = sqrt(transform[0] * transform[0] + transform[3] * transform[3]) - val sy = sqrt(transform[1] * transform[1] + transform[4] * transform[4]) + val a = transform[0] + val c = transform[1] + val b = transform[3] + val d = transform[4] + // Fast-path: identity (no rotation, no scale, no shear) + if (a == 1f && d == 1f && c == 0f && b == 0f) { + return 1f + } + val sx = sqrt(a * a + b * b) + val sy = sqrt(c * c + d * d) return (sx + sy) * 0.5f } @@ -889,7 +925,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } private fun getFontAtlas(font: Font, fontSize: Float): FontAtlas { - val renderSize = when(fontSize) { + val renderSize = when (fontSize) { in 0f..36f -> 24f else -> 48f } From 954d81481a35c0662ec43952e56780b041fac707 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Wed, 10 Dec 2025 14:14:35 +0000 Subject: [PATCH 20/47] fix transformation matrix --- .../api/ui/v1/internal/GLRendererImpl.kt | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 1013211b7..7e2a363f2 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -3,10 +3,11 @@ package org.polyfrost.oneconfig.api.ui.v1.internal import dev.deftu.omnicore.api.client.render.GlCapabilities +import dev.deftu.omnicore.api.client.render.OmniResolution import dev.deftu.omnicore.api.client.render.OmniTextRenderer import dev.deftu.omnicore.api.client.render.stack.OmniPoseStack import dev.deftu.omnicore.api.color.OmniColor -import dev.deftu.omnicore.api.math.OmniMatrix3f +import dev.deftu.omnicore.api.math.OmniMatrix4f import dev.deftu.omnicore.internal.client.render.shader.ShaderInternals import org.apache.logging.log4j.LogManager import org.lwjgl.BufferUtils @@ -641,11 +642,21 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re count += 1 } + private fun FloatArray.getScaledMat4(): OmniMatrix4f { + // asm: scale to MC instance coordinates and mutate to a 4x4 matrix + val sf = pixelRatio / OmniResolution.scaleFactor.toFloat() + return OmniMatrix4f.from(floatArrayOf( + this[0] * sf, this[1] * sf, 0f, 0f, + this[3] * sf, this[4] * sf, 0f, 0f, + 0f, 0f, 1f, 0f, + this[6] * sf, this[7] * sf, 0f, 1f + )) + } + override fun text(font: Font, x: Float, y: Float, text: String, color: Color, fontSize: Float) { if (font === UIManager.INSTANCE.mcFont) { val ctx = UIManager.INSTANCE.renderingContext - // todo hi deftu https://github.com/Deftu/OmniCore/issues/57 - ctx.pose.push(OmniPoseStack.Entry(ctx.pose.current.positionMatrix, OmniMatrix3f.from(transform))) + ctx.pose.push(OmniPoseStack.Entry(transform.getScaledMat4(), ctx.pose.current.normalMatrix)) // asm: can be optimized by https://github.com/Deftu/OmniCore/issues/58 OmniTextRenderer.render(ctx.pose, text, x, y, OmniColor.argb(color.argb), false) ctx.pose.pop() From 91aedf602498d0806e1c92e103f204e36450f8c6 Mon Sep 17 00:00:00 2001 From: Deftu Date: Thu, 18 Dec 2025 16:19:53 +0200 Subject: [PATCH 21/47] Add 1.21.11 support and bump DGT --- .../org/polyfrost/gradle/addDependencies.kt | 7 +++ gradle/libs.versions.toml | 6 +-- minecraft/build.gradle.kts | 11 +++-- minecraft/root.gradle.kts | 46 ++++++++++--------- modules/dependencies/legacy/build.gradle.kts | 2 +- settings.gradle.kts | 9 +++- 6 files changed, 51 insertions(+), 30 deletions(-) diff --git a/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt b/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt index f17f736e5..fd61e4ecd 100644 --- a/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt +++ b/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt @@ -42,6 +42,7 @@ private val fabricApiModuleVersions = mapOf( "api-base-12108" to "0.4.64+9ec45cd8f3", // 1.21.8 "api-base-12109" to "0.5.2+2fa446b294", // 1.21.9 "api-base-12110" to "1.0.0+14b92d8968", // 1.21.10 + "api-base-12111" to "1.0.5+4ebb5c0853", // 1.21.11 "lifecycle-events-v1-common" to "1.1.0+2c3f108c81e6", // Common (Legacy Fabric API) "lifecycle-events-v1-10809" to "1.1.0+1.8.9+2c3f108c81e6", // 1.8.9 "lifecycle-events-v1-11202" to "1.1.0+1.12.2+2c3f108c81e6", // 1.12.2 @@ -63,6 +64,7 @@ private val fabricApiModuleVersions = mapOf( "lifecycle-events-v1-12108" to "2.6.3+db4dfd85f3", // 1.21.8 "lifecycle-events-v1-12109" to "2.6.8+33df5e6e94", // 1.21.9 "lifecycle-events-v1-12110" to "2.6.9+33df5e6e68", // 1.21.10 + "lifecycle-events-v1-12111" to "2.6.15+4ebb5c0853", // 1.21.11 "keybindings-api-v1-common" to "1.1.1+281301ea81e6", // Common (Legacy Fabric API) "keybindings-api-v1-10809" to "1.1.1+1.8.9+2c3f108c81e6", // 1.8.9 "keybindings-api-v1-11202" to "1.1.1+1.12.2+2c3f108c81e6", // 1.12.2 @@ -84,6 +86,7 @@ private val fabricApiModuleVersions = mapOf( "key-binding-api-v1-12108" to "1.0.65+946bf4c3f3", // 1.21.8 "key-binding-api-v1-12109" to "1.1.0+4ec8267494", // 1.21.9 "key-binding-api-v1-12110" to "1.1.1+b3ba9c4868", // 1.21.10 + "key-binding-api-v1-12111" to "1.1.7+4fc5413f53", // 1.21.11 "rendering-api-v1-common" to "1.0.0+7c545fdb81e6", // Common (Legacy Fabric API) "rendering-api-v1-10809" to "1.0.0+1.8.9+2c3f108c81e6", // 1.8.9 "rendering-api-v1-11202" to "1.0.0+1.8.9+2c3f108c81e6", // 1.12.2 @@ -105,6 +108,7 @@ private val fabricApiModuleVersions = mapOf( "rendering-v1-12108" to "12.4.0+e8d43c76f3", // 1.21.8 "rendering-v1-12109" to "15.0.2+9bce411b94", // 1.21.9 "rendering-v1-12110" to "16.0.1+328a75ba68", // 1.21.10 + "rendering-v1-12111" to "16.2.5+1fb1cde953", // 1.21.11 "screen-api-v1-11605" to "1.0.1+3cc0f0907d", // 1.16.5 "screen-api-v1-11701" to "1.0.5+cf39a74318", // 1.17.1 "screen-api-v1-11802" to "1.0.11+d882b91560", // 1.18.2 @@ -123,6 +127,7 @@ private val fabricApiModuleVersions = mapOf( "screen-api-v1-12108" to "2.1.0+277ecf7df3", // 1.21.8 "screen-api-v1-12109" to "3.0.2+86b3ae5794", // 1.21.9 "screen-api-v1-12110" to "3.1.0+9c82a79868", // 1.21.10 + "screen-api-v1-12111" to "3.1.7+4ebb5c0853", // 1.21.11 "command-api-v1-11605" to "1.1.3+3cc0f0907d", // 1.16.5 "command-api-v1-11701" to "1.1.4+cf39a74318", // 1.17.1 "command-api-v1-11802" to "1.1.10+d7c144a860", // 1.18.2 @@ -141,6 +146,7 @@ private val fabricApiModuleVersions = mapOf( "command-api-v2-12108" to "2.2.53+946bf4c3f3", // 1.21.8 "command-api-v2-12109" to "2.3.5+33df5e6e94", // 1.21.9 "command-api-v2-12110" to "2.3.7+328a75ba68", // 1.21.10 + "command-api-v2-12111" to "2.4.6+4ebb5c0853", // 1.21.11 "transitive-access-wideners-v1-11802" to "1.1.0+e747827960", // 1.18.2 "transitive-access-wideners-v1-11902" to "1.3.3+08b73de490", // 1.19.2 "transitive-access-wideners-v1-11904" to "3.3.0+1b5f819af4", // 1.19.4 @@ -157,6 +163,7 @@ private val fabricApiModuleVersions = mapOf( "transitive-access-wideners-v1-12108" to "6.4.1+ac3e15d1f3", // 1.21.8 "transitive-access-wideners-v1-12109" to "6.5.2+5d9dbead94", // 1.21.9 "transitive-access-wideners-v1-12110" to "6.5.3+41eb434368", // 1.21.10 + "transitive-access-wideners-v1-12111" to "7.0.7+1fb1cde953", // 1.21.11 ) /** diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8bf6b1d8d..9eedb80e5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,8 +21,8 @@ copycat = "0.1.3" copycat-image-awt = "0.1.1" # Per version -textile = "1.0.0-beta.9" -omnicore = "1.0.0-beta.39" +textile = "1.0.0-beta.11" +omnicore = "1.0.0-beta.40" lwjgl = "3.3.3" # All downloaded by the isolated-lwjgl3-loader # Legacy only @@ -35,7 +35,7 @@ brigadier = "1.0.18" oneconfig-loader = "1.1.0-alpha.48" # Gradle -dgt = "2.62.0" +dgt = "2.69.0" kotlinx-abi = "0.18.1" licenser = "2.1.1" jetbrains-idea-ext = "1.3" diff --git a/minecraft/build.gradle.kts b/minecraft/build.gradle.kts index b70045426..3bc5a32b2 100644 --- a/minecraft/build.gradle.kts +++ b/minecraft/build.gradle.kts @@ -39,7 +39,9 @@ if (mcData.isForge) { toolkitLoomHelper { disableRunConfigs(GameSide.SERVER) - useDevAuth("+") + if (mcData.version < MinecraftVersions.VERSION_1_21_11) { + useDevAuth("+") + } useProperty("mixin.debug.export", "true", GameSide.CLIENT) useProperty("debugBytecode", "true", GameSide.CLIENT) @@ -207,7 +209,8 @@ dependencies { rconfig("1.21.7", "3.7.2"), rconfig("1.21.8", "3.7.2", "1.21.7"), rconfig("1.21.9", "3.9.1"), - rconfig("1.21.10", "3.9.1", "1.21.9") + rconfig("1.21.10", "3.9.1", "1.21.9"), + rconfig("1.21.11", "3.9.1", "1.21.9"), ) compileOnlyCompat(rconfig[mcVersionString]) @@ -249,7 +252,8 @@ dependencies { yacl("1.21.7", "3.7.1", "1.21.6"), yacl("1.21.8", "3.7.1", "1.21.6"), yacl("1.21.9", "3.8.0", "1.21.6"), - yacl("1.21.10", "3.8.0", "1.21.9") + yacl("1.21.10", "3.8.0", "1.21.9"), + yacl("1.21.11", "3.8.0", "1.21.9"), ) compileOnlyCompat(yacl[mcVersionString]) @@ -274,6 +278,7 @@ dependencies { modMenu("1.21.7", "15.0.0-beta.3"), modMenu("1.21.8", "15.0.0-beta.3"), modMenu("1.21.10", "16.0.0-rc.1"), + modMenu("1.21.11", "17.0.0-alpha.1"), ) compileOnlyCompat(modMenu[mcVersionString]) diff --git a/minecraft/root.gradle.kts b/minecraft/root.gradle.kts index 77528ef84..4e213bc39 100644 --- a/minecraft/root.gradle.kts +++ b/minecraft/root.gradle.kts @@ -14,27 +14,31 @@ preprocess { strictExtraMappings.set(true) // FOR ALL NEW VERSIONS ENSURE TO UPDATE settings.gradle.kts ! - "1.21.10-neoforge"(1_21_10, "srg") { - "1.21.10-fabric"(1_21_10, "srg") { - "1.21.8-fabric"(1_21_08, "srg") { - "1.21.8-neoforge"(1_21_08, "srg") { - "1.21.5-neoforge"(1_21_05, "srg") { - "1.21.5-fabric"(1_21_05, "srg") { - "1.21.4-fabric"(1_21_04, "srg") { - "1.21.4-neoforge"(1_21_04, "srg") { - "1.21.1-neoforge"(1_21_01, "srg", file("mappings/1.21.4-forge+1.21.1-forge.txt")) { - "1.21.1-fabric"(1_21_01, "srg") { - "1.20.4-fabric"(1_20_04, "srg") { - "1.20.4-neoforge"(1_20_04, "srg") { - "1.20.4-forge"(1_20_04, "srg") { - "1.20.1-forge"(1_20_01, "srg", file("mappings/1.20.4-forge+1.20.1-forge.txt")) { - "1.20.1-fabric"(1_20_01, "srg") { - "1.16.5-fabric"(1_16_05, "srg", file("mappings/1.20.1-fabric+1.16.5-fabric.txt")) { - "1.16.5-forge"(1_16_05, "srg") { - "1.12.2-forge"(1_12_02, "srg", file("mappings/1.16.5-forge+1.12.2-forge.txt")) { - "1.12.2-fabric"(1_12_02, "srg") { - "1.8.9-fabric"(1_08_09, "srg") { - "1.8.9-forge"(1_08_09, "srg") + "1.21.11-fabric"(1_21_11, "srg") { + "1.21.11-neoforge"(1_21_11, "srg") { + "1.21.10-neoforge"(1_21_10, "srg") { + "1.21.10-fabric"(1_21_10, "srg") { + "1.21.8-fabric"(1_21_08, "srg") { + "1.21.8-neoforge"(1_21_08, "srg") { + "1.21.5-neoforge"(1_21_05, "srg") { + "1.21.5-fabric"(1_21_05, "srg") { + "1.21.4-fabric"(1_21_04, "srg") { + "1.21.4-neoforge"(1_21_04, "srg") { + "1.21.1-neoforge"(1_21_01, "srg", file("mappings/1.21.4-forge+1.21.1-forge.txt")) { + "1.21.1-fabric"(1_21_01, "srg") { + "1.20.4-fabric"(1_20_04, "srg") { + "1.20.4-neoforge"(1_20_04, "srg") { + "1.20.4-forge"(1_20_04, "srg") { + "1.20.1-forge"(1_20_01, "srg", file("mappings/1.20.4-forge+1.20.1-forge.txt")) { + "1.20.1-fabric"(1_20_01, "srg") { + "1.16.5-fabric"(1_16_05, "srg", file("mappings/1.20.1-fabric+1.16.5-fabric.txt")) { + "1.16.5-forge"(1_16_05, "srg") { + "1.12.2-forge"(1_12_02, "srg", file("mappings/1.16.5-forge+1.12.2-forge.txt")) { + "1.12.2-fabric"(1_12_02, "srg") { + "1.8.9-fabric"(1_08_09, "srg") { + "1.8.9-forge"(1_08_09, "srg") + } + } } } } diff --git a/modules/dependencies/legacy/build.gradle.kts b/modules/dependencies/legacy/build.gradle.kts index edd26cd99..27ed664f7 100644 --- a/modules/dependencies/legacy/build.gradle.kts +++ b/modules/dependencies/legacy/build.gradle.kts @@ -1,7 +1,7 @@ import org.polyfrost.gradle.provideIncludedDependencies plugins { - id("gg.essential.loom") + id("dev.deftu.gradle.loom") } repositories { diff --git a/settings.gradle.kts b/settings.gradle.kts index 2200de399..8fb912204 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,7 +24,7 @@ pluginManagement { plugins { kotlin("jvm") version("2.2.10") - id("dev.deftu.gradle.multiversion-root") version("2.62.0") // Update in libs.versions.toml too!!! + id("dev.deftu.gradle.multiversion-root") version("2.69.0") // Update in libs.versions.toml too!!! } } @@ -110,6 +110,9 @@ listOf( "1.21.10-neoforge", "1.21.10-fabric", + + "1.21.11-neoforge", + "1.21.11-fabric", ).forEach { version -> val proj = ":minecraft:$version" include(proj) @@ -125,7 +128,9 @@ listOf( "1.21.1-fabric", "1.21.4-fabric", "1.21.5-fabric", - "1.21.8-fabric" + "1.21.8-fabric", +// "1.21.10-fabric", +// "1.21.11-fabric", ).contains(version)) { include(bootstrapProj) project(bootstrapProj).apply { From 21dccd008194cb091827ca694d1807df9918c0ea Mon Sep 17 00:00:00 2001 From: Deftu Date: Thu, 18 Dec 2025 16:30:26 +0200 Subject: [PATCH 22/47] Bump to DGT revision 4 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 146a69938..5b1af1b5c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ ksp.incremental=false dgt.java.version=8 dgt.loom.mappings=official-like -dgt.minecraft.revision=3 +dgt.minecraft.revision=4 # Project Configuration project.group=org.polyfrost.oneconfig From 78cdb6fc586f2f9f40429ad69af036bbcedc6577 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Fri, 16 Jan 2026 10:38:47 +0000 Subject: [PATCH 23/47] macos moment --- .../api/ui/v1/internal/GLRendererImpl.kt | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 7e2a363f2..14db6be4f 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -409,8 +409,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re var offset = 0L offset = enableAttrib(iRect, 4, offset) offset = enableAttrib(iRadii, 4, offset) - offset = enableAttrib(iColor0, 1, offset, GL_UNSIGNED_INT) - offset = enableAttrib(iColor1, 1, offset, GL_UNSIGNED_INT) + offset = enableAttribui(iColor0, 1, offset) + offset = enableAttribui(iColor1, 1, offset) offset = enableAttrib(iUVRect, 4, offset) enableAttrib(iThickness, 1, offset) @@ -516,8 +516,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re var offset = 0L offset = enableAttrib(iRect, 4, offset) offset = enableAttrib(iRadii, 4, offset) - offset = enableAttrib(iColor0, 1, offset, GL_UNSIGNED_INT) - offset = enableAttrib(iColor1, 1, offset, GL_UNSIGNED_INT) + offset = enableAttribui(iColor0, 1, offset) + offset = enableAttribui(iColor1, 1, offset) offset = enableAttrib(iUVRect, 4, offset) enableAttrib(iThickness, 1, offset) } @@ -539,15 +539,24 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (GlCapabilities.isGl3Available) org.lwjgl.opengl.GL30.glBindVertexArray(prevVao) } - private fun enableAttrib(loc: Int, size: Int, offset: Long, type: Int = GL_FLOAT): Long { + private fun enableAttrib(loc: Int, size: Int, offset: Long): Long { glEnableVertexAttribArray(loc) - glVertexAttribPointer(loc, size, type, false, STRIDE * 4, offset) + glVertexAttribPointer(loc, size, GL_FLOAT, false, STRIDE * 4, offset) // I don't know why core disables the extension functions... but ok! if (GlCapabilities.isGl33Available) org.lwjgl.opengl.GL33.glVertexAttribDivisor(loc, 1) else org.lwjgl.opengl.ARBInstancedArrays.glVertexAttribDivisorARB(loc, 1) return offset + size * 4L } + private fun enableAttribui(loc: Int, size: Int, offset: Long): Long { + glEnableVertexAttribArray(loc) + if (GlCapabilities.isGl3Available) org.lwjgl.opengl.GL30.glVertexAttribIPointer(loc, size, GL_UNSIGNED_INT, STRIDE * 4, offset) + else org.lwjgl.opengl.EXTGPUShader4.glVertexAttribIPointerEXT(loc, size, GL_UNSIGNED_INT, STRIDE * 4, offset) + if (GlCapabilities.isGl33Available) org.lwjgl.opengl.GL33.glVertexAttribDivisor(loc, 1) + else org.lwjgl.opengl.ARBInstancedArrays.glVertexAttribDivisorARB(loc, 1) + return offset + size * 4L + } + override fun rect( x: Float, y: Float, width: Float, height: Float, color: Color, From 8020eec06b60e72fb3e58d5e88231d2361cde837 Mon Sep 17 00:00:00 2001 From: Deftu Date: Tue, 20 Jan 2026 09:29:52 +0200 Subject: [PATCH 24/47] do the stuff for the stuff --- bootstrap/build.gradle.kts | 2 + gradle/libs.versions.toml | 6 +- gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- minecraft/build.gradle.kts | 56 +++++++++++------- minecraft/root.gradle.kts | 48 ++++++++------- .../versions/26.1-fabric/gradle.properties | 4 ++ modules/dependencies/legacy/build.gradle.kts | 2 +- settings.gradle.kts | 6 +- 9 files changed, 74 insertions(+), 52 deletions(-) create mode 100644 minecraft/versions/26.1-fabric/gradle.properties diff --git a/bootstrap/build.gradle.kts b/bootstrap/build.gradle.kts index f70882630..a733224fe 100644 --- a/bootstrap/build.gradle.kts +++ b/bootstrap/build.gradle.kts @@ -6,6 +6,8 @@ import dev.deftu.gradle.utils.version.MinecraftReleaseVersion import org.polyfrost.gradle.provideFabricApiDependency import org.polyfrost.gradle.provideIncludedDependencies +println("[${mcData.version::class.java}] ${mcData.version}") + plugins { java alias(libs.plugins.kotlin) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9eedb80e5..572086f84 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,8 +21,8 @@ copycat = "0.1.3" copycat-image-awt = "0.1.1" # Per version -textile = "1.0.0-beta.11" -omnicore = "1.0.0-beta.40" +textile = "1.0.0-beta.17" +omnicore = "1.0.0-beta.41" lwjgl = "3.3.3" # All downloaded by the isolated-lwjgl3-loader # Legacy only @@ -35,7 +35,7 @@ brigadier = "1.0.18" oneconfig-loader = "1.1.0-alpha.48" # Gradle -dgt = "2.69.0" +dgt = "2.71.0" kotlinx-abi = "0.18.1" licenser = "2.1.1" jetbrains-idea-ext = "1.3" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 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 HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e2847c820..23449a2b5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/minecraft/build.gradle.kts b/minecraft/build.gradle.kts index 3bc5a32b2..244e80ca2 100644 --- a/minecraft/build.gradle.kts +++ b/minecraft/build.gradle.kts @@ -129,7 +129,7 @@ fun DependencyHandlerScope.handleApiDep(dependency: String, isMod: Boolean = fal fun DependencyHandlerScope.handleApiDep(dependency: ExternalModuleDependency, isMod: Boolean = false) { val dep = "${dependency.group}:${dependency.name}:${dependency.version}" - if (isMod) "oneConfigModulesCompileOnlyApi"(modApi(dep) { + if (isMod) "oneConfigModulesCompileOnlyApi"(maybeModApi(dep) { isTransitive = false attributes { attribute(includeInLoader, JBoolean.TRUE) @@ -167,7 +167,7 @@ dependencies { ) fun DependencyHandlerScope.compileOnlyCompat(notation: String?) = - notation?.let { modCompileOnly(it) { isTransitive = false } } + notation?.let { maybeModCompileOnly(it) { isTransitive = false } } fun DependencyHandlerScope.compileOnlyCompat(notation: CompatDependency?) { when { @@ -298,7 +298,7 @@ dependencies { if (mcData.isFabric) { provideFabricApiDependency(tripleVersion).forEach { @Suppress("USELESS_CAST") - modApi(if (it.dep is String) it.dep as String else "${(it.dep as ExternalModuleDependency).group}:${(it.dep as ExternalModuleDependency).name}:${(it.dep as ExternalModuleDependency).version}") { + maybeModApi(if (it.dep is String) it.dep as String else "${(it.dep as ExternalModuleDependency).group}:${(it.dep as ExternalModuleDependency).name}:${(it.dep as ExternalModuleDependency).version}") { isTransitive = false } } @@ -351,35 +351,43 @@ dependencies { } } - if ((mcData.version as MinecraftReleaseVersion).isNewerThan(MinecraftVersions.VERSION_1_21_4)) { + if (mcData.version > MinecraftVersions.VERSION_1_21_4) { compileOnly("net.azureaaron:dandelion:1.0.0-alpha.3") { isTransitive = false } } api("dev.deftu:enhancedeventbus:2.0.0") // TODO } tasks { + val manifestFunc = { manifest: Manifest -> + val attributesMap = buildMap { + putAll( + mapOf( + "Specification-Title" to modData.id, + "Specification-Vendor" to "Polyfrost", + "Specification-Version" to "1", // We are version 1 of ourselves, whatever the hell that means + "Implementation-Title" to rootProject.name, + "Implementation-Version" to project.version, + "Implementation-Vendor" to "Polyfrost", + "Implementation-Timestamp" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(Date()), + "OneConfig-Main-Class" to "org.polyfrost.oneconfig.internal.bootstrap.Bootstrap", + "MixinConfigs" to "mixins.oneconfigv1.init.json,mixins.oneconfigv1.json",) + ) + } + manifest.attributes(attributesMap) + Unit + } + withType(Jar::class) { exclude("**/**_Test.**") exclude("**/**_Test$**.**") } - remapJar { - manifest { - val attributesMap = buildMap { - putAll( - mapOf( - "Specification-Title" to modData.id, - "Specification-Vendor" to "Polyfrost", - "Specification-Version" to "1", // We are version 1 of ourselves, whatever the hell that means - "Implementation-Title" to rootProject.name, - "Implementation-Version" to project.version, - "Implementation-Vendor" to "Polyfrost", - "Implementation-Timestamp" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(Date()), - "OneConfig-Main-Class" to "org.polyfrost.oneconfig.internal.bootstrap.Bootstrap", - "MixinConfigs" to "mixins.oneconfigv1.init.json,mixins.oneconfigv1.json", - ) - ) - } - attributes(attributesMap) + if (mcData.version.isDrop) { + jar { + manifest(manifestFunc) + } + } else { + named("remapJar") { + manifest(manifestFunc) } } processResources { @@ -387,6 +395,10 @@ tasks { exclude("patched-lwjgl/**") } } + + fun Manifest.applyManifest() { + + } } afterEvaluate { diff --git a/minecraft/root.gradle.kts b/minecraft/root.gradle.kts index 4e213bc39..b1d822d5b 100644 --- a/minecraft/root.gradle.kts +++ b/minecraft/root.gradle.kts @@ -14,29 +14,31 @@ preprocess { strictExtraMappings.set(true) // FOR ALL NEW VERSIONS ENSURE TO UPDATE settings.gradle.kts ! - "1.21.11-fabric"(1_21_11, "srg") { - "1.21.11-neoforge"(1_21_11, "srg") { - "1.21.10-neoforge"(1_21_10, "srg") { - "1.21.10-fabric"(1_21_10, "srg") { - "1.21.8-fabric"(1_21_08, "srg") { - "1.21.8-neoforge"(1_21_08, "srg") { - "1.21.5-neoforge"(1_21_05, "srg") { - "1.21.5-fabric"(1_21_05, "srg") { - "1.21.4-fabric"(1_21_04, "srg") { - "1.21.4-neoforge"(1_21_04, "srg") { - "1.21.1-neoforge"(1_21_01, "srg", file("mappings/1.21.4-forge+1.21.1-forge.txt")) { - "1.21.1-fabric"(1_21_01, "srg") { - "1.20.4-fabric"(1_20_04, "srg") { - "1.20.4-neoforge"(1_20_04, "srg") { - "1.20.4-forge"(1_20_04, "srg") { - "1.20.1-forge"(1_20_01, "srg", file("mappings/1.20.4-forge+1.20.1-forge.txt")) { - "1.20.1-fabric"(1_20_01, "srg") { - "1.16.5-fabric"(1_16_05, "srg", file("mappings/1.20.1-fabric+1.16.5-fabric.txt")) { - "1.16.5-forge"(1_16_05, "srg") { - "1.12.2-forge"(1_12_02, "srg", file("mappings/1.16.5-forge+1.12.2-forge.txt")) { - "1.12.2-fabric"(1_12_02, "srg") { - "1.8.9-fabric"(1_08_09, "srg") { - "1.8.9-forge"(1_08_09, "srg") + "26.1-fabric"(26_01_00, "srg") { + "1.21.11-fabric"(1_21_11, "srg") { + "1.21.11-neoforge"(1_21_11, "srg") { + "1.21.10-neoforge"(1_21_10, "srg") { + "1.21.10-fabric"(1_21_10, "srg") { + "1.21.8-fabric"(1_21_08, "srg") { + "1.21.8-neoforge"(1_21_08, "srg") { + "1.21.5-neoforge"(1_21_05, "srg") { + "1.21.5-fabric"(1_21_05, "srg") { + "1.21.4-fabric"(1_21_04, "srg") { + "1.21.4-neoforge"(1_21_04, "srg") { + "1.21.1-neoforge"(1_21_01, "srg", file("mappings/1.21.4-forge+1.21.1-forge.txt")) { + "1.21.1-fabric"(1_21_01, "srg") { + "1.20.4-fabric"(1_20_04, "srg") { + "1.20.4-neoforge"(1_20_04, "srg") { + "1.20.4-forge"(1_20_04, "srg") { + "1.20.1-forge"(1_20_01, "srg", file("mappings/1.20.4-forge+1.20.1-forge.txt")) { + "1.20.1-fabric"(1_20_01, "srg") { + "1.16.5-fabric"(1_16_05, "srg", file("mappings/1.20.1-fabric+1.16.5-fabric.txt")) { + "1.16.5-forge"(1_16_05, "srg") { + "1.12.2-forge"(1_12_02, "srg", file("mappings/1.16.5-forge+1.12.2-forge.txt")) { + "1.12.2-fabric"(1_12_02, "srg") { + "1.8.9-fabric"(1_08_09, "srg") { + "1.8.9-forge"(1_08_09, "srg") + } } } } diff --git a/minecraft/versions/26.1-fabric/gradle.properties b/minecraft/versions/26.1-fabric/gradle.properties new file mode 100644 index 000000000..e6e3be017 --- /dev/null +++ b/minecraft/versions/26.1-fabric/gradle.properties @@ -0,0 +1,4 @@ +fabric.loom.disableObfuscation=true +dgt.loom.mappings.use=false +minecraft.version=26.1-snapshot-3 +dgt.fabric.api.version=0.141.3+26.1 diff --git a/modules/dependencies/legacy/build.gradle.kts b/modules/dependencies/legacy/build.gradle.kts index 27ed664f7..edd26cd99 100644 --- a/modules/dependencies/legacy/build.gradle.kts +++ b/modules/dependencies/legacy/build.gradle.kts @@ -1,7 +1,7 @@ import org.polyfrost.gradle.provideIncludedDependencies plugins { - id("dev.deftu.gradle.loom") + id("gg.essential.loom") } repositories { diff --git a/settings.gradle.kts b/settings.gradle.kts index 8fb912204..24d354335 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,8 +23,8 @@ pluginManagement { } plugins { - kotlin("jvm") version("2.2.10") - id("dev.deftu.gradle.multiversion-root") version("2.69.0") // Update in libs.versions.toml too!!! + kotlin("jvm") version("2.3.0") + id("dev.deftu.gradle.multiversion-root") version("2.70.0") // Update in libs.versions.toml too!!! } } @@ -113,6 +113,8 @@ listOf( "1.21.11-neoforge", "1.21.11-fabric", + + "26.1-fabric" ).forEach { version -> val proj = ":minecraft:$version" include(proj) From 903c0f92bb77e11852289f648c5b64cd7953e654 Mon Sep 17 00:00:00 2001 From: Deftu Date: Tue, 20 Jan 2026 13:52:22 +0200 Subject: [PATCH 25/47] Shenanigans have been thoroughly accounted for :3 --- .../org/polyfrost/gradle/addDependencies.kt | 43 +++++++++++++------ minecraft/build.gradle.kts | 18 +++++--- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt b/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt index fd61e4ecd..9cd3dfab6 100644 --- a/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt +++ b/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt @@ -14,7 +14,6 @@ private val legacyFabricApiModules = listOf( private val fabricApiModules = listOf( // command-api-v2 introduced in 1.19, transitive-access-wideners-v1 introduced in 1.18 "api-base", "lifecycle-events-v1", - "key-binding-api-v1", "rendering-v1", "screen-api-v1" ) @@ -43,6 +42,7 @@ private val fabricApiModuleVersions = mapOf( "api-base-12109" to "0.5.2+2fa446b294", // 1.21.9 "api-base-12110" to "1.0.0+14b92d8968", // 1.21.10 "api-base-12111" to "1.0.5+4ebb5c0853", // 1.21.11 + "api-base-260100" to "2.0.0+574290ba7d", // 26.1 "lifecycle-events-v1-common" to "1.1.0+2c3f108c81e6", // Common (Legacy Fabric API) "lifecycle-events-v1-10809" to "1.1.0+1.8.9+2c3f108c81e6", // 1.8.9 "lifecycle-events-v1-11202" to "1.1.0+1.12.2+2c3f108c81e6", // 1.12.2 @@ -65,6 +65,7 @@ private val fabricApiModuleVersions = mapOf( "lifecycle-events-v1-12109" to "2.6.8+33df5e6e94", // 1.21.9 "lifecycle-events-v1-12110" to "2.6.9+33df5e6e68", // 1.21.10 "lifecycle-events-v1-12111" to "2.6.15+4ebb5c0853", // 1.21.11 + "lifecycle-events-v1-260100" to "4.0.2+a208210e7d", // 26.1 "keybindings-api-v1-common" to "1.1.1+281301ea81e6", // Common (Legacy Fabric API) "keybindings-api-v1-10809" to "1.1.1+1.8.9+2c3f108c81e6", // 1.8.9 "keybindings-api-v1-11202" to "1.1.1+1.12.2+2c3f108c81e6", // 1.12.2 @@ -87,6 +88,7 @@ private val fabricApiModuleVersions = mapOf( "key-binding-api-v1-12109" to "1.1.0+4ec8267494", // 1.21.9 "key-binding-api-v1-12110" to "1.1.1+b3ba9c4868", // 1.21.10 "key-binding-api-v1-12111" to "1.1.7+4fc5413f53", // 1.21.11 + "key-mapping-api-v1-260100" to "2.0.0+574290ba7d", // 26.1 "rendering-api-v1-common" to "1.0.0+7c545fdb81e6", // Common (Legacy Fabric API) "rendering-api-v1-10809" to "1.0.0+1.8.9+2c3f108c81e6", // 1.8.9 "rendering-api-v1-11202" to "1.0.0+1.8.9+2c3f108c81e6", // 1.12.2 @@ -109,6 +111,7 @@ private val fabricApiModuleVersions = mapOf( "rendering-v1-12109" to "15.0.2+9bce411b94", // 1.21.9 "rendering-v1-12110" to "16.0.1+328a75ba68", // 1.21.10 "rendering-v1-12111" to "16.2.5+1fb1cde953", // 1.21.11 + "rendering-v1-260100" to "18.0.0+a9f246707d", // 26.1 "screen-api-v1-11605" to "1.0.1+3cc0f0907d", // 1.16.5 "screen-api-v1-11701" to "1.0.5+cf39a74318", // 1.17.1 "screen-api-v1-11802" to "1.0.11+d882b91560", // 1.18.2 @@ -128,6 +131,7 @@ private val fabricApiModuleVersions = mapOf( "screen-api-v1-12109" to "3.0.2+86b3ae5794", // 1.21.9 "screen-api-v1-12110" to "3.1.0+9c82a79868", // 1.21.10 "screen-api-v1-12111" to "3.1.7+4ebb5c0853", // 1.21.11 + "screen-api-v1-260100" to "4.0.0+574290ba7d", // 26.1 "command-api-v1-11605" to "1.1.3+3cc0f0907d", // 1.16.5 "command-api-v1-11701" to "1.1.4+cf39a74318", // 1.17.1 "command-api-v1-11802" to "1.1.10+d7c144a860", // 1.18.2 @@ -147,6 +151,7 @@ private val fabricApiModuleVersions = mapOf( "command-api-v2-12109" to "2.3.5+33df5e6e94", // 1.21.9 "command-api-v2-12110" to "2.3.7+328a75ba68", // 1.21.10 "command-api-v2-12111" to "2.4.6+4ebb5c0853", // 1.21.11 + "command-api-v2-260100" to "3.0.0+574290ba7d", // 26.1 "transitive-access-wideners-v1-11802" to "1.1.0+e747827960", // 1.18.2 "transitive-access-wideners-v1-11902" to "1.3.3+08b73de490", // 1.19.2 "transitive-access-wideners-v1-11904" to "3.3.0+1b5f819af4", // 1.19.4 @@ -164,6 +169,7 @@ private val fabricApiModuleVersions = mapOf( "transitive-access-wideners-v1-12109" to "6.5.2+5d9dbead94", // 1.21.9 "transitive-access-wideners-v1-12110" to "6.5.3+41eb434368", // 1.21.10 "transitive-access-wideners-v1-12111" to "7.0.7+1fb1cde953", // 1.21.11 + "transitive-access-wideners-v1-260100" to "8.0.1+a208210e7d", // 26.1 ) /** @@ -172,7 +178,7 @@ private val fabricApiModuleVersions = mapOf( * @param version The version of Minecraft. If null, the method is running inside the `:dependencies:legacy` module. * @param loader The mod loader being used. */ -fun Project.provideIncludedDependencies(version: Triple?, loader: String?): List { // Either a String or ExternalModuleDependency +fun Project.provideIncludedDependencies(version: Triple?, loader: String?, shenanigans: String? = version?.toMCVer()): List { // Either a String or ExternalModuleDependency project.logger.lifecycle("===> Adding dependencies for Minecraft ${version?.toMCVer()} & $loader") val libs = rootProject @@ -201,17 +207,21 @@ fun Project.provideIncludedDependencies(version: Triple?, loader: deps.add(libs.findLibrary("copycat-image-awt").get().get()) - if (version != null && version.second >= 16) { + if (version != null && (version.second >= 16 || version.first >= 2)) { logger.lifecycle("===> Adding LWJGL dependencies for Minecraft ${version.toMCVer()} & $loader") // Modern (1.16+) val lwjglBase = "org.lwjgl:lwjgl" - val lwjglVersion = when (version.second) { - in 16..18 -> "3.2.2" - 19 -> "3.3.1" - 20 -> "3.3.2" - 21 -> "3.3.3" - else -> error("Unsupported Minecraft version: ${version.toMCVer()}") + val lwjglVersion = if (version.first >= 2) { + "3.3.3" + } else { + when (version.second) { + in 16..18 -> "3.2.2" + 19 -> "3.3.1" + 20 -> "3.3.2" + 21 -> "3.3.3" + else -> error("Unsupported Minecraft version: ${version.toMCVer()}") + } } deps.add("$lwjglBase-tinyfd:$lwjglVersion") @@ -243,8 +253,8 @@ fun Project.provideIncludedDependencies(version: Triple?, loader: actualDeps.add(OCDependency(dep)) } if (version != null) { - actualDeps.add(OCDependency("dev.deftu:textile-${version.toMCVer()}-$loader:${libs.findVersion("textile").get().displayName}", true)) - actualDeps.add(OCDependency("dev.deftu:omnicore-${version.toMCVer()}-$loader:${libs.findVersion("omnicore").get().displayName}", true)) + actualDeps.add(OCDependency("dev.deftu:textile-${shenanigans}-$loader:${libs.findVersion("textile").get().displayName}", true)) + actualDeps.add(OCDependency("dev.deftu:omnicore-${shenanigans}-$loader:${libs.findVersion("omnicore").get().displayName}", true)) } return actualDeps @@ -253,7 +263,7 @@ fun Project.provideIncludedDependencies(version: Triple?, loader: fun Project.provideFabricApiDependency(version: Triple): List { val deps = mutableListOf() - if (version.second <= 12) { + if (version.first == 1 && version.second <= 12) { // Legacy Fabric for (module in legacyFabricApiModules) { val commonVersionValue = fabricApiModuleVersions["$module-common"] ?: error("No version found for $module-common") @@ -265,14 +275,19 @@ fun Project.provideFabricApiDependency(version: Triple): List() finalList.addAll(fabricApiModules) - if (version.second >= 18) { + if (version.first >= 2 || version.second >= 18) { finalList.add("transitive-access-wideners-v1") } - if (version.second >= 19) { + if (version.first >= 2 || version.second >= 19) { finalList.add("command-api-v2") } else { finalList.add("command-api-v1") } + if (version.first >= 2) { + finalList.add("key-mapping-api-v1") + } else { + finalList.add("key-binding-api-v1") + } for (module in finalList) { val mcVersionValue = fabricApiModuleVersions["$module-${version.toPreprocessorNumber()}"] ?: error("No version found for $module-${version.toMCVer()}") deps.add(OCDependency("net.fabricmc.fabric-api:fabric-$module:$mcVersionValue", true)) diff --git a/minecraft/build.gradle.kts b/minecraft/build.gradle.kts index 244e80ca2..a3570736b 100644 --- a/minecraft/build.gradle.kts +++ b/minecraft/build.gradle.kts @@ -6,8 +6,10 @@ import com.replaymod.gradle.preprocess.PreprocessTask import com.replaymod.gradle.preprocess.ProjectGraphNode import com.replaymod.gradle.preprocess.RootPreprocessExtension import dev.deftu.gradle.utils.GameSide +import dev.deftu.gradle.utils.version.MinecraftDropVersion import dev.deftu.gradle.utils.version.MinecraftReleaseVersion import dev.deftu.gradle.utils.version.MinecraftVersions +import dev.deftu.gradle.utils.version.patchless import gg.essential.gradle.util.RelocationTransform.Companion.registerRelocationAttribute import gg.essential.gradle.util.prebundle import org.gradle.kotlin.dsl.invoke @@ -177,9 +179,14 @@ dependencies { } } - val mcVersion = mcData.version as MinecraftReleaseVersion - val tripleVersion = Triple(mcVersion.major, mcVersion.minor, mcVersion.patch) - val mcVersionString = listOf(mcVersion.major, mcVersion.minor, mcVersion.patch).joinToString(".") + val mcVersion = mcData.version + val tripleVersion = when (mcVersion) { + is MinecraftDropVersion -> Triple(mcVersion.year, mcVersion.drop, mcVersion.patch) + is MinecraftReleaseVersion -> Triple(mcVersion.major, mcVersion.minor, mcVersion.patch) + else -> error("no") + } + + val mcVersionString = mcData.version.patchless compileOnlyCompat("gg.essential:vigilance-1.8.9-forge:299") compileOnlyCompat("org.notenoughupdates.moulconfig:common:3.11.0") @@ -284,8 +291,9 @@ dependencies { provideIncludedDependencies( - Triple(mcVersion.major, mcVersion.minor, mcVersion.patch), - mcData.loader.friendlyString + tripleVersion, + mcData.loader.friendlyString, + mcVersion.toString() ).forEach { if (it.dep is String) { @Suppress("USELESS_CAST") From 9cb1963d9872c971807dd2ef19928e5be3e04cd3 Mon Sep 17 00:00:00 2001 From: Deftu Date: Tue, 20 Jan 2026 14:04:24 +0200 Subject: [PATCH 26/47] We need toString not patchless --- minecraft/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minecraft/build.gradle.kts b/minecraft/build.gradle.kts index a3570736b..7196ecc22 100644 --- a/minecraft/build.gradle.kts +++ b/minecraft/build.gradle.kts @@ -186,7 +186,7 @@ dependencies { else -> error("no") } - val mcVersionString = mcData.version.patchless + val mcVersionString = mcData.version.toString() compileOnlyCompat("gg.essential:vigilance-1.8.9-forge:299") compileOnlyCompat("org.notenoughupdates.moulconfig:common:3.11.0") From bc4491e5e0280214a338ff559fab6d1648869ef7 Mon Sep 17 00:00:00 2001 From: Deftu Date: Wed, 21 Jan 2026 14:36:15 +0200 Subject: [PATCH 27/47] Minecraft 26.1 is mostly functional now --- gradle.properties | 2 +- gradle/libs.versions.toml | 2 +- minecraft/src/main/resources/fabric.mod.json | 2 +- .../polyfrost/oneconfig/internal/compat/ModMenuCompat.kt | 2 +- .../compat/yacl/Mixin_YetAnotherConfigLib_Builder.java | 2 ++ .../compat/yacl/AbstractDropdownControllerCompat.kt | 2 ++ .../oneconfig/internal/compat/yacl/ExtraHandler.kt | 2 ++ .../oneconfig/internal/compat/yacl/ExtraV1Handlers.kt | 3 +++ .../oneconfig/internal/compat/yacl/YaclV1Compat.kt | 2 ++ .../mixin/compat/rconfig/Mixin_Configurations.java | 2 ++ .../polyfrost/oneconfig/internal/compat/RConfigCompat.kt | 2 +- .../polyfrost/oneconfig/internal/compat/RConfigCompat.kt | 4 +++- modules/relocator/src/main/kotlin/utils.kt | 9 +++++++-- settings.gradle.kts | 2 +- 14 files changed, 29 insertions(+), 9 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5b1af1b5c..1ee718262 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ ksp.incremental=false dgt.java.version=8 dgt.loom.mappings=official-like -dgt.minecraft.revision=4 +dgt.minecraft.revision=5 # Project Configuration project.group=org.polyfrost.oneconfig diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 572086f84..83d6cb783 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -35,7 +35,7 @@ brigadier = "1.0.18" oneconfig-loader = "1.1.0-alpha.48" # Gradle -dgt = "2.71.0" +dgt = "2.72.0" kotlinx-abi = "0.18.1" licenser = "2.1.1" jetbrains-idea-ext = "1.3" diff --git a/minecraft/src/main/resources/fabric.mod.json b/minecraft/src/main/resources/fabric.mod.json index 249b1b465..42b0ec77b 100644 --- a/minecraft/src/main/resources/fabric.mod.json +++ b/minecraft/src/main/resources/fabric.mod.json @@ -28,7 +28,7 @@ }, "depends": { "fabricloader": ">=0.12.0", - "minecraft": "${mc_version}" + "minecraft": "${fabric_mc_version}" }, "custom": { "modmenu": { diff --git a/minecraft/versions/1.16.5-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/ModMenuCompat.kt b/minecraft/versions/1.16.5-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/ModMenuCompat.kt index a79510d64..fc4dc4785 100644 --- a/minecraft/versions/1.16.5-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/ModMenuCompat.kt +++ b/minecraft/versions/1.16.5-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/ModMenuCompat.kt @@ -1,6 +1,6 @@ package org.polyfrost.oneconfig.internal.compat -//#if FABRIC +//#if FABRIC && MC < 26.1 import com.terraformersmc.modmenu.ModMenu import com.terraformersmc.modmenu.util.mod.Mod import dev.deftu.omnicore.api.client.screen.currentScreen diff --git a/minecraft/versions/1.20.1-fabric/src/main/java/org/polyfrost/oneconfig/internal/mixin/compat/yacl/Mixin_YetAnotherConfigLib_Builder.java b/minecraft/versions/1.20.1-fabric/src/main/java/org/polyfrost/oneconfig/internal/mixin/compat/yacl/Mixin_YetAnotherConfigLib_Builder.java index ceaa07dda..566cb443d 100644 --- a/minecraft/versions/1.20.1-fabric/src/main/java/org/polyfrost/oneconfig/internal/mixin/compat/yacl/Mixin_YetAnotherConfigLib_Builder.java +++ b/minecraft/versions/1.20.1-fabric/src/main/java/org/polyfrost/oneconfig/internal/mixin/compat/yacl/Mixin_YetAnotherConfigLib_Builder.java @@ -1,5 +1,6 @@ package org.polyfrost.oneconfig.internal.mixin.compat.yacl; +//#if MC < 26.1 //#if MC != 1.20.4 || FABRIC import dev.isxander.yacl3.api.ConfigCategory; import dev.isxander.yacl3.api.YetAnotherConfigLib; @@ -27,4 +28,5 @@ public void build(CallbackInfoReturnable cir) { YaclV1Compat.build(title, categories, saveFunction); } } +//#endif //#endif \ No newline at end of file diff --git a/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/AbstractDropdownControllerCompat.kt b/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/AbstractDropdownControllerCompat.kt index 8cd244676..7d6f6e9c1 100644 --- a/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/AbstractDropdownControllerCompat.kt +++ b/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/AbstractDropdownControllerCompat.kt @@ -1,5 +1,6 @@ package org.polyfrost.oneconfig.internal.compat.yacl +//#if MC < 26.1 //#if MC != 1.20.4 || FABRIC import dev.isxander.yacl3.api.Controller import dev.isxander.yacl3.gui.controllers.dropdown.AbstractDropdownController @@ -25,4 +26,5 @@ internal object AbstractDropdownControllerCompat : ExtraHandler> { fun handle(controller: Controller<*>, builder: YaclPropertyBuilder): Class? } +//#endif //#endif \ No newline at end of file diff --git a/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/ExtraV1Handlers.kt b/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/ExtraV1Handlers.kt index 55d3a539c..f41777303 100644 --- a/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/ExtraV1Handlers.kt +++ b/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/ExtraV1Handlers.kt @@ -1,8 +1,11 @@ package org.polyfrost.oneconfig.internal.compat.yacl + +//#if MC < 26.1 //#if MC != 1.20.4 || FABRIC object ExtraV1Handlers { init { extraYaclHandlers.add(AbstractDropdownControllerCompat) } } +//#endif //#endif \ No newline at end of file diff --git a/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/YaclV1Compat.kt b/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/YaclV1Compat.kt index 923f90b54..2f6e6a427 100644 --- a/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/YaclV1Compat.kt +++ b/minecraft/versions/1.20.1-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/yacl/YaclV1Compat.kt @@ -4,6 +4,7 @@ import dev.deftu.omnicore.api.client.getIconResource import dev.deftu.omnicore.api.client.getIconResourcePath import net.minecraft.network.chat.Component as Text // preprocessor moment, ping me (wyvest) if you want an explanation why this is needed +//#if MC < 26.1 //#if MC != 1.20.4 || FABRIC import dev.deftu.omnicore.api.loader.ModInfo import dev.isxander.yacl3.api.ConfigCategory @@ -207,4 +208,5 @@ internal class YaclPropertyBuilder internal constructor(option: Option<*>) { this@YaclPropertyBuilder.metadata.entries.forEach { (key, value) -> addMetadata(key, value) } } } +//#endif //#endif \ No newline at end of file diff --git a/minecraft/versions/1.20.4-forge/src/main/java/org/polyfrost/oneconfig/internal/mixin/compat/rconfig/Mixin_Configurations.java b/minecraft/versions/1.20.4-forge/src/main/java/org/polyfrost/oneconfig/internal/mixin/compat/rconfig/Mixin_Configurations.java index c96ee9c3b..1e5503669 100644 --- a/minecraft/versions/1.20.4-forge/src/main/java/org/polyfrost/oneconfig/internal/mixin/compat/rconfig/Mixin_Configurations.java +++ b/minecraft/versions/1.20.4-forge/src/main/java/org/polyfrost/oneconfig/internal/mixin/compat/rconfig/Mixin_Configurations.java @@ -1,5 +1,6 @@ package org.polyfrost.oneconfig.internal.mixin.compat.rconfig; +//#if MC < 26.1 import com.llamalad7.mixinextras.sugar.Local; import com.teamresourceful.resourcefulconfig.api.types.ResourcefulConfig; import com.teamresourceful.resourcefulconfig.common.config.Configurations; @@ -25,3 +26,4 @@ private void addConfig(CallbackInfo ci, @Local(argsOnly = true) ResourcefulConfi } } +//#endif diff --git a/minecraft/versions/1.20.4-forge/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/RConfigCompat.kt b/minecraft/versions/1.20.4-forge/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/RConfigCompat.kt index b19db31fa..ab459f0db 100644 --- a/minecraft/versions/1.20.4-forge/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/RConfigCompat.kt +++ b/minecraft/versions/1.20.4-forge/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/RConfigCompat.kt @@ -168,4 +168,4 @@ internal object RConfigCompat { } } -} \ No newline at end of file +} diff --git a/minecraft/versions/1.21.5-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/RConfigCompat.kt b/minecraft/versions/1.21.5-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/RConfigCompat.kt index f48c37bdf..f142d5487 100644 --- a/minecraft/versions/1.21.5-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/RConfigCompat.kt +++ b/minecraft/versions/1.21.5-fabric/src/main/kotlin/org/polyfrost/oneconfig/internal/compat/RConfigCompat.kt @@ -1,5 +1,6 @@ package org.polyfrost.oneconfig.internal.compat +//#if MC < 26.1 import com.teamresourceful.resourcefulconfig.api.types.ResourcefulConfig import com.teamresourceful.resourcefulconfig.api.types.ResourcefulConfigButton import com.teamresourceful.resourcefulconfig.api.types.ResourcefulConfigElement @@ -191,4 +192,5 @@ internal object RConfigCompat { } } -} \ No newline at end of file +} +//#endif diff --git a/modules/relocator/src/main/kotlin/utils.kt b/modules/relocator/src/main/kotlin/utils.kt index 885ab53e7..3754003e4 100644 --- a/modules/relocator/src/main/kotlin/utils.kt +++ b/modules/relocator/src/main/kotlin/utils.kt @@ -11,9 +11,14 @@ internal enum class SourceKind(val fileExtension: String) { ; } -internal fun convertStringToIntVersion(version: String) = - version.let { if (it.count { char -> char == '.' } == 1) "$it.0" else it }.split(".") +internal fun convertStringToIntVersion(version: String): Int { + val version = if (version.substringBefore('.') != "1") { + version.substringBefore("-") + } else version + + return version.let { if (it.count { char -> char == '.' } == 1) "$it.0" else it }.split(".") .joinToString("") { it.padStart(2, '0') }.toInt() +} internal enum class SourceLocation(val path: String) { PRE_PROCESSED("build/preprocessed/main"), diff --git a/settings.gradle.kts b/settings.gradle.kts index 24d354335..7f551d99e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,7 +24,7 @@ pluginManagement { plugins { kotlin("jvm") version("2.3.0") - id("dev.deftu.gradle.multiversion-root") version("2.70.0") // Update in libs.versions.toml too!!! + id("dev.deftu.gradle.multiversion-root") version("2.72.0") // Update in libs.versions.toml too!!! } } From 50a258791eb18cd1572e86c3d784d018909e564c Mon Sep 17 00:00:00 2001 From: Deftu Date: Thu, 22 Jan 2026 09:54:44 +0200 Subject: [PATCH 28/47] stuff --- bootstrap/build.gradle.kts | 2 -- gradle/libs.versions.toml | 6 +++--- minecraft/build.gradle.kts | 5 ----- settings.gradle.kts | 2 +- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/bootstrap/build.gradle.kts b/bootstrap/build.gradle.kts index a733224fe..f70882630 100644 --- a/bootstrap/build.gradle.kts +++ b/bootstrap/build.gradle.kts @@ -6,8 +6,6 @@ import dev.deftu.gradle.utils.version.MinecraftReleaseVersion import org.polyfrost.gradle.provideFabricApiDependency import org.polyfrost.gradle.provideIncludedDependencies -println("[${mcData.version::class.java}] ${mcData.version}") - plugins { java alias(libs.plugins.kotlin) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 83d6cb783..547c6fb8d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,10 +2,10 @@ # Libraries # All -kotlin = "2.2.10" +kotlin = "2.3.0" kotlinx-coroutines = "1.10.2" kotlinx-atomicfu = "0.29.0" -fabric-language-kotlin = "1.13.5+kotlin.2.2.10" +fabric-language-kotlin = "1.13.8+kotlin.2.3.0" google-ksp = "2.2.10-2.0.2" polyui = "2.0.7" annotations = "24.1.0" @@ -35,7 +35,7 @@ brigadier = "1.0.18" oneconfig-loader = "1.1.0-alpha.48" # Gradle -dgt = "2.72.0" +dgt = "2.73.0" kotlinx-abi = "0.18.1" licenser = "2.1.1" jetbrains-idea-ext = "1.3" diff --git a/minecraft/build.gradle.kts b/minecraft/build.gradle.kts index 7196ecc22..0716b1fb8 100644 --- a/minecraft/build.gradle.kts +++ b/minecraft/build.gradle.kts @@ -9,7 +9,6 @@ import dev.deftu.gradle.utils.GameSide import dev.deftu.gradle.utils.version.MinecraftDropVersion import dev.deftu.gradle.utils.version.MinecraftReleaseVersion import dev.deftu.gradle.utils.version.MinecraftVersions -import dev.deftu.gradle.utils.version.patchless import gg.essential.gradle.util.RelocationTransform.Companion.registerRelocationAttribute import gg.essential.gradle.util.prebundle import org.gradle.kotlin.dsl.invoke @@ -403,10 +402,6 @@ tasks { exclude("patched-lwjgl/**") } } - - fun Manifest.applyManifest() { - - } } afterEvaluate { diff --git a/settings.gradle.kts b/settings.gradle.kts index 7f551d99e..6c846bbe4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,7 +24,7 @@ pluginManagement { plugins { kotlin("jvm") version("2.3.0") - id("dev.deftu.gradle.multiversion-root") version("2.72.0") // Update in libs.versions.toml too!!! + id("dev.deftu.gradle.multiversion-root") version("2.73.0") // Update in libs.versions.toml too!!! } } From 02d97bfcf131f1f13d35e9d57e3d9792545e3b30 Mon Sep 17 00:00:00 2001 From: Deftu Date: Sat, 24 Jan 2026 20:22:36 +0200 Subject: [PATCH 29/47] al;l of the stuff is worky hooray --- gradle/libs.versions.toml | 2 +- .../java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java | 8 +++++++- .../oneconfig/api/ui/v1/internal/GLRendererImpl.kt | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 547c6fb8d..12153281a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kotlinx-coroutines = "1.10.2" kotlinx-atomicfu = "0.29.0" fabric-language-kotlin = "1.13.8+kotlin.2.3.0" google-ksp = "2.2.10-2.0.2" -polyui = "2.0.7" +polyui = "2.1.1" annotations = "24.1.0" hypixel-modapi = "1.0.1" hypixel-data = "0.2.0" # Dep of hypixel-modapi diff --git a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java index e911aa8a7..6a236d011 100644 --- a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java +++ b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java @@ -59,6 +59,7 @@ import org.polyfrost.polyui.data.Font; import org.polyfrost.polyui.renderer.Renderer; import org.polyfrost.polyui.renderer.Window; +import org.polyfrost.polyui.unit.Vec2; import java.util.ServiceLoader; import java.util.function.Consumer; @@ -190,7 +191,12 @@ default PolyUI createDefault() { EventManager.register(ResizeEvent.class, event -> { float ratio = Platform.screen().pixelRatio(); polyUI.resize(event.newWidth, event.newHeight, false); - framebuffer.resize((int) (polyUI.getMaster().getWidth() * ratio), (int) (polyUI.getMaster().getHeight() * ratio)); + + long visibleSize = polyUI.getVisibleSize(); + int polyUiWidth = (int) Vec2.getX(visibleSize); + int polyUiHeight = (int) Vec2.getY(visibleSize); + System.out.println("Resizing to: " + polyUiWidth + "x" + polyUiHeight + " with ratio " + ratio); + framebuffer.resize(polyUiWidth, polyUiHeight); polyUI.getWindow().setPixelRatio(ratio); }); diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 14db6be4f..4df148238 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -16,6 +16,7 @@ import org.lwjgl.opengl.GL13.* import org.lwjgl.opengl.GL14.* import org.lwjgl.opengl.GL15.* import org.lwjgl.opengl.GL20.* +import org.lwjgl.opengl.GL33.glBindSampler import org.polyfrost.oneconfig.api.platform.v1.Platform import org.polyfrost.oneconfig.api.ui.v1.UIManager import org.polyfrost.oneconfig.api.ui.v1.api.NanoSvgApi @@ -502,6 +503,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, atlas) + glBindSampler(0, 0) // asm: on VAO the state is stored, so we only need to set it up once if (!GlCapabilities.isGl3Available) { From 309e9655c1b323cead22f9888f211e6bb475e08e Mon Sep 17 00:00:00 2001 From: Wyvest Date: Sat, 24 Jan 2026 13:27:33 -0500 Subject: [PATCH 30/47] Add version '26.1-fabric' to settings.gradle.kts --- settings.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/settings.gradle.kts b/settings.gradle.kts index b11d6d9c5..7867db321 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -133,6 +133,7 @@ listOf( "1.21.8-fabric", "1.21.10-fabric", "1.21.11-fabric", + "26.1-fabric" ).contains(version)) { include(bootstrapProj) project(bootstrapProj).apply { From 95bf6c54b5af3c04207a3048f647920e352376c1 Mon Sep 17 00:00:00 2001 From: Wyvest Date: Sat, 24 Jan 2026 13:38:28 -0500 Subject: [PATCH 31/47] Update Java version from 21 to 25 in build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cc1919a99..480965bfa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,7 +47,7 @@ jobs: - name: Setup Java uses: actions/setup-java@v4 with: - java-version: 21 + java-version: 25 distribution: temurin - name: Setup Gradle From 571217dfe39002a0ab931f7c78f3e911b328a98c Mon Sep 17 00:00:00 2001 From: Wyvest Date: Sat, 24 Jan 2026 13:53:13 -0500 Subject: [PATCH 32/47] Create gradle.properties --- bootstrap/versions/26.1-fabric/gradle.properties | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 bootstrap/versions/26.1-fabric/gradle.properties diff --git a/bootstrap/versions/26.1-fabric/gradle.properties b/bootstrap/versions/26.1-fabric/gradle.properties new file mode 100644 index 000000000..18f4546dc --- /dev/null +++ b/bootstrap/versions/26.1-fabric/gradle.properties @@ -0,0 +1,4 @@ +fabric.loom.disableObfuscation=true +dgt.loom.mappings.use=false +minecraft.version=26.1-snapshot-3 +dgt.fabric.api.version=0.141.3+26.1 \ No newline at end of file From fe6cb684eef4cd9a4f7d72897a976b66f841e010 Mon Sep 17 00:00:00 2001 From: Wyvest Date: Sat, 24 Jan 2026 13:55:02 -0500 Subject: [PATCH 33/47] Update build.gradle.kts --- modules/dependencies/legacy/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dependencies/legacy/build.gradle.kts b/modules/dependencies/legacy/build.gradle.kts index 27ed664f7..edd26cd99 100644 --- a/modules/dependencies/legacy/build.gradle.kts +++ b/modules/dependencies/legacy/build.gradle.kts @@ -1,7 +1,7 @@ import org.polyfrost.gradle.provideIncludedDependencies plugins { - id("dev.deftu.gradle.loom") + id("gg.essential.loom") } repositories { From 641a8cb0d041a4c4bd5cc91f97fbb236e5dbf1eb Mon Sep 17 00:00:00 2001 From: Wyvest Date: Sat, 24 Jan 2026 15:00:24 -0500 Subject: [PATCH 34/47] Add bootstrap node for fabric version 26.1 --- bootstrap/root.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bootstrap/root.gradle.kts b/bootstrap/root.gradle.kts index 066c73440..0d5c78439 100644 --- a/bootstrap/root.gradle.kts +++ b/bootstrap/root.gradle.kts @@ -22,6 +22,7 @@ preprocess { val fabric12108 = createNode("bootstrap-1.21.8-fabric", 1_21_08, "yarn") val fabric12110 = createNode("bootstrap-1.21.10-fabric", 1_21_10, "yarn") val fabric12111 = createNode("bootstrap-1.21.11-fabric", 1_21_11, "yarn") + val fabric261 = createNode("bootstrap-26.1-fabric", 26_01_00, "yarn") forge11202.link(forge10809) forge11605.link(forge11202) @@ -32,6 +33,7 @@ preprocess { fabric12108.link(fabric12105) fabric12110.link(fabric12108) fabric12111.link(fabric12110) + fabric261.link(fabric12111) strictExtraMappings.set(true) } From 2b78b721f5193cfce4061c457c940ed94b62ebf3 Mon Sep 17 00:00:00 2001 From: Deftu Date: Sun, 25 Jan 2026 20:14:29 +0200 Subject: [PATCH 35/47] Update GLRendererImpl.kt --- .../oneconfig/api/ui/v1/internal/GLRendererImpl.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 4df148238..6ad83a8bf 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -363,10 +363,10 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re require("GL_EXT_gpu_shader4" in extensions) { "GL_EXT_gpu_shader4 is not supported and is required" } require("GL_ARB_instanced_arrays" in extensions) { "GL_ARB_instanced_arrays is not supported and is required" } require("GL_ARB_draw_instanced" in extensions) { "GL_ARB_draw_instanced is not supported and is required" } -// if ("GL_EXT_framebuffer_object" in extensions) { -// LOGGER.info("Using mipmaps as extension GL_EXT_framebuffer_object is available") -// mipmapMode = 2 -// } + if ("GL_EXT_framebuffer_object" in extensions) { + LOGGER.info("Using mipmaps as extension GL_EXT_framebuffer_object is available") + mipmapMode = 2 + } } } @@ -680,7 +680,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re var penX = x val scaleFactor = fontSize / fAtlas.renderedSize - val penY = y + (fAtlas.ascent + fAtlas.descent) * scaleFactor + val penY = (y + (fAtlas.ascent + fAtlas.descent) * scaleFactor) + 2f val col = java.lang.Float.intBitsToFloat(color.argb.capAlpha()) val buffer = buffer @@ -948,6 +948,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private fun getFontAtlas(font: Font, fontSize: Float): FontAtlas { val renderSize = when (fontSize) { + in 0f..16f -> 6f in 0f..36f -> 24f else -> 48f } From d67f62bb3ab7f7fe89b0cd422f47435ce21f024f Mon Sep 17 00:00:00 2001 From: Deftu Date: Mon, 26 Jan 2026 19:05:01 +0200 Subject: [PATCH 36/47] Fix Gradle error --- settings.gradle.kts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 7867db321..b10c3d6b2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -119,7 +119,11 @@ listOf( val proj = ":minecraft:$version" include(proj) project(proj).apply { - projectDir = file("minecraft/versions/$version") + projectDir = file("minecraft/versions/$version").also { + if (!it.exists() && !it.mkdirs()) { + throw IllegalStateException("Could not create project directory: ${it.absolutePath}") + } + } buildFileName = "../../build.gradle.kts" } val bootstrapProj = ":bootstrap:bootstrap-$version" @@ -137,7 +141,11 @@ listOf( ).contains(version)) { include(bootstrapProj) project(bootstrapProj).apply { - projectDir = file("bootstrap/versions/$version") + projectDir = file("bootstrap/versions/$version").also { + if (!it.exists() && !it.mkdirs()) { + throw IllegalStateException("Could not create project directory: ${it.absolutePath}") + } + } buildFileName = "../../build.gradle.kts" } } From 71b417c2e27ade7e2e8c9b16adc8efd78d820bba Mon Sep 17 00:00:00 2001 From: Deftu Date: Mon, 26 Jan 2026 19:31:58 +0200 Subject: [PATCH 37/47] Fix more Gradle errors --- bootstrap/build.gradle.kts | 15 +++++++++++---- settings.gradle.kts | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/bootstrap/build.gradle.kts b/bootstrap/build.gradle.kts index f70882630..3ef13fdb5 100644 --- a/bootstrap/build.gradle.kts +++ b/bootstrap/build.gradle.kts @@ -2,6 +2,7 @@ import dev.deftu.gradle.utils.GameSide import dev.deftu.gradle.utils.includeOrShade +import dev.deftu.gradle.utils.version.MinecraftDropVersion import dev.deftu.gradle.utils.version.MinecraftReleaseVersion import org.polyfrost.gradle.provideFabricApiDependency import org.polyfrost.gradle.provideIncludedDependencies @@ -39,9 +40,15 @@ repositories { dependencies { if (mcData.version.preprocessorKey >= 11300 || mcData.isFabric) { - val mcVersion = mcData.version as MinecraftReleaseVersion + val mcVersion = mcData.version + val tripleVersion = when (mcVersion) { + is MinecraftDropVersion -> Triple(mcVersion.year, mcVersion.drop, mcVersion.patch) + is MinecraftReleaseVersion -> Triple(mcVersion.major, mcVersion.minor, mcVersion.patch) + else -> error("no") + } + provideIncludedDependencies( - Triple(mcVersion.major, mcVersion.minor, mcVersion.patch), + tripleVersion, mcData.loader.friendlyString ).forEach { includeOrShade(compileOnly(it.dep)!!) @@ -54,9 +61,9 @@ dependencies { } includeOrShade(compileOnly(project(":minecraft:$mcData")) { isTransitive = false }) if (mcData.isFabric) { - provideFabricApiDependency(Triple(mcVersion.major, mcVersion.minor, mcVersion.patch)).forEach { + provideFabricApiDependency(tripleVersion).forEach { @Suppress("USELESS_CAST") - includeOrShade(modCompileOnly(if (it.dep is String) it.dep as String else "${(it.dep as ExternalModuleDependency).group}:${(it.dep as ExternalModuleDependency).name}:${(it.dep as ExternalModuleDependency).version}") { + includeOrShade(maybeModCompileOnly(if (it.dep is String) it.dep as String else "${(it.dep as ExternalModuleDependency).group}:${(it.dep as ExternalModuleDependency).name}:${(it.dep as ExternalModuleDependency).version}") { isTransitive = false }) } diff --git a/settings.gradle.kts b/settings.gradle.kts index b10c3d6b2..8509aa6fd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -137,7 +137,7 @@ listOf( "1.21.8-fabric", "1.21.10-fabric", "1.21.11-fabric", - "26.1-fabric" +// "26.1-fabric" ).contains(version)) { include(bootstrapProj) project(bootstrapProj).apply { From a8edef4c389d441d87a11ed497405932a00d4bdb Mon Sep 17 00:00:00 2001 From: Deftu Date: Wed, 28 Jan 2026 00:28:59 +0200 Subject: [PATCH 38/47] push mouse events to input manager --- .../oneconfig/api/ui/v1/keybind/KeybindManager.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/keybind/KeybindManager.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/keybind/KeybindManager.kt index ad68d505c..93bfbf8ef 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/keybind/KeybindManager.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/keybind/KeybindManager.kt @@ -30,6 +30,7 @@ import dev.deftu.omnicore.api.client.input.OmniKeys import org.apache.logging.log4j.LogManager import org.polyfrost.oneconfig.api.event.v1.eventHandler import org.polyfrost.oneconfig.api.event.v1.events.KeyInputEvent +import org.polyfrost.oneconfig.api.event.v1.events.MouseInputEvent import org.polyfrost.oneconfig.api.event.v1.events.ScreenOpenEvent import org.polyfrost.oneconfig.api.event.v1.events.TickEvent import org.polyfrost.oneconfig.api.event.v1.events.WindowFocusEvent @@ -54,6 +55,12 @@ object KeybindManager { if (state == 2) return@eventHandler translateKey(inputManager, key, char, state == 1) } + + eventHandler { (btn, state): MouseInputEvent -> + if (state == 1) inputManager.mousePressed(btn) + else inputManager.mouseReleased(btn) + } + eventHandler { _: TickEvent.End -> keyBinder.update(50_000L, inputManager.mods, true) } From 75e12fdd05ed83008bf255cb6c96df2bf17c9cc1 Mon Sep 17 00:00:00 2001 From: Deftu Date: Wed, 28 Jan 2026 12:57:46 +0200 Subject: [PATCH 39/47] Attempts at fixing broken text rendering --- .../oneconfig/api/ui/v1/internal/GLRendererImpl.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 6ad83a8bf..a4c79dc32 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -363,10 +363,10 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re require("GL_EXT_gpu_shader4" in extensions) { "GL_EXT_gpu_shader4 is not supported and is required" } require("GL_ARB_instanced_arrays" in extensions) { "GL_ARB_instanced_arrays is not supported and is required" } require("GL_ARB_draw_instanced" in extensions) { "GL_ARB_draw_instanced is not supported and is required" } - if ("GL_EXT_framebuffer_object" in extensions) { - LOGGER.info("Using mipmaps as extension GL_EXT_framebuffer_object is available") - mipmapMode = 2 - } +// if ("GL_EXT_framebuffer_object" in extensions) { +// LOGGER.info("Using mipmaps as extension GL_EXT_framebuffer_object is available") +// mipmapMode = 2 +// } } } @@ -948,7 +948,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private fun getFontAtlas(font: Font, fontSize: Float): FontAtlas { val renderSize = when (fontSize) { - in 0f..16f -> 6f + in 0f..16f -> 12f in 0f..36f -> 24f else -> 48f } From 32c724fcd40692b4677e72bb3ec1e41c8675130c Mon Sep 17 00:00:00 2001 From: Deftu Date: Sat, 31 Jan 2026 13:37:57 +0200 Subject: [PATCH 40/47] Fix FMU issue --- minecraft/src/main/resources/fabric.mod.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minecraft/src/main/resources/fabric.mod.json b/minecraft/src/main/resources/fabric.mod.json index 42b0ec77b..d4cc243d0 100644 --- a/minecraft/src/main/resources/fabric.mod.json +++ b/minecraft/src/main/resources/fabric.mod.json @@ -28,7 +28,7 @@ }, "depends": { "fabricloader": ">=0.12.0", - "minecraft": "${fabric_mc_version}" + "minecraft": "~${fabric_mc_version}" }, "custom": { "modmenu": { From a6eee5cdf56e1495f4eb638ff5c0460dca79aa50 Mon Sep 17 00:00:00 2001 From: Deftu Date: Sat, 31 Jan 2026 13:38:20 +0200 Subject: [PATCH 41/47] Fix crash in legacy versions --- .../polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index a4c79dc32..e0f294803 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -418,7 +418,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glBindBuffer(GL_ARRAY_BUFFER, quadVbo) glEnableVertexAttribArray(aLocal) glVertexAttribPointer(aLocal, 2, GL_FLOAT, false, 0, 0L) - org.lwjgl.opengl.GL30C.glBindVertexArray(0) + org.lwjgl.opengl.GL30.glBindVertexArray(0) } val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) From 659054e26d28fc14e6896cbfed5de421ee594cf8 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Fri, 6 Feb 2026 12:48:47 +0000 Subject: [PATCH 42/47] Use SDF font rendering and various optimizations to the renderer --- gradle/libs.versions.toml | 2 +- .../oneconfig/api/ui/v1/UIManager.java | 8 +- .../oneconfig/api/ui/v1/api/StbApi.java | 8 + .../api/ui/v1/internal/GLAtlasManager.kt | 188 ++++++++ .../api/ui/v1/internal/GLRendererImpl.kt | 450 +++++++----------- .../oneconfig/api/ui/v1/internal/StbImpl.kt | 14 + 6 files changed, 385 insertions(+), 285 deletions(-) create mode 100644 modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 12153281a..fdcf2e368 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kotlinx-coroutines = "1.10.2" kotlinx-atomicfu = "0.29.0" fabric-language-kotlin = "1.13.8+kotlin.2.3.0" google-ksp = "2.2.10-2.0.2" -polyui = "2.1.1" +polyui = "2.1.6" annotations = "24.1.0" hypixel-modapi = "1.0.1" hypixel-data = "0.2.0" # Dep of hypixel-modapi diff --git a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java index 6a236d011..4c4476755 100644 --- a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java +++ b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/UIManager.java @@ -192,11 +192,11 @@ default PolyUI createDefault() { float ratio = Platform.screen().pixelRatio(); polyUI.resize(event.newWidth, event.newHeight, false); - long visibleSize = polyUI.getVisibleSize(); - int polyUiWidth = (int) Vec2.getX(visibleSize); - int polyUiHeight = (int) Vec2.getY(visibleSize); + long size = polyUI.getSize(); + int polyUiWidth = (int) Vec2.getX(size); + int polyUiHeight = (int) Vec2.getY(size); System.out.println("Resizing to: " + polyUiWidth + "x" + polyUiHeight + " with ratio " + ratio); - framebuffer.resize(polyUiWidth, polyUiHeight); + framebuffer.resize((int) (polyUiWidth * ratio), (int) (polyUiHeight * ratio)); polyUI.getWindow().setPixelRatio(ratio); }); diff --git a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java index 29443a217..7cdccd0fd 100644 --- a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java +++ b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java @@ -22,10 +22,18 @@ public interface StbApi { boolean font_InitFont(long info, ByteBuffer data); + int font_FindGlyphIndex(long info, int codepoint); + float font_ScaleForMappingEmToPixels(long info, float pixels); void font_GetFontVMetrics(long info, int[] ascent, int[] descent, int[] lineGap); + void font_GetGlyphHMetrics(long info, int glyphIndex, int[] advanceWidth, int[] leftSideBearing); + + long font_GetGlyphBitmap(long info, float scaleX, float scaleY, int glyphIndex, int[] w, int[] h, int[] x_off, int[] y_off); + + long font_GetGlyphSDF(long info, float scale, int glyphIndex, int padding, byte onEdgeValue, float pixelDistScale, int[] w, int[] h, int[] x_off, int[] y_off); + boolean font_PackBegin(long packCtx, ByteBuffer pixels, int width, int height, int strideInBytes, int padding, long allocCtx); boolean font_PackFontRange(long packCtx, ByteBuffer fontData, int fontIndex, float fontSize, int firstUnicodeCodepointInRange, int numCharsInRange, long packedCharArray); diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt new file mode 100644 index 000000000..6245918a2 --- /dev/null +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt @@ -0,0 +1,188 @@ +package org.polyfrost.oneconfig.api.ui.v1.internal + +import org.lwjgl.opengl.GL11.* +import org.lwjgl.opengl.GL12.* +import org.lwjgl.opengl.GL13.* +import org.lwjgl.system.MemoryUtil +import org.polyfrost.polyui.unit.Vec4 +import java.nio.ByteBuffer + +/** + * An OpenGL Atlas Manager designed to efficiently place textures of different sizes into a texture atlas, of dimensions [atlasWidth]x[atlasHeight]. + * + * Its ID is [atlas] and can be bound using [bind] and [unbind]. Use [cleanup] to delete it, and [insert] to add your textures. + */ +class GLAtlasManager(val atlasWidth: Int, val atlasHeight: Int) { + val atlas: Int = glGenTextures() + + init { + val prev = glGetInteger(GL_TEXTURE_BINDING_2D) + val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) + glBindTexture(GL_TEXTURE_2D, atlas) + glActiveTexture(GL_TEXTURE0) + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA, + atlasWidth, + atlasHeight, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + null as ByteBuffer? + ) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) + glBindTexture(GL_TEXTURE_2D, prev) + glActiveTexture(prevActive) + } + + private val skyline = ArrayList().also { + it.add(SkylineNode(0, 0, atlasWidth)) + } + + /** + * Insert a given texture, a ByteBuffer of [GL_UNSIGNED_BYTE] pixels, of dimensions [width] and [height] into this atlas. + * + * Specify the format of your data with the [format] parameter. + * + * @return A normalised UVWH Vec4 object referring to the dimensions and position of the texture inserted into the atlas. + */ + fun insert( + width: Int, + height: Int, + pixels: ByteBuffer, + format: Int = GL_RGBA + ): Vec4 = insert(width, height, MemoryUtil.memAddress(pixels), format) + + /** + * Insert a given texture, a ByteBuffer of [GL_UNSIGNED_BYTE] pixels, of dimensions [width] and [height] into this atlas. + * + * Specify the format of your data with the [format] parameter. + * + * @return A normalised UVWH Vec4 object referring to the dimensions and position of the texture inserted into the atlas. + */ + fun insert( + width: Int, + height: Int, + pixels: Long, + format: Int = GL_RGBA + ): Vec4 { + val pos = findPosition(width, height) + ?: throw IllegalStateException("Texture atlas full") + + addSkylineLevel(pos.index, pos.x, pos.y, width, height) + + val prev = glGetInteger(GL_TEXTURE_BINDING_2D) + val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) + glActiveTexture(GL_TEXTURE0) + glBindTexture(GL_TEXTURE_2D, atlas) + glPixelStorei(GL_UNPACK_ALIGNMENT, 1) + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) + nglTexSubImage2D(GL_TEXTURE_2D, 0, + pos.x, pos.y, width, height, + format, GL_UNSIGNED_BYTE, + pixels + ) + glBindTexture(GL_TEXTURE_2D, prev) + glActiveTexture(prevActive) + + return Vec4.of( + pos.x.toFloat() / atlasWidth, + pos.y.toFloat() / atlasHeight, + width.toFloat() / atlasWidth, + height.toFloat() / atlasHeight + ) + } + + private fun findPosition(w: Int, h: Int): Placement? { + var bestY = Int.MAX_VALUE + var bestX = Int.MAX_VALUE + var bestIndex = -1 + + for (i in skyline.indices) { + val y = fitsAt(i, w, h) + if (y >= 0) { + if (y < bestY || (y == bestY && skyline[i].x < bestX)) { + bestY = y + bestX = skyline[i].x + bestIndex = i + } + } + } + + return if (bestIndex == -1) null else Placement(bestX, bestY, bestIndex) + } + + private fun fitsAt(index: Int, w: Int, h: Int): Int { + val node = skyline[index] + if (node.x + w > atlasWidth) return -1 + + var widthLeft = w + var y = node.y + var i = index + + while (widthLeft > 0) { + val n = skyline[i] + y = maxOf(y, n.y) + if (y + h > atlasHeight) return -1 + + widthLeft -= n.w + i++ + if (i >= skyline.size && widthLeft > 0) return -1 + } + + return y + } + + private fun addSkylineLevel(index: Int, x: Int, y: Int, w: Int, h: Int) { + val newNode = SkylineNode(x, y + h, w) + + while (index < skyline.size) { + val node = skyline[index] + // Stop once we're past the new rect + if (node.x >= x + w) break + + val nodeEnd = node.x + node.w + val overlap = nodeEnd - (x + w) + if (overlap > 0) { + // Shrink node from the left + node.x = x + w + node.w = overlap + break + } else { + // Fully covered by new rect + skyline.removeAt(index) + continue + } + } + + skyline.add(index, newNode) + mergeSkyline() + } + + private fun mergeSkyline() { + var i = 0 + while (i < skyline.size - 1) { + val a = skyline[i] + val b = skyline[i + 1] + if (a.y == b.y) { + a.w += b.w + skyline.removeAt(i + 1) + } else i++ + } + } + + fun bind() = glBindTexture(GL_TEXTURE_2D, atlas) + + fun unbind() = glBindTexture(GL_TEXTURE_2D, 0) + + fun cleanup() = glDeleteTextures(atlas) + + private data class SkylineNode(var x: Int, var y: Int, var w: Int) + private data class Placement(val x: Int, val y: Int, val index: Int) +} diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index a4c79dc32..4ac37d38a 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -5,8 +5,6 @@ package org.polyfrost.oneconfig.api.ui.v1.internal import dev.deftu.omnicore.api.client.render.GlCapabilities import dev.deftu.omnicore.api.client.render.OmniResolution import dev.deftu.omnicore.api.client.render.OmniTextRenderer -import dev.deftu.omnicore.api.client.render.stack.OmniPoseStack -import dev.deftu.omnicore.api.color.OmniColor import dev.deftu.omnicore.api.math.OmniMatrix4f import dev.deftu.omnicore.internal.client.render.shader.ShaderInternals import org.apache.logging.log4j.LogManager @@ -16,8 +14,7 @@ import org.lwjgl.opengl.GL13.* import org.lwjgl.opengl.GL14.* import org.lwjgl.opengl.GL15.* import org.lwjgl.opengl.GL20.* -import org.lwjgl.opengl.GL33.glBindSampler -import org.polyfrost.oneconfig.api.platform.v1.Platform +import org.lwjgl.system.MemoryUtil import org.polyfrost.oneconfig.api.ui.v1.UIManager import org.polyfrost.oneconfig.api.ui.v1.api.NanoSvgApi import org.polyfrost.oneconfig.api.ui.v1.api.RendererExt @@ -29,7 +26,7 @@ import org.polyfrost.polyui.data.Font import org.polyfrost.polyui.data.PolyImage import org.polyfrost.polyui.renderer.Renderer import org.polyfrost.polyui.unit.Vec2 -import org.polyfrost.polyui.unit.Vec4 +import org.polyfrost.polyui.utils.roundTo import org.polyfrost.polyui.utils.toDirectByteBuffer import org.polyfrost.polyui.utils.toDirectByteBufferNT import java.nio.ByteBuffer @@ -39,14 +36,13 @@ import kotlin.math.* private val LOGGER = LogManager.getLogger("PolyUI/GLRenderer") private const val MAX_UI_DEPTH = 16 -private const val FONT_MAX_BITMAP_W = 1536 -private const val FONT_MAX_BITMAP_H = 512 private const val ATLAS_SIZE = 2048 private const val ATLAS_SVG_UPSCALE_FACTOR = 2f -private const val STRIDE = 4 + 4 + 1 + 1 + 4 + 1 // bounds, radii, color0, color1, UV, thick -private const val MAX_BATCH = 1024 +private const val STRIDE = 4 + 4 + 1 + 1 + 4 + 1 + 4 // bounds, radii, color0, color1, UV, thick, clip +private const val MAX_BATCH = 2048 +private const val FONT_SCALE_MAX_FIDELITY = 0.25f +private const val FONT_RENDERED_SIZE = 64f -private val EMPTY_ROW = floatArrayOf(0f, 0f, 0f, 0f) private val NO_UV = floatArrayOf(-1f, -1f, 1f, 1f) private val IDENTITY = floatArrayOf( 1f, 0f, 0f, @@ -74,18 +70,15 @@ private inline fun FloatArray.setThenClear(other: FloatArray) { class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Renderer, RendererExt { private val buffer = BufferUtils.createFloatBuffer(MAX_BATCH * STRIDE) - private val scissorStack = IntArray(MAX_UI_DEPTH * 4) + private val scissorStack = FloatArray(MAX_UI_DEPTH * 4) private val transformStack = Array(MAX_UI_DEPTH) { FloatArray(9) } private val transformBuffer = BufferUtils.createFloatBuffer(9) - private val fonts = HashMap() + private val fonts = HashMap() private val init get() = program != 0 - - // lateinit - private var mipmapMode = 0 + private lateinit var atlas: GLAtlasManager // GL objects private var instancedVbo = 0 - private var atlas = 0 private var program = 0 private var vao = 0 // GL3+ only private var quadVbo = 0 @@ -100,10 +93,12 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private var iColor1 = 0 private var iUVRect = 0 private var iThickness = 0 + private var iClipRect = 0 // Current batch state - private val viewport = IntArray(4) + private var width = 0f + private var height = 0f private var count = 0 private var transformDepth = 0 private var scissorDepth = 0 @@ -112,11 +107,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private var alphaCap = 255 private var popFlushNeeded = false - // atlas data - private var slotX = 0 - private var slotY = 0 - private var atlasRowHeight = 0 - private val FRAG = """ #version $$$ // replaced by compileShader #if __VERSION__ >= 130 @@ -131,11 +121,13 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re uniform sampler2D uTex; - VARYING vec2 vUV; - VARYING vec2 vUV2; // used for gradients - VARYING vec2 vPos; // pixel coords in rect space - VARYING vec4 vRect; // rect x, y, w, h - VARYING vec4 vRadii; // per-corner radii + VARYING vec2 vUV; // UV sampler position + VARYING vec2 vUV2; // used for gradients + VARYING vec2 vHalfSize; // half the rectangle size + VARYING vec2 vP; // rect x, y + VARYING vec2 vScreenPos; // screen position of the rectangle + VARYING vec4 vClipRect; // clipping rectangle + VARYING vec4 vRadii; // per-corner radii VARYING vec4 vColor0; // RGBA VARYING vec4 vColor1; // RGBA (for gradients) VARYING float vThickness; // -1 for text, -2 for linear gradient, -3 for radial, -4 for box, >0 for hollow rect @@ -156,7 +148,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } float hollowRoundedBoxSDF(vec2 p, vec2 b, vec4 r, float thickness) { - float outer = roundedBoxSDF(p, b + 0.2, r + 0.2); + float outer = roundedBoxSDF(p, b + 0.3, r + 0.3); float inner = roundedBoxSDF(p, b - thickness, max(r - thickness, 0.0)); return max(outer, -inner); } @@ -165,44 +157,67 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re vec2 q = abs(p) - (halfSize - radius); return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius; } + + float boxSDF(vec2 p, vec2 halfSize) { + vec2 q = abs(p) - halfSize; + return max(q.x, q.y); + } + + float hollowBoxSDF(vec2 p, vec2 halfSize, float thickness) { + float outer = boxSDF(p, halfSize + 0.3); + float inner = boxSDF(p, halfSize - thickness); + return max(outer, -inner); + } void main() { - vec2 halfSize = 0.5 * vRect.zw; - vec2 center = vRect.xy + halfSize; - vec2 p = vPos - center; - - float d = (vThickness > 0.0) ? hollowRoundedBoxSDF(p, halfSize, vRadii, vThickness) : roundedBoxSDF(p, halfSize, vRadii); + float clip = + step(vClipRect.x, vScreenPos.x) * + step(vClipRect.y, vScreenPos.y) * + step(vScreenPos.x, vClipRect.z) * + step(vScreenPos.y, vClipRect.w); + // if (clip == 0.0) discard; + + float d; + if (vRadii.y == -1.0) { + d = (vThickness > 0.0) ? hollowBoxSDF(vP, vHalfSize, vThickness) : boxSDF(vP, vHalfSize); + } else { + d = (vThickness > 0.0) ? hollowRoundedBoxSDF(vP, vHalfSize, vRadii, vThickness) : roundedBoxSDF(vP, vHalfSize, vRadii); + } vec4 col = vColor0; if (vUV.x >= 0.0 && vThickness >= -1.0) { // textured if UV.x >= 0 vec4 texColor = TEXTURE(uTex, vUV); // text check: use red channel as alpha - col = (vThickness == -1.0) ? vec4(col.rgb, col.a * texColor.r) : col * texColor; + if (vThickness == -1.0) { + float w = fwidth(texColor.r); + // bias increases as glyph gets smaller + float bias = 0.5 - min(w * 0.6, 0.08); + col.a *= smoothstep(bias - w, bias + w, texColor.r); + } else col = col * texColor; } else if (vThickness == -2.0) { // linear gradient, vUV as start and vUV2 as end vec2 dir = vUV2 - vUV; - float len = length(dir); - float t = clamp(dot((p + halfSize) - vUV, dir / len) / len, 0.0, 1.0); + float invLen2 = 1.0 / dot(dir, dir); + float t = clamp(dot((vP + vHalfSize) - vUV, dir) * invLen2, 0.0, 1.0); col = mix(vColor0, vColor1, t); } else if (vThickness == -3.0) { // radial gradient, vUV as center and vUV2.x as radius - float dist = length(p + halfSize - vUV); + float dist = length(vP + vHalfSize - vUV); float t = clamp((dist - vUV2.x) / (vUV2.y - vUV2.x), 0.0, 1.0); col = mix(vColor0, vColor1, t); } else if (vThickness == -4.0) { // box gradient, vUV.x as radius and vUV.y as feather - float dist = roundBoxSDF(p, halfSize, vUV.x); + float dist = roundBoxSDF(vP, vHalfSize, vUV.x); float t = clamp((dist + vUV.y * 0.5) / vUV.y, 0.0, 1.0); col = mix(vColor0, vColor1, t); } else if (vThickness == -5.0) { // drop shadow, vUV.x as spread and vUV.y as blur - float dShadow = roundBoxSDF(p, halfSize + vUV.x, vRadii.x); + float dShadow = roundBoxSDF(vP, vHalfSize + vUV.x, vRadii.x); col = vec4(vColor0.rgb, vColor0.a * (1.0 - smoothstep(-vUV.y, vUV.y, dShadow))); } // Proper antialiasing based on distance field - float f = fwidth(d); - float alpha = col.a * (1.0 - smoothstep(-f, f, d)); + float alpha = col.a * clip * clamp(0.5 - d, 0.0, 1.0); fragColor = vec4(col.rgb * alpha, alpha); } @@ -228,6 +243,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re ATTRIBUTE U_INT iColor1; ATTRIBUTE vec4 iUVRect; ATTRIBUTE float iThickness; + ATTRIBUTE vec4 iClipRect; uniform mat3 uTransform = mat3( 1.0, 0.0, 0.0, @@ -236,8 +252,10 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re ); uniform vec2 uWindow; - VARYING vec2 vPos; - VARYING vec4 vRect; + VARYING vec2 vP; + VARYING vec2 vHalfSize; + VARYING vec2 vScreenPos; + VARYING vec4 vClipRect; VARYING vec4 vRadii; VARYING vec4 vColor0; VARYING vec4 vColor1; @@ -266,14 +284,15 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re gl_Position = vec4(ndc, 0.0, 1.0); - vPos = pos; - vRect = iRect; - vRadii = iRadii; - vColor0 = unpackColor(iColor0); - vColor1 = unpackColor(iColor1); - vUV = uv; - // pass through for gradients. - vUV2 = iUVRect.zw; + vHalfSize = iRect.zw * 0.5; + vP = pos - iRect.xy - vHalfSize; + vScreenPos = transformed.xy; + vClipRect = iClipRect; + vRadii = iRadii; + vColor0 = unpackColor(iColor0); + vColor1 = unpackColor(iColor1); + vUV = uv; + vUV2 = iUVRect.zw; // pass through for gradients. vThickness = iThickness; } """.trimIndent() @@ -413,7 +432,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re offset = enableAttribui(iColor0, 1, offset) offset = enableAttribui(iColor1, 1, offset) offset = enableAttrib(iUVRect, 4, offset) - enableAttrib(iThickness, 1, offset) + offset = enableAttrib(iThickness, 1, offset) + enableAttrib(iClipRect, 4, offset) glBindBuffer(GL_ARRAY_BUFFER, quadVbo) glEnableVertexAttribArray(aLocal) @@ -422,28 +442,14 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - atlas = glGenTextures() - glBindTexture(GL_TEXTURE_2D, atlas) - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGBA, - ATLAS_SIZE, - ATLAS_SIZE, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - null as ByteBuffer? - ) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, if (mipmapMode == 0) GL_LINEAR else GL_LINEAR_MIPMAP_LINEAR) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) + atlas = GLAtlasManager(ATLAS_SIZE, ATLAS_SIZE) glBindTexture(GL_TEXTURE_2D, prevTex) glBindBuffer(GL_ARRAY_BUFFER, prevBuf) } override fun beginFrame(width: Float, height: Float, pixelRatio: Float) { + this.width = width + this.height = height scissorDepth = 0 alphaCap = 255 count = 0 @@ -457,7 +463,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glUniformMatrix3fv(uTransform, false, transform) glUseProgram(prevProg) glDisable(GL_SCISSOR_TEST) - Platform.gl().glViewport(viewport) this.pixelRatio = pixelRatio } @@ -502,8 +507,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } glActiveTexture(GL_TEXTURE0) - glBindTexture(GL_TEXTURE_2D, atlas) - glBindSampler(0, 0) + atlas.bind() + if (GlCapabilities.isGl33Available) org.lwjgl.opengl.GL33.glBindSampler(0, 0) // asm: on VAO the state is stored, so we only need to set it up once if (!GlCapabilities.isGl3Available) { @@ -569,6 +574,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re ) { val buffer = buffer if (count >= MAX_BATCH) flush() + val topRightRadius = if (topLeftRadius == 0f && topLeftRadius == topRightRadius && topLeftRadius == bottomLeftRadius && topLeftRadius == bottomRightRadius) -1f else topRightRadius buffer.put(x).put(y).put(width).put(height) buffer.put(topLeftRadius).put(topRightRadius).put(bottomRightRadius).put(bottomLeftRadius) buffer.put(java.lang.Float.intBitsToFloat(color.argb.capAlpha())) @@ -612,7 +618,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re buffer.put(NO_UV) // -1f UVs to indicate no texture buffer.put(0f) } - + buffer.put(scissorStack, (scissorDepth - 4).coerceAtLeast(0), 4) count += 1 } @@ -629,12 +635,14 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re bottomRightRadius: Float ) { if (count >= MAX_BATCH) flush() + val topRightRadius = if (topLeftRadius == 0f && topLeftRadius == topRightRadius && topLeftRadius == bottomLeftRadius && topLeftRadius == bottomRightRadius) -1f else topRightRadius buffer.put(x).put(y).put(width).put(height) buffer.put(topLeftRadius).put(topRightRadius).put(bottomRightRadius).put(bottomLeftRadius) buffer.put(java.lang.Float.intBitsToFloat(color.argb.capAlpha())) buffer.put(0f) // color1 unused buffer.put(NO_UV) // -1f UVs to indicate no texture buffer.put(lineWidth) + buffer.put(scissorStack, (scissorDepth - 4).coerceAtLeast(0), 4) count += 1 } @@ -644,12 +652,14 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re ) { if (count >= MAX_BATCH) flush() + val topRightRadius = if (topLeftRadius == 0f && topLeftRadius == topRightRadius && topLeftRadius == bottomLeftRadius && topLeftRadius == bottomRightRadius) -1f else topRightRadius buffer.put(x).put(y).put(width).put(height) buffer.put(topLeftRadius).put(topRightRadius).put(bottomRightRadius).put(bottomLeftRadius) buffer.put(java.lang.Float.intBitsToFloat(colorMask.capAlpha())) buffer.put(0f) // color1 unused buffer.put(image.uv.x).put(image.uv.y).put(image.uv.w).put(image.uv.h) buffer.put(0f) // thickness = 0 for filled rect + buffer.put(scissorStack, (scissorDepth - 4).coerceAtLeast(0), 4) count += 1 } @@ -666,36 +676,37 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re override fun text(font: Font, x: Float, y: Float, text: String, color: Color, fontSize: Float) { if (font === UIManager.INSTANCE.mcFont) { - val ctx = UIManager.INSTANCE.renderingContext - ctx.pose.push(OmniPoseStack.Entry(transform.getScaledMat4(), ctx.pose.current.normalMatrix)) - // asm: can be optimized by https://github.com/Deftu/OmniCore/issues/58 - OmniTextRenderer.render(ctx.pose, text, x, y, OmniColor.argb(color.argb), false) - ctx.pose.pop() + // todo broken on 1.21.10(+) +// val ctx = UIManager.INSTANCE.renderingContext +// ctx.pose.push(OmniPoseStack.Entry(transform.getScaledMat4(), ctx.pose.current.normalMatrix)) +// asm: can be optimized by https://github.com/Deftu/OmniCore/issues/58 +// OmniTextRenderer.render(ctx.pose, text, x, y, OmniColor.argb(color.argb), false) +// ctx.pose.pop() return } - val fAtlas = getFontAtlas(font, fontSize) val s = transformScale() - val fAtlasForRendering = if (s == 1f) fAtlas else getFontAtlas(font, fontSize * s) + val fAtlas = getFontAtlas(font) if (count >= MAX_BATCH) flush() - var penX = x - val scaleFactor = fontSize / fAtlas.renderedSize - val penY = (y + (fAtlas.ascent + fAtlas.descent) * scaleFactor) + 2f + var penX = floor(x + 0.5f) + val scaleFactor = (fontSize.roundTo(FONT_SCALE_MAX_FIDELITY) / FONT_RENDERED_SIZE) * s + val penY = (y + (fAtlas.ascent + fAtlas.descent) * scaleFactor) + (fontSize / 6f) val col = java.lang.Float.intBitsToFloat(color.argb.capAlpha()) val buffer = buffer - for (c in text) { - if (count >= MAX_BATCH) { - flush() - } - val glyph = fAtlas.get(c) + text.forEachCodepoint { + if (count >= MAX_BATCH) flush() + val glyph = fAtlas.get(it) + // opt: early exit when we are out of the scissored region + if (scissorDepth > 3 && penX > scissorStack[scissorDepth - 2]) return buffer.put(penX + glyph.xOff * scaleFactor).put(penY + glyph.yOff * scaleFactor) .put(glyph.width * scaleFactor).put(glyph.height * scaleFactor) - buffer.put(EMPTY_ROW) // zero radii + buffer.put(0f).put(-1f).put(0f).put(0f) // zero radii (-1 optimization) buffer.put(col) buffer.put(0f) // color1 unused - buffer.put(if (s == 1f) glyph else fAtlasForRendering.get(c), 0, 4) + buffer.put(glyph, 0, 4) // UVs buffer.put(-1f) // thickness = -1 for text + buffer.put(scissorStack, (scissorDepth - 4).coerceAtLeast(0), 4) penX += glyph.xAdvance * scaleFactor count += 1 } @@ -704,7 +715,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re override fun textBounds(font: Font, text: String, fontSize: Float): Vec2 { return if (font === UIManager.INSTANCE.mcFont) { Vec2(OmniTextRenderer.width(text).toFloat(), OmniTextRenderer.lineHeight.toFloat()) - } else getFontAtlas(font, fontSize).measure(text, fontSize) + } else getFontAtlas(font).measure(text, fontSize) } override fun line(x1: Float, y1: Float, x2: Float, y2: Float, color: Color, width: Float) { @@ -723,26 +734,20 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re ) { if (count >= MAX_BATCH) flush() buffer.put(x).put(y).put(width).put(height) - buffer.put(EMPTY_ROW) // zero radii + buffer.put(0f).put(-1f).put(0f).put(0f) // zero radii buffer.put(java.lang.Float.intBitsToFloat(alphaCap shl 24)) // black, alpha to alphaCap buffer.put(0f) // color1 unused buffer.put(spread).put(blur).put(0f).put(0f) buffer.put(-5f) // thickness = -5 for drop shadow + buffer.put(scissorStack, (scissorDepth - 4).coerceAtLeast(0), 4) count += 1 } override fun pushScissor(x: Float, y: Float, width: Float, height: Float) { - flush() - val nx = (x * pixelRatio).roundToInt() - val ny = (viewport[3] - (y + height) * pixelRatio).roundToInt() - val nw = (width * pixelRatio).roundToInt() - val nh = (height * pixelRatio).roundToInt() - scissorStack[scissorDepth++] = nx - scissorStack[scissorDepth++] = ny - scissorStack[scissorDepth++] = nw - scissorStack[scissorDepth++] = nh - glEnable(GL_SCISSOR_TEST) - glScissor(nx + viewport[0], ny + viewport[1], nw, nh) + scissorStack[scissorDepth++] = x + scissorStack[scissorDepth++] = y + scissorStack[scissorDepth++] = x + width + scissorStack[scissorDepth++] = y + height } override fun pushScissorIntersecting(x: Float, y: Float, width: Float, height: Float) { @@ -750,49 +755,38 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re pushScissor(x, y, width, height) return } - flush() val px = scissorStack[scissorDepth - 4] val py = scissorStack[scissorDepth - 3] - val pw = scissorStack[scissorDepth - 2] - val ph = scissorStack[scissorDepth - 1] - val nx = (x * pixelRatio).roundToInt() - val ny = (viewport[3] - (y + height) * pixelRatio).roundToInt() + val pl = scissorStack[scissorDepth - 2] + val pr = scissorStack[scissorDepth - 1] - val ix = maxOf(nx, px) - val iy = maxOf(ny, py) - val iw = maxOf(0, minOf(nx + (width * pixelRatio).roundToInt(), px + pw) - ix) - val ih = maxOf(0, minOf(ny + (height * pixelRatio).roundToInt(), py + ph) - iy) + val ix = maxOf(x, px) + val iy = maxOf(y, py) + val il = minOf(x + width, pl) + val ir = minOf(y + height, pr) scissorStack[scissorDepth++] = ix scissorStack[scissorDepth++] = iy - scissorStack[scissorDepth++] = iw - scissorStack[scissorDepth++] = ih - - glEnable(GL_SCISSOR_TEST) - glScissor(ix + viewport[0], iy + viewport[1], iw, ih) + scissorStack[scissorDepth++] = il + scissorStack[scissorDepth++] = ir } override fun popScissor() { - flush() if (scissorDepth <= 4) { scissorDepth = 0 - glDisable(GL_SCISSOR_TEST) + pushScissor(0f, 0f, width, height) return } scissorDepth -= 4 - val nx = scissorStack[scissorDepth - 4] - val ny = scissorStack[scissorDepth - 3] - val nw = scissorStack[scissorDepth - 2] - val nh = scissorStack[scissorDepth - 1] - glEnable(GL_SCISSOR_TEST) - glScissor(nx + viewport[0], ny + viewport[1], nw, nh) } override fun globalAlpha(alpha: Float) { alphaCap = (alpha * 255f).toInt() } - override fun resetGlobalAlpha() = globalAlpha(1f) + override fun resetGlobalAlpha() { + alphaCap = 255 + } override fun transformsWithPoint() = false @@ -886,43 +880,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val h = IntArray(1) val d = initImage(image, w, h) - if (slotX + w[0] >= ATLAS_SIZE) { - slotX = 0 - slotY += atlasRowHeight - atlasRowHeight = 0 - if (slotY + h[0] >= ATLAS_SIZE) { - throw IllegalStateException("Texture atlas full!") - } - } - // Store UV rect for this image - image.uv = Vec4.of( - slotX / ATLAS_SIZE.toFloat(), - slotY / ATLAS_SIZE.toFloat(), - w[0] / ATLAS_SIZE.toFloat(), - h[0] / ATLAS_SIZE.toFloat() - ) - - val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) - val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - glActiveTexture(GL_TEXTURE0) - glBindTexture(GL_TEXTURE_2D, atlas) - glPixelStorei(GL_UNPACK_ALIGNMENT, 1) - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) - glTexSubImage2D(GL_TEXTURE_2D, 0, slotX, slotY, w[0], h[0], GL_RGBA, GL_UNSIGNED_BYTE, d) - when (mipmapMode) { - 1 -> org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D) - 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) - } - glBindTexture(GL_TEXTURE_2D, prevTex) - glActiveTexture(prevActive) - + image.uv = atlas.insert(w[0], h[0], d) if (image.type == PolyImage.Type.Raster) stb.image_free(d) - - slotX += w[0] + 1 - if (h[0] + 1 > atlasRowHeight) atlasRowHeight = h[0] + 1 image.reportInit() } @@ -946,26 +906,21 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } } - private fun getFontAtlas(font: Font, fontSize: Float): FontAtlas { - val renderSize = when (fontSize) { - in 0f..16f -> 12f - in 0f..36f -> 24f - else -> 48f - } - return fonts.getOrPut(font.resourcePath.hashCode() + renderSize.toInt()) { + private fun getFontAtlas(font: Font): FontAtlas { + return fonts.getOrPut(font.resourcePath) { val data = font.load { LOGGER.error("Failed to load font: $font", it) - return@getOrPut fonts[PolyUI.defaultFonts.regular.resourcePath.hashCode() + 12f.toInt()] + return@getOrPut fonts[PolyUI.defaultFonts.regular.resourcePath] ?: throw IllegalStateException("Default font couldn't be loaded") }.toDirectByteBuffer() - FontAtlas(data, renderSize) + FontAtlas(data) } } private var i = 0 override fun dumpAtlas() { val buf = BufferUtils.createByteBuffer(ATLAS_SIZE * ATLAS_SIZE * 4) - glBindTexture(GL_TEXTURE_2D, atlas) + atlas.bind() glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf) glBindTexture(GL_TEXTURE_2D, 0) stb.image_write_png( @@ -984,7 +939,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (program != 0) glDeleteProgram(program) if (quadVbo != 0) glDeleteBuffers(quadVbo) if (instancedVbo != 0) glDeleteBuffers(instancedVbo) - if (atlas != 0) glDeleteTextures(atlas) + atlas.cleanup() + fonts.values.forEach(FontAtlas::cleanup) if (vao != 0) org.lwjgl.opengl.GL30C.glDeleteVertexArrays(vao) fonts.clear() } @@ -996,143 +952,77 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re cleanup() } - private inner class FontAtlas(data: ByteBuffer, val renderedSize: Float) { - private val glyphs: Array + private inner class FontAtlas(private val data: ByteBuffer) { + private val glyphs = HashMap() val ascent: Float val descent: Float val lineGap: Float + private val fontInfo = stb.font_CreateFontInfo() + val scale: Float init { val stb = stb - val fontInfo = stb.font_CreateFontInfo() if (!stb.font_InitFont(fontInfo, data)) { throw IllegalStateException("Failed to initialize font") } - val scale = stb.font_ScaleForMappingEmToPixels(fontInfo, renderedSize) + scale = stb.font_ScaleForMappingEmToPixels(fontInfo, FONT_RENDERED_SIZE) val asc = IntArray(1) val des = IntArray(1) val gap = IntArray(1) stb.font_GetFontVMetrics(fontInfo, asc, des, gap) - stb.free(fontInfo) - val pixelHeight = (asc[0] - des[0]) * scale ascent = asc[0] * scale descent = des[0] * scale lineGap = gap[0] * scale + } - val range = stb.font_CreatePackRange() - stb.font_RangeSetFontSize(range, renderedSize) - stb.font_RangeSetFirstUnicodeCodepointInRange(range, 32) - stb.font_RangeSetNumChars(range, 95) - val packed = stb.font_CreatePackedCharArray(95) - stb.font_RangeSetChardata(range, packed) - - val bitMap = BufferUtils.createByteBuffer(FONT_MAX_BITMAP_W * FONT_MAX_BITMAP_H) - val pack = stb.font_CreatePackContext() - if (!stb.font_PackBegin(pack, bitMap, FONT_MAX_BITMAP_W, FONT_MAX_BITMAP_H, 0, 1, 0L)) { - throw IllegalStateException("Failed to initialize font packer") - } - - if (!stb.font_PackFontRange(pack, data, 0, pixelHeight, 32, 95, packed)) { - throw IllegalStateException("Failed to pack font range") - } - stb.font_PackEnd(pack) - stb.free(pack) - - var minX = Short.MAX_VALUE - var minY = Short.MAX_VALUE - var maxX = Short.MIN_VALUE - var maxY = Short.MIN_VALUE - for (i in 0..<95) { - val g = stb.font_GetPackedGlyph(packed, i) - val x0 = stb.glyph_x0(g) - val y0 = stb.glyph_y0(g) - val x1 = stb.glyph_x1(g) - val y1 = stb.glyph_y1(g) - if (x0 < minX) minX = x0 - if (y0 < minY) minY = y0 - if (x1 > maxX) maxX = x1 - if (y1 > maxY) maxY = y1 - } - val totalSizeX = maxX - minX - val totalSizeY = maxY - minY - - if (slotX + totalSizeX > ATLAS_SIZE) { - slotX = 0 - slotY += atlasRowHeight - atlasRowHeight = 0 - } - val sx = slotX - val sy = slotY - - - glyphs = Array(95) { - val g = stb.font_GetPackedGlyph(packed, it) - val x0 = stb.glyph_x0(g) - val y0 = stb.glyph_y0(g) - val x1 = stb.glyph_x1(g) - val y1 = stb.glyph_y1(g) - - floatArrayOf( - (sx + x0) / ATLAS_SIZE.toFloat(), - (sy + y0) / ATLAS_SIZE.toFloat(), - (x1 - x0) / ATLAS_SIZE.toFloat(), - (y1 - y0) / ATLAS_SIZE.toFloat(), - stb.glyph_xoff(g), - stb.glyph_yoff(g), - (x1 - x0).toFloat(), - (y1 - y0).toFloat(), - stb.glyph_xadvance(g) - ) - } - stb.free(packed) - stb.free(range) - - val prevActive = glGetInteger(GL_ACTIVE_TEXTURE) - val prevTex = glGetInteger(GL_TEXTURE_BINDING_2D) - glActiveTexture(GL_TEXTURE0) - glBindTexture(GL_TEXTURE_2D, atlas) - glPixelStorei(GL_UNPACK_ALIGNMENT, 1) - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) - // can't write to the alpha channel in GL3 core! lol haha - glTexSubImage2D( - GL_TEXTURE_2D, - 0, - sx, - sy, - FONT_MAX_BITMAP_W, - FONT_MAX_BITMAP_H, - GL_RED, - GL_UNSIGNED_BYTE, - bitMap + private fun makeGlyph(codepoint: Int): FloatArray { + val w = IntArray(1) + val h = IntArray(1) + val xoff = IntArray(1) + val yoff = IntArray(1) + val xAdvance = IntArray(1) + + val idx = stb.font_FindGlyphIndex(fontInfo, codepoint) +// if (idx == 0) { +// val o = getFontAtlas(Font.of("polyui/fonts/NotoEmoji-Regular.ttf"), 12f).get(codepoint) +// glyphs[codepoint] = o +// return o +// } + + stb.font_GetGlyphHMetrics(fontInfo, idx, xAdvance, null) + var sdf = stb.font_GetGlyphSDF(fontInfo, scale, idx, 4, 128.toByte(), 64f, w, h, xoff, yoff) + if (sdf == 0L) sdf = stb.font_GetGlyphBitmap(fontInfo, scale, scale, idx, w, h, xoff, yoff) + if (sdf == 0L) sdf = MemoryUtil.memAddress(BufferUtils.createByteBuffer(w[0] * h[0] * 4)) + + val (u, v, uw, uh) = atlas.insert(w[0], h[0], sdf, GL_RED) + return floatArrayOf( + u, v, uw, uh, + xoff[0].toFloat(), + yoff[0].toFloat(), + w[0].toFloat(), + h[0].toFloat(), + xAdvance[0].toFloat() * scale ) - when (mipmapMode) { - 1 -> org.lwjgl.opengl.GL30.glGenerateMipmap(GL_TEXTURE_2D) - 2 -> org.lwjgl.opengl.EXTFramebufferObject.glGenerateMipmapEXT(GL_TEXTURE_2D) - } - glBindTexture(GL_TEXTURE_2D, prevTex) - glActiveTexture(prevActive) - - slotX += totalSizeX + 1 - atlasRowHeight = maxOf(atlasRowHeight, totalSizeY + 1) } fun measure(text: String, fontSize: Float): Vec2 { var width = 0f // var height = 0f - val scaleFactor = fontSize / this.renderedSize - for (c in text) { - val g = get(c) - width += g.xAdvance * scaleFactor -// height = maxOf(height, g.height + g.offsetY) + val scaleFactor = fontSize.roundTo(FONT_SCALE_MAX_FIDELITY) / FONT_RENDERED_SIZE + text.forEachCodepoint { + width += get(it).xAdvance * scaleFactor } return Vec2.of(width, fontSize) } @Suppress("DEPRECATION") @kotlin.internal.InlineOnly - inline fun get(char: Char) = if (char.toInt() in 32..32 + 95) glyphs[(char.toInt() - 32)] else glyphs['?'.toInt()] + inline fun get(codepoint: Int) = glyphs.getOrPut(codepoint) { makeGlyph(codepoint) } + + fun cleanup() { + stb.free(fontInfo) + glyphs.clear() + } } @kotlin.internal.InlineOnly diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt index a3a698224..d68feba49 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt @@ -37,6 +37,8 @@ class StbImpl : StbApi { override fun font_InitFont(info: Long, data: ByteBuffer) = nstbtt_InitFont(info, MemoryUtil.memAddress(data), 0) != 0 + override fun font_FindGlyphIndex(info: Long, codepoint: Int) = nstbtt_FindGlyphIndex(info, codepoint) + override fun font_ScaleForMappingEmToPixels(info: Long, pixels: Float) = nstbtt_ScaleForMappingEmToPixels(info, pixels) @@ -49,6 +51,18 @@ class StbImpl : StbApi { nstbtt_GetFontVMetrics(info, ascent, descent, lineGap) } + override fun font_GetGlyphHMetrics(info: Long, glyphIndex: Int, advanceWidth: IntArray?, leftSideBearing: IntArray?) { + nstbtt_GetGlyphHMetrics(info, glyphIndex, advanceWidth, leftSideBearing) + } + + override fun font_GetGlyphBitmap(info: Long, scaleX: Float, scaleY: Float, glyphIndex: Int, w: IntArray?, h: IntArray?, x_off: IntArray?, y_off: IntArray?): Long { + return nstbtt_GetGlyphBitmap(info, scaleX, scaleY, glyphIndex, w, h, x_off, y_off) + } + + override fun font_GetGlyphSDF(info: Long, scale: Float, glyphIndex: Int, padding: Int, onEdgeValue: Byte, pixelDistScale: Float, w: IntArray?, h: IntArray?, x_off: IntArray?, y_off: IntArray?): Long { + return nstbtt_GetGlyphSDF(info, scale, glyphIndex, padding, onEdgeValue, pixelDistScale, w, h, x_off, y_off) + } + override fun font_PackBegin( packCtx: Long, pixels: ByteBuffer, From 77f1f5a6d0b41c899b6c90f9e35b09adc019b24b Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Wed, 11 Feb 2026 13:46:24 +0000 Subject: [PATCH 43/47] fix GLRendererImpl --- .../api/ui/v1/internal/GLRendererImpl.kt | 202 +++++++++--------- 1 file changed, 98 insertions(+), 104 deletions(-) diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index 5eed835f9..ff1ed8b66 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -26,6 +26,7 @@ import org.polyfrost.polyui.data.Font import org.polyfrost.polyui.data.PolyImage import org.polyfrost.polyui.renderer.Renderer import org.polyfrost.polyui.unit.Vec2 +import org.polyfrost.polyui.utils.forEachCodepoint import org.polyfrost.polyui.utils.roundTo import org.polyfrost.polyui.utils.toDirectByteBuffer import org.polyfrost.polyui.utils.toDirectByteBufferNT @@ -110,47 +111,43 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private val FRAG = """ #version $$$ // replaced by compileShader #if __VERSION__ >= 130 - #define VARYING in + #define IN in #define TEXTURE texture out vec4 fragColor; #else - #define VARYING varying + #define IN varying #define TEXTURE texture2D #define fragColor gl_FragColor #endif uniform sampler2D uTex; - VARYING vec2 vUV; // UV sampler position - VARYING vec2 vUV2; // used for gradients - VARYING vec2 vHalfSize; // half the rectangle size - VARYING vec2 vP; // rect x, y - VARYING vec2 vScreenPos; // screen position of the rectangle - VARYING vec4 vClipRect; // clipping rectangle - VARYING vec4 vRadii; // per-corner radii - VARYING vec4 vColor0; // RGBA - VARYING vec4 vColor1; // RGBA (for gradients) - VARYING float vThickness; // -1 for text, -2 for linear gradient, -3 for radial, -4 for box, >0 for hollow rect + IN vec4 vUV; // UV sampler position + IN vec4 vP_HalfSize; // rect x, y, 0.5x wh + IN vec2 vScreenPos; // screen position of the rectangle + IN vec4 vClipRect; // clipping rectangle + IN vec4 vRadii; // per-corner radii + IN vec4 vColor0; // RGBA + IN vec4 vColor1; // RGBA (for gradients) + IN float vThickness; // -1 for text, -2 for linear gradient, -3 for radial, -4 for box, >0 for hollow rect // Signed distance function for rounded box float roundedBoxSDF(vec2 p, vec2 b, vec4 r) { - // px = 1.0 if p.x > 0, else 0.0 - float px = step(0.0, p.x); - float py = step(0.0, p.y); - - // Select radius per quadrant - float rLeft = mix(r.x, r.w, py); // top-left / bottom-left - float rRight = mix(r.y, r.z, py); // top-right / bottom-right - float radius = mix(rLeft, rRight, px); // left vs right + vec2 s = step(0.0, p); + float radius = + mix( + mix(r.x, r.y, s.x), + mix(r.w, r.z, s.x), + s.y + ); vec2 q = abs(p) - (b - radius); return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius; } float hollowRoundedBoxSDF(vec2 p, vec2 b, vec4 r, float thickness) { - float outer = roundedBoxSDF(p, b + 0.3, r + 0.3); - float inner = roundedBoxSDF(p, b - thickness, max(r - thickness, 0.0)); - return max(outer, -inner); + float d = roundedBoxSDF(p, b, r); + return abs(d) - thickness; } float roundBoxSDF(vec2 p, vec2 halfSize, float radius) { @@ -164,9 +161,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } float hollowBoxSDF(vec2 p, vec2 halfSize, float thickness) { - float outer = boxSDF(p, halfSize + 0.3); - float inner = boxSDF(p, halfSize - thickness); - return max(outer, -inner); + float d = boxSDF(p, halfSize); + return abs(d) - thickness; } void main() { @@ -175,49 +171,48 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re step(vClipRect.y, vScreenPos.y) * step(vScreenPos.x, vClipRect.z) * step(vScreenPos.y, vClipRect.w); - // if (clip == 0.0) discard; - - float d; - if (vRadii.y == -1.0) { - d = (vThickness > 0.0) ? hollowBoxSDF(vP, vHalfSize, vThickness) : boxSDF(vP, vHalfSize); - } else { - d = (vThickness > 0.0) ? hollowRoundedBoxSDF(vP, vHalfSize, vRadii, vThickness) : roundedBoxSDF(vP, vHalfSize, vRadii); - } +// if (clip == 0.0) discard; vec4 col = vColor0; - if (vUV.x >= 0.0 && vThickness >= -1.0) { // textured if UV.x >= 0 - vec4 texColor = TEXTURE(uTex, vUV); - // text check: use red channel as alpha - if (vThickness == -1.0) { - float w = fwidth(texColor.r); + float d; + if (vThickness <= 0.0) { + if (vThickness == -1.0) { // text + float sdf = TEXTURE(uTex, vUV.xy).r; + float w = fwidth(sdf); // bias increases as glyph gets smaller float bias = 0.5 - min(w * 0.6, 0.08); - col.a *= smoothstep(bias - w, bias + w, texColor.r); - } else col = col * texColor; - } - else if (vThickness == -2.0) { // linear gradient, vUV as start and vUV2 as end - vec2 dir = vUV2 - vUV; - float invLen2 = 1.0 / dot(dir, dir); - float t = clamp(dot((vP + vHalfSize) - vUV, dir) * invLen2, 0.0, 1.0); - col = mix(vColor0, vColor1, t); - } - else if (vThickness == -3.0) { // radial gradient, vUV as center and vUV2.x as radius - float dist = length(vP + vHalfSize - vUV); - float t = clamp((dist - vUV2.x) / (vUV2.y - vUV2.x), 0.0, 1.0); - col = mix(vColor0, vColor1, t); - } - else if (vThickness == -4.0) { // box gradient, vUV.x as radius and vUV.y as feather - float dist = roundBoxSDF(vP, vHalfSize, vUV.x); - float t = clamp((dist + vUV.y * 0.5) / vUV.y, 0.0, 1.0); - col = mix(vColor0, vColor1, t); - } - else if (vThickness == -5.0) { // drop shadow, vUV.x as spread and vUV.y as blur - float dShadow = roundBoxSDF(vP, vHalfSize + vUV.x, vRadii.x); - col = vec4(vColor0.rgb, vColor0.a * (1.0 - smoothstep(-vUV.y, vUV.y, dShadow))); + col.a *= smoothstep(bias - w, bias + w, sdf); + } + else if (vThickness == -2.0) { // image + col = col * TEXTURE(uTex, vUV.xy); + } + else if (vThickness == -3.0) { // linear gradient, vUV.xy as start and vUV.zw as end + vec2 dir = vUV.zw - vUV.xy; + float invLen2 = 1.0 / dot(dir, dir); + float t = clamp(dot((vP_HalfSize.xy + vP_HalfSize.zw) - vUV.xy, dir) * invLen2, 0.0, 1.0); + col = mix(vColor0, vColor1, t); + } + else if (vThickness == -4.0) { // radial gradient, vUV as center and vUV.w as radius + float dist = length(vP_HalfSize.xy + vP_HalfSize.zw - vUV.xy); + float t = clamp((dist - vUV.w) / (vUV.w - vUV.z), 0.0, 1.0); + col = mix(vColor0, vColor1, t); + } + else if (vThickness == -5.0) { // box gradient, vUV.x as radius and vUV.y as feather + float dist = roundBoxSDF(vP_HalfSize.xy, vP_HalfSize.zw, vUV.x); + float t = clamp((dist + vUV.y * 0.5) / vUV.y, 0.0, 1.0); + col = mix(vColor0, vColor1, t); + } + else if (vThickness == -6.0) { // drop shadow, vUV.x as spread and vUV.y as blur + float dShadow = roundBoxSDF(vP_HalfSize.xy, vP_HalfSize.zw + vUV.x, vRadii.x); + col.a *= (1.0 - smoothstep(-vUV.y, vUV.y, dShadow)); + } + d = (vRadii.y == -1.0) ? boxSDF(vP_HalfSize.xy, vP_HalfSize.zw) : roundedBoxSDF(vP_HalfSize.xy, vP_HalfSize.zw, vRadii); + } else { + d = (vRadii.y == -1.0) ? hollowBoxSDF(vP_HalfSize.xy, vP_HalfSize.zw, vThickness) : hollowRoundedBoxSDF(vP_HalfSize.xy, vP_HalfSize.zw, vRadii, vThickness); } // Proper antialiasing based on distance field - float alpha = col.a * clip * clamp(0.5 - d, 0.0, 1.0); + float alpha = col.a * clamp(0.5 - d, 0.0, 1.0); fragColor = vec4(col.rgb * alpha, alpha); } @@ -228,11 +223,11 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re #extension GL_EXT_gpu_shader4 : enable #if __VERSION__ >= 130 #define ATTRIBUTE in - #define VARYING out + #define OUT out #define U_INT uint #else #define ATTRIBUTE attribute - #define VARYING varying + #define OUT varying #define U_INT unsigned int #endif @@ -252,16 +247,14 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re ); uniform vec2 uWindow; - VARYING vec2 vP; - VARYING vec2 vHalfSize; - VARYING vec2 vScreenPos; - VARYING vec4 vClipRect; - VARYING vec4 vRadii; - VARYING vec4 vColor0; - VARYING vec4 vColor1; - VARYING vec2 vUV; - VARYING vec2 vUV2; - VARYING float vThickness; + OUT vec4 vP_HalfSize; + OUT vec2 vScreenPos; + OUT vec4 vClipRect; + OUT vec4 vRadii; + OUT vec4 vColor0; + OUT vec4 vColor1; + OUT vec4 vUV; + OUT float vThickness; vec4 unpackColor(U_INT c) { float a = float((c >> 24) & 0xFFu) / 255.0; @@ -274,26 +267,25 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re void main() { // Position inside rect - vec2 pos = iRect.xy + aLocal * iRect.zw; - vec2 uv = (iThickness > -2.0) ? iUVRect.xy + aLocal * iUVRect.zw : iUVRect.xy; // for gradients, just pass through the first two param to frag + vec2 pos = aLocal * iRect.zw; + vec2 uv = (iThickness > -3.0) ? iUVRect.xy + aLocal * iUVRect.zw : iUVRect.xy; // for gradients, just pass through the first two param to frag + vec2 halfSize = iRect.zw * 0.5; - vec3 transformed = uTransform * vec3(pos, 1.0); + vec3 transformed = uTransform * vec3(pos + iRect.xy, 1.0); vec2 ndc = (transformed.xy / uWindow) * 2.0 - 1.0; ndc.y = -ndc.y; gl_Position = vec4(ndc, 0.0, 1.0); - vHalfSize = iRect.zw * 0.5; - vP = pos - iRect.xy - vHalfSize; - vScreenPos = transformed.xy; - vClipRect = iClipRect; - vRadii = iRadii; - vColor0 = unpackColor(iColor0); - vColor1 = unpackColor(iColor1); - vUV = uv; - vUV2 = iUVRect.zw; // pass through for gradients. - vThickness = iThickness; + vP_HalfSize = vec4(pos - halfSize, halfSize); + vScreenPos = transformed.xy; + vClipRect = iClipRect; + vRadii = iRadii; + vColor0 = unpackColor(iColor0); + vColor1 = unpackColor(iColor1); + vUV = vec4(uv, iUVRect.zw); + vThickness = iThickness; } """.trimIndent() @@ -424,8 +416,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re iColor1 = glGetAttribLocation(program, "iColor1") iUVRect = glGetAttribLocation(program, "iUVRect") iThickness = glGetAttribLocation(program, "iThickness") + iClipRect = glGetAttribLocation(program, "iClipRect") - if (GlCapabilities.isGl3Available) { + if (vao != 0) { var offset = 0L offset = enableAttrib(iRect, 4, offset) offset = enableAttrib(iRadii, 4, offset) @@ -495,7 +488,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glBufferSubData(GL_ARRAY_BUFFER, 0, buffer) val prevVao: Int - if (GlCapabilities.isGl3Available) { + if (vao != 0) { prevVao = glGetInteger(org.lwjgl.opengl.GL30.GL_VERTEX_ARRAY_BINDING) org.lwjgl.opengl.GL30.glBindVertexArray(vao) } else prevVao = 0 @@ -511,7 +504,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re if (GlCapabilities.isGl33Available) org.lwjgl.opengl.GL33.glBindSampler(0, 0) // asm: on VAO the state is stored, so we only need to set it up once - if (!GlCapabilities.isGl3Available) { + if (vao == 0) { // Quad attrib glBindBuffer(GL_ARRAY_BUFFER, quadVbo) glEnableVertexAttribArray(aLocal) @@ -526,7 +519,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re offset = enableAttribui(iColor0, 1, offset) offset = enableAttribui(iColor1, 1, offset) offset = enableAttrib(iUVRect, 4, offset) - enableAttrib(iThickness, 1, offset) + offset = enableAttrib(iThickness, 1, offset) + enableAttrib(iClipRect, 4, offset) } // Draw all instances @@ -543,7 +537,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glActiveTexture(prevActive) glBindTexture(GL_TEXTURE_2D, prevTex) glBindBuffer(GL_ARRAY_BUFFER, prevBuf) - if (GlCapabilities.isGl3Available) org.lwjgl.opengl.GL30.glBindVertexArray(prevVao) + if (vao != 0) org.lwjgl.opengl.GL30.glBindVertexArray(prevVao) } private fun enableAttrib(loc: Int, size: Int, offset: Long): Long { @@ -583,40 +577,40 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re when (val type = color.type) { is PolyColor.Gradient.Type.LeftToRight -> { buffer.put(0f).put(height / 2f).put(width).put(height / 2f) - buffer.put(-2f) + buffer.put(-3f) } is PolyColor.Gradient.Type.TopToBottom -> { buffer.put(width / 2f).put(0f).put(width / 2f).put(height) - buffer.put(-2f) + buffer.put(-3f) } is PolyColor.Gradient.Type.BottomLeftToTopRight -> { buffer.put(0f).put(height).put(width).put(0f) - buffer.put(-2f) + buffer.put(-3f) } is PolyColor.Gradient.Type.TopLeftToBottomRight -> { buffer.put(0f).put(0f).put(width).put(height) - buffer.put(-2f) + buffer.put(-3f) } is PolyColor.Gradient.Type.Radial -> { buffer.put(if (type.centerX == -1f) width / 2f else type.centerX) .put(if (type.centerY == -1f) height / 2f else type.centerY).put(type.innerRadius) .put(type.outerRadius) - buffer.put(-3f) + buffer.put(-4f) } is PolyColor.Gradient.Type.Box -> { buffer.put(type.radius).put(type.feather).put(0f).put(0f) - buffer.put(-4f) + buffer.put(-5f) } } } else { buffer.put(0f) // color1 unused buffer.put(NO_UV) // -1f UVs to indicate no texture - buffer.put(0f) + buffer.put(0f) // standard filled rect } buffer.put(scissorStack, (scissorDepth - 4).coerceAtLeast(0), 4) count += 1 @@ -658,7 +652,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re buffer.put(java.lang.Float.intBitsToFloat(colorMask.capAlpha())) buffer.put(0f) // color1 unused buffer.put(image.uv.x).put(image.uv.y).put(image.uv.w).put(image.uv.h) - buffer.put(0f) // thickness = 0 for filled rect + buffer.put(-2f) // thickness = -2 for textured rect buffer.put(scissorStack, (scissorDepth - 4).coerceAtLeast(0), 4) count += 1 } @@ -719,8 +713,8 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } override fun line(x1: Float, y1: Float, x2: Float, y2: Float, color: Color, width: Float) { - if (y1 == y2) rect(x1, y1, x2 - x1, width, color, 0f, 0f, 0f, 0f) - else rect(x1, y1, width, y2 - y1, color, 0f, 0f, 0f, 0f) + if (y1 == y2) rect(x1, y1, x2 - x1, width, color, 0f, -1f, 0f, 0f) + else rect(x1, y1, width, y2 - y1, color, 0f, -1f, 0f, 0f) } override fun dropShadow( @@ -738,7 +732,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re buffer.put(java.lang.Float.intBitsToFloat(alphaCap shl 24)) // black, alpha to alphaCap buffer.put(0f) // color1 unused buffer.put(spread).put(blur).put(0f).put(0f) - buffer.put(-5f) // thickness = -5 for drop shadow + buffer.put(-6f) // thickness = -6 for drop shadow buffer.put(scissorStack, (scissorDepth - 4).coerceAtLeast(0), 4) count += 1 } @@ -774,7 +768,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re override fun popScissor() { if (scissorDepth <= 4) { scissorDepth = 0 - pushScissor(0f, 0f, width, height) + pushScissor(0f, 0f, 1_000_000_000f, 1_000_000_000f) return } scissorDepth -= 4 From 7ac0f9835a794c45fb07d68f27966e0dd7bc622d Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Wed, 11 Feb 2026 15:40:18 +0000 Subject: [PATCH 44/47] fix GLRendererImpl and HUD editor not rendering, and 1.8 crash --- gradle/libs.versions.toml | 2 +- .../platform/v1/internal/GLPlatformImpl.java | 11 ++++ .../api/ui/v1/internal/wrappers/MCWindow.java | 7 +++ .../ui/v1/internal/wrappers/PolyUIScreen.java | 9 +++- .../api/ui/v1/internal/GLAtlasManager.kt | 4 +- .../api/ui/v1/internal/GLRendererImpl.kt | 50 +++++++++---------- .../api/ui/v1/internal/NVGRendererImpl.kt | 2 +- .../oneconfig/api/ui/v1/internal/StbImpl.kt | 7 +-- .../oneconfig/api/platform/v1/GLPlatform.java | 8 +++ 9 files changed, 66 insertions(+), 34 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fdcf2e368..79c8a1421 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kotlinx-coroutines = "1.10.2" kotlinx-atomicfu = "0.29.0" fabric-language-kotlin = "1.13.8+kotlin.2.3.0" google-ksp = "2.2.10-2.0.2" -polyui = "2.1.6" +polyui = "2.1.7" annotations = "24.1.0" hypixel-modapi = "1.0.1" hypixel-data = "0.2.0" # Dep of hypixel-modapi diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java index 619ae55ac..dd3d6eefc 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java @@ -34,6 +34,7 @@ import org.polyfrost.oneconfig.utils.v1.MHUtils; import java.nio.Buffer; +import java.nio.ByteBuffer; import java.nio.IntBuffer; import static org.lwjgl.opengl.GL11.*; @@ -64,6 +65,16 @@ public long getFunctionAddress(String addr) { } //@formatter:on + + @Override + public long memAddress(ByteBuffer buf) { + //#if MC <= 1.12.2 + return org.lwjgl.MemoryUtil.getAddress(buf); + //#else + //$$ return org.lwjgl.system.MemoryUtil.memAddress(buf); + //#endif + } + /** * This method is called to update the game's internally tracked OpenGL state * to match what NanoVG leaves dropped into the OpenGL context. diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/MCWindow.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/MCWindow.java index 74f4bc664..4f75ddafe 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/MCWindow.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/MCWindow.java @@ -47,6 +47,8 @@ public class MCWindow extends Window { //$$ private final long handle; //#endif + private final float[] viewport = new float[4]; + public MCWindow(Minecraft mc) { super(Platform.screen().viewportWidth(), Platform.screen().viewportHeight(), Platform.screen().pixelRatio()); //#if MC>=11300 @@ -54,6 +56,11 @@ public MCWindow(Minecraft mc) { //#endif } + @Override + public float[] getViewport() { + return viewport; + } + @Override public void close() { Platform.screen().close(); diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java index b911666cf..edf2844c6 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java @@ -128,6 +128,11 @@ public void onRender(@NotNull OmniRenderingContext ctx, int mouseX, int mouseY, int x = Platform.screen().viewportWidth() / 2 - w / 2; int y = Platform.screen().viewportHeight() / 2 - h / 2; glViewport(x, y, w, h); + float[] v = polyUI.getWindow().getViewport(); + v[0] = (float) x; + v[1] = (float) y; + v[2] = (float) w; + v[3] = (float) h; polyUI.render(); glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); //#if MC >= 1.21.5 @@ -236,8 +241,8 @@ public boolean hasBackgroundBlur() { public void mouseMoved(double mouseX, double mouseY) { Drawable master = polyUI.getMaster(); // guys it's not that deep - float ox = Platform.screen().windowWidth() / 2f - master.getWidth() / 2f; - float oy = Platform.screen().windowHeight() / 2f - master.getHeight() / 2f; + float ox = Platform.screen().windowWidth() / 2f - master.getVisibleWidth() / 2f; + float oy = Platform.screen().windowHeight() / 2f - master.getVisibleHeight() / 2f; float mx, my; //#if MC >= 1.13 diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt index 6245918a2..57c496d59 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt @@ -3,7 +3,7 @@ package org.polyfrost.oneconfig.api.ui.v1.internal import org.lwjgl.opengl.GL11.* import org.lwjgl.opengl.GL12.* import org.lwjgl.opengl.GL13.* -import org.lwjgl.system.MemoryUtil +import org.polyfrost.oneconfig.api.platform.v1.Platform import org.polyfrost.polyui.unit.Vec4 import java.nio.ByteBuffer @@ -55,7 +55,7 @@ class GLAtlasManager(val atlasWidth: Int, val atlasHeight: Int) { height: Int, pixels: ByteBuffer, format: Int = GL_RGBA - ): Vec4 = insert(width, height, MemoryUtil.memAddress(pixels), format) + ): Vec4 = insert(width, height, Platform.gl().memAddress(pixels), format) /** * Insert a given texture, a ByteBuffer of [GL_UNSIGNED_BYTE] pixels, of dimensions [width] and [height] into this atlas. diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index ff1ed8b66..d71b9c110 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -14,7 +14,7 @@ import org.lwjgl.opengl.GL13.* import org.lwjgl.opengl.GL14.* import org.lwjgl.opengl.GL15.* import org.lwjgl.opengl.GL20.* -import org.lwjgl.system.MemoryUtil +import org.polyfrost.oneconfig.api.platform.v1.Platform import org.polyfrost.oneconfig.api.ui.v1.UIManager import org.polyfrost.oneconfig.api.ui.v1.api.NanoSvgApi import org.polyfrost.oneconfig.api.ui.v1.api.RendererExt @@ -98,8 +98,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re // Current batch state - private var width = 0f - private var height = 0f + private var viewport = FloatArray(4) private var count = 0 private var transformDepth = 0 private var scissorDepth = 0 @@ -124,7 +123,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re IN vec4 vUV; // UV sampler position IN vec4 vP_HalfSize; // rect x, y, 0.5x wh - IN vec2 vScreenPos; // screen position of the rectangle IN vec4 vClipRect; // clipping rectangle IN vec4 vRadii; // per-corner radii IN vec4 vColor0; // RGBA @@ -166,11 +164,11 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } void main() { - float clip = - step(vClipRect.x, vScreenPos.x) * - step(vClipRect.y, vScreenPos.y) * - step(vScreenPos.x, vClipRect.z) * - step(vScreenPos.y, vClipRect.w); +// float clip = +// step(vClipRect.x, gl_FragCoord.x) * +// step(vClipRect.y, gl_FragCoord.y) * +// step(gl_FragCoord.x, vClipRect.z) * +// step(gl_FragCoord.y, vClipRect.w); // if (clip == 0.0) discard; vec4 col = vColor0; @@ -248,7 +246,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re uniform vec2 uWindow; OUT vec4 vP_HalfSize; - OUT vec2 vScreenPos; OUT vec4 vClipRect; OUT vec4 vRadii; OUT vec4 vColor0; @@ -279,7 +276,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re gl_Position = vec4(ndc, 0.0, 1.0); vP_HalfSize = vec4(pos - halfSize, halfSize); - vScreenPos = transformed.xy; vClipRect = iClipRect; vRadii = iRadii; vColor0 = unpackColor(iColor0); @@ -440,9 +436,12 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glBindBuffer(GL_ARRAY_BUFFER, prevBuf) } - override fun beginFrame(width: Float, height: Float, pixelRatio: Float) { - this.width = width - this.height = height + override fun beginFrame(width: Float, height: Float, pixelRatio: Float, viewport: FloatArray?) { + this.viewport = viewport ?: run { + this.viewport[2] = width + this.viewport[3] = height + this.viewport + } scissorDepth = 0 alphaCap = 255 count = 0 @@ -738,10 +737,11 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re } override fun pushScissor(x: Float, y: Float, width: Float, height: Float) { - scissorStack[scissorDepth++] = x - scissorStack[scissorDepth++] = y - scissorStack[scissorDepth++] = x + width - scissorStack[scissorDepth++] = y + height + val ny = ((viewport[3] + viewport[1]) - (y + height) * pixelRatio) + scissorStack[scissorDepth++] = x * pixelRatio + scissorStack[scissorDepth++] = ny + scissorStack[scissorDepth++] = (x + width) * pixelRatio + scissorStack[scissorDepth++] = ny + height * pixelRatio } override fun pushScissorIntersecting(x: Float, y: Float, width: Float, height: Float) { @@ -753,11 +753,12 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val py = scissorStack[scissorDepth - 3] val pl = scissorStack[scissorDepth - 2] val pr = scissorStack[scissorDepth - 1] + val ny = ((viewport[3] + viewport[1]) - (y + height) * pixelRatio) - val ix = maxOf(x, px) - val iy = maxOf(y, py) - val il = minOf(x + width, pl) - val ir = minOf(y + height, pr) + val ix = maxOf(x * pixelRatio, px) + val iy = maxOf(ny, py) + val il = minOf((x + width) * pixelRatio, pl) + val ir = minOf(ny + height * pixelRatio, pr) scissorStack[scissorDepth++] = ix scissorStack[scissorDepth++] = iy @@ -768,7 +769,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re override fun popScissor() { if (scissorDepth <= 4) { scissorDepth = 0 - pushScissor(0f, 0f, 1_000_000_000f, 1_000_000_000f) + pushScissor(0f, 0f, 1_000_000f, 1_000_000f) return } scissorDepth -= 4 @@ -955,7 +956,6 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val scale: Float init { - val stb = stb if (!stb.font_InitFont(fontInfo, data)) { throw IllegalStateException("Failed to initialize font") } @@ -986,7 +986,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re stb.font_GetGlyphHMetrics(fontInfo, idx, xAdvance, null) var sdf = stb.font_GetGlyphSDF(fontInfo, scale, idx, 4, 128.toByte(), 64f, w, h, xoff, yoff) if (sdf == 0L) sdf = stb.font_GetGlyphBitmap(fontInfo, scale, scale, idx, w, h, xoff, yoff) - if (sdf == 0L) sdf = MemoryUtil.memAddress(BufferUtils.createByteBuffer(w[0] * h[0] * 4)) + if (sdf == 0L) sdf = Platform.gl().memAddress(BufferUtils.createByteBuffer(w[0] * h[0] * 4)) val (u, v, uw, uh) = atlas.insert(w[0], h[0], sdf, GL_RED) return floatArrayOf( diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NVGRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NVGRendererImpl.kt index 52a928dda..71d4066b0 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NVGRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NVGRendererImpl.kt @@ -145,7 +145,7 @@ class NVGRendererImpl( } } - override fun beginFrame(width: Float, height: Float, pixelRatio: Float) { + override fun beginFrame(width: Float, height: Float, pixelRatio: Float, viewport: FloatArray?) { if (isDrawing) throw IllegalStateException("Already drawing") if (mcVersion >= 1_16_05) { diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt index d68feba49..837cf719e 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt @@ -4,6 +4,7 @@ import org.lwjgl.stb.* import org.lwjgl.stb.STBImage.* import org.lwjgl.stb.STBTruetype.* import org.lwjgl.system.MemoryUtil +import org.polyfrost.oneconfig.api.platform.v1.Platform import org.polyfrost.oneconfig.api.ui.v1.api.StbApi import java.nio.ByteBuffer @@ -35,7 +36,7 @@ class StbImpl : StbApi { override fun font_CreatePackContext() = STBTTPackContext.malloc().address() - override fun font_InitFont(info: Long, data: ByteBuffer) = nstbtt_InitFont(info, MemoryUtil.memAddress(data), 0) != 0 + override fun font_InitFont(info: Long, data: ByteBuffer) = nstbtt_InitFont(info, Platform.gl().memAddress(data), 0) != 0 override fun font_FindGlyphIndex(info: Long, codepoint: Int) = nstbtt_FindGlyphIndex(info, codepoint) @@ -73,7 +74,7 @@ class StbImpl : StbApi { allocCtx: Long ) = nstbtt_PackBegin( packCtx, - MemoryUtil.memAddress(pixels), + Platform.gl().memAddress(pixels), width, height, strideInBytes, @@ -91,7 +92,7 @@ class StbImpl : StbApi { packedCharArray: Long ) = nstbtt_PackFontRange( packCtx, - MemoryUtil.memAddress(fontData), + Platform.gl().memAddress(fontData), fontIndex, fontSize, firstUnicodeCodepointInRange, diff --git a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java index f5b168d12..ec5b745c3 100644 --- a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java +++ b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java @@ -29,6 +29,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.nio.ByteBuffer; + public interface GLPlatform { /** @@ -39,6 +41,12 @@ public interface GLPlatform { */ long getFunctionAddress(String addr); + /** + * Return the memory address of the given buffer. + * @implNote delegates to the {@code MemoryUtil.memAddress(ByteBuffer)} method. + */ + long memAddress(ByteBuffer buf); + void syncOpenGLContext(); /** From 1476ec2793958f10806dd5b0861c680df24b55ef Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Wed, 11 Feb 2026 18:09:45 +0000 Subject: [PATCH 45/47] dump --- modules/ui/api/ui.api | 4 ++++ modules/utils/api/utils.api | 1 + 2 files changed, 5 insertions(+) diff --git a/modules/ui/api/ui.api b/modules/ui/api/ui.api index 3e8776876..6709c7304 100644 --- a/modules/ui/api/ui.api +++ b/modules/ui/api/ui.api @@ -131,7 +131,11 @@ public abstract interface class org/polyfrost/oneconfig/api/ui/v1/api/StbApi { public abstract fun font_CreatePackContext ()J public abstract fun font_CreatePackRange ()J public abstract fun font_CreatePackedCharArray (I)J + public abstract fun font_FindGlyphIndex (JI)I public abstract fun font_GetFontVMetrics (J[I[I[I)V + public abstract fun font_GetGlyphBitmap (JFFI[I[I[I[I)J + public abstract fun font_GetGlyphHMetrics (JI[I[I)V + public abstract fun font_GetGlyphSDF (JFIIBF[I[I[I[I)J public abstract fun font_GetPackedGlyph (JI)J public abstract fun font_InitFont (JLjava/nio/ByteBuffer;)Z public abstract fun font_PackBegin (JLjava/nio/ByteBuffer;IIIIJ)Z diff --git a/modules/utils/api/utils.api b/modules/utils/api/utils.api index cdcf7f51e..6babbc38f 100644 --- a/modules/utils/api/utils.api +++ b/modules/utils/api/utils.api @@ -55,6 +55,7 @@ public abstract interface class org/polyfrost/oneconfig/api/platform/v1/GLPlatfo public abstract fun getFunctionAddress (Ljava/lang/String;)J public fun glViewport ()[I public abstract fun glViewport ([I)[I + public abstract fun memAddress (Ljava/nio/ByteBuffer;)J public abstract fun syncOpenGLContext ()V } From 473cc2306e8f31569d7d139145fa57084bb1ea60 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Wed, 11 Feb 2026 21:37:51 +0000 Subject: [PATCH 46/47] fix resizing issue --- .../v1/internal/ScreenPlatformImpl.java | 26 +++++++++---------- .../ui/v1/internal/wrappers/PolyUIScreen.java | 5 ++-- .../oneconfig/internal/OneConfig.java | 6 +++++ .../mixin/events/Mixin_ResizeEvent.java | 4 +-- .../api/ui/v1/internal/NanoSvgImpl.kt | 11 +++----- .../api/platform/v1/ScreenPlatform.java | 23 ++++++++++++++++ 6 files changed, 50 insertions(+), 25 deletions(-) diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java index 59f5dbd9f..208f59629 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/ScreenPlatformImpl.java @@ -33,9 +33,9 @@ import org.polyfrost.oneconfig.api.platform.v1.ScreenPlatform; public class ScreenPlatformImpl implements ScreenPlatform { -// //#if MC > 1.13 -// //$$ private final float[] pixelScaleFactor = new float[1]; -// //#endif + //#if MC > 1.13 + //$$ private final float[] pixelScaleFactor = new float[1]; + //#endif @Override public int viewportWidth() { @@ -79,16 +79,16 @@ public int windowHeight() { // so we use the (well what was assumed to be correct) values provided by GLFW on modern versions. // however, this is not actually correct as shown by issue #478 (above), so we will remove this override for now. // this may have been fixed in GLFW v3.4; but Minecraft is not using that version yet. see https://github.com/glfw/glfw/pull/2457. -// @Override -// public float pixelRatio() { -// // asm: considerably more reliable than just doing viewport / window -// //#if MC > 1.13 -// //$$ org.lwjgl.glfw.GLFW.glfwGetWindowContentScale(Minecraft.getInstance().getWindow().getWindow(), pixelScaleFactor, null); -// //$$ return pixelScaleFactor[0]; -// //#else -// return org.lwjgl.opengl.Display.getPixelScaleFactor(); -// //#endif -// } + @Override + public float pixelRatio() { + // asm: considerably more reliable than just doing viewport / window + //#if MC > 1.13 + //$$ org.lwjgl.glfw.GLFW.glfwGetWindowContentScale(Minecraft.getInstance().getWindow().getWindow(), pixelScaleFactor, null); + //$$ return pixelScaleFactor[0]; + //#else + return org.lwjgl.opengl.Display.getPixelScaleFactor(); + //#endif + } @Override public void display(@Nullable Object screen, int ticks) { diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java index edf2844c6..efa3b7b84 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/ui/v1/internal/wrappers/PolyUIScreen.java @@ -96,9 +96,8 @@ public void onInitialize(int width, int height) { @Override @MustBeInvokedByOverriders public final void onResize(int width, int height) { - float w = (float) Platform.screen().windowWidth(); - float h = (float) Platform.screen().windowHeight(); - adjustResolution(w, h, false); + float scale = Platform.screen().mcToScreenScale(); + adjustResolution(width * scale, height * scale, false); } @Override diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java index e8d04780e..eec04040a 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java @@ -27,6 +27,7 @@ package org.polyfrost.oneconfig.internal; import com.mojang.brigadier.Command; +import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.tree.LiteralCommandNode; import dev.deftu.clipboard.Clipboard; import dev.deftu.omnicore.api.client.OmniClient; @@ -201,6 +202,11 @@ private static void registerCommands() { OneConfigUI.INSTANCE.toggleDebug(); return ctx.getSource().replyChat("OK"); }) + ).then(OmniClientCommands.literal("pixelRatio").then(OmniClientCommands.argument("ratio", FloatArgumentType.floatArg(0.1f, 10f))) + .executes((ctx) -> { + UIManager.INSTANCE.getDefaultInstance().getWindow().setPixelRatio(ctx.getArgument("ratio", float.class)); + return ctx.getSource().replyChat("OK"); + }) ) .then(OmniClientCommands.literal("dumpAtlas") .executes((ctx) -> { diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/mixin/events/Mixin_ResizeEvent.java b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/mixin/events/Mixin_ResizeEvent.java index 15a113294..e5dcfa170 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/mixin/events/Mixin_ResizeEvent.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/mixin/events/Mixin_ResizeEvent.java @@ -16,7 +16,7 @@ public abstract class Mixin_ResizeEvent { //#if MC <= 1.13 - @Inject(method = "resize", at = @At("HEAD")) + @Inject(method = "resize", at = @At("TAIL")) private void resizeCallback(int width, int height, CallbackInfo ci) { EventManager.INSTANCE.post(new ResizeEvent(width, height)); } @@ -24,7 +24,7 @@ private void resizeCallback(int width, int height, CallbackInfo ci) { //$$ @Shadow //$$ public abstract com.mojang.blaze3d.platform.Window getWindow(); //$$ - //$$ @Inject(method = "resizeDisplay", at = @At("HEAD")) + //$$ @Inject(method = "resizeDisplay", at = @At("TAIL")) //$$ private void resizeCallback(CallbackInfo ci) { //$$ int[] w = new int[1]; //$$ int[] h = new int[1]; diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NanoSvgImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NanoSvgImpl.kt index 2ae885144..b62c95852 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NanoSvgImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/NanoSvgImpl.kt @@ -1,10 +1,7 @@ package org.polyfrost.oneconfig.api.ui.v1.internal -import org.lwjgl.nanovg.NSVGImage -import org.lwjgl.nanovg.NanoSVG.nsvgCreateRasterizer -import org.lwjgl.nanovg.NanoSVG.nsvgDelete -import org.lwjgl.nanovg.NanoSVG.nsvgParse -import org.lwjgl.nanovg.NanoSVG.nsvgRasterize +import org.lwjgl.nanovg.NanoSVG.* +import org.polyfrost.oneconfig.api.platform.v1.Platform import org.polyfrost.oneconfig.api.ui.v1.api.NanoSvgApi import java.nio.ByteBuffer @@ -17,7 +14,7 @@ class NanoSvgImpl : NanoSvgApi { } override fun delete(address: Long) { - nsvgDelete(NSVGImage.create(address)) + nnsvgDelete(address) } override fun rasterize( @@ -30,7 +27,7 @@ class NanoSvgImpl : NanoSvgApi { h: Int, stride: Int ) { - nsvgRasterize(handle, NSVGImage.create(address), x, y, scale, data, w, h, stride) + nnsvgRasterize(handle, address, x, y, scale, Platform.gl().memAddress(data), w, h, stride) } private var handle: Long = -1L diff --git a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java index 240b8d0eb..57fa8ed20 100644 --- a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java +++ b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/ScreenPlatform.java @@ -26,6 +26,7 @@ package org.polyfrost.oneconfig.api.platform.v1; +import dev.deftu.omnicore.api.client.render.OmniResolution; import org.jetbrains.annotations.Nullable; public interface ScreenPlatform { @@ -42,6 +43,28 @@ default float pixelRatio() { return (float) viewportWidth() / windowWidth(); } + /** + * Return a scaling factor from the Minecraft scaled coordinate system to standard window coordinates. + *
+ * These window/screen coordinates are used by mouse and input, as well as resizing. + * See the inverse, {@link #screenToMcScale()}. + * @implNote same as {@link OmniResolution#getScaleFactor()} / {@link #pixelRatio()} + */ + default float mcToScreenScale() { + return (float) OmniResolution.getScaleFactor() / pixelRatio(); + } + + /** + * Return a scaling factor from the standard window coordinates to Minecraft scaled coordinate space. + *
+ * These coordinates can be used in Minecraft rendering methods so they render at the correct place. + * See the inverse, {@link #mcToScreenScale()}. + * @implNote same as {@code 1f / }{@link #mcToScreenScale()} + */ + default float screenToMcScale() { + return pixelRatio() / (float) OmniResolution.getScaleFactor(); + } + void display(@Nullable Object screen, int ticks); default void display(Object screen) { From 8d4ae5243bb9418507fe8c9ca041478bf1862294 Mon Sep 17 00:00:00 2001 From: nextdayy <79922345+nextdayy@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:29:24 +0000 Subject: [PATCH 47/47] fix rendering on LWJGL2 and add guard to EventHandler construction --- .../platform/v1/internal/GLPlatformImpl.java | 9 +++++ .../api/event/v1/invoke/EventHandler.java | 10 ++++++ .../oneconfig/api/ui/v1/api/StbApi.java | 23 ++++++------ .../api/ui/v1/internal/GLAtlasManager.kt | 17 +-------- .../api/ui/v1/internal/GLRendererImpl.kt | 34 ++++++++++-------- .../oneconfig/api/ui/v1/internal/StbImpl.kt | 35 ++++++++++--------- .../oneconfig/api/platform/v1/GLPlatform.java | 11 ++++++ 7 files changed, 82 insertions(+), 57 deletions(-) diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java index dd3d6eefc..44749f87c 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/api/platform/v1/internal/GLPlatformImpl.java @@ -75,6 +75,15 @@ public long memAddress(ByteBuffer buf) { //#endif } + @Override + public void glVertexAttribIPointer(int index, int size, int type, int stride, long pointer) { + //#if MC <= 1.12.2 + org.lwjgl.opengl.EXTGpuShader4.glVertexAttribIPointerEXT(index, size, type, stride, pointer); + //#else + //$$ org.lwjgl.opengl.GL30.glVertexAttribIPointer(index, size, type, stride, pointer); + //#endif + } + /** * This method is called to update the game's internally tracked OpenGL state * to match what NanoVG leaves dropped into the OpenGL context. diff --git a/modules/events/src/main/java/org/polyfrost/oneconfig/api/event/v1/invoke/EventHandler.java b/modules/events/src/main/java/org/polyfrost/oneconfig/api/event/v1/invoke/EventHandler.java index f3b673d28..16bec5cb8 100644 --- a/modules/events/src/main/java/org/polyfrost/oneconfig/api/event/v1/invoke/EventHandler.java +++ b/modules/events/src/main/java/org/polyfrost/oneconfig/api/event/v1/invoke/EventHandler.java @@ -31,6 +31,7 @@ import org.polyfrost.oneconfig.api.event.v1.EventManager; import org.polyfrost.oneconfig.api.event.v1.events.Event; +import java.lang.reflect.Modifier; import java.util.function.Consumer; import java.util.function.Predicate; @@ -54,6 +55,9 @@ public abstract class EventHandler implements Comparable EventHandler ofRemoving(Class cls, Predicate handler) { + if (Modifier.isAbstract(cls.getModifiers())) { + throw new IllegalArgumentException("Cannot register to an abstract event type - is there subtypes you need to specify?"); + } return new EventHandler() { @Override public boolean handle(E event) { @@ -77,6 +81,9 @@ public Class getEventClass() { */ @kotlin.OverloadResolutionByLambdaReturnType public static EventHandler of(Class cls, Consumer handler) { + if (Modifier.isAbstract(cls.getModifiers())) { + throw new IllegalArgumentException("Cannot register to an abstract event type - is there subtypes you need to specify?"); + } return new EventHandler() { @Override public boolean handle(E event) { @@ -93,6 +100,9 @@ public Class getEventClass() { @kotlin.OverloadResolutionByLambdaReturnType public static EventHandler of(Class cls, Runnable handler) { + if (Modifier.isAbstract(cls.getModifiers())) { + throw new IllegalArgumentException("Cannot register to an abstract event type - is there subtypes you need to specify?"); + } return new EventHandler() { @Override public boolean handle(E event) { diff --git a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java index 7cdccd0fd..cfd0ce5d9 100644 --- a/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java +++ b/modules/ui/src/main/java/org/polyfrost/oneconfig/api/ui/v1/api/StbApi.java @@ -12,7 +12,7 @@ public interface StbApi { void image_write_png(String filename, int w, int h, int comp, ByteBuffer data, int strideInBytes); - long font_CreateFontInfo(); + StbFontInfo font_CreateFontInfo(); long font_CreatePackRange(); @@ -20,19 +20,19 @@ public interface StbApi { long font_CreatePackContext(); - boolean font_InitFont(long info, ByteBuffer data); + boolean font_InitFont(StbFontInfo info, ByteBuffer data); - int font_FindGlyphIndex(long info, int codepoint); + int font_FindGlyphIndex(StbFontInfo info, int codepoint); - float font_ScaleForMappingEmToPixels(long info, float pixels); + float font_ScaleForMappingEmToPixels(StbFontInfo info, float pixels); - void font_GetFontVMetrics(long info, int[] ascent, int[] descent, int[] lineGap); + void font_GetFontVMetrics(StbFontInfo info, int[] ascent, int[] descent, int[] lineGap); - void font_GetGlyphHMetrics(long info, int glyphIndex, int[] advanceWidth, int[] leftSideBearing); + void font_GetGlyphHMetrics(StbFontInfo info, int glyphIndex, int[] advanceWidth, int[] leftSideBearing); - long font_GetGlyphBitmap(long info, float scaleX, float scaleY, int glyphIndex, int[] w, int[] h, int[] x_off, int[] y_off); + ByteBuffer font_GetGlyphBitmap(StbFontInfo info, float scaleX, float scaleY, int glyphIndex, int[] w, int[] h, int[] x_off, int[] y_off); - long font_GetGlyphSDF(long info, float scale, int glyphIndex, int padding, byte onEdgeValue, float pixelDistScale, int[] w, int[] h, int[] x_off, int[] y_off); + ByteBuffer font_GetGlyphSDF(StbFontInfo info, float scale, int glyphIndex, int padding, byte onEdgeValue, float pixelDistScale, int[] w, int[] h, int[] x_off, int[] y_off); boolean font_PackBegin(long packCtx, ByteBuffer pixels, int width, int height, int strideInBytes, int padding, long allocCtx); @@ -48,8 +48,6 @@ public interface StbApi { void font_RangeSetChardata(long range, long packedCharArray); - void free(long struct); - long font_GetPackedGlyph(long packedCharArray, int index); short glyph_x0(long glyph); @@ -66,4 +64,9 @@ public interface StbApi { float glyph_yoff(long glyph); + interface StbFontInfo { + long address(); + void free(); + } + } diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt index 57c496d59..14631672a 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLAtlasManager.kt @@ -3,7 +3,6 @@ package org.polyfrost.oneconfig.api.ui.v1.internal import org.lwjgl.opengl.GL11.* import org.lwjgl.opengl.GL12.* import org.lwjgl.opengl.GL13.* -import org.polyfrost.oneconfig.api.platform.v1.Platform import org.polyfrost.polyui.unit.Vec4 import java.nio.ByteBuffer @@ -55,20 +54,6 @@ class GLAtlasManager(val atlasWidth: Int, val atlasHeight: Int) { height: Int, pixels: ByteBuffer, format: Int = GL_RGBA - ): Vec4 = insert(width, height, Platform.gl().memAddress(pixels), format) - - /** - * Insert a given texture, a ByteBuffer of [GL_UNSIGNED_BYTE] pixels, of dimensions [width] and [height] into this atlas. - * - * Specify the format of your data with the [format] parameter. - * - * @return A normalised UVWH Vec4 object referring to the dimensions and position of the texture inserted into the atlas. - */ - fun insert( - width: Int, - height: Int, - pixels: Long, - format: Int = GL_RGBA ): Vec4 { val pos = findPosition(width, height) ?: throw IllegalStateException("Texture atlas full") @@ -83,7 +68,7 @@ class GLAtlasManager(val atlasWidth: Int, val atlasHeight: Int) { glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0) glPixelStorei(GL_UNPACK_SKIP_ROWS, 0) - nglTexSubImage2D(GL_TEXTURE_2D, 0, + glTexSubImage2D(GL_TEXTURE_2D, 0, pos.x, pos.y, width, height, format, GL_UNSIGNED_BYTE, pixels diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt index d71b9c110..7148cc062 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/GLRendererImpl.kt @@ -454,13 +454,11 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glUniform2f(uWindow, width, height) glUniformMatrix3fv(uTransform, false, transform) glUseProgram(prevProg) - glDisable(GL_SCISSOR_TEST) this.pixelRatio = pixelRatio } override fun endFrame() { flush() - glDisable(GL_SCISSOR_TEST) } private fun flush() { @@ -477,7 +475,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val prevBlendDstAlpha = glGetInteger(GL_BLEND_DST_ALPHA) val prevDepth = glGetBoolean(GL_DEPTH_TEST) val prevCull = glGetBoolean(GL_CULL_FACE) + val prevScissor = glGetBoolean(GL_SCISSOR_TEST) glEnable(GL_BLEND) + glDisable(GL_SCISSOR_TEST) glDisable(GL_CULL_FACE) glDisable(GL_DEPTH_TEST) glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) @@ -532,6 +532,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re glBlendFuncSeparate(prevBlendSrcRgb, prevBlendDstRgb, prevBlendSrcAlpha, prevBlendDstAlpha) if (prevDepth) glEnable(GL_DEPTH_TEST) if (prevCull) glEnable(GL_CULL_FACE) + if (prevScissor) glEnable(GL_SCISSOR_TEST) glUseProgram(prevProg) glActiveTexture(prevActive) glBindTexture(GL_TEXTURE_2D, prevTex) @@ -550,8 +551,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private fun enableAttribui(loc: Int, size: Int, offset: Long): Long { glEnableVertexAttribArray(loc) - if (GlCapabilities.isGl3Available) org.lwjgl.opengl.GL30.glVertexAttribIPointer(loc, size, GL_UNSIGNED_INT, STRIDE * 4, offset) - else org.lwjgl.opengl.EXTGPUShader4.glVertexAttribIPointerEXT(loc, size, GL_UNSIGNED_INT, STRIDE * 4, offset) + Platform.gl().glVertexAttribIPointer(loc, size, GL_UNSIGNED_INT, STRIDE * 4, offset) if (GlCapabilities.isGl33Available) org.lwjgl.opengl.GL33.glVertexAttribDivisor(loc, 1) else org.lwjgl.opengl.ARBInstancedArrays.glVertexAttribDivisorARB(loc, 1) return offset + size * 4L @@ -659,12 +659,14 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re private fun FloatArray.getScaledMat4(): OmniMatrix4f { // asm: scale to MC instance coordinates and mutate to a 4x4 matrix val sf = pixelRatio / OmniResolution.scaleFactor.toFloat() - return OmniMatrix4f.from(floatArrayOf( - this[0] * sf, this[1] * sf, 0f, 0f, - this[3] * sf, this[4] * sf, 0f, 0f, - 0f, 0f, 1f, 0f, - this[6] * sf, this[7] * sf, 0f, 1f - )) + return OmniMatrix4f.from( + floatArrayOf( + this[0] * sf, this[1] * sf, 0f, 0f, + this[3] * sf, this[4] * sf, 0f, 0f, + 0f, 0f, 1f, 0f, + this[6] * sf, this[7] * sf, 0f, 1f + ) + ) } override fun text(font: Font, x: Float, y: Float, text: String, color: Color, fontSize: Float) { @@ -692,6 +694,10 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re val glyph = fAtlas.get(it) // opt: early exit when we are out of the scissored region if (scissorDepth > 3 && penX > scissorStack[scissorDepth - 2]) return + if (it == 32) { // space + penX += glyph.xAdvance * scaleFactor + return@forEachCodepoint + } buffer.put(penX + glyph.xOff * scaleFactor).put(penY + glyph.yOff * scaleFactor) .put(glyph.width * scaleFactor).put(glyph.height * scaleFactor) buffer.put(0f).put(-1f).put(0f).put(0f) // zero radii (-1 optimization) @@ -984,9 +990,9 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re // } stb.font_GetGlyphHMetrics(fontInfo, idx, xAdvance, null) - var sdf = stb.font_GetGlyphSDF(fontInfo, scale, idx, 4, 128.toByte(), 64f, w, h, xoff, yoff) - if (sdf == 0L) sdf = stb.font_GetGlyphBitmap(fontInfo, scale, scale, idx, w, h, xoff, yoff) - if (sdf == 0L) sdf = Platform.gl().memAddress(BufferUtils.createByteBuffer(w[0] * h[0] * 4)) + val sdf = stb.font_GetGlyphSDF(fontInfo, scale, idx, 4, 128.toByte(), 64f, w, h, xoff, yoff) + ?: stb.font_GetGlyphBitmap(fontInfo, scale, scale, idx, w, h, xoff, yoff) + ?: BufferUtils.createByteBuffer(w[0] * h[0] * 4) val (u, v, uw, uh) = atlas.insert(w[0], h[0], sdf, GL_RED) return floatArrayOf( @@ -1014,7 +1020,7 @@ class GLRendererImpl(private val nsvg: NanoSvgApi, private val stb: StbApi) : Re inline fun get(codepoint: Int) = glyphs.getOrPut(codepoint) { makeGlyph(codepoint) } fun cleanup() { - stb.free(fontInfo) + fontInfo.free() glyphs.clear() } } diff --git a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt index 837cf719e..9f22ae407 100644 --- a/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt +++ b/modules/ui/src/main/kotlin/org/polyfrost/oneconfig/api/ui/v1/internal/StbImpl.kt @@ -28,7 +28,7 @@ class StbImpl : StbApi { STBImageWrite.stbi_write_png(filename, w, h, comp, data, strideInBytes) } - override fun font_CreateFontInfo() = STBTTFontinfo.malloc().address() + override fun font_CreateFontInfo(): StbApi.StbFontInfo = FontInfo(STBTTFontinfo.malloc()) override fun font_CreatePackRange() = STBTTPackRange.malloc().address() @@ -36,32 +36,32 @@ class StbImpl : StbApi { override fun font_CreatePackContext() = STBTTPackContext.malloc().address() - override fun font_InitFont(info: Long, data: ByteBuffer) = nstbtt_InitFont(info, Platform.gl().memAddress(data), 0) != 0 + override fun font_InitFont(info: StbApi.StbFontInfo, data: ByteBuffer) = nstbtt_InitFont(info.address(), Platform.gl().memAddress(data), 0) != 0 - override fun font_FindGlyphIndex(info: Long, codepoint: Int) = nstbtt_FindGlyphIndex(info, codepoint) + override fun font_FindGlyphIndex(info: StbApi.StbFontInfo, codepoint: Int) = nstbtt_FindGlyphIndex(info.address(), codepoint) - override fun font_ScaleForMappingEmToPixels(info: Long, pixels: Float) = - nstbtt_ScaleForMappingEmToPixels(info, pixels) + override fun font_ScaleForMappingEmToPixels(info: StbApi.StbFontInfo, pixels: Float) = + nstbtt_ScaleForMappingEmToPixels(info.address(), pixels) override fun font_GetFontVMetrics( - info: Long, + info: StbApi.StbFontInfo, ascent: IntArray, descent: IntArray, lineGap: IntArray ) { - nstbtt_GetFontVMetrics(info, ascent, descent, lineGap) + nstbtt_GetFontVMetrics(info.address(), ascent, descent, lineGap) } - override fun font_GetGlyphHMetrics(info: Long, glyphIndex: Int, advanceWidth: IntArray?, leftSideBearing: IntArray?) { - nstbtt_GetGlyphHMetrics(info, glyphIndex, advanceWidth, leftSideBearing) + override fun font_GetGlyphHMetrics(info: StbApi.StbFontInfo, glyphIndex: Int, advanceWidth: IntArray?, leftSideBearing: IntArray?) { + nstbtt_GetGlyphHMetrics(info.address(), glyphIndex, advanceWidth, leftSideBearing) } - override fun font_GetGlyphBitmap(info: Long, scaleX: Float, scaleY: Float, glyphIndex: Int, w: IntArray?, h: IntArray?, x_off: IntArray?, y_off: IntArray?): Long { - return nstbtt_GetGlyphBitmap(info, scaleX, scaleY, glyphIndex, w, h, x_off, y_off) + override fun font_GetGlyphBitmap(info: StbApi.StbFontInfo, scaleX: Float, scaleY: Float, glyphIndex: Int, w: IntArray?, h: IntArray?, x_off: IntArray?, y_off: IntArray?): ByteBuffer? { + return stbtt_GetGlyphBitmap((info as FontInfo).struct, scaleX, scaleY, glyphIndex, w, h, x_off, y_off) } - override fun font_GetGlyphSDF(info: Long, scale: Float, glyphIndex: Int, padding: Int, onEdgeValue: Byte, pixelDistScale: Float, w: IntArray?, h: IntArray?, x_off: IntArray?, y_off: IntArray?): Long { - return nstbtt_GetGlyphSDF(info, scale, glyphIndex, padding, onEdgeValue, pixelDistScale, w, h, x_off, y_off) + override fun font_GetGlyphSDF(info: StbApi.StbFontInfo, scale: Float, glyphIndex: Int, padding: Int, onEdgeValue: Byte, pixelDistScale: Float, w: IntArray?, h: IntArray?, x_off: IntArray?, y_off: IntArray?): ByteBuffer? { + return stbtt_GetGlyphSDF((info as FontInfo).struct, scale, glyphIndex, padding, onEdgeValue, pixelDistScale, w, h, x_off, y_off) } override fun font_PackBegin( @@ -123,10 +123,6 @@ class StbImpl : StbApi { MemoryUtil.memPutAddress(range + STBTTPackRange.CHARDATA_FOR_RANGE, packedCharArray) } - override fun free(struct: Long) { - MemoryUtil.nmemFree(struct) - } - override fun font_GetPackedGlyph(packedCharArray: Long, index: Int) = packedCharArray + index * STBTTPackedchar.SIZEOF override fun glyph_x0(glyph: Long) = STBTTPackedchar.nx0(glyph) @@ -142,4 +138,9 @@ class StbImpl : StbApi { override fun glyph_xoff(glyph: Long) = STBTTPackedchar.nxoff(glyph) override fun glyph_yoff(glyph: Long) = STBTTPackedchar.nyoff(glyph) + + private class FontInfo(val struct: STBTTFontinfo) : StbApi.StbFontInfo { + override fun address() = struct.address() + override fun free() = struct.free() + } } diff --git a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java index ec5b745c3..62cad54db 100644 --- a/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java +++ b/modules/utils/src/main/java/org/polyfrost/oneconfig/api/platform/v1/GLPlatform.java @@ -47,6 +47,17 @@ public interface GLPlatform { */ long memAddress(ByteBuffer buf); + /** + * This method will try and run glVertexAttribIPointer on the current OpenGL context. + *
If the context is OpenGL3+, it will run the core API method. + *
If not, it will run the method using the EXT_gpu_shader4 extension. + *
If this is missing, this will blow up. + * + * @implNote This method exists solely to fix the issue that in LWJGL2, the extension has a different class name + * to that in LWJGL3. thanks, guys. + */ + void glVertexAttribIPointer(int index, int size, int type, int stride, long pointer); + void syncOpenGLContext(); /**