From 1f924e15eb96728112699ceeaa03e366ca896c0f Mon Sep 17 00:00:00 2001
From: "coderabbitai[bot]"
<136622811+coderabbitai[bot]@users.noreply.github.com>
Date: Sat, 22 Feb 2025 01:43:18 +0000
Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20Add=20docstrings=20to=20`refacto?=
=?UTF-8?q?r/ui`?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Docstrings generation was requested by @Edouard127.
* https://github.com/Avanatiker/NeoLambda/pull/98#issuecomment-2675797941
The following files were modified:
* `common/src/main/java/com/lambda/mixin/render/ChatHudMixin.java`
* `common/src/main/java/com/lambda/mixin/render/ChatInputSuggestorMixin.java`
* `common/src/main/java/com/lambda/mixin/render/ChatScreenMixin.java`
* `common/src/main/java/com/lambda/mixin/render/DrawContextMixin.java`
* `common/src/main/java/com/lambda/mixin/render/SplashOverlayMixin.java`
* `common/src/main/kotlin/com/lambda/graphics/RenderMain.kt`
* `common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt`
* `common/src/main/kotlin/com/lambda/graphics/buffer/Buffer.kt`
* `common/src/main/kotlin/com/lambda/graphics/buffer/IRenderContext.kt`
* `common/src/main/kotlin/com/lambda/graphics/buffer/VertexPipeline.kt`
* `common/src/main/kotlin/com/lambda/graphics/buffer/frame/CachedFrame.kt`
* `common/src/main/kotlin/com/lambda/graphics/buffer/frame/FrameBuffer.kt`
* `common/src/main/kotlin/com/lambda/graphics/buffer/frame/ScreenFrameBuffer.kt`
* `common/src/main/kotlin/com/lambda/graphics/buffer/pixel/PixelBuffer.kt`
* `common/src/main/kotlin/com/lambda/graphics/buffer/vertex/ElementBuffer.kt`
* `common/src/main/kotlin/com/lambda/graphics/buffer/vertex/VertexArray.kt`
* `common/src/main/kotlin/com/lambda/graphics/buffer/vertex/VertexBuffer.kt`
* `common/src/main/kotlin/com/lambda/graphics/gl/GlStateUtils.kt`
* `common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt`
* `common/src/main/kotlin/com/lambda/graphics/gl/Memory.kt`
* `common/src/main/kotlin/com/lambda/graphics/pipeline/ScissorAdapter.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/esp/ChunkedESP.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/esp/ESPRenderer.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/gui/AbstractGUIRenderer.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/gui/TextureRenderer.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaAtlas.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaEmoji.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaFont.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/sdf/DistanceFieldTexture.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt`
* `common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt`
* `common/src/main/kotlin/com/lambda/graphics/shader/Shader.kt`
* `common/src/main/kotlin/com/lambda/graphics/shader/ShaderUtils.kt`
* `common/src/main/kotlin/com/lambda/graphics/texture/AnimatedTexture.kt`
* `common/src/main/kotlin/com/lambda/graphics/texture/Texture.kt`
* `common/src/main/kotlin/com/lambda/graphics/texture/TextureOwner.kt`
* `common/src/main/kotlin/com/lambda/graphics/texture/TextureUtils.kt`
* `common/src/main/kotlin/com/lambda/gui/GuiManager.kt`
* `common/src/main/kotlin/com/lambda/gui/LambdaScreen.kt`
* `common/src/main/kotlin/com/lambda/gui/ScreenLayout.kt`
* `common/src/main/kotlin/com/lambda/gui/component/DockingRect.kt`
* `common/src/main/kotlin/com/lambda/gui/component/core/FilledRect.kt`
* `common/src/main/kotlin/com/lambda/gui/component/core/OutlineRect.kt`
* `common/src/main/kotlin/com/lambda/gui/component/core/TextField.kt`
* `common/src/main/kotlin/com/lambda/gui/component/layout/Layout.kt`
* `common/src/main/kotlin/com/lambda/gui/component/window/TitleBar.kt`
* `common/src/main/kotlin/com/lambda/gui/component/window/Window.kt`
* `common/src/main/kotlin/com/lambda/gui/component/window/WindowContent.kt`
* `common/src/main/kotlin/com/lambda/gui/impl/clickgui/ModuleLayout.kt`
* `common/src/main/kotlin/com/lambda/gui/impl/clickgui/ModuleWindow.kt`
* `common/src/main/kotlin/com/lambda/gui/impl/clickgui/settings/BooleanButton.kt`
* `common/src/main/kotlin/com/lambda/module/HudModule.kt`
* `common/src/main/kotlin/com/lambda/module/Module.kt`
* `common/src/main/kotlin/com/lambda/module/modules/client/LambdaMoji.kt`
* `common/src/main/kotlin/com/lambda/module/modules/player/MapDownloader.kt`
---
.../com/lambda/mixin/render/ChatHudMixin.java | 14 ++
.../mixin/render/ChatInputSuggestorMixin.java | 47 +++++
.../lambda/mixin/render/ChatScreenMixin.java | 10 +
.../lambda/mixin/render/DrawContextMixin.java | 29 ++-
.../mixin/render/SplashOverlayMixin.java | 9 +
.../kotlin/com/lambda/graphics/RenderMain.kt | 23 +++
.../lambda/graphics/animation/Animation.kt | 38 +++-
.../com/lambda/graphics/buffer/Buffer.kt | 106 +++++++----
.../lambda/graphics/buffer/IRenderContext.kt | 29 ++-
.../lambda/graphics/buffer/VertexPipeline.kt | 12 ++
.../graphics/buffer/frame/CachedFrame.kt | 10 +-
.../graphics/buffer/frame/FrameBuffer.kt | 46 +++++
.../buffer/frame/ScreenFrameBuffer.kt | 42 ++++-
.../graphics/buffer/pixel/PixelBuffer.kt | 13 ++
.../graphics/buffer/vertex/ElementBuffer.kt | 9 +
.../graphics/buffer/vertex/VertexArray.kt | 33 +++-
.../graphics/buffer/vertex/VertexBuffer.kt | 10 +
.../com/lambda/graphics/gl/GlStateUtils.kt | 26 +++
.../kotlin/com/lambda/graphics/gl/Matrices.kt | 19 +-
.../kotlin/com/lambda/graphics/gl/Memory.kt | 7 +
.../graphics/pipeline/ScissorAdapter.kt | 20 ++
.../graphics/renderer/esp/ChunkedESP.kt | 7 +
.../graphics/renderer/esp/ESPRenderer.kt | 9 +
.../renderer/gui/AbstractGUIRenderer.kt | 11 ++
.../graphics/renderer/gui/TextureRenderer.kt | 20 ++
.../renderer/gui/font/FontRenderer.kt | 117 +++++++++---
.../renderer/gui/font/core/LambdaAtlas.kt | 56 +++++-
.../renderer/gui/font/core/LambdaEmoji.kt | 22 ++-
.../renderer/gui/font/core/LambdaFont.kt | 8 +
.../gui/font/sdf/DistanceFieldTexture.kt | 7 +
.../renderer/gui/rect/FilledRectRenderer.kt | 58 ++++++
.../renderer/gui/rect/OutlineRectRenderer.kt | 27 +++
.../com/lambda/graphics/shader/Shader.kt | 51 +++++-
.../com/lambda/graphics/shader/ShaderUtils.kt | 45 +++++
.../graphics/texture/AnimatedTexture.kt | 15 ++
.../com/lambda/graphics/texture/Texture.kt | 94 +++++++---
.../lambda/graphics/texture/TextureOwner.kt | 45 +++--
.../lambda/graphics/texture/TextureUtils.kt | 38 ++++
.../main/kotlin/com/lambda/gui/GuiManager.kt | 30 ++-
.../kotlin/com/lambda/gui/LambdaScreen.kt | 95 +++++++++-
.../kotlin/com/lambda/gui/ScreenLayout.kt | 11 +-
.../com/lambda/gui/component/DockingRect.kt | 8 +
.../lambda/gui/component/core/FilledRect.kt | 39 +++-
.../lambda/gui/component/core/OutlineRect.kt | 13 +-
.../lambda/gui/component/core/TextField.kt | 8 +-
.../com/lambda/gui/component/layout/Layout.kt | 173 +++++++++++++-----
.../lambda/gui/component/window/TitleBar.kt | 9 +
.../com/lambda/gui/component/window/Window.kt | 30 ++-
.../gui/component/window/WindowContent.kt | 36 +++-
.../lambda/gui/impl/clickgui/ModuleLayout.kt | 14 +-
.../lambda/gui/impl/clickgui/ModuleWindow.kt | 10 +-
.../impl/clickgui/settings/BooleanButton.kt | 7 +-
.../kotlin/com/lambda/module/HudModule.kt | 10 +-
.../main/kotlin/com/lambda/module/Module.kt | 5 +
.../module/modules/client/LambdaMoji.kt | 18 +-
.../module/modules/player/MapDownloader.kt | 8 +
56 files changed, 1477 insertions(+), 229 deletions(-)
diff --git a/common/src/main/java/com/lambda/mixin/render/ChatHudMixin.java b/common/src/main/java/com/lambda/mixin/render/ChatHudMixin.java
index a1e8dd4b5..66109cce0 100644
--- a/common/src/main/java/com/lambda/mixin/render/ChatHudMixin.java
+++ b/common/src/main/java/com/lambda/mixin/render/ChatHudMixin.java
@@ -28,6 +28,20 @@
@Mixin(ChatHud.class)
public class ChatHudMixin {
+ /**
+ * Redirects the chat HUD text rendering to apply custom text parsing and color adjustments.
+ *
+ *
This method intercepts calls to {@code DrawContext#drawTextWithShadow} during chat rendering.
+ * It processes the text using {@code LambdaMoji.INSTANCE.parse} to incorporate custom formatting (e.g., emoji support),
+ * overrides the x-coordinate by rendering at x = 0, and adjusts the text color by combining a white base (0xFFFFFF)
+ * with an alpha value derived from the provided {@code color} parameter.
+ *
+ * @param text the text to be rendered, processed for custom formatting
+ * @param x the original x-coordinate (ignored as rendering occurs at x = 0)
+ * @param y the y-coordinate for rendering the text
+ * @param color the original text color used to compute the alpha channel for the final rendered color
+ * @return the result of the underlying text rendering call
+ */
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/OrderedText;III)I"))
int redirectRenderCall(DrawContext instance, TextRenderer textRenderer, OrderedText text, int x, int y, int color) {
return instance.drawTextWithShadow(textRenderer, LambdaMoji.INSTANCE.parse(text, x, y, color), 0, y, 16777215 + (color << 24));
diff --git a/common/src/main/java/com/lambda/mixin/render/ChatInputSuggestorMixin.java b/common/src/main/java/com/lambda/mixin/render/ChatInputSuggestorMixin.java
index 170b025e1..eafc58bf2 100644
--- a/common/src/main/java/com/lambda/mixin/render/ChatInputSuggestorMixin.java
+++ b/common/src/main/java/com/lambda/mixin/render/ChatInputSuggestorMixin.java
@@ -55,19 +55,56 @@ public abstract class ChatInputSuggestorMixin {
@Shadow
private @Nullable CompletableFuture pendingSuggestions;
+ /**
+ * Displays the current suggestion list.
+ *
+ * This shadowed method should be overridden to update the suggestion display. If
+ * {@code narrateFirstSuggestion} is {@code true}, the method should also provide narration
+ * for the first suggestion to enhance accessibility.
+ *
+ * @param narrateFirstSuggestion if {@code true}, the first suggestion is narrated; otherwise, it is not
+ */
@Shadow
public abstract void show(boolean narrateFirstSuggestion);
+ /**
+ * Determines if the current chat input text should be treated as a command.
+ *
+ *
This method overrides the provided showCompletions flag during the refresh
+ * process by evaluating the text currently entered in the chat input field. It returns
+ * true if the input is recognized as a command, and false otherwise.
+ *
+ * @param showCompletions the initial flag indicating whether completions should be shown (its value is ignored)
+ * @return true if the chat input text is recognized as a command, false otherwise
+ */
@ModifyVariable(method = "refresh", at = @At(value = "STORE"), index = 3)
private boolean refreshModify(boolean showCompletions) {
return CommandManager.INSTANCE.isCommand(textField.getText());
}
+ /**
+ * Redirects the command dispatcher retrieval to use a custom dispatcher based on the current chat input.
+ *
+ * Instead of invoking the default dispatcher from the network handler during a refresh, this method
+ * fetches a dispatcher tailored to the chat input text from the CommandManager.
+ *
+ * @return a command dispatcher that reflects the current chat input context
+ */
@Redirect(method = "refresh", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;getCommandDispatcher()Lcom/mojang/brigadier/CommandDispatcher;"))
private CommandDispatcher refreshRedirect(ClientPlayNetworkHandler instance) {
return CommandManager.INSTANCE.currentDispatcher(textField.getText());
}
+ /**
+ * Injects emoji suggestion logic at the end of the chat refresh process.
+ *
+ * This method verifies that emoji suggestions are enabled and that the current input is not a command.
+ * It extracts text up to the cursor, identifies the last colon to determine the start of the emoji query,
+ * and filters available emojis based on the subsequent substring. The resulting suggestions are then
+ * prepared and, once completed, are displayed.
+ *
+ * @param ci the callback information for the injection point
+ */
@Inject(method = "refresh", at = @At("TAIL"))
private void refreshEmojiSuggestion(CallbackInfo ci) {
if (!LambdaMoji.INSTANCE.isEnabled() ||
@@ -105,6 +142,16 @@ private void refreshEmojiSuggestion(CallbackInfo ci) {
@Unique
private static final Pattern COLON_PATTERN = Pattern.compile("(:[a-zA-Z0-9_]+)");
+ /**
+ * Returns the index of the last occurrence of a colon that precedes valid emoji key characters.
+ *
+ *
The method uses a regular expression to identify sequences starting with a colon
+ * followed by alphanumeric characters or underscores. If the input is null, empty, or no
+ * matching sequence is found, it returns -1.
+ *
+ * @param input the string to be searched for a colon pattern
+ * @return the index of the last colon matching the pattern, or -1 if none is found
+ */
@Unique
private int neoLambda$getLastColon(String input) {
if (Strings.isNullOrEmpty(input)) return -1;
diff --git a/common/src/main/java/com/lambda/mixin/render/ChatScreenMixin.java b/common/src/main/java/com/lambda/mixin/render/ChatScreenMixin.java
index cc6b0edb8..5187060f4 100644
--- a/common/src/main/java/com/lambda/mixin/render/ChatScreenMixin.java
+++ b/common/src/main/java/com/lambda/mixin/render/ChatScreenMixin.java
@@ -26,6 +26,16 @@
@Mixin(ChatScreen.class)
public abstract class ChatScreenMixin {
+ /**
+ * Intercepts the chat message sending process to execute Lambda commands.
+ *
+ * If the chat text is recognized as a Lambda command, the command is executed via the CommandManager,
+ * and the default message sending is canceled by setting the callback's return value to true.
+ *
+ * @param chatText the text of the chat message being processed
+ * @param addToHistory flag indicating whether the message should be added to the chat history (not used for Lambda commands)
+ * @param cir callback used to override the normal sending behavior of the chat message
+ */
@Inject(method = "sendMessage", at = @At("HEAD"), cancellable = true)
void sendMessageInject(String chatText, boolean addToHistory, CallbackInfoReturnable cir) {
if (!CommandManager.INSTANCE.isLambdaCommand(chatText)) return;
diff --git a/common/src/main/java/com/lambda/mixin/render/DrawContextMixin.java b/common/src/main/java/com/lambda/mixin/render/DrawContextMixin.java
index d71452858..e0c887514 100644
--- a/common/src/main/java/com/lambda/mixin/render/DrawContextMixin.java
+++ b/common/src/main/java/com/lambda/mixin/render/DrawContextMixin.java
@@ -45,8 +45,35 @@
@Mixin(DrawContext.class)
public abstract class DrawContextMixin {
- @Shadow protected abstract void drawTooltip(TextRenderer textRenderer, List components, int x, int y, TooltipPositioner positioner);
+ /**
+ * Renders a tooltip using the provided text renderer, tooltip components, and positioning strategy.
+ *
+ * This shadowed method is implemented by the target class to draw tooltips at the specified coordinates.
+ * The tooltip components determine the content displayed, while the positioner defines how the tooltip is positioned on the screen.
+ *
+ * @param textRenderer the renderer used for drawing the tooltip's text
+ * @param components the list of components forming the tooltip's content
+ * @param x the x-coordinate for the tooltip's starting position
+ * @param y the y-coordinate for the tooltip's starting position
+ * @param positioner the strategy that determines the tooltip's placement
+ */
+@Shadow protected abstract void drawTooltip(TextRenderer textRenderer, List components, int x, int y, TooltipPositioner positioner);
+ /**
+ * Overrides the default tooltip rendering to include additional components.
+ *
+ * This injected method converts a list of text components into tooltip components. If optional tooltip data
+ * is present, it is inserted into the list, and if the currently focused item is a filled map, a map preview
+ * component is added. It then calls the shadowed tooltip drawing method with the modified components and cancels
+ * further execution of the original method.
+ *
+ * @param textRenderer the renderer used to draw text
+ * @param text the list of text elements to be converted into tooltip components
+ * @param data an optional tooltip data element to be incorporated into the tooltip
+ * @param x the x-coordinate for tooltip positioning
+ * @param y the y-coordinate for tooltip positioning
+ * @param ci the callback information used to cancel the original tooltip rendering
+ */
@Inject(method = "drawTooltip(Lnet/minecraft/client/font/TextRenderer;Ljava/util/List;Ljava/util/Optional;II)V", at = @At("HEAD"), cancellable = true)
void drawItemTooltip(TextRenderer textRenderer, List text, Optional data, int x, int y, CallbackInfo ci) {
List list = text.stream().map(Text::asOrderedText).map(TooltipComponent::of).collect(Collectors.toList());
diff --git a/common/src/main/java/com/lambda/mixin/render/SplashOverlayMixin.java b/common/src/main/java/com/lambda/mixin/render/SplashOverlayMixin.java
index 3787b762b..5478ca4f1 100644
--- a/common/src/main/java/com/lambda/mixin/render/SplashOverlayMixin.java
+++ b/common/src/main/java/com/lambda/mixin/render/SplashOverlayMixin.java
@@ -60,6 +60,15 @@ public LogoTextureMixin(Identifier location) {
super(location);
}
+ /**
+ * Redirects the default texture loading to supply a custom banner texture.
+ *
+ * This method intercepts the call to load texture data from the default resource pack and returns
+ * an InputSupplier that provides an InputStream for the custom texture located at "textures/lambda_banner.png".
+ * The provided resource pack, resource type, and identifier are ignored.
+ *
+ * @return an InputSupplier that supplies the custom banner texture's input stream
+ */
@Redirect(method = "loadTextureData", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/DefaultResourcePack;open(Lnet/minecraft/resource/ResourceType;Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/InputSupplier;"))
InputSupplier loadTextureData(DefaultResourcePack instance, ResourceType type, Identifier id) {
return () -> LambdaResourceKt.getStream("textures/lambda_banner.png");
diff --git a/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt b/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt
index e448cd798..c8163f0fa 100644
--- a/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt
@@ -36,6 +36,13 @@ object RenderMain {
var screenSize = Vec2d.ZERO
var scaleFactor = 1.0
+ /**
+ * Renders the 2D interface elements.
+ *
+ * This function resets the transformation matrices with a translation along the z-axis to position the 2D
+ * layer appropriately, then sets up the OpenGL state and posts rendering events for fixed GUI elements,
+ * the HUD, and scaled elements using the default and current GUI scaling factors.
+ */
@JvmStatic
fun render2D() {
resetMatrices(Matrix4f().translate(0f, 0f, -3000f))
@@ -50,6 +57,12 @@ object RenderMain {
}
}
+ /**
+ * Prepares the 3D rendering context by resetting matrices with the given transformation,
+ * updating the projection matrix, and posting a world render event.
+ *
+ * @param matrix the transformation matrix used to reset the rendering matrices.
+ */
@JvmStatic
fun render3D(matrix: Matrix4f) {
resetMatrices(matrix)
@@ -60,6 +73,16 @@ object RenderMain {
}
}
+ /**
+ * Recalculates the screen dimensions and updates the orthographic projection matrix based on a scaling factor.
+ *
+ * This function retrieves the current framebuffer dimensions, computes the scaled width and height
+ * by dividing them by the provided factor, and then updates the global screen size and scale factor.
+ * It sets the projection matrix to an orthographic projection using the calculated dimensions with a
+ * near plane of 1000f and a far plane of 21000f.
+ *
+ * @param factor the scale factor used to adjust the framebuffer dimensions.
+ */
private fun rescale(factor: Double) {
val width = mc.window.framebufferWidth.toFloat()
val height = mc.window.framebufferHeight.toFloat()
diff --git a/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt b/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt
index 286740dfb..b13edf513 100644
--- a/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt
@@ -27,11 +27,43 @@ class Animation(initialValue: Double, val update: (Double) -> Double) {
private var prevValue = initialValue
private var currValue = initialValue
- operator fun getValue(thisRef: Any?, property: KProperty<*>) = value()
- operator fun setValue(thisRef: Any?, property: KProperty<*>, valueIn: Double) = setValue(valueIn)
+ /**
+ * Retrieves the current interpolated animation value.
+ *
+ * This operator function enables property delegation by returning the animation's
+ * current value as computed by the [value] method, which interpolates between the previous
+ * and current states.
+ */
+operator fun getValue(thisRef: Any?, property: KProperty<*>) = value()
+ /**
+ * Delegated setter that updates the animation's value.
+ *
+ * This operator function is triggered when a delegated property is assigned a new value. It sets both the previous
+ * and current values of the animation to the provided [valueIn].
+ *
+ * @param thisRef The object owning the delegated property (unused).
+ * @param property Metadata for the property being assigned (unused).
+ * @param valueIn The new value to set for the animation.
+ */
+operator fun setValue(thisRef: Any?, property: KProperty<*>, valueIn: Double) = setValue(valueIn)
- fun value(): Double = lerp(mc.partialTicks, prevValue, currValue)
+ /**
+ * Computes and returns the current interpolated animation value.
+ *
+ * This function uses linear interpolation between the previous and current animation values,
+ * leveraging the partial tick value from the rendering context (mc.partialTicks) to ensure smooth transitions.
+ *
+ * @return the interpolated animation value.
+ */
+fun value(): Double = lerp(mc.partialTicks, prevValue, currValue)
+ /**
+ * Resets the animation state by updating both the previous and current values.
+ *
+ * This ensures that the animation starts from a consistent value without any interpolation.
+ *
+ * @param valueIn The new value to set as both the previous and current animation state.
+ */
fun setValue(valueIn: Double) {
prevValue = valueIn
currValue = valueIn
diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/Buffer.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/Buffer.kt
index 0025bfdff..7375c3f21 100644
--- a/common/src/main/kotlin/com/lambda/graphics/buffer/Buffer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/buffer/Buffer.kt
@@ -114,18 +114,29 @@ abstract class Buffer(
private val bufferIds = IntArray(buffers)
/**
- * Binds the buffer id to the [target]
- */
+ * Binds the specified buffer id to this buffer's target.
+ *
+ * This operation makes the buffer identified by [id] the active buffer for subsequent OpenGL operations
+ * on the target defined by this buffer.
+ *
+ * @param id the unique identifier of the buffer to bind.
+ */
open fun bind(id: Int) = glBindBuffer(target, id)
/**
- * Binds current the buffer [index] to the [target]
- */
+ * Binds the active buffer to its target.
+ *
+ * Retrieves the buffer ID associated with the current [index] using [bufferAt] and binds it
+ * by calling the overloaded [bind] method.
+ */
fun bind() = bind(bufferAt(index))
/**
- * Returns the id of the buffer based on the index
- */
+ * Retrieves the buffer identifier at the specified index.
+ *
+ * @param index The 0-based index of the buffer ID.
+ * @return The buffer identifier corresponding to the given index.
+ */
fun bufferAt(index: Int) = bufferIds[index]
/**
@@ -136,8 +147,17 @@ abstract class Buffer(
}
/**
- * Update the current buffer without re-allocating
- * Alternative to [map]
+ * Updates the current buffer's data at the given offset without reallocating its memory.
+ *
+ * This method uploads the provided data to the buffer using a sub-data update mechanism.
+ * It verifies that the buffer's target is valid and bound before performing the update;
+ * if either check fails, an IllegalArgumentException is returned.
+ *
+ * @param data the new data to upload into the buffer.
+ * @param offset the byte offset within the buffer at which the update should start.
+ * @return an IllegalArgumentException if the buffer is not valid or bound; otherwise, null.
+ *
+ * @see map
*/
open fun update(
data: ByteBuffer,
@@ -155,10 +175,14 @@ abstract class Buffer(
}
/**
- * Allocates a region of memory for the buffer
- * This function handles the buffer binding
+ * Allocates and initializes buffer storage using the provided data.
+ *
+ * This function validates the buffer's target and usage before allocation. If the validation fails, it returns an
+ * IllegalArgumentException. Otherwise, it binds and allocates storage for each buffer in sequence, updating the current
+ * buffer index by swapping after each allocation, and finally resets the binding.
*
- * @param data The data to put in the new allocated buffer
+ * @param data The ByteBuffer containing the initial data for the buffer.
+ * @return An IllegalArgumentException if validation fails; null if allocation succeeds.
*/
open fun allocate(data: ByteBuffer): Throwable? {
if (!bufferValid(target, access))
@@ -179,10 +203,14 @@ abstract class Buffer(
}
/**
- * Grows the backing buffers
- * This function handles the buffer binding
+ * Allocates memory for each backing buffer using the specified size.
+ *
+ * This method first validates that the buffer's target and usage are valid. If either check fails, it returns an
+ * [IllegalArgumentException] with a descriptive message. Otherwise, it binds each backing buffer in turn, allocates its
+ * memory storage, and updates to the next buffer before finally unbinding.
*
- * @param size The size of the new buffer
+ * @param size The desired size for each buffer allocation.
+ * @return An [IllegalArgumentException] if validation fails, or null if the allocation succeeds.
*/
open fun allocate(size: Long): Throwable? {
if (!bufferValid(target, access))
@@ -203,9 +231,14 @@ abstract class Buffer(
}
/**
- * Create a new buffer storage
- * This function cannot be called twice for the same buffer
- * This function handles the buffer binding
+ * Allocates new storage for the OpenGL buffer using the provided data.
+ *
+ * This function validates the target and usage before creating storage for each buffer in a multi-buffer
+ * configuration. It handles the binding of each buffer and automatically swaps buffers during storage allocation.
+ * Note that this operation should only be performed once per buffer.
+ *
+ * @param data the ByteBuffer containing the data to initialize the buffer storage.
+ * @return an IllegalArgumentException for an invalid target or usage, or null if storage allocation is successful.
*/
open fun storage(data: ByteBuffer): Throwable? {
if (!bufferValid(target, access))
@@ -226,11 +259,14 @@ abstract class Buffer(
}
/**
- * Create a new buffer storage
- * This function cannot be called twice for the same buffer
- * This function handles the buffer binding
+ * Allocates storage for the buffer object.
+ *
+ * This function initializes storage for each allocated buffer using the specified size,
+ * automatically handling binding and unbinding. It validates the buffer's target, access flags,
+ * and usage before allocation. Note that it should only be called once per buffer.
*
- * @param size The size of the storage buffer
+ * @param size the desired storage size in bytes (negative values are coerced to zero)
+ * @return an IllegalArgumentException if the target or usage is invalid; null if storage allocation succeeds
*/
open fun storage(size: Long): Throwable? {
if (!bufferValid(target, access))
@@ -251,12 +287,16 @@ abstract class Buffer(
}
/**
- * Maps all or part of a buffer object's data store into the client's address space
+ * Maps a specified region of the buffer's data store into client memory, processes it using the provided lambda, and then unmaps the buffer.
*
- * @param size Specifies the length of the range to be mapped.
- * @param offset Specifies the starting offset within the buffer of the range to be mapped.
- * @param block Lambda scope with the mapped buffer passed in
- * @return Error encountered during the mapping process
+ * The function validates the offset, size, and mapping access flags before mapping the buffer. It then passes the mapped ByteBuffer to the lambda,
+ * allowing for direct data manipulation. After the lambda completes, the buffer is unmapped. If any validation or operation fails, a Throwable
+ * describing the error is returned; otherwise, null is returned to indicate success.
+ *
+ * @param size the length of the memory region to map.
+ * @param offset the starting offset within the buffer for mapping.
+ * @param block a lambda function that receives the mapped ByteBuffer for data manipulation.
+ * @return null if the mapping and unmapping succeed; otherwise, a Throwable with the error details.
*/
open fun map(
size: Long,
@@ -311,12 +351,14 @@ abstract class Buffer(
}
/**
- * Sets the given data into the client mapped memory and executes the provided processing function to manage data transfer.
- *
- * @param data Data to set in memory
- * @param offset The starting offset within the buffer of the range to be mapped
- * @return Error encountered during the mapping process
- */
+ * Uploads the specified data to the buffer starting at the given offset.
+ *
+ * This abstract function should be implemented to perform the actual data transfer into the buffer.
+ *
+ * @param data The ByteBuffer containing the data to be uploaded.
+ * @param offset The offset within the buffer at which to begin the upload.
+ * @return A Throwable if an error occurs during the upload process, or null if the upload is successful.
+ */
abstract fun upload(data: ByteBuffer, offset: Long): Throwable?
init {
diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/IRenderContext.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/IRenderContext.kt
index 3bb15197e..109132933 100644
--- a/common/src/main/kotlin/com/lambda/graphics/buffer/IRenderContext.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/buffer/IRenderContext.kt
@@ -36,16 +36,41 @@ interface IRenderContext {
fun render()
fun upload()
- fun clear()
+ /**
+ * Clears the current rendering context.
+ *
+ * This resets the context by removing any queued or rendered data,
+ * preparing it for new drawing commands.
+ */
+fun clear()
+ /**
+ * Executes an immediate draw by sequentially calling upload, render, and clear.
+ *
+ * This method provides a single entry point for performing the complete draw cycle without requiring separate calls for
+ * uploading data, rendering the content, and clearing the context.
+ */
fun immediateDraw() {
upload()
render()
clear()
}
- fun grow(amount: Int)
+ /**
+ * Increases the capacity of the rendering context by the specified amount.
+ *
+ * @param amount The additional capacity units to add.
+ */
+fun grow(amount: Int)
+ /**
+ * Executes the given block within the current rendering context.
+ *
+ * This method allows for scoping multiple rendering operations or configurations within
+ * a single lambda, using the current context as the receiver.
+ *
+ * @param block a lambda with receiver that encapsulates rendering commands.
+ */
fun use(block: IRenderContext.() -> Unit) {
block()
}
diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/VertexPipeline.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/VertexPipeline.kt
index 808b690ee..ef3aa4e4a 100644
--- a/common/src/main/kotlin/com/lambda/graphics/buffer/VertexPipeline.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/buffer/VertexPipeline.kt
@@ -177,6 +177,13 @@ class VertexPipeline(
uploadedIndices = indicesCount
}
+ /**
+ * Resets the vertex position and index counters to their initial state.
+ *
+ * This method sets the vertex position pointer back to its original location and resets
+ * the vertex index, indices count, and uploaded indices counters to zero, preparing the
+ * pipeline for a new rendering sequence.
+ */
override fun clear() {
verticesPosition = verticesPointer
vertexIndex = 0
@@ -184,6 +191,11 @@ class VertexPipeline(
uploadedIndices = 0
}
+ /**
+ * Finalizes the vertex pipeline.
+ *
+ * Currently, this method is a placeholder reserved for future cleanup or resource finalization logic. It does not perform any actions.
+ */
fun finalize() {
}
diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/frame/CachedFrame.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/frame/CachedFrame.kt
index 9126de77e..46caf44a8 100644
--- a/common/src/main/kotlin/com/lambda/graphics/buffer/frame/CachedFrame.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/buffer/frame/CachedFrame.kt
@@ -43,12 +43,14 @@ class CachedFrame(val width: Int, val height: Int) {
fun bind(slot: Int = 0) = frameBuffer.bindColorTexture(slot)
/**
- * Executes custom drawing operations on the framebuffer.
+ * Executes custom drawing operations within the cached framebuffer.
*
- * The method temporarily modifies the view and projection matrices, the viewport,
- * and then restores them after the block is executed.
+ * This function temporarily adjusts the OpenGL state by saving the current view and projection matrices,
+ * as well as the viewport dimensions, then sets up a translation and an orthographic projection matching
+ * the framebuffer's size. After executing the provided drawing block, it restores all previous settings.
*
- * @param block A block of code that performs custom drawing operations on the framebuffer.
+ * @param block A lambda containing the drawing operations to be executed on the framebuffer.
+ * @return The current CachedFrame instance.
*/
fun write(block: () -> Unit): CachedFrame {
frameBuffer.write {
diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/frame/FrameBuffer.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/frame/FrameBuffer.kt
index d340b524c..957f66b00 100644
--- a/common/src/main/kotlin/com/lambda/graphics/buffer/frame/FrameBuffer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/buffer/frame/FrameBuffer.kt
@@ -45,6 +45,15 @@ open class FrameBuffer(
private var lastWidth = -1
private var lastHeight = -1
+ /**
+ * Binds this framebuffer, updates its configuration, executes the given rendering block, and restores the previous framebuffer binding.
+ *
+ * Temporarily replaces the currently bound framebuffer with this instance, ensuring it is properly configured by invoking an update,
+ * and then executes the provided block of rendering commands. After the block completes, it restores the prior framebuffer context.
+ *
+ * @param block the lambda containing rendering operations to execute while this framebuffer is active.
+ * @return this framebuffer instance.
+ */
open fun write(block: () -> Unit): FrameBuffer {
val prev = lastFrameBuffer ?: mc.framebuffer.fbo
@@ -60,6 +69,16 @@ open class FrameBuffer(
return this
}
+ /**
+ * Updates the framebuffer attachments to match the current dimensions.
+ *
+ * If the current width and height match the previously recorded dimensions, the function
+ * simply clears the framebuffer using the configured clear mask. Otherwise, it updates the
+ * color texture attachment and, if enabled, the depth texture attachment by reconfiguring
+ * texture parameters and reallocating storage to the new dimensions. After resetting the clear
+ * color and depth values and clearing the framebuffer, it verifies that the framebuffer is complete,
+ * throwing an error if it is not.
+ */
private fun update() {
if (width == lastWidth && height == lastWidth) {
glClear(clearMask)
@@ -91,11 +110,30 @@ open class FrameBuffer(
}
}
+ /**
+ * Binds the framebuffer's color attachment texture to the specified texture slot.
+ *
+ * This method makes the framebuffer's color texture available for use in subsequent rendering operations.
+ * The current instance is returned to facilitate method chaining.
+ *
+ * @param slot The texture slot index to which the color texture is bound. Defaults to 0.
+ * @return The current FrameBuffer instance.
+ */
open fun bindColorTexture(slot: Int = 0): FrameBuffer {
TextureUtils.bindTexture(colorAttachment, slot)
return this
}
+ /**
+ * Binds the framebuffer's depth texture to the specified texture slot.
+ *
+ * This method binds the depth texture to the given texture unit, enabling it for subsequent rendering operations.
+ * If the framebuffer was created without a depth attachment, an [IllegalStateException] is thrown.
+ *
+ * @param slot the texture slot to bind the depth texture to (default is 0).
+ * @return this [FrameBuffer] instance.
+ * @throws IllegalStateException if the framebuffer does not have a depth attachment.
+ */
open fun bindDepthTexture(slot: Int = 0): FrameBuffer {
check(depth) {
"Cannot bind depth texture of a non-depth framebuffer"
@@ -109,6 +147,14 @@ open class FrameBuffer(
val pipeline = VertexPipeline(VertexMode.TRIANGLES, VertexAttrib.Group.POS_UV)
private var lastFrameBuffer: Int? = null
+ /**
+ * Configures an OpenGL texture object with linear filtering and clamp-to-edge wrapping.
+ *
+ * This function binds the texture identified by [id], sets both its minification and magnification filters to
+ * linear filtering, and applies clamp-to-edge wrapping for its S and T coordinates.
+ *
+ * @param id the identifier of the texture to configure.
+ */
private fun setupBufferTexture(id: Int) {
TextureUtils.bindTexture(id)
TextureUtils.setupTexture(GL_LINEAR, GL_LINEAR)
diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/frame/ScreenFrameBuffer.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/frame/ScreenFrameBuffer.kt
index 466473a81..3cd4f3474 100644
--- a/common/src/main/kotlin/com/lambda/graphics/buffer/frame/ScreenFrameBuffer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/buffer/frame/ScreenFrameBuffer.kt
@@ -25,6 +25,21 @@ import com.lambda.util.math.Vec2d
import org.lwjgl.opengl.GL11C.*
class ScreenFrameBuffer(depth: Boolean = false) : FrameBuffer(depth = depth) {
+ /**
+ * Renders the frame buffer content onto a quad using the specified shader.
+ *
+ * This function binds the frame buffer's color texture and activates the provided shader,
+ * allowing for further customization via the optional [shaderBlock]. It then computes normalized
+ * UV coordinates based on the given screen positions ([pos1] and [pos2]) relative to the current
+ * screen dimensions, and defines a quadrilateral for rendering. Finally, it applies a blending mode,
+ * uploads, renders, and clears the internal pipeline.
+ *
+ * @param shader The shader used for rendering the frame buffer content.
+ * @param pos1 The starting screen position (in pixels) for the rendering region. Defaults to [Vec2d.ZERO].
+ * @param pos2 The ending screen position (in pixels) for the rendering region. Defaults to [RenderMain.screenSize].
+ * @param shaderBlock Optional lambda for additional shader configuration.
+ * @return The current instance of [ScreenFrameBuffer] to support method chaining.
+ */
fun read(
shader: Shader,
pos1: Vec2d = Vec2d.ZERO,
@@ -59,6 +74,15 @@ class ScreenFrameBuffer(depth: Boolean = false) : FrameBuffer(depth = depth) {
return this
}
+ /**
+ * Updates the frame buffer's dimensions to match the current window size and executes rendering instructions with a specific blend configuration.
+ *
+ * This method sets the frame buffer's width and height based on the current Minecraft window dimensions, then calls the superclass
+ * write method while wrapping the provided rendering block within a blend function using source alpha and one minus source alpha factors.
+ *
+ * @param block the lambda containing rendering instructions to be executed with the configured blending.
+ * @return the current instance of ScreenFrameBuffer.
+ */
override fun write(block: () -> Unit): ScreenFrameBuffer {
width = mc.window.framebufferWidth
height = mc.window.framebufferHeight
@@ -68,9 +92,23 @@ class ScreenFrameBuffer(depth: Boolean = false) : FrameBuffer(depth = depth) {
} as ScreenFrameBuffer
}
- override fun bindColorTexture(slot: Int) =
+ /**
+ * Binds the color texture to the specified slot and returns the current instance as a ScreenFrameBuffer.
+ *
+ * This method delegates to the superclass implementation and casts its result to ensure type consistency.
+ *
+ * @param slot The texture binding slot.
+ */
+ override fun bindColorTexture(slot: Int) =
super.bindColorTexture(slot) as ScreenFrameBuffer
- override fun bindDepthTexture(slot: Int) =
+ /**
+ * Binds the depth texture to the specified slot by invoking the superclass method and casting the result
+ * to a ScreenFrameBuffer.
+ *
+ * @param slot the texture slot to which the depth texture is bound.
+ * @return the current ScreenFrameBuffer instance.
+ */
+ override fun bindDepthTexture(slot: Int) =
super.bindDepthTexture(slot) as ScreenFrameBuffer
}
\ No newline at end of file
diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/pixel/PixelBuffer.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/pixel/PixelBuffer.kt
index c8e590125..d0a4ca677 100644
--- a/common/src/main/kotlin/com/lambda/graphics/buffer/pixel/PixelBuffer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/buffer/pixel/PixelBuffer.kt
@@ -49,6 +49,19 @@ class PixelBuffer(
private val channels = channelMapping[texture.format] ?: throw IllegalArgumentException("Invalid image format, expected OpenGL format, got ${texture.format} instead")
private val size = texture.width * texture.height * channels * 1L
+ /**
+ * Uploads pixel data from the provided buffer to the associated texture via the Pixel Buffer Object.
+ *
+ * This method binds the pixel buffer and texture, then transfers pixel data using glTexSubImage2D,
+ * covering the texture's entire dimensions and using an offset for asynchronous transfers. Depending
+ * on the bufferMapping flag, it either maps the buffer for a memory-based update or performs a direct update.
+ * After swapping internal buffers and unbinding, it returns any error encountered during the upload,
+ * or null if the upload was successful.
+ *
+ * @param data The ByteBuffer containing the pixel data to upload.
+ * @param offset The offset within the pixel buffer from which to start the data transfer.
+ * @return A Throwable if an error occurred during the upload, or null on success.
+ */
override fun upload(
data: ByteBuffer,
offset: Long,
diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/ElementBuffer.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/ElementBuffer.kt
index 700ff8a8f..567528c14 100644
--- a/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/ElementBuffer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/ElementBuffer.kt
@@ -30,6 +30,15 @@ class ElementBuffer(mode: VertexMode) :
override val target: Int = GL_ELEMENT_ARRAY_BUFFER
override val access: Int = GL_MAP_WRITE_BIT
+ /**
+ * Uploads data to the buffer.
+ *
+ * Delegates to the allocation routine to upload the provided data and returns any error encountered during this process.
+ *
+ * @param data the ByteBuffer containing the data to be uploaded.
+ * @param offset the offset within the data (currently not used).
+ * @return a Throwable if an error occurs during allocation, or null if the upload succeeds.
+ */
override fun upload(
data: ByteBuffer,
offset: Long,
diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/VertexArray.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/VertexArray.kt
index 5362c6ad4..f2b2e4937 100644
--- a/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/VertexArray.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/VertexArray.kt
@@ -27,19 +27,50 @@ class VertexArray : Buffer(isVertexArray = true) {
override val target: Int = -1
override val access: Int = -1
+ /**
+ * Throws an UnsupportedOperationException to indicate that memory mapping is not supported for vertex array objects.
+ *
+ * @param size the intended size of the memory mapping.
+ * @param offset the intended offset in the buffer.
+ * @param block the callback to process the mapped ByteBuffer (unused).
+ * @throws UnsupportedOperationException always thrown to indicate that mapping is not supported.
+ */
override fun map(
size: Long,
offset: Long,
block: (ByteBuffer) -> Unit
): Throwable = throw UnsupportedOperationException("Cannot map a vertex array object to memory")
+ /**
+ * Attempts to upload data to the vertex array object.
+ *
+ * This operation is not supported for vertex array objects and always throws an
+ * UnsupportedOperationException.
+ *
+ * @param data the buffer containing the data to upload (unused)
+ * @param offset the offset at which data would have been uploaded (unused)
+ * @throws UnsupportedOperationException always thrown to indicate that data uploads are not supported for vertex array objects.
+ */
override fun upload(
data: ByteBuffer,
offset: Long,
): Throwable = throw UnsupportedOperationException("Data cannot be uploaded to a vertex array object")
- override fun allocate(size: Long) = throw UnsupportedOperationException("Cannot grow a vertex array object")
+ /**
+ * Throws an UnsupportedOperationException because vertex array objects cannot be resized.
+ *
+ * @param size The requested allocation size, which is ignored because growing a vertex array is unsupported.
+ * @throws UnsupportedOperationException always thrown to indicate the operation is not supported.
+ */
+override fun allocate(size: Long) = throw UnsupportedOperationException("Cannot grow a vertex array object")
+ /**
+ * Binds the vertex array object using the specified identifier.
+ *
+ * This method calls `glBindVertexArray` to bind the vertex array and resets the current vertex buffer binding.
+ *
+ * @param id the OpenGL identifier of the vertex array.
+ */
override fun bind(id: Int) {
glBindVertexArray(id); BufferRenderer.currentVertexBuffer = null
}
diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/VertexBuffer.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/VertexBuffer.kt
index 1d9ff8185..c1b9ff16d 100644
--- a/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/VertexBuffer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/buffer/vertex/VertexBuffer.kt
@@ -32,6 +32,16 @@ class VertexBuffer(
override val target: Int = GL_ARRAY_BUFFER
override val access: Int = GL_MAP_WRITE_BIT
+ /**
+ * Uploads vertex data to the vertex buffer.
+ *
+ * This method allocates memory for the vertex buffer using the provided data.
+ * The offset parameter is not used in the current implementation.
+ *
+ * @param data the ByteBuffer containing the vertex data.
+ * @param offset the starting offset for the upload operation (currently ignored).
+ * @return a Throwable if an error occurs during allocation, otherwise null.
+ */
override fun upload(
data: ByteBuffer,
offset: Long,
diff --git a/common/src/main/kotlin/com/lambda/graphics/gl/GlStateUtils.kt b/common/src/main/kotlin/com/lambda/graphics/gl/GlStateUtils.kt
index ddcefd46e..b5f4c2495 100644
--- a/common/src/main/kotlin/com/lambda/graphics/gl/GlStateUtils.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/gl/GlStateUtils.kt
@@ -24,6 +24,15 @@ object GlStateUtils {
private var blendState = false
private var cullState = true
+ /**
+ * Temporarily configures OpenGL states for rendering, executes the provided block, and then restores the previous state.
+ *
+ * This function saves the current depth testing, blending, and face culling states. It then sets up OpenGL by disabling depth testing,
+ * enabling blending, disabling face culling, setting the depth mask to false, and enabling line smoothing before executing the provided block.
+ * After the block completes, it restores the original depth testing, blending, face culling, depth mask, and line smoothing settings.
+ *
+ * @param block OpenGL operations to perform under the temporary state configuration.
+ */
fun setupGL(block: () -> Unit) {
val savedDepthTest = depthTestState
val savedBlend = blendState
@@ -46,6 +55,15 @@ object GlStateUtils {
cull(savedCull)
}
+ /**
+ * Enables depth testing and optionally configures the depth mask during the execution of a code block.
+ *
+ * When invoked, depth testing is enabled. If [maskWrite] is true, the depth buffer is made writable before the
+ * block is executed and set back to non-writable afterward. Finally, depth testing is disabled once the block finishes.
+ *
+ * @param maskWrite if true, enables writing to the depth buffer for the duration of the block.
+ * @param block the code to execute with the modified depth state.
+ */
fun withDepth(maskWrite: Boolean = false, block: () -> Unit) {
depthTest(true)
if (maskWrite) glDepthMask(true)
@@ -54,6 +72,14 @@ object GlStateUtils {
depthTest(false)
}
+ /**
+ * Executes the provided block with face culling enabled.
+ *
+ * This function turns on face culling, executes the given block of code, and then disables face culling,
+ * ensuring that the OpenGL state is restored after the block execution.
+ *
+ * @param block the code to run with face culling enabled.
+ */
fun withFaceCulling(block: () -> Unit) {
cull(true)
block()
diff --git a/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt b/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt
index 71189e7e5..95126a355 100644
--- a/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt
@@ -89,11 +89,13 @@ object Matrices {
}
/**
- * Translates the current matrix by the given x, y, and z values.
+ * Applies a translation to the top matrix on the transformation stack.
*
- * @param x The translation amount along the X axis.
- * @param y The translation amount along the Y axis.
- * @param z The translation amount along the Z axis. Defaults to `0f`.
+ * The given offsets are used to modify the current transformation matrix in-place.
+ *
+ * @param x the translation offset along the X axis.
+ * @param y the translation offset along the Y axis.
+ * @param z the translation offset along the Z axis (default is 0f).
*/
fun translate(x: Float, y: Float, z: Float = 0f) {
stack.last().translate(x, y, z)
@@ -152,12 +154,13 @@ object Matrices {
}
/**
- * Temporarily sets a vertex offset vector for the duration of a block.
+ * Applies a temporary vertex offset to mitigate precision issues in matrix operations on large coordinates.
*
- * Use this to avoid precision loss when using matrices while being on huge coordinates.
+ * The provided `offset` is set prior to executing the block and then reset to null, ensuring that the transformation
+ * is only applied during the block's execution.
*
- * @param offset The transformation offset to apply to vertices.
- * @param block The block of code to execute with the transformation applied.
+ * @param offset the offset to apply to vertices for reducing precision loss.
+ * @param block the block of code within which the vertex offset is active.
*/
fun withVertexOffset(offset: Vec3d, block: () -> Unit) {
vertexOffset = offset
diff --git a/common/src/main/kotlin/com/lambda/graphics/gl/Memory.kt b/common/src/main/kotlin/com/lambda/graphics/gl/Memory.kt
index c99fe6d68..2e75cba3f 100644
--- a/common/src/main/kotlin/com/lambda/graphics/gl/Memory.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/gl/Memory.kt
@@ -113,4 +113,11 @@ val Long.kibibyte get() = this * 1024
val Long.mebibyte get() = this * 1024 * 1024
val Long.gibibyte get() = this * 1024 * 1024 * 1024
+/**
+ * Copies the contents of this ByteBuffer into the specified destination ByteBuffer.
+ *
+ * Data is transferred starting at the current positions of both buffers, and their positions are advanced by the number of bytes copied.
+ *
+ * @param dst the destination ByteBuffer to receive the copied bytes.
+ */
fun ByteBuffer.putTo(dst: ByteBuffer) { dst.put(this) }
diff --git a/common/src/main/kotlin/com/lambda/graphics/pipeline/ScissorAdapter.kt b/common/src/main/kotlin/com/lambda/graphics/pipeline/ScissorAdapter.kt
index be66c63a7..30c710d08 100644
--- a/common/src/main/kotlin/com/lambda/graphics/pipeline/ScissorAdapter.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/pipeline/ScissorAdapter.kt
@@ -28,6 +28,17 @@ import com.mojang.blaze3d.systems.RenderSystem.enableScissor
object ScissorAdapter {
private var stack = ArrayDeque()
+ /**
+ * Restricts rendering operations to the specified scissor rectangle.
+ *
+ * This function clamps the provided rectangle to the boundaries of the current scissor area (if one exists),
+ * pushes the resulting rectangle onto an internal stack, and sets the scissor test to that area. It then
+ * executes the given lambda block within this constrained context. After the block completes, the function
+ * restores the previous scissor state or disables scissor testing if no prior rectangle exists.
+ *
+ * @param rect The area to which rendering should be confined.
+ * @param block A lambda with rendering instructions to execute within the scissor area.
+ */
fun scissor(rect: Rect, block: () -> Unit) {
val processed = stack.lastOrNull()?.let(rect::clamp) ?: rect
@@ -40,6 +51,15 @@ object ScissorAdapter {
stack.lastOrNull()?.let { scissorRect(it) } ?: disableScissor()
}
+ /**
+ * Configures the scissor test region using the provided rectangle.
+ *
+ * The function scales the rectangle by the current rendering scale factor, computes the screen-space coordinates,
+ * and adjusts the y-coordinate relative to the framebuffer height. It then enables the scissor test with the computed
+ * integer bounds.
+ *
+ * @param rect The rectangle defining the area to restrict rendering.
+ */
private fun scissorRect(rect: Rect) {
val pos1 = rect.leftTop * RenderMain.scaleFactor
val pos2 = rect.rightBottom * RenderMain.scaleFactor
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/ChunkedESP.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/ChunkedESP.kt
index fb5c0d201..6087aa279 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/ChunkedESP.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/ChunkedESP.kt
@@ -117,6 +117,13 @@ class ChunkedESP private constructor(
}
}
+ /**
+ * Asynchronously rebuilds the ESP renderer for the current chunk.
+ *
+ * A new [StaticESPRenderer] instance is created on the main thread with a specific configuration, then updated using
+ * the owner's update function for every coordinate within the chunk. Finally, an upload task is queued that uploads
+ * the new renderer and sets it as the active renderer for the chunk.
+ */
suspend fun rebuild() {
val newRenderer = awaitMainThread { StaticESPRenderer(false) }
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/ESPRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/ESPRenderer.kt
index 3087e16c0..861cfc21d 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/ESPRenderer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/ESPRenderer.kt
@@ -45,6 +45,12 @@ open class ESPRenderer(tickedMode: Boolean) {
outlines.upload()
}
+ /**
+ * Renders the ESP effect.
+ *
+ * Activates the shader and updates its uniforms with the current tick delta and camera position,
+ * then applies face culling and a specific line width to render the faces and outlines.
+ */
fun render() {
shader.use()
shader["u_TickDelta"] = Lambda.mc.partialTicks
@@ -54,6 +60,9 @@ open class ESPRenderer(tickedMode: Boolean) {
GlStateUtils.withLineWidth(RenderSettings.outlineWidth, outlines::render)
}
+ /**
+ * Clears the vertex data from both face and outline pipelines.
+ */
open fun clear() {
faces.clear()
outlines.clear()
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/AbstractGUIRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/AbstractGUIRenderer.kt
index 3bd9a33c0..219560650 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/AbstractGUIRenderer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/AbstractGUIRenderer.kt
@@ -35,6 +35,17 @@ abstract class AbstractGUIRenderer(
) {
private val pipeline = VertexPipeline(VertexMode.TRIANGLES, attribGroup)
+ /**
+ * Renders GUI elements using the vertex pipeline and shader.
+ *
+ * This method clears the current vertex pipeline, activates the shader, and then executes the
+ * provided lambda [block] to customize vertex data. If [shade] is true, additional shader uniforms
+ * are configured for dynamic shading effects—such as time, colors, and size adjustments—for rendering.
+ * Finally, the pipeline data is uploaded to the GPU and rendered.
+ *
+ * @param shade Whether to apply shading effects (default is false).
+ * @param block A lambda that operates on the vertex pipeline to customize the rendering.
+ */
protected fun render(
shade: Boolean = false,
block: VertexPipeline.() -> Unit
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/TextureRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/TextureRenderer.kt
index b8a736f64..5388fd4ac 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/TextureRenderer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/TextureRenderer.kt
@@ -34,6 +34,15 @@ object TextureRenderer {
private val mainShader = shader("renderer/pos_tex")
private val coloredShader = shader("renderer/pos_tex_shady")
+ /**
+ * Draws the specified texture within the given rectangular area.
+ *
+ * This function binds the provided texture and activates the main shader before rendering
+ * a quad that corresponds to the area defined by the rectangle.
+ *
+ * @param texture the texture to render.
+ * @param rect the area within which the texture should be drawn.
+ */
fun drawTexture(texture: Texture, rect: Rect) {
texture.bind()
mainShader.use()
@@ -41,6 +50,17 @@ object TextureRenderer {
drawInternal(rect)
}
+ /**
+ * Renders a texture with a dynamic shading effect.
+ *
+ * Binds the given texture and activates a specialized shader that applies animated color shading.
+ * The shading parameters are determined using the current time (via glfwGetTime()) and the settings
+ * from GuiSettings, including color speed, primary and secondary colors, and a size factor calculated
+ * from the screen dimensions. The final rendering is delegated to the internal drawing routine.
+ *
+ * @param texture the texture to render with shading.
+ * @param rect the rectangular area defining where the texture should be drawn.
+ */
fun drawTextureShaded(texture: Texture, rect: Rect) {
texture.bind()
coloredShader.use()
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt
index a3774186c..495ef53ce 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt
@@ -46,14 +46,17 @@ object FontRenderer : AbstractGUIRenderer(VertexAttrib.Group.FONT, shader("font/
private val gap get() = RenderSettings.gap * 0.5f - 0.8f
/**
- * Builds the vertex array for rendering the provided text string at a specified position.
+ * Renders a text string at a specified position with configurable color, scale, shadow, and emoji parsing.
*
- * @param text The text to render.
- * @param position The position to render the text.
- * @param color The color of the text.
- * @param scale The scale factor of the text.
- * @param shadow Whether to render a shadow for the text.
- * @param parseEmoji Whether to parse and render emojis in the text.
+ * This function sets up shader parameters for font and emoji textures, binds the current font assets,
+ * and processes the text to generate glyph vertices for rendering.
+ *
+ * @param text the text string to render.
+ * @param position the position at which the text is drawn.
+ * @param color the color to use for the text.
+ * @param scale the scale factor for the text size.
+ * @param shadow if true, renders a shadow effect along with the text.
+ * @param parseEmoji if true, parses and renders emoji characters in the text.
*/
fun drawString(
text: String,
@@ -75,6 +78,18 @@ object FontRenderer : AbstractGUIRenderer(VertexAttrib.Group.FONT, shader("font/
}
}
+ /**
+ * Renders a single glyph at the specified position with the given scale and color.
+ *
+ * This function sets up shader parameters and binds the current font and emoji textures before
+ * computing the effective scale and adjusted positions based on the glyph’s dimensions and the current
+ * baseline offset. It then builds and renders the glyph’s quad.
+ *
+ * @param glyph the glyph information containing size and texture coordinates.
+ * @param position the rendering position where the glyph will be drawn.
+ * @param color the color applied to the glyph (default is [Color.WHITE]).
+ * @param scale the scale factor for the glyph (default is 1.0).
+ */
fun drawGlyph(
glyph: GlyphInfo,
position: Vec2d,
@@ -99,13 +114,17 @@ object FontRenderer : AbstractGUIRenderer(VertexAttrib.Group.FONT, shader("font/
}
/**
- * Renders a single glyph at a given position.
+ * Constructs and adds a quad for the specified glyph to the vertex pipeline.
*
- * @param glyph The glyph information to render.
- * @param origin The position to start from
- * @param pos1 The starting position of the glyph.
- * @param pos2 The end position of the glyph
- * @param color The color of the glyph.
+ * The quad's vertices are computed by offsetting the provided boundary positions (`pos1` and `pos2`)
+ * with the given `origin`. Each vertex is assigned texture coordinates derived from the glyph data and
+ * tinted with the specified color.
+ *
+ * @param glyph The glyph providing texture mapping coordinates.
+ * @param origin The positional offset applied to the glyph's vertices.
+ * @param pos1 One corner of the glyph's bounding rectangle.
+ * @param pos2 The diagonally opposite corner of the glyph's bounding rectangle.
+ * @param color The color to apply to the glyph.
*/
private fun VertexPipeline.buildGlyph(
glyph: GlyphInfo,
@@ -150,22 +169,35 @@ object FontRenderer : AbstractGUIRenderer(VertexAttrib.Group.FONT, shader("font/
}
/**
- * Calculates the height of the text based on the specified scale.
- *
- * @param scale The scale factor for the height calculation.
- * @return The height of the text at the specified scale.
- */
+ * Computes the effective height of the rendered text.
+ *
+ * The height is derived from the current font's base height, adjusted by a scaling factor
+ * that ensures consistent visual proportions.
+ *
+ * @param scale the scaling factor to apply (default is 1.0)
+ * @return the effective height of the text for the provided scale
+ */
fun getHeight(scale: Double = 1.0) = chars.height * getScaleFactor(scale) * 0.7
/**
- * Iterates over each character and emoji in the text and applies a block operation.
+ * Processes a text string by iterating over its characters and emojis, computing rendering positions, and invoking a block for each glyph.
*
- * @param text The text to iterate over.
- * @param color The color of the text.
- * @param scale The scale of the text.
- * @param shadow Whether to render a shadow.
- * @param parseEmoji Whether to parse and include emojis.
- * @param block The function to apply to each character or emoji glyph.
+ * The function calculates an adjusted scale factor and applies a gap between glyphs as well as a baseline offset for proper
+ * vertical alignment. For every glyph, if shadow rendering is enabled, it first invokes the block for a shadow glyph (using an offset)
+ * followed by the main glyph. It handles control characters (such as newlines) to adjust positioning, and when emoji parsing is enabled,
+ * it recursively splits the text to separately process emoji sequences and regular characters.
+ *
+ * @param text the string to process.
+ * @param color the base color used for rendering the glyphs.
+ * @param scale the scale factor applied to the text size.
+ * @param shadow if true, renders a shadow glyph before the main glyph.
+ * @param parseEmoji if true, detects and processes emoji sequences in the text.
+ * @param block a function that is invoked for each glyph. It receives:
+ * - GlyphInfo: the glyph information.
+ * - Vec2d: the starting position of the glyph.
+ * - Vec2d: the ending position of the glyph (computed from its size).
+ * - Color: the color to render the glyph.
+ * - Boolean: a flag indicating whether the glyph represents a shadow.
*/
private fun processText(
text: String,
@@ -184,6 +216,18 @@ object FontRenderer : AbstractGUIRenderer(VertexAttrib.Group.FONT, shader("font/
var posX = 0.0
var posY = getHeight(scale) * -0.5 + baselineOffset * actualScale
+ /**
+ * Renders a glyph with the provided information and styling.
+ *
+ * If the glyph information is null, no rendering occurs. The function calculates the glyph's scaled size
+ * and computes its drawing coordinates based on the current position and scale factor. A non-zero offset
+ * indicates that the glyph is rendered as a shadow; in this case, the horizontal drawing position remains
+ * unchanged. Otherwise, the drawing position is advanced based on the glyph's width and a predefined gap.
+ *
+ * @param info The glyph information containing its size and other rendering details; if null, the glyph is not drawn.
+ * @param color The color applied to the glyph.
+ * @param offset An optional offset for positioning; a non-zero value flags the glyph as a shadow.
+ */
fun drawGlyph(info: GlyphInfo?, color: Color, offset: Double = 0.0) {
if (info == null) return
val isShadow = offset != 0.0
@@ -198,6 +242,16 @@ object FontRenderer : AbstractGUIRenderer(VertexAttrib.Group.FONT, shader("font/
val parsed = if (parseEmoji) emojis.parse(text) else mutableListOf()
+ /**
+ * Processes a segment of text for rendering, handling regular characters and emojis.
+ *
+ * The function iterates over the given text section, drawing each glyph while managing control characters
+ * such as newlines and carriage returns to update the rendering position. When emojis are enabled and
+ * detected, it splits the text to render emoji characters separately, ensuring proper text layout.
+ *
+ * @param section The portion of text to be processed.
+ * @param hasEmojis Indicates whether the section may contain emojis that require special handling.
+ */
fun processTextSection(section: String, hasEmojis: Boolean) {
if (section.isEmpty()) return
if (!parseEmoji || parsed.isEmpty() || !hasEmojis) {
@@ -243,11 +297,14 @@ object FontRenderer : AbstractGUIRenderer(VertexAttrib.Group.FONT, shader("font/
}
/**
- * Calculates the scale factor for the text based on the provided scale.
- *
- * @param scale The base scale factor.
- * @return The adjusted scale factor.
- */
+ * Computes an adjusted scale factor for text rendering.
+ *
+ * This method applies a constant multiplier (8.5) to the base scale and normalizes it
+ * by the current text font's height, ensuring consistent text sizing across different fonts.
+ *
+ * @param scale the input base scale factor.
+ * @return the resulting adjusted scale factor.
+ */
fun getScaleFactor(scale: Double): Double = scale * 8.5 / chars.height
/**
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaAtlas.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaAtlas.kt
index 2eaf82985..732937e28 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaAtlas.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaAtlas.kt
@@ -72,8 +72,26 @@ object LambdaAtlas : Loadable {
private val metricCache = mutableMapOf()
private val heightCache = Object2DoubleArrayMap()
- operator fun LambdaFont.get(char: Char): GlyphInfo? = fontMap.getValue(this)[char]
- operator fun LambdaEmoji.get(string: String): GlyphInfo? = emojiMap.getValue(this)[string.removeSurrounding(":")]
+ /**
+ * Retrieves the glyph information for the specified character for this font.
+ *
+ * Returns the [GlyphInfo] from the font's internal glyph map corresponding to the provided character,
+ * or null if no glyph information is available.
+ *
+ * @param char The character to look up.
+ * @return The glyph information associated with the character, or null if it is not found.
+ */
+operator fun LambdaFont.get(char: Char): GlyphInfo? = fontMap.getValue(this)[char]
+ /**
+ * Retrieves the glyph information for an emoji based on the provided identifier.
+ *
+ * The input string is expected to be wrapped in colons (e.g., ":smile:"); the surrounding colons
+ * are removed before looking up the glyph in the emoji map.
+ *
+ * @param string the emoji identifier, potentially enclosed in colons.
+ * @return the corresponding glyph information, or null if it is not found.
+ */
+operator fun LambdaEmoji.get(string: String): GlyphInfo? = emojiMap.getValue(this)[string.removeSurrounding(":")]
val LambdaFont.height: Double
get() = heightCache.getDouble(fontCache[this@height])
@@ -147,6 +165,19 @@ object LambdaAtlas : Loadable {
bufferPool[this@buildBuffer] = image
}
+ /**
+ * Builds a texture atlas by rendering multiple glyphs from the font.
+ *
+ * The function loads the font (or retrieves it from a cache), calculates a texture image based on the given number
+ * of characters, and draws each glyph onto the image. It computes the UV coordinates for each character and stores
+ * the associated glyph metadata, while also updating a shared buffer pool with the generated image. An exception is
+ * thrown if the texture atlas is too small to accommodate all glyphs.
+ *
+ * @param characters The total number of characters to render into the atlas (default is 2048). This value also influences
+ * the calculated texture size.
+ *
+ * @throws IllegalStateException if the texture atlas is not large enough to fit the glyphs.
+ */
fun LambdaFont.buildBuffer(
characters: Int = 2048 // How many characters from that font should be used for the generation
) {
@@ -198,7 +229,15 @@ object LambdaAtlas : Loadable {
bufferPool[this@buildBuffer] = image
}
- // TODO: Change this when we've refactored the loadables
+ /**
+ * Loads all font and emoji entries, schedules texture uploads, and returns a summary message.
+ *
+ * Iterates over all registered fonts and emojis to initialize their underlying resources, prepares a summary count based on
+ * the current buffer pool size, and schedules the upload of buffered images to their respective owners. The buffer pool is cleared
+ * after the upload to prevent race conditions.
+ *
+ * @return A summary string indicating the number of fonts loaded.
+ */
override fun load(): String {
LambdaFont.entries.forEach(LambdaFont::load)
LambdaEmoji.entries.forEach(LambdaEmoji::load)
@@ -213,6 +252,17 @@ object LambdaAtlas : Loadable {
return str
}
+ /**
+ * Renders the specified character as a buffered image using the provided font.
+ *
+ * If the font cannot display the character, the function returns null. Otherwise, it retrieves or
+ * computes the font metrics to determine the image dimensions, creates a buffered image, applies
+ * anti-aliasing and default rendering hints, and draws the character in white.
+ *
+ * @param font the font used for rendering the character.
+ * @param codePoint the character to render.
+ * @return a BufferedImage with the rendered character, or null if the font cannot display it.
+ */
private fun getCharImage(font: Font, codePoint: Char): BufferedImage? {
if (!font.canDisplay(codePoint)) return null
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaEmoji.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaEmoji.kt
index 0175f2156..a450e028a 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaEmoji.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaEmoji.kt
@@ -25,15 +25,25 @@ enum class LambdaEmoji(val url: String) {
private val emojiRegex = Regex(":[a-zA-Z0-9_]+:")
/**
- * Parses the emojis in the given text.
- *
- * @param text The text to parse.
- *
- * @return A list of parsed strings that does not contain the colons
- */
+ * Extracts emoji names from the provided text.
+ *
+ * The function scans the input text for patterns matching emojis in the `:name:` format and returns a mutable list
+ * of the emoji names with the surrounding colons removed.
+ *
+ * @param text the input text containing potential emoji patterns
+ * @return a mutable list of extracted emoji names
+ */
fun parse(text: String): MutableList =
emojiRegex.findAll(text).map { it.value }.toMutableList()
+ /**
+ * Triggers the build of buffers for all available emoji sets.
+ *
+ * Iterates through each entry in the enum, calling its buffer-building function, and returns
+ * a message indicating the total number of emoji sets processed.
+ *
+ * @return a string reporting the number of loaded emoji sets.
+ */
fun load(): String {
entries.forEach { it.buildBuffer() }
return "Loaded ${entries.size} emoji sets"
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaFont.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaFont.kt
index f6d3ed01f..387ae4343 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaFont.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/core/LambdaFont.kt
@@ -23,6 +23,14 @@ enum class LambdaFont(val fontName: String) {
FiraSansRegular("FiraSans-Regular"),
FiraSansBold("FiraSans-Bold");
+ /**
+ * Loads all font entries by triggering their buffer-building routines and returns a summary message.
+ *
+ * Iterates through each font in the enumeration, invoking its [buildBuffer] method, and returns a string
+ * indicating the number of fonts loaded, formatted as "Loaded X fonts" where X is the total number.
+ *
+ * @return a string summarizing the count of loaded fonts.
+ */
fun load(): String {
entries.forEach { it.buildBuffer() }
return "Loaded ${entries.size} fonts"
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/sdf/DistanceFieldTexture.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/sdf/DistanceFieldTexture.kt
index 1f8eaf5e0..85b59ec5f 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/sdf/DistanceFieldTexture.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/sdf/DistanceFieldTexture.kt
@@ -56,6 +56,13 @@ class DistanceFieldTexture(image: BufferedImage) : Texture(image, levels = 0) {
}
}
+ /**
+ * Binds the SDF texture's underlying frame to the specified texture slot.
+ *
+ * This ensures that the distance field texture is activated in the given slot for rendering.
+ *
+ * @param slot the texture slot index to bind the frame to.
+ */
override fun bind(slot: Int) {
frame.bind(slot)
}
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt
index a4178b69b..013820cd2 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt
@@ -30,6 +30,17 @@ object FilledRectRenderer : AbstractGUIRenderer(
private const val MIN_SIZE = 0.5
private const val MIN_ALPHA = 3
+ /**
+ * Renders a filled rectangle with uniformly rounded corners and a single fill color.
+ *
+ * This overload delegates to the more detailed version by applying the same color to all corners and using
+ * a uniform rounding radius. When shading is enabled, an additional shading effect is applied.
+ *
+ * @param rect the rectangle defining the position and dimensions.
+ * @param roundRadius the uniform radius for rounding each corner; defaults to 0.0.
+ * @param color the fill color for the rectangle, applied to all corners; defaults to Color.WHITE.
+ * @param shade if true, applies a shading effect; defaults to false.
+ */
fun filledRect(
rect: Rect,
roundRadius: Double = 0.0,
@@ -37,6 +48,20 @@ object FilledRectRenderer : AbstractGUIRenderer(
shade: Boolean = false,
) = filledRect(rect, roundRadius, color, color, color, color, shade)
+ /**
+ * Renders a filled rectangle with rounded corners and individual corner colors.
+ *
+ * This overload applies a uniform rounding radius to all corners and delegates to the
+ * implementation that supports distinct radii for each corner.
+ *
+ * @param rect the boundaries of the rectangle.
+ * @param roundRadius the uniform rounding radius applied to each corner.
+ * @param leftTop the color at the top-left corner.
+ * @param rightTop the color at the top-right corner.
+ * @param rightBottom the color at the bottom-right corner.
+ * @param leftBottom the color at the bottom-left corner.
+ * @param shade if true, shading is applied to the rectangle.
+ */
fun filledRect(
rect: Rect,
roundRadius: Double = 0.0,
@@ -52,6 +77,20 @@ object FilledRectRenderer : AbstractGUIRenderer(
shade
)
+ /**
+ * Renders a filled rectangle with customizable corner rounding and a uniform fill color.
+ *
+ * This overload simplifies rendering when the same color is applied uniformly to all corners.
+ * It delegates to the more detailed version that accepts separate colors for each corner.
+ *
+ * @param rect The rectangle defining the position and dimensions.
+ * @param leftTopRadius The rounding radius of the top-left corner.
+ * @param rightTopRadius The rounding radius of the top-right corner.
+ * @param rightBottomRadius The rounding radius of the bottom-right corner.
+ * @param leftBottomRadius The rounding radius of the bottom-left corner.
+ * @param color The color used to fill the rectangle.
+ * @param shade If true, enables shading during rendering.
+ */
fun filledRect(
rect: Rect,
leftTopRadius: Double = 0.0,
@@ -67,6 +106,25 @@ object FilledRectRenderer : AbstractGUIRenderer(
shade
)
+ /**
+ * Renders a filled rectangle with customizable corner radii and individual corner colors.
+ *
+ * The function calculates the rectangle's size from its top-left and bottom-right coordinates,
+ * and performs early exits if the rectangle is too small or if all corner colors are nearly transparent.
+ * Each provided corner radius is clamped to ensure it does not exceed half the rectangle's dimensions.
+ * If shading is enabled, a shading effect is applied during rendering.
+ *
+ * @param rect The rectangle defining the position and dimensions.
+ * @param leftTopRadius The rounding radius for the top-left corner.
+ * @param rightTopRadius The rounding radius for the top-right corner.
+ * @param rightBottomRadius The rounding radius for the bottom-right corner.
+ * @param leftBottomRadius The rounding radius for the bottom-left corner.
+ * @param leftTop The color for the top-left corner.
+ * @param rightTop The color for the top-right corner.
+ * @param rightBottom The color for the bottom-right corner.
+ * @param leftBottom The color for the bottom-left corner.
+ * @param shade If true, applies a shading effect to the rendered rectangle.
+ */
fun filledRect(
rect: Rect,
leftTopRadius: Double = 0.0,
diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt
index 127cacc98..9aad270ce 100644
--- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt
@@ -40,6 +40,17 @@ object OutlineRectRenderer : AbstractGUIRenderer(
private const val QUALITY = 8
private const val VERTICES_COUNT = QUALITY * 4
+ /**
+ * Renders an outlined rectangle with optional rounded corners and glow effect using a uniform color.
+ *
+ * This overload applies the same color to every corner by delegating to the detailed outlineRect function.
+ *
+ * @param rect the rectangle defining the area for the outline.
+ * @param roundRadius the radius used to round the rectangle's corners (defaults to 0.0 for sharp corners).
+ * @param glowRadius the radius defining the glow effect; if below 1, rendering is skipped.
+ * @param color the color applied uniformly to all corners.
+ * @param shade if true, applies a shading effect during rendering.
+ */
fun outlineRect(
rect: Rect,
roundRadius: Double = 0.0,
@@ -48,6 +59,22 @@ object OutlineRectRenderer : AbstractGUIRenderer(
shade: Boolean = false,
) = outlineRect(rect, roundRadius, glowRadius, color, color, color, color, shade)
+ /**
+ * Renders an outlined rectangle with optional rounded corners and glow.
+ *
+ * The function computes the vertex data for the rectangle's outline—applying rounded
+ * corners and a glow effect if specified—and renders quads to form both the outline and
+ * its glow. Rendering is skipped entirely if the glow radius is below 1.
+ *
+ * @param rect The base rectangle for the outline.
+ * @param roundRadius The radius for rounded corners; if zero, the corners remain sharp.
+ * @param glowRadius The thickness of the glow effect; values below 1 disable rendering.
+ * @param leftTop Color for the top-left corner.
+ * @param rightTop Color for the top-right corner.
+ * @param rightBottom Color for the bottom-right corner.
+ * @param leftBottom Color for the bottom-left corner.
+ * @param shade When true, applies a shading effect during rendering.
+ */
fun outlineRect(
rect: Rect,
roundRadius: Double = 0.0,
diff --git a/common/src/main/kotlin/com/lambda/graphics/shader/Shader.kt b/common/src/main/kotlin/com/lambda/graphics/shader/Shader.kt
index c5b718a4d..17a2b07a8 100644
--- a/common/src/main/kotlin/com/lambda/graphics/shader/Shader.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/shader/Shader.kt
@@ -37,12 +37,28 @@ class Shader private constructor(fragmentPath: String, vertexPath: String) {
loadShader(ShaderType.FRAGMENT_SHADER, "shaders/fragment/$fragmentPath.frag")
)
+ /**
+ * Activates the shader program and updates the "u_ProjModel" uniform.
+ *
+ * This function sets the active OpenGL program to this shader and ensures that the
+ * current projection model matrix from RenderMain is applied by updating the corresponding uniform.
+ */
fun use() {
glUseProgram(id)
set("u_ProjModel", RenderMain.projModel)
}
- private fun loc(name: String) =
+ /**
+ * Retrieves the location of the specified uniform variable.
+ *
+ * This function checks a cache for the uniform location. If the uniform location is already cached,
+ * it returns the cached value. Otherwise, it queries OpenGL for the location using `glGetUniformLocation`,
+ * caches the result, and then returns it.
+ *
+ * @param name the name of the uniform variable.
+ * @return the location of the uniform variable.
+ */
+ private fun loc(name: String) =
if (uniformCache.containsKey(name))
uniformCache.getInt(name)
else
@@ -75,16 +91,43 @@ class Shader private constructor(fragmentPath: String, vertexPath: String) {
color.alpha / 255f
)
- operator fun set(name: String, mat: Matrix4f) =
+ /**
+ * Assigns a 4x4 matrix value to a uniform variable in the shader program.
+ *
+ * This operator overload uses the uniform variable name to locate its position
+ * within the shader and updates it with the provided matrix data.
+ *
+ * @param name the name of the uniform variable.
+ * @param mat the 4x4 matrix to assign to the uniform.
+ */
+ operator fun set(name: String, mat: Matrix4f) =
uniformMatrix(loc(name), mat)
companion object {
private val shaderCache = hashMapOf, Shader>()
- fun shader(path: String) =
+ /**
+ * Retrieves or creates a shader instance using a single shader path.
+ *
+ * This function returns a [Shader] by applying the provided file path for both the vertex and fragment shader sources.
+ *
+ * @param path the file path for the shader sources used for both vertex and fragment shaders.
+ * @return the corresponding [Shader] instance.
+ */
+ fun shader(path: String) =
shader(path, path)
- fun shader(fragmentPath: String, vertexPath: String) =
+ /**
+ * Retrieves a Shader instance for the specified fragment and vertex shader paths.
+ *
+ * This function checks the cache for an existing Shader corresponding to the given paths. If none is found,
+ * it creates a new Shader instance, caches it, and returns the instance.
+ *
+ * @param fragmentPath The file path to the fragment shader.
+ * @param vertexPath The file path to the vertex shader.
+ * @return The Shader instance associated with the provided shader paths.
+ */
+ fun shader(fragmentPath: String, vertexPath: String) =
shaderCache.getOrPut(fragmentPath to vertexPath) {
Shader(fragmentPath, vertexPath)
}
diff --git a/common/src/main/kotlin/com/lambda/graphics/shader/ShaderUtils.kt b/common/src/main/kotlin/com/lambda/graphics/shader/ShaderUtils.kt
index 6cfda3c32..edbbad3fc 100644
--- a/common/src/main/kotlin/com/lambda/graphics/shader/ShaderUtils.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/shader/ShaderUtils.kt
@@ -30,6 +30,18 @@ object ShaderUtils {
private val matrixBuffer = BufferUtils.createFloatBuffer(4 * 4)
private const val shaderInfoLogLength = 512
+ /**
+ * Loads and compiles an OpenGL shader using the source from the specified resource.
+ *
+ * This function creates a shader object based on the provided shader type, reads the shader source code from
+ * the given LambdaResource using UTF-8 encoding, and attaches and compiles the shader source. If compilation fails,
+ * a RuntimeException is thrown with detailed error information.
+ *
+ * @param type The shader type defining the OpenGL shader to create.
+ * @param resource The LambdaResource containing the shader source code.
+ * @return The OpenGL handle for the successfully compiled shader.
+ * @throws RuntimeException If the shader compilation fails.
+ */
fun loadShader(type: ShaderType, resource: LambdaResource): Int {
// Create new shader object
val shader = glCreateShader(type.gl)
@@ -53,6 +65,18 @@ object ShaderUtils {
return shader
}
+ /**
+ * Creates a new OpenGL shader program by linking the provided shader objects.
+ *
+ * This function creates a new shader program, attaches all supplied shader IDs,
+ * and attempts to link them together. If linking fails, it throws a RuntimeException
+ * containing detailed error information. On successful linking, all shader objects
+ * are deleted.
+ *
+ * @param shaders one or more shader IDs to be linked into the program.
+ * @return the ID of the linked shader program.
+ * @throws RuntimeException if the shader program fails to link.
+ */
fun createShaderProgram(vararg shaders: Int): Int {
// Create new shader program
val program = glCreateProgram()
@@ -73,6 +97,16 @@ object ShaderUtils {
return program
}
+ /**
+ * Compiles the specified OpenGL shader.
+ *
+ * This function compiles the shader identified by the given ID and checks its compilation status.
+ * It returns null when compilation is successful; if the compilation fails, it returns the shader's
+ * error log (limited to a predefined length).
+ *
+ * @param shader the ID of the shader to compile.
+ * @return null if the shader compiles successfully, or a string containing the error log if compilation fails.
+ */
private fun compileShader(shader: Int): String? {
glCompileShader(shader)
val status = glGetShaderi(shader, GL_COMPILE_STATUS)
@@ -81,6 +115,17 @@ object ShaderUtils {
else glGetShaderInfoLog(shader, shaderInfoLogLength)
}
+ /**
+ * Attaches the specified shaders to the shader program and links it.
+ *
+ * This function iterates over the provided shader IDs and attaches each to the given program.
+ * It then links the program and checks the linking status. If linking is successful, it returns null;
+ * otherwise, it returns the error log from the linking process.
+ *
+ * @param program the OpenGL shader program identifier.
+ * @param shaders an array of shader identifiers to attach and link.
+ * @return null if linking succeeds; otherwise, the linking error log.
+ */
private fun linkProgram(program: Int, shaders: IntArray): String? {
shaders.forEach {
glAttachShader(program, it)
diff --git a/common/src/main/kotlin/com/lambda/graphics/texture/AnimatedTexture.kt b/common/src/main/kotlin/com/lambda/graphics/texture/AnimatedTexture.kt
index 6229c2c17..938194f08 100644
--- a/common/src/main/kotlin/com/lambda/graphics/texture/AnimatedTexture.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/texture/AnimatedTexture.kt
@@ -39,11 +39,26 @@ class AnimatedTexture(path: LambdaResource) : Texture(image = null) {
private var currentFrame = 0
private var lastUpload = 0L
+ /**
+ * Binds the animated texture to the specified texture slot.
+ *
+ * This method updates the texture's current frame via [update] before binding it,
+ * ensuring that the most recent frame is rendered.
+ *
+ * @param slot the texture unit to which the texture is bound.
+ */
override fun bind(slot: Int) {
update()
super.bind(slot)
}
+ /**
+ * Updates the animated texture by advancing to the next frame if its display duration has elapsed.
+ *
+ * This function checks if the elapsed time since the last frame upload meets or exceeds the current frame's duration.
+ * When the condition is met, it slices the GIF data to obtain the current frame's byte block, uploads it to the pixel buffer,
+ * resets the buffer, advances the frame counter (wrapping around at the end), and updates the timestamp for the last upload.
+ */
fun update() {
if (System.currentTimeMillis() - lastUpload >= frameDurations[currentFrame]) {
// This is cool because instead of having a buffer for each frame we can
diff --git a/common/src/main/kotlin/com/lambda/graphics/texture/Texture.kt b/common/src/main/kotlin/com/lambda/graphics/texture/Texture.kt
index 5ac12882a..081c92c07 100644
--- a/common/src/main/kotlin/com/lambda/graphics/texture/Texture.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/texture/Texture.kt
@@ -75,25 +75,35 @@ open class Texture {
var height = -1; protected set
/**
- * Binds the texture to a specific slot in the graphics pipeline.
+ * Binds this texture to the specified slot in the graphics pipeline.
+ *
+ * @param slot The slot to bind the texture to. Defaults to 0.
*/
open fun bind(slot: Int = 0) {
bindTexture(id, slot)
}
/**
- * Unbinds the currently bound texture
+ * Unbinds any texture from the specified slot.
+ *
+ * This method removes the current texture binding on the given slot by binding a texture ID of 0.
+ * If no slot is explicitly provided, the operation defaults to slot 0.
+ *
+ * @param slot The slot index from which to unbind the texture.
*/
open fun unbind(slot: Int = 0) {
bindTexture(0, slot)
}
/**
- * Uploads an image to the texture and generates mipmaps for the texture if applicable
- * This function does not bind the texture
+ * Uploads the given image data to the texture at the specified mipmap level.
+ *
+ * This function updates the texture's dimensions to match the image, marks it as initialized, and
+ * configures level-of-detail parameters before setting texture filtering options. If mipmapping is enabled,
+ * mipmaps are automatically generated. Note that the texture must be bound before calling this function.
*
- * @param image The image to upload to the texture
- * @param offset The mipmap level to upload the image to
+ * @param image the BufferedImage containing the texture data.
+ * @param offset the mipmap level where the image data is applied (typically 0 for the base level).
*/
fun upload(image: BufferedImage, offset: Int = 0) {
// Store level_base +1 through `level` images and generate
@@ -111,13 +121,17 @@ open class Texture {
}
/**
- * Uploads an image to the texture and generates mipmaps for the texture if applicable
- * This function does not bind the texture
+ * Uploads image data from a ByteBuffer to the texture.
*
- * @param buffer The image buffer to upload to the texture
- * @param width The width of the texture
- * @param height The height of the texture
- * @param offset The mipmap level to upload the image to
+ * This method updates the texture's dimensions, configures Level of Detail (LOD) parameters,
+ * and marks the texture as initialized. The image data is uploaded at the specified mipmap level,
+ * and if mipmap generation is enabled (i.e. when more than zero levels are configured), it triggers
+ * the creation of the full mipmap chain. Note that the texture is assumed to be bound before calling this method.
+ *
+ * @param buffer The image data to be uploaded.
+ * @param width The width of the texture image.
+ * @param height The height of the texture image.
+ * @param offset The mipmap level where the image data will be applied, typically 0 for the base level.
*/
fun upload(buffer: ByteBuffer, width: Int, height: Int, offset: Int = 0) {
// Store level_base +1 through `level` images and generate
@@ -135,13 +149,18 @@ open class Texture {
}
/**
- * Updates the data of a texture
- * This function does not bind the texture
+ * Updates the content of an existing texture with new image data.
+ *
+ * If the texture is not yet initialized, this method delegates to [upload] to set up
+ * the texture data. When the texture is already initialized, it updates the texture
+ * at the specified mipmap level. Note that this method does not bind the texture;
+ * it assumes the texture is already bound.
*
- * @param image The image to upload to the texture
- * @param offset The mipmap level to upload the image to
+ * @param image The BufferedImage containing the new texture data.
+ * @param offset The mipmap level to update (default is 0).
*
- * @throws IllegalStateException If the texture has the consistency flag and is already initialized
+ * @throws IllegalStateException if the provided image data's dimensions are incompatible
+ * with the texture's existing dimensions.
*/
fun update(image: BufferedImage, offset: Int = 0) {
if (!initialized) return upload(image, offset)
@@ -151,15 +170,18 @@ open class Texture {
}
/**
- * Updates the data of a texture
- * This function does not bind the texture
+ * Updates the texture content with new image data from the provided ByteBuffer.
+ *
+ * If the texture is not yet initialized, this function delegates to the texture upload routine.
+ * For an already initialized texture, it checks that the new dimensions do not exceed the original ones
+ * and updates the specified mipmap level without binding the texture.
*
- * @param buffer The image buffer to upload to the texture
- * @param width The width of the texture
- * @param height The height of the texture
- * @param offset The mipmap level to upload the image to
+ * @param buffer The ByteBuffer containing the new texture data.
+ * @param width The width of the new image data.
+ * @param height The height of the new image data.
+ * @param offset The mipmap level at which to update the texture.
*
- * @throws IllegalStateException If the texture has the consistency flag and is already initialized
+ * @throws IllegalStateException if the provided dimensions exceed those of the initialized texture.
*/
fun update(buffer: ByteBuffer, width: Int, height: Int, offset: Int = 0) {
if (!initialized) return upload(buffer, width, height, offset)
@@ -168,6 +190,17 @@ open class Texture {
glTexSubImage2D(GL_TEXTURE_2D, offset, 0, 0, width, height, format, GL_UNSIGNED_BYTE, buffer)
}
+ /**
+ * Configures the level-of-detail (LOD) parameters for the texture.
+ *
+ * This method sets the minimum and maximum LOD values, as well as the base and maximum mipmap levels,
+ * using the specified total number of mipmap levels. The [levels] parameter includes the base level (level 0),
+ * so the highest valid mipmap level is [levels] - 1.
+ *
+ * Note: This configuration may not work correctly with textures using immutable storage.
+ *
+ * @param levels The total number of mipmap levels, including the base level.
+ */
private fun setupLOD(levels: Int) {
// When you call glTextureStorage, you're specifying the total number of levels, including level 0
// This is a 0-based index system, which means that the maximum mipmap level is n-1
@@ -180,7 +213,18 @@ open class Texture {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels)
}
- private fun checkDimensions(width: Int, height: Int) =
+ /**
+ * Validates that the dimensions of the new texture data do not exceed the allowed total dimensions.
+ *
+ * This method checks that the sum of the provided width and height does not exceed the sum of the texture's
+ * current width and height, and ensures that the texture has been initialized. If the condition fails, it
+ * throws an IllegalStateException with details about the expected and received total dimensions.
+ *
+ * @param width The width of the new texture data.
+ * @param height The height of the new texture data.
+ * @throws IllegalStateException if the texture is uninitialized or if the new data's dimensions exceed the allowed limits.
+ */
+ private fun checkDimensions(width: Int, height: Int) =
check(width + height <= this.width + this.height && initialized) {
"Client tried to update a texture with more data than allowed\n" +
"Expected ${this.width + this.height} bytes but got ${width + height}"
diff --git a/common/src/main/kotlin/com/lambda/graphics/texture/TextureOwner.kt b/common/src/main/kotlin/com/lambda/graphics/texture/TextureOwner.kt
index 5ace20405..677012bab 100644
--- a/common/src/main/kotlin/com/lambda/graphics/texture/TextureOwner.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/texture/TextureOwner.kt
@@ -34,11 +34,13 @@ object TextureOwner {
get() = textureMap.getValue(this@texture)[0]
/**
- * Retrieves a specific texture owned by the object by its index
- *
- * @param index The index of the texture to retrieve
- * @return The texture [T] at the given index
- */
+ * Retrieves the texture associated with the receiver object at the specified index.
+ *
+ * The returned texture is cast to the provided generic type [T], allowing for type-safe access.
+ *
+ * @param index the position of the texture in the object's associated texture list.
+ * @return the texture at the specified index, cast as type [T].
+ */
@Suppress("unchecked_cast")
fun Any.texture(index: Int) =
textureMap.getValue(this@texture)[index] as T
@@ -57,11 +59,12 @@ object TextureOwner {
}
/**
- * Binds a list of textures to texture slots, ensuring no more than 32 textures
- * are bound at once (to fit within the typical GPU limitations)
+ * Binds the provided textures to consecutive GPU slots starting at slot 0.
+ *
+ * Ensures that no more than 32 textures are bound at once to comply with GPU limitations.
*
- * @param textures The list of textures to be bound
- * @throws IllegalArgumentException If more than 32 textures are provided
+ * @param textures the textures to be bound
+ * @throws IllegalArgumentException if more than 32 textures are provided
*/
fun bind(vararg textures: Texture) {
check(textures.size < 33) { "Texture slot overflow, expected to use less than 33 slots, got ${textures.size} slots" }
@@ -92,21 +95,23 @@ object TextureOwner {
Texture(path.readImage(), levels = mipmaps).also { textureMap.computeIfAbsent(this@upload) { mutableListOf() }.add(it) }
/**
- * Uploads a distance field texture from image data and associates it with the object
- * Distance field textures are commonly used for rendering fonts.
- *
- * @param data The image data as a [BufferedImage] to create the distance field texture
- * @return The created distance field texture object
- */
+ * Uploads a distance field texture from the provided image data and associates it with the calling object.
+ *
+ * Distance field textures are typically used for rendering high-quality fonts. The created texture is
+ * added to the object's texture list maintained in the texture map.
+ *
+ * @param data The image data used to create the distance field texture.
+ * @return The newly created distance field texture.
+ */
fun Any.uploadField(data: BufferedImage) =
DistanceFieldTexture(data).also { textureMap.computeIfAbsent(this@uploadField) { mutableListOf() }.add(it) }
/**
- * Uploads a GIF and associates it with the object as an animated texture
- *
- * @param path The resource path to the GIF file
- * @return The created animated texture object
- */
+ * Uploads an animated GIF as a texture and associates it with the calling object's texture list.
+ *
+ * @param path The resource path of the GIF file.
+ * @return The animated texture instance that was created.
+ */
fun Any.uploadGif(path: String) =
AnimatedTexture(path).also { textureMap.computeIfAbsent(this@uploadGif) { mutableListOf() }.add(it) }
}
diff --git a/common/src/main/kotlin/com/lambda/graphics/texture/TextureUtils.kt b/common/src/main/kotlin/com/lambda/graphics/texture/TextureUtils.kt
index fada950a8..32c0daf9d 100644
--- a/common/src/main/kotlin/com/lambda/graphics/texture/TextureUtils.kt
+++ b/common/src/main/kotlin/com/lambda/graphics/texture/TextureUtils.kt
@@ -33,11 +33,29 @@ object TextureUtils {
.withCompressionLevel(COMPRESSION_LEVEL)
.withMultiThreadedCompressionEnabled(THREADED_COMPRESSION)
+ /**
+ * Binds a texture to a specified texture slot.
+ *
+ * Activates the texture unit corresponding to GL_TEXTURE0 plus the slot offset, then binds the texture identified by the provided texture ID.
+ *
+ * @param id the identifier of the texture to bind.
+ * @param slot the texture slot index (default is 0).
+ */
fun bindTexture(id: Int, slot: Int = 0) {
RenderSystem.activeTexture(GL_TEXTURE0 + slot)
RenderSystem.bindTexture(id)
}
+ /**
+ * Configures the active texture's sampling and pixel storage parameters.
+ *
+ * This function sets the texture's minification and magnification filters using the provided values,
+ * clamps the S and T texture coordinates to the edge, and resets the pixel unpacking parameters to their
+ * default state. This ensures proper texture sampling and data alignment when uploading image data.
+ *
+ * @param minFilter the OpenGL filter to apply for texture minification.
+ * @param magFilter the OpenGL filter to apply for texture magnification.
+ */
fun setupTexture(minFilter: Int, magFilter: Int) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter)
@@ -50,6 +68,16 @@ object TextureUtils {
glPixelStorei(GL_UNPACK_ALIGNMENT, 4)
}
+ /**
+ * Converts a BufferedImage to a native image pointer.
+ *
+ * This function encodes the given [bufferedImage] using a PNG encoder preset, transfers the encoded data into a ByteBuffer,
+ * and then delegates to the ByteBuffer-based image reader with the specified [format]. It returns a pointer to the native image.
+ *
+ * @param bufferedImage the image to be converted.
+ * @param format the target format for the native image.
+ * @return a pointer to the native image.
+ */
fun readImage(
bufferedImage: BufferedImage,
format: NativeImage.Format,
@@ -66,6 +94,16 @@ object TextureUtils {
return readImage(buffer, format)
}
+ /**
+ * Reads image data from a ByteBuffer using a specified format and returns a pointer to the resulting native image.
+ *
+ * This function interprets the raw image data in the provided ByteBuffer according to the given format,
+ * converts it into a NativeImage, and then returns the pointer to the native image data.
+ *
+ * @param image A ByteBuffer containing raw image data.
+ * @param format The format used to decode the image data.
+ * @return A pointer to the native image as a Long.
+ */
fun readImage(
image: ByteBuffer,
format: NativeImage.Format,
diff --git a/common/src/main/kotlin/com/lambda/gui/GuiManager.kt b/common/src/main/kotlin/com/lambda/gui/GuiManager.kt
index fc5feea18..e15bb1727 100644
--- a/common/src/main/kotlin/com/lambda/gui/GuiManager.kt
+++ b/common/src/main/kotlin/com/lambda/gui/GuiManager.kt
@@ -27,10 +27,28 @@ import kotlin.reflect.KClass
object GuiManager : Loadable {
val typeMap = mutableMapOf, (owner: Layout, converted: Any) -> Layout>()
+ /**
+ * Registers a layout conversion adapter for the specified type T.
+ *
+ * The provided lambda is stored in a mapping with the key set as the reified type's KClass,
+ * enabling type-specific conversions of a Layout. The lambda casts the given instance to T
+ * and applies the conversion.
+ *
+ * @param block A conversion lambda that accepts a Layout and an instance of type T, returning a modified Layout.
+ */
private inline fun typeAdapter(noinline block: (Layout, T) -> Layout) {
typeMap[T::class] = { owner, converted -> block(owner, converted as T) }
}
+ /**
+ * Loads and registers built-in GUI type adapters.
+ *
+ * This method overrides the load function from the Loadable interface to register a BooleanSetting
+ * adapter. The adapter maps a Layout to a conversion function that applies the booleanSetting method.
+ * It returns a message indicating the total number of loaded GUI type adapters.
+ *
+ * @return a status message with the count of loaded GUI type adapters.
+ */
override fun load(): String {
typeAdapter { owner, ref ->
owner.booleanSetting(ref)
@@ -40,8 +58,16 @@ object GuiManager : Loadable {
}
/**
- * Attempts to convert the given [reference] to the [Layout]
- */
+ * Converts the provided [reference] into a [Layout] using a registered type adapter.
+ *
+ * This extension function checks the runtime type of [reference] against a registry of layout converters.
+ * If an appropriate adapter is found, it is invoked with the current layout and [reference], followed by
+ * applying the optional [block] for further configuration.
+ *
+ * @param reference the object used to determine the conversion adapter based on its runtime type.
+ * @param block an optional lambda for further configuring the converted [Layout].
+ * @return the converted [Layout] if an adapter for the reference's type exists; otherwise, `null`.
+ */
@UIBuilder
inline fun Layout.layoutOf(
reference: Any,
diff --git a/common/src/main/kotlin/com/lambda/gui/LambdaScreen.kt b/common/src/main/kotlin/com/lambda/gui/LambdaScreen.kt
index cf9a58d83..f4376f63a 100644
--- a/common/src/main/kotlin/com/lambda/gui/LambdaScreen.kt
+++ b/common/src/main/kotlin/com/lambda/gui/LambdaScreen.kt
@@ -57,6 +57,11 @@ class LambdaScreen(
}
}
+ /**
+ * Activates this screen.
+ *
+ * Closes any currently open screen and schedules a render call to set this instance as the active GUI.
+ */
fun show() {
mc.currentScreen?.close()
@@ -65,20 +70,55 @@ class LambdaScreen(
}
}
+ /**
+ * Called when the screen becomes visible.
+ *
+ * Triggers the layout's show event to notify that the GUI has been displayed.
+ */
override fun onDisplayed() {
layout.onEvent(GuiEvent.Show)
}
+ /**
+ * Signals that the screen is being removed.
+ *
+ * Triggers a [GuiEvent.Hide] event in the layout system to handle any necessary cleanup or state updates when the screen is dismissed.
+ */
override fun removed() {
layout.onEvent(GuiEvent.Hide)
}
- override fun shouldPause() = false
-
+ /**
+ * Determines whether the game should pause when this screen is active.
+ *
+ * Always returns false so that gameplay continues uninterrupted.
+ *
+ * @return false
+ */
+override fun shouldPause() = false
+
+ /**
+ * Renders the screen without applying the default background tint.
+ *
+ * This override removes the background tint to ensure the custom layout is displayed as intended.
+ *
+ * @param context the drawing context used for rendering.
+ * @param mouseX the current mouse x-coordinate.
+ * @param mouseY the current mouse y-coordinate.
+ * @param delta the time elapsed since the last frame.
+ */
override fun render(context: DrawContext?, mouseX: Int, mouseY: Int, delta: Float) {
// Let's remove background tint
}
+ /**
+ * Processes key press events by mapping the input key codes and dispatching them to the GUI layout.
+ *
+ * This method translates the provided keyCode and scanCode into a virtual key code using a US keyboard mapping,
+ * then triggers a corresponding key press event on the layout. When the escape key is pressed, it closes the screen.
+ *
+ * @return true, indicating the event was handled.
+ */
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
val translated = KeyCode.virtualMapUS(keyCode, scanCode)
layout.onEvent(GuiEvent.KeyPress(translated))
@@ -90,25 +130,66 @@ class LambdaScreen(
return true
}
+ /**
+ * Processes a character typing event by dispatching it to the layout.
+ *
+ * @param chr the character that was typed.
+ * @param modifiers modifier keys active during the event; currently not used.
+ * @return always true, indicating the event was handled.
+ */
override fun charTyped(chr: Char, modifiers: Int): Boolean {
layout.onEvent(GuiEvent.CharTyped(chr))
return true
}
+ /**
+ * Handles mouse click events by converting the click coordinates to the screen's coordinate system and dispatching a click event to the layout.
+ *
+ * @return true, indicating that the event was handled.
+ */
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
layout.onEvent(GuiEvent.MouseClick(Mouse.Button.fromMouseCode(button), Mouse.Action.Click, rescaleMouse(mouseX, mouseY)))
return true
}
+ /**
+ * Handles mouse release events by dispatching a corresponding event to the layout system.
+ *
+ * This method rescales the provided mouse coordinates and converts the button code to trigger a mouse click event
+ * with a release action.
+ *
+ * @param mouseX the horizontal coordinate of the mouse pointer
+ * @param mouseY the vertical coordinate of the mouse pointer
+ * @param button the code of the mouse button that was released
+ * @return true indicating the event was handled
+ */
override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
layout.onEvent(GuiEvent.MouseClick(Mouse.Button.fromMouseCode(button), Mouse.Action.Release, rescaleMouse(mouseX, mouseY)))
return true
}
+ /**
+ * Handles mouse movement events by rescaling window coordinates and dispatching them to the layout.
+ *
+ * The method converts the given mouse coordinates from window space to the screen's coordinate system
+ * and then triggers a corresponding mouse move event in the layout system.
+ *
+ * @param mouseX the horizontal position of the mouse cursor in window coordinates.
+ * @param mouseY the vertical position of the mouse cursor in window coordinates.
+ */
override fun mouseMoved(mouseX: Double, mouseY: Double) {
layout.onEvent(GuiEvent.MouseMove(rescaleMouse(mouseX, mouseY)))
}
+ /**
+ * Processes a mouse scroll event by rescaling the mouse coordinates and dispatching a vertical scroll event to the layout.
+ *
+ * @param mouseX The x-coordinate of the mouse in window space.
+ * @param mouseY The y-coordinate of the mouse in window space.
+ * @param horizontalAmount The horizontal scroll amount; this value is currently ignored.
+ * @param verticalAmount The vertical scroll delta.
+ * @return Always returns true to indicate the event was handled.
+ */
override fun mouseScrolled(
mouseX: Double,
mouseY: Double,
@@ -119,6 +200,16 @@ class LambdaScreen(
return true
}
+ /**
+ * Rescales the provided mouse coordinates from the window's coordinate system to the screen's coordinate system.
+ *
+ * The function normalizes the mouse position by dividing it by the window dimensions, then scales
+ * it using the current screen size.
+ *
+ * @param mouseX the x-coordinate of the mouse in window space.
+ * @param mouseY the y-coordinate of the mouse in window space.
+ * @return the rescaled mouse position as a Vec2d in the screen's coordinate system.
+ */
private fun rescaleMouse(mouseX: Double, mouseY: Double): Vec2d {
val mcMouse = Vec2d(mouseX, mouseY)
val mcWindow = Vec2d(mc.window.scaledWidth, mc.window.scaledHeight)
diff --git a/common/src/main/kotlin/com/lambda/gui/ScreenLayout.kt b/common/src/main/kotlin/com/lambda/gui/ScreenLayout.kt
index 07c642ebc..72a5dc8d0 100644
--- a/common/src/main/kotlin/com/lambda/gui/ScreenLayout.kt
+++ b/common/src/main/kotlin/com/lambda/gui/ScreenLayout.kt
@@ -30,8 +30,15 @@ class ScreenLayout : Layout(owner = null) {
companion object {
/**
- * Creates gui layout
- */
+ * Creates a new GUI layout screen.
+ *
+ * This function instantiates a new ScreenLayout, applies the provided configuration block to it,
+ * and returns a LambdaScreen identified by the supplied name.
+ *
+ * @param name a unique identifier for the screen
+ * @param block a configuration block that customizes the new ScreenLayout instance
+ * @return a LambdaScreen instance containing the configured ScreenLayout
+ */
@UIBuilder
fun gui(name: String, block: ScreenLayout.() -> Unit) =
LambdaScreen(name, ScreenLayout().apply(block))
diff --git a/common/src/main/kotlin/com/lambda/gui/component/DockingRect.kt b/common/src/main/kotlin/com/lambda/gui/component/DockingRect.kt
index 785f3e826..32c6dfbdd 100644
--- a/common/src/main/kotlin/com/lambda/gui/component/DockingRect.kt
+++ b/common/src/main/kotlin/com/lambda/gui/component/DockingRect.kt
@@ -68,6 +68,14 @@ abstract class DockingRect {
private fun relativeToAbs(posIn: Vec2d) = posIn + dockingOffset
private fun absToRelative(posIn: Vec2d) = posIn - dockingOffset
+ /**
+ * Automatically adjusts the docking alignment of the component based on its position relative to the screen center.
+ *
+ * This function calculates horizontal and vertical center ranges (approximately the middle third of the screen) and compares
+ * the component's center position (dockingBase) against these ranges. If the component is outside the center range and alignment is allowed,
+ * it sets the horizontal docking (dockingH) to LEFT or RIGHT and the vertical docking (dockingV) to TOP or BOTTOM accordingly.
+ * If horizontal or vertical alignment is disallowed, the docking defaults to LEFT or TOP respectively.
+ */
fun autoDocking() {
val screenCenterX = (screenSize.x * 0.3333)..(screenSize.x * 0.6666)
val screenCenterY = (screenSize.y * 0.3333)..(screenSize.y * 0.6666)
diff --git a/common/src/main/kotlin/com/lambda/gui/component/core/FilledRect.kt b/common/src/main/kotlin/com/lambda/gui/component/core/FilledRect.kt
index bcf8a0266..82663f408 100644
--- a/common/src/main/kotlin/com/lambda/gui/component/core/FilledRect.kt
+++ b/common/src/main/kotlin/com/lambda/gui/component/core/FilledRect.kt
@@ -64,6 +64,13 @@ class FilledRect(
}
}
+ /**
+ * Sets a uniform radius for all four corners of the rectangle.
+ *
+ * This method assigns the given radius to each of the rectangle's corner properties.
+ *
+ * @param radius the radius value to apply to all corners.
+ */
fun setRadius(radius: Double) {
leftTopRadius = radius
rightTopRadius = radius
@@ -71,6 +78,14 @@ class FilledRect(
leftBottomRadius = radius
}
+ /**
+ * Sets the same color for all corners of the filled rectangle.
+ *
+ * Updates the left top, right top, right bottom, and left bottom corner colors
+ * to the specified value.
+ *
+ * @param color the color to apply to all corners.
+ */
fun setColor(color: Color) {
leftTopColor = color
rightTopColor = color
@@ -78,6 +93,12 @@ class FilledRect(
leftBottomColor = color
}
+ /**
+ * Applies a horizontal gradient by setting the left corners to [colorL] and the right corners to [colorR].
+ *
+ * @param colorL the color for the top-left and bottom-left corners.
+ * @param colorR the color for the top-right and bottom-right corners.
+ */
fun setColorH(colorL: Color, colorR: Color) {
leftTopColor = colorL
rightTopColor = colorR
@@ -85,6 +106,14 @@ class FilledRect(
leftBottomColor = colorL
}
+ /**
+ * Updates the rectangle's corner colors with a vertical gradient.
+ *
+ * Sets both top corners to the specified [colorT] and both bottom corners to [colorB].
+ *
+ * @param colorT the color for the top corners.
+ * @param colorB the color for the bottom corners.
+ */
fun setColorV(colorT: Color, colorB: Color) {
leftTopColor = colorT
rightTopColor = colorT
@@ -94,8 +123,14 @@ class FilledRect(
companion object {
/**
- * Creates a [FilledRect] component - layout-based rect representation
- */
+ * Creates and adds a new [FilledRect] component to the current layout.
+ *
+ * The function instantiates a [FilledRect] using the receiver as its owner, automatically adds it to the layout's children,
+ * and then applies an optional configuration block for further customization.
+ *
+ * @param block an optional lambda to configure the newly created [FilledRect].
+ * @return the newly created and configured [FilledRect] component.
+ */
@UIBuilder
fun Layout.rect(block: FilledRect.() -> Unit = {}) =
FilledRect(this).apply(children::add).apply(block)
diff --git a/common/src/main/kotlin/com/lambda/gui/component/core/OutlineRect.kt b/common/src/main/kotlin/com/lambda/gui/component/core/OutlineRect.kt
index c34124c2a..f057dd507 100644
--- a/common/src/main/kotlin/com/lambda/gui/component/core/OutlineRect.kt
+++ b/common/src/main/kotlin/com/lambda/gui/component/core/OutlineRect.kt
@@ -53,6 +53,13 @@ class OutlineRect(
}
}
+ /**
+ * Sets all the corner colors of the outline to the specified [color].
+ *
+ * This method assigns the given [color] to the top-left, top-right, bottom-right, and bottom-left corners.
+ *
+ * @param color the color to apply to all corners.
+ */
fun setColor(color: Color) {
leftTopColor = color
rightTopColor = color
@@ -62,8 +69,10 @@ class OutlineRect(
companion object {
/**
- * Creates a [OutlineRect] component - layout-based rect representation
- */
+ * Creates an OutlineRect component, adds it to the parent layout's children, and applies the optional configuration.
+ *
+ * @param block an optional lambda to configure the [OutlineRect] after its creation.
+ */
@UIBuilder
fun Layout.outline(block: OutlineRect.() -> Unit = {}) =
OutlineRect(this).apply(children::add).apply(block)
diff --git a/common/src/main/kotlin/com/lambda/gui/component/core/TextField.kt b/common/src/main/kotlin/com/lambda/gui/component/core/TextField.kt
index 7b14c69e9..17f7d7c1b 100644
--- a/common/src/main/kotlin/com/lambda/gui/component/core/TextField.kt
+++ b/common/src/main/kotlin/com/lambda/gui/component/core/TextField.kt
@@ -56,7 +56,13 @@ class TextField(
companion object {
/**
- * Creates a [TextField] component
+ * Creates a new [TextField] component.
+ *
+ * This function instantiates a [TextField] with the current [Layout] as its owner, automatically
+ * adds it to the layout's children list, and applies an optional configuration block.
+ *
+ * @param block an optional lambda that configures the [TextField] instance.
+ * @return the newly created and configured [TextField] component.
*/
@UIBuilder
fun Layout.textField(
diff --git a/common/src/main/kotlin/com/lambda/gui/component/layout/Layout.kt b/common/src/main/kotlin/com/lambda/gui/component/layout/Layout.kt
index 5d97358ba..85a17fcc8 100644
--- a/common/src/main/kotlin/com/lambda/gui/component/layout/Layout.kt
+++ b/common/src/main/kotlin/com/lambda/gui/component/layout/Layout.kt
@@ -142,9 +142,12 @@ open class Layout(
private var mouseScrollActions = mutableListOf Unit>()
/**
- * Performs the action on this layout
+ * Applies the provided configuration block to this layout.
*
- * @param action The action to be performed.
+ * This extension function executes the given lambda with the layout as its receiver,
+ * enabling convenient DSL-style configuration.
+ *
+ * @param action the configuration block to be executed on the layout.
*/
@LayoutBuilder
fun T.use(action: T.() -> Unit) {
@@ -152,9 +155,12 @@ open class Layout(
}
/**
- * Sets the action to be performed when the element gets shown.
+ * Registers an action to be executed when this layout is shown.
+ *
+ * The provided lambda is added to the list of callbacks that trigger when the layout becomes visible.
+ * The action is executed with the layout as its receiver.
*
- * @param action The action to be performed.
+ * @param action the lambda to execute when the layout is shown
*/
@LayoutBuilder
fun T.onShow(action: T.() -> Unit) {
@@ -162,9 +168,12 @@ open class Layout(
}
/**
- * Sets the action to be performed when the element gets hidden.
+ * Registers a callback to be executed when the layout is hidden.
+ *
+ * The provided lambda is added to this layout's hide event actions, allowing you to define
+ * custom behavior that occurs when the layout transitions from visible to hidden.
*
- * @param action The action to be performed.
+ * @param action the lambda to execute when the layout is hidden
*/
@LayoutBuilder
fun T.onHide(action: T.() -> Unit) {
@@ -172,9 +181,11 @@ open class Layout(
}
/**
- * Sets the action to be performed on each tick.
+ * Registers an action to be executed on every tick event for the layout.
*
- * @param action The action to be performed.
+ * Multiple tick actions can be registered, and each will be invoked during the tick update cycle.
+ *
+ * @param action a lambda function with receiver that specifies the operation to perform on each tick.
*/
@LayoutBuilder
fun T.onTick(action: T.() -> Unit) {
@@ -182,9 +193,12 @@ open class Layout(
}
/**
- * Sets the update action to be performed before each frame.
+ * Registers an update action to be executed before each frame.
+ *
+ * The provided lambda is appended to the layout's update actions and is invoked during each update cycle,
+ * allowing dynamic modifications to the layout prior to rendering.
*
- * @param action The action to be performed.
+ * @param action the lambda specifying the update behavior.
*/
@LayoutBuilder
fun T.onUpdate(action: T.() -> Unit) {
@@ -192,9 +206,12 @@ open class Layout(
}
/**
- * Sets the action to be performed on each frame.
+ * Registers a callback to be executed on every render frame.
*
- * @param action The action to be performed.
+ * This function adds the provided lambda to the layout's render actions, ensuring it is invoked
+ * during each frame when rendering the layout.
+ *
+ * @param action The lambda to execute during the layout's render cycle.
*/
@LayoutBuilder
fun T.onRender(action: T.() -> Unit) {
@@ -202,9 +219,12 @@ open class Layout(
}
/**
- * Sets the action to be performed when a key gets pressed.
+ * Registers a callback to handle key press events on the layout.
+ *
+ * When a key press event occurs, the provided [action] is executed with the [KeyCode] corresponding
+ * to the pressed key.
*
- * @param action The action to be performed.
+ * @param action Lambda to be invoked on key press, receiving a [KeyCode] as its parameter.
*/
@LayoutBuilder
fun T.onKeyPress(action: T.(key: KeyCode) -> Unit) {
@@ -212,9 +232,11 @@ open class Layout(
}
/**
- * Sets the action to be performed when user types a char.
+ * Registers an action to be executed when a character is typed.
*
- * @param action The action to be performed.
+ * The provided lambda is invoked with the typed character whenever a character input event occurs.
+ *
+ * @param action a lambda function executed with the character input.
*/
@LayoutBuilder
fun T.onCharTyped(action: T.(char: Char) -> Unit) {
@@ -222,9 +244,11 @@ open class Layout(
}
/**
- * Sets the action to be performed when mouse button gets clicked.
+ * Registers a mouse click event handler on this layout.
+ *
+ * The provided lambda is executed when a mouse button is clicked, receiving both the mouse button and the associated click action.
*
- * @param action The action to be performed.
+ * @param action the callback to invoke on a mouse click event, with the clicked button and action as parameters.
*/
@LayoutBuilder
fun T.onMouseClick(action: T.(button: Mouse.Button, action: Mouse.Action) -> Unit) {
@@ -232,9 +256,11 @@ open class Layout(
}
/**
- * Sets the action to be performed when mouse moves.
+ * Registers an action to execute when the mouse moves over the layout.
*
- * @param action The action to be performed.
+ * The provided lambda is invoked with the current mouse position (a Vec2d), allowing custom behavior in response to mouse movement.
+ *
+ * @param action A lambda that processes the mouse position during a mouse move event.
*/
@LayoutBuilder
fun T.onMouseMove(action: T.(mouse: Vec2d) -> Unit) {
@@ -242,9 +268,12 @@ open class Layout(
}
/**
- * Sets the action to be performed on mouse scroll.
+ * Registers a mouse scroll event handler for the layout.
+ *
+ * The provided lambda receives the scroll delta, allowing you to define custom behavior in response
+ * to mouse scroll input.
*
- * @param action The action to be performed.
+ * @param action the lambda to be executed on a mouse scroll event, with the scroll delta as its parameter.
*/
@LayoutBuilder
fun T.onMouseScroll(action: T.(delta: Double) -> Unit) {
@@ -252,7 +281,12 @@ open class Layout(
}
/**
- * Force overrides drawn x position of the layout
+ * Sets a custom lambda to override the layout's computed x position.
+ *
+ * The provided lambda is invoked during rendering to determine the x coordinate,
+ * allowing for custom horizontal positioning that bypasses the default layout logic.
+ *
+ * @param transform a lambda returning the x coordinate for the layout.
*/
@LayoutBuilder
fun overrideX(transform: () -> Double) {
@@ -260,7 +294,11 @@ open class Layout(
}
/**
- * Force overrides drawn y position of the layout
+ * Overrides the layout's y-coordinate during rendering.
+ *
+ * Sets a transformation function to compute a forced y position for the layout, bypassing its default positioning.
+ *
+ * @param transform A lambda that calculates and returns the new y-coordinate.
*/
@LayoutBuilder
fun overrideY(transform: () -> Double) {
@@ -268,7 +306,13 @@ open class Layout(
}
/**
- * Force overrides drawn position of the layout
+ * Overrides the layout's drawn position by applying custom transformation functions.
+ *
+ * The provided lambda functions compute new x and y coordinates that will be used during rendering,
+ * effectively bypassing the layout's default position calculation.
+ *
+ * @param x lambda function returning the new x-coordinate.
+ * @param y lambda function returning the new y-coordinate.
*/
@LayoutBuilder
fun overridePosition(x: () -> Double, y: () -> Double) {
@@ -277,7 +321,11 @@ open class Layout(
}
/**
- * Force overrides drawn width of the layout
+ * Overrides the layout's drawn width with a custom computed value.
+ *
+ * This function sets a lambda that computes the width during rendering, enabling dynamic adjustments.
+ *
+ * @param transform A lambda that returns the desired width as a Double.
*/
@LayoutBuilder
fun overrideWidth(transform: () -> Double) {
@@ -285,7 +333,9 @@ open class Layout(
}
/**
- * Force overrides drawn height of the layout
+ * Overrides the layout's drawn height using a custom transform function.
+ *
+ * @param transform A lambda returning the new height value to be applied during rendering.
*/
@LayoutBuilder
fun overrideHeight(transform: () -> Double) {
@@ -293,7 +343,13 @@ open class Layout(
}
/**
- * Force overrides drawn size of the layout
+ * Overrides the layout's rendered dimensions.
+ *
+ * By supplying custom lambda expressions for width and height, this function
+ * forces the layout to use the specified dimensions instead of its default size.
+ *
+ * @param width Lambda that returns the new width value.
+ * @param height Lambda that returns the new height value.
*/
@LayoutBuilder
fun overrideSize(width: () -> Double, height: () -> Double) {
@@ -302,7 +358,20 @@ open class Layout(
}
/**
- * Makes this layout expand up to parents rect
+ * Expands the layout to match its parent's bounding rectangle.
+ *
+ * This method sets override functions for the layout's x-position, y-position, width, and height,
+ * causing the layout to fill its parent's render area. By default, if a parent exists, the layout adopts
+ * the parent's render properties; otherwise, it falls back to the layout's existing dimensions.
+ *
+ * @param overrideX Lambda that computes the x-coordinate. Defaults to the parent's render x-position or
+ * the layout's own x value if no parent is present.
+ * @param overrideY Lambda that computes the y-coordinate. Defaults to the parent's render y-position or
+ * the layout's own y value if no parent is present.
+ * @param overrideWidth Lambda that computes the width. Defaults to the parent's render width or
+ * the layout's own width if no parent is present.
+ * @param overrideHeight Lambda that computes the height. Defaults to the parent's render height or
+ * the layout's own height if no parent is present.
*/
@LayoutBuilder
fun fillParent(
@@ -318,7 +387,12 @@ open class Layout(
}
/**
- * Removes this layout from its parent
+ * Removes this layout from its parent.
+ *
+ * This function removes the layout from its parent's list of children, ensuring that it is not a root layout and preventing duplicate removals.
+ * It will throw an IllegalStateException if the layout has no owner (i.e., is a root layout) or if it has already been removed.
+ *
+ * @throws IllegalStateException if the layout is a root layout or if it has been destroyed previously.
*/
fun destroy() {
check(owner != null) {
@@ -352,6 +426,16 @@ open class Layout(
}
}
+ /**
+ * Processes a GUI event by updating the layout's state and dispatching the event to registered actions and child layouts.
+ *
+ * Depending on the event type, it updates internal properties such as mouse position, triggers specific action lists
+ * (e.g., show, hide, tick, key press, char typed, mouse move, mouse scroll, and mouse click), and propagates the event
+ * to its children. For mouse click events, the action is adjusted based on the child's hover or selection state.
+ * In the case of a render event, it executes render actions and conditionally applies scissor clipping before rendering children.
+ *
+ * @param e the GUI event to process
+ */
fun onEvent(e: GuiEvent) {
// Update self
when (e) {
@@ -421,12 +505,12 @@ open class Layout(
companion object {
/**
- * Creates an empty [Layout].
- *
- * @param block Actions to perform within this component.
- *
- * Check [Layout] description for more info about batching.
- */
+ * Creates a new child [Layout] instance within the current layout.
+ *
+ * The new layout is added to the parent's children list and configured using the provided lambda.
+ *
+ * @param block Optional lambda to configure the newly created [Layout].
+ */
@UIBuilder
fun Layout.layout(
block: Layout.() -> Unit = {},
@@ -434,14 +518,14 @@ open class Layout(
.apply(children::add).apply(block)
/**
- * Creates new [AnimationTicker].
- *
- * Use it to create and manage animations.
+ * Creates an [AnimationTicker] for the layout.
*
- * It's ok to have multiple tickers per component if you need to tick different animations at different timings.
+ * The ticker manages animation updates and, if registered (default), is automatically
+ * ticked on the layout's tick events. Otherwise, you must invoke its tick() method manually.
+ * Multiple tickers can be attached to a layout to handle animations with distinct timings.
*
- * @param register Whether to tick this [AnimationTicker].
- * Otherwise, you will have to tick it manually
+ * @param register whether the ticker should be automatically ticked on each layout tick.
+ * @return the newly created [AnimationTicker] instance.
*/
@UIBuilder
fun Layout.animationTicker(register: Boolean = true) = AnimationTicker().apply {
@@ -451,9 +535,10 @@ open class Layout(
}
/**
- * Creates new [Mouse.CursorController].
+ * Creates a [Mouse.CursorController] for managing the mouse cursor state.
*
- * Use it to set the mouse cursor type for various conditions: hovering, resizing, typing etc...
+ * Use the returned controller to specify the cursor appearance for various UI conditions such as hovering,
+ * resizing, or typing. The controller is automatically reset when the layout is hidden.
*/
@UIBuilder
fun Layout.cursorController(): Mouse.CursorController {
diff --git a/common/src/main/kotlin/com/lambda/gui/component/window/TitleBar.kt b/common/src/main/kotlin/com/lambda/gui/component/window/TitleBar.kt
index 746e064b9..5125e2135 100644
--- a/common/src/main/kotlin/com/lambda/gui/component/window/TitleBar.kt
+++ b/common/src/main/kotlin/com/lambda/gui/component/window/TitleBar.kt
@@ -89,6 +89,15 @@ class TitleBar(
}
companion object {
+ /**
+ * Adds a title bar component to the window.
+ *
+ * This extension function creates a [TitleBar] with the specified title text and dragging capability,
+ * then adds it to the window's children.
+ *
+ * @param text The text to display on the title bar.
+ * @param drag If true, the title bar can be dragged.
+ */
@UIBuilder
fun Window.titleBar(
text: String,
diff --git a/common/src/main/kotlin/com/lambda/gui/component/window/Window.kt b/common/src/main/kotlin/com/lambda/gui/component/window/Window.kt
index 890808b6c..c46e8c88c 100644
--- a/common/src/main/kotlin/com/lambda/gui/component/window/Window.kt
+++ b/common/src/main/kotlin/com/lambda/gui/component/window/Window.kt
@@ -217,26 +217,20 @@ open class Window(
companion object {
/**
- * Creates new empty [Window]
+ * Creates a new [Window] instance, adds it to the current layout, and configures it with the specified properties.
*
- * @param position The initial position of the window
+ * The window is initialized with the given position, size, title, and behavior settings. Its content can be customized
+ * further via the provided lambda.
*
- * @param size The initial size of the window
- *
- * @param title The title of the window
- *
- * @param draggable Whether to allow user to drag the window
- *
- * @param scrollable Whether to let user scroll the content
- * This will also make your elements be vertically ordered
- *
- * @param minimizing The [Minimizing] mode.
- *
- * @param resizable Whether to allow user to resize the window
- *
- * @param autoResize Indicates if this window could be automatically resized based on content height
- *
- * @param block Actions to perform within content space of the window
+ * @param position the initial position of the window.
+ * @param size the initial size of the window.
+ * @param title the title displayed in the window's title bar.
+ * @param draggable if true, allows the window to be dragged.
+ * @param scrollable if true, enables vertical scrolling for the window’s content.
+ * @param minimizing the minimizing behavior of the window (e.g., [Minimizing.Relative]).
+ * @param resizable if true, permits the window to be resized.
+ * @param autoResize if enabled, allows the window to automatically adjust its size based on its content height.
+ * @param block a lambda to configure the window's content.
*/
@UIBuilder
fun Layout.window(
diff --git a/common/src/main/kotlin/com/lambda/gui/component/window/WindowContent.kt b/common/src/main/kotlin/com/lambda/gui/component/window/WindowContent.kt
index 52b94f6c7..a3e4edfc1 100644
--- a/common/src/main/kotlin/com/lambda/gui/component/window/WindowContent.kt
+++ b/common/src/main/kotlin/com/lambda/gui/component/window/WindowContent.kt
@@ -58,7 +58,12 @@ class WindowContent(
}
/**
- * Overrides the summary height of the content
+ * Overrides the default content height calculation.
+ *
+ * Allows specifying a custom lambda that computes the total height of the content,
+ * typically based on factors such as padding, spacing, and the dimensions of child elements.
+ *
+ * @param block a lambda that returns the new content height as a Double.
*/
@LayoutBuilder
fun overrideContentHeight(block: () -> Double) {
@@ -66,7 +71,12 @@ class WindowContent(
}
/**
- * Overrides the action performed on ordering update
+ * Sets a custom reordering action for updating the positions of the window content's children.
+ *
+ * This function allows you to override the default layout update behavior by providing a lambda
+ * that will be executed when the children order is recalculated.
+ *
+ * @param block The lambda that defines the custom reordering logic.
*/
@LayoutBuilder
fun reorderChildren(block: () -> Unit) {
@@ -115,15 +125,25 @@ class WindowContent(
}
}
- fun getContentHeight() = contentHeight()
+ /**
+ * Returns the calculated content height.
+ *
+ * This function computes the total height of the content by invoking the designated lambda,
+ * which factors in elements such as padding, spacing, and the dimensions of its child components.
+ *
+ * @return the total height of the content.
+ */
+fun getContentHeight() = contentHeight()
companion object {
/**
- * Creates an empty [WindowContent] component
- *
- * @param scrollable Whether to let user scroll this layout
- * This will also make your elements be vertically ordered
- */
+ * Creates and attaches a [WindowContent] component to this [Window].
+ *
+ * The new component is automatically added to the window's children. It is configured to be scrollable if
+ * the [scrollable] parameter is true, which also enforces vertical ordering for its child elements.
+ *
+ * @param scrollable if true, enables user scrolling for the layout.
+ */
@UIBuilder
fun Window.windowContent(scrollable: Boolean) =
WindowContent(this, scrollable).apply(children::add)
diff --git a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/ModuleLayout.kt b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/ModuleLayout.kt
index e7f0fe369..927bc1c16 100644
--- a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/ModuleLayout.kt
+++ b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/ModuleLayout.kt
@@ -145,6 +145,12 @@ class ModuleLayout(
}
}
+ /**
+ * Adjusts the corner radii of the filled rectangle based on its position and auto-resize configuration.
+ *
+ * If the rectangle is not the last element or auto-resizing is disabled, all corner radii are reset to 0.
+ * Otherwise, the top corner radii are reset and the bottom corner radii are reduced by the configured padding.
+ */
private fun FilledRect.correctRadius() {
if (!isLast || !ClickGui.autoResize) {
setRadius(0.0)
@@ -159,8 +165,12 @@ class ModuleLayout(
companion object {
/**
- * Creates a [ModuleLayout] - visual representation of the [Module]
- */
+ * Creates a ModuleLayout that visually represents the specified module and appends it
+ * to the children of the current layout.
+ *
+ * @param module the module instance to be displayed.
+ * @return the newly created ModuleLayout that has been added to the layout.
+ */
@UIBuilder
fun Layout.moduleLayout(module: Module) =
ModuleLayout(this, module).apply(children::add)
diff --git a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/ModuleWindow.kt b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/ModuleWindow.kt
index db2fd5e8c..c98f40fbf 100644
--- a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/ModuleWindow.kt
+++ b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/ModuleWindow.kt
@@ -44,7 +44,15 @@ class ModuleWindow(
companion object {
/**
- * Creates a [ModuleWindow]
+ * Creates and attaches a [ModuleWindow] to the current layout.
+ *
+ * This extension function instantiates a [ModuleWindow] with the provided module [tag]
+ * and optional initial [position]. It adds the new window to the layout's children and applies
+ * the given [block] to configure the window's [WindowContent].
+ *
+ * @param tag the module tag used to filter the modules displayed in the window.
+ * @param position the window's initial position; defaults to [Vec2d.ZERO].
+ * @param block an optional lambda for configuring the window's content.
*/
@UIBuilder
fun Layout.moduleWindow(
diff --git a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/settings/BooleanButton.kt b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/settings/BooleanButton.kt
index aa048667c..ad0296175 100644
--- a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/settings/BooleanButton.kt
+++ b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/settings/BooleanButton.kt
@@ -81,8 +81,11 @@ class BooleanButton(
companion object {
/**
- * Creates a [BooleanButton] - visual representation of the [BooleanSetting]
- */
+ * Creates a [BooleanButton] representing the specified [BooleanSetting] and adds it to the layout.
+ *
+ * @param setting the boolean setting whose state is controlled by the button.
+ * @return the newly created [BooleanButton].
+ */
@UIBuilder
fun Layout.booleanSetting(setting: BooleanSetting) =
BooleanButton(this, setting).apply(children::add)
diff --git a/common/src/main/kotlin/com/lambda/module/HudModule.kt b/common/src/main/kotlin/com/lambda/module/HudModule.kt
index 820728a6b..db722acfc 100644
--- a/common/src/main/kotlin/com/lambda/module/HudModule.kt
+++ b/common/src/main/kotlin/com/lambda/module/HudModule.kt
@@ -76,7 +76,15 @@ abstract class HudModule(
val rect by rectHandler::rect
val animation = AnimationTicker()
- protected fun onRender(block: () -> Unit) =
+ /**
+ * Registers a callback to be executed when the HUD rendering event occurs.
+ *
+ * The supplied block is invoked each time a RenderEvent.GUI.HUD event is triggered,
+ * allowing for custom rendering logic during the HUD update phase.
+ *
+ * @param block Lambda to execute on each HUD render event.
+ */
+ protected fun onRender(block: () -> Unit) =
listen { block() }
init {
diff --git a/common/src/main/kotlin/com/lambda/module/Module.kt b/common/src/main/kotlin/com/lambda/module/Module.kt
index 5519ec086..f9e43fffa 100644
--- a/common/src/main/kotlin/com/lambda/module/Module.kt
+++ b/common/src/main/kotlin/com/lambda/module/Module.kt
@@ -159,6 +159,11 @@ abstract class Module(
}
}
+ /**
+ * Enables the module.
+ *
+ * Sets the module's enabled state to true, triggering any registered on-enable actions.
+ */
fun enable() {
isEnabled = true
}
diff --git a/common/src/main/kotlin/com/lambda/module/modules/client/LambdaMoji.kt b/common/src/main/kotlin/com/lambda/module/modules/client/LambdaMoji.kt
index b97bca99b..8c69e3f11 100644
--- a/common/src/main/kotlin/com/lambda/module/modules/client/LambdaMoji.kt
+++ b/common/src/main/kotlin/com/lambda/module/modules/client/LambdaMoji.kt
@@ -55,7 +55,23 @@ object LambdaMoji : Module(
}
}
- // FixMe: Doesn't render properly when the chat scale is modified
+ /**
+ * Parses the provided ordered text to replace emoji characters with whitespace placeholders while
+ * enqueuing their corresponding glyphs for later rendering.
+ *
+ * The function processes each character in the input text, preserving style information. Detected
+ * emoji characters are replaced with computed whitespace (based on current font metrics and scaling)
+ * to maintain text layout. For every emoji found, its glyph, along with positional and color
+ * adjustments, is added to the render queue.
+ *
+ * Note: This function may not render correctly when the chat scale is modified.
+ *
+ * @param text The ordered text containing the characters and associated style information.
+ * @param x The x-coordinate offset used for calculating the emoji rendering position.
+ * @param y The y-coordinate offset used for calculating the emoji rendering position.
+ * @param color The base color used for rendering, with its alpha component adjusted for emojis.
+ * @return An OrderedText object with emojis replaced by whitespace to preserve layout and styles.
+ */
fun parse(text: OrderedText, x: Float, y: Float, color: Int): OrderedText {
val saved = mutableMapOf()
val builder = StringBuilder()
diff --git a/common/src/main/kotlin/com/lambda/module/modules/player/MapDownloader.kt b/common/src/main/kotlin/com/lambda/module/modules/player/MapDownloader.kt
index 74a5da185..fab841e4b 100644
--- a/common/src/main/kotlin/com/lambda/module/modules/player/MapDownloader.kt
+++ b/common/src/main/kotlin/com/lambda/module/modules/player/MapDownloader.kt
@@ -59,6 +59,14 @@ object MapDownloader : Module(
private val MapState.hash: String
get() = colors.hash("SHA-256")
+ /**
+ * Converts the MapState into a 128x128 ARGB BufferedImage.
+ *
+ * This extension creates an image by iterating over each pixel in the map state's color array,
+ * retrieving the corresponding render color with [MapColor.getRenderColor], and assembling the ARGB value.
+ *
+ * @return the generated [BufferedImage] representing the map state.
+ */
fun MapState.toBufferedImage(): BufferedImage {
val image = BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB)