From 3a89a0909a0b96623567d73eeca4f6c8d6181ad9 Mon Sep 17 00:00:00 2001 From: EmeraldLockdown <86802223+EmeraldLoc@users.noreply.github.com> Date: Sat, 9 May 2026 12:52:59 -0500 Subject: [PATCH 1/3] Some fixes for the scroll pr --- src/pc/djui/djui_cursor.c | 53 +++++++++++++++++++-------------- src/pc/djui/djui_flow_layout.c | 19 +++++------- src/pc/djui/djui_flow_layout.h | 7 ++--- src/pc/djui/djui_interactable.c | 12 +++----- 4 files changed, 45 insertions(+), 46 deletions(-) diff --git a/src/pc/djui/djui_cursor.c b/src/pc/djui/djui_cursor.c index 5d2470097..608661c16 100644 --- a/src/pc/djui/djui_cursor.c +++ b/src/pc/djui/djui_cursor.c @@ -3,9 +3,11 @@ #include "djui_flow_layout.h" #include "pc/controller/controller_mouse.h" #include "pc/gfx/gfx_window_manager_api.h" +#include "pc/debuglog.h" #include "pc/pc_main.h" #define CURSOR_GFX_MAX_SIZE 20 +#define DJUI_CURSOR_ALIGNMENT_TOLERANCE 20.0f extern ALIGNED8 u8 gd_texture_hand_open[]; extern ALIGNED8 u8 gd_texture_hand_closed[]; @@ -69,7 +71,7 @@ static f32 djui_cursor_base_distance(struct DjuiBase* base, f32 xScale, f32 ySca return sqrtf((x * x) * xScale + (y * y) * yScale); } -static void djui_cursor_move_check(s8 xDir, s8 yDir, struct DjuiBase** pick, struct DjuiBase* base) { +static void djui_cursor_move_check(s8 xDir, s8 yDir, struct DjuiBase **pick, struct DjuiBase *base) { if (!base->visible) { return; } if (base->interactable != NULL && base->interactable->enabled) { @@ -78,8 +80,9 @@ static void djui_cursor_move_check(s8 xDir, s8 yDir, struct DjuiBase** pick, str y1 = base->elem.y; x2 = base->elem.x + base->elem.width; y2 = base->elem.y + base->elem.height; - bool xWithin = (gCursorX >= x1 && gCursorX <= x2) || sCursorMouseControlled; - bool yWithin = (gCursorY >= y1 && gCursorY <= y2) || sCursorMouseControlled; + + bool xWithin = (gCursorX >= x1 - DJUI_CURSOR_ALIGNMENT_TOLERANCE && gCursorX <= x2 + DJUI_CURSOR_ALIGNMENT_TOLERANCE); + bool yWithin = (gCursorY >= y1 - DJUI_CURSOR_ALIGNMENT_TOLERANCE && gCursorY <= y2 + DJUI_CURSOR_ALIGNMENT_TOLERANCE); bool valid = false; if (yDir > 0 && gCursorY < y1 && xWithin) { valid = true; } @@ -101,7 +104,7 @@ static void djui_cursor_move_check(s8 xDir, s8 yDir, struct DjuiBase** pick, str } // check all children - struct DjuiBaseChild* child = base->child; + struct DjuiBaseChild *child = base->child; while (child != NULL) { djui_cursor_move_check(xDir, yDir, pick, child->base); child = child->next; @@ -114,26 +117,32 @@ void djui_cursor_move(s8 xDir, s8 yDir) { struct DjuiBase* pick = NULL; djui_cursor_move_check(xDir, yDir, &pick, &gDjuiRoot->base); if (pick != NULL) { + // look for scroll flow layout + struct DjuiBase* parent = pick->parent; + while (parent) { + if (parent->render == gDjuiFlowLayoutScrollRender) { + // auto scroll to have the element in bounds + struct DjuiFlowLayout* layout = (struct DjuiFlowLayout*)parent; + f32 targetTop = pick->elem.y; + f32 targetBottom = pick->elem.y + pick->elem.height; + f32 visibleTop = parent->clip.y; + f32 visibleBottom = parent->clip.y + parent->clip.height; + + LOG_CONSOLE("Element Y is %f, whereas clip y for flow is %f", targetTop, visibleTop) + LOG_CONSOLE("Clip Height is %f, whereas clip height for flow is %f", pick->clip.height, parent->clip.height) + + if (targetTop < visibleTop) { + layout->scrollY -= (visibleTop - targetTop); + } else if (targetBottom > visibleBottom) { + layout->scrollY += (targetBottom - visibleBottom); + } + break; + } + parent = parent->parent; + } + sCursorMouseControlled = false; djui_cursor_input_controlled_center(pick); - - // auto-scroll scrollable flow layout to show the picked element - if (gDjuiFlowLayoutScrollRender) { - struct DjuiBase* parent = pick->parent; - while (parent) { - if (parent->render == gDjuiFlowLayoutScrollRender) { - struct DjuiFlowLayout* layout = (struct DjuiFlowLayout*)parent; - f32 targetTop = pick->elem.y; - f32 targetBot = pick->elem.y + pick->elem.height; - f32 visTop = parent->clip.y; - f32 visBot = parent->clip.y + parent->clip.height; - if (targetTop < visTop) { layout->scrollY -= (visTop - targetTop); } - else if (targetBot > visBot) { layout->scrollY += (targetBot - visBot); } - break; - } - parent = parent->parent; - } - } } } diff --git a/src/pc/djui/djui_flow_layout.c b/src/pc/djui/djui_flow_layout.c index 9b686dfdb..f1653f1aa 100644 --- a/src/pc/djui/djui_flow_layout.c +++ b/src/pc/djui/djui_flow_layout.c @@ -1,6 +1,7 @@ #include "djui.h" -bool (*gDjuiFlowLayoutScrollRender)(struct DjuiBase*) = NULL; +static bool djui_flow_layout_scroll_render(struct DjuiBase* base); +bool (*gDjuiFlowLayoutScrollRender)(struct DjuiBase*) = djui_flow_layout_scroll_render; //////////////// // properties // @@ -53,7 +54,7 @@ static bool djui_flow_layout_scroll_render(struct DjuiBase* base) { // draw background djui_rect_render(base); - // compute content height from visible children + // get content height from visible children f32 contentHeight = layout->margin.value; struct DjuiBaseChild* child = base->child; while (child != NULL) { @@ -75,6 +76,7 @@ static bool djui_flow_layout_scroll_render(struct DjuiBase* base) { // draw scrollbar indicator if (maxScroll > 0) { + // !! Scroll TODO: This doesn't use any themes! Just a random color! struct DjuiBaseRect* clip = &base->clip; f32 thumbRatio = clip->height / contentHeight; f32 thumbH = clip->height * thumbRatio; @@ -98,8 +100,7 @@ static bool djui_flow_layout_scroll_render(struct DjuiBase* base) { return true; } -static void djui_flow_layout_on_scroll(struct DjuiBase* base, float x, float y) { - UNUSED f32 unused = x; +static void djui_flow_layout_on_scroll(struct DjuiBase* base, UNUSED float x, float y) { struct DjuiFlowLayout* layout = (struct DjuiFlowLayout*)base; layout->scrollY -= y * 48.0f; } @@ -116,22 +117,16 @@ static void flow_scroll_update(struct DjuiBase* base) { layout->touchStartY = gCursorY; } -static void flow_scroll_end(UNUSED struct DjuiBase* base) {} - void djui_flow_layout_enable_scroll(struct DjuiFlowLayout* layout) { layout->scrollEnabled = true; layout->scrollY = 0; layout->base.render = djui_flow_layout_scroll_render; layout->base.abandonAfterChildRenderFail = false; - if (!gDjuiFlowLayoutScrollRender) { - gDjuiFlowLayoutScrollRender = djui_flow_layout_scroll_render; - } - djui_interactable_create(&layout->base, NULL); + layout->base.interactable->enabled = false; djui_interactable_hook_scroll(&layout->base, djui_flow_layout_on_scroll); - djui_interactable_hook_cursor_down(&layout->base, - flow_scroll_begin, flow_scroll_update, flow_scroll_end); + djui_interactable_hook_cursor_down(&layout->base, flow_scroll_begin, flow_scroll_update, NULL); } static void djui_flow_layout_destroy(struct DjuiBase* base) { diff --git a/src/pc/djui/djui_flow_layout.h b/src/pc/djui/djui_flow_layout.h index dede55ab1..48207b045 100644 --- a/src/pc/djui/djui_flow_layout.h +++ b/src/pc/djui/djui_flow_layout.h @@ -5,11 +5,10 @@ struct DjuiFlowLayout { struct DjuiBase base; enum DjuiFlowDirection flowDirection; struct DjuiScreenValue margin; - // Scroll bool scrollEnabled; - f32 scrollY; - f32 contentHeight; - f32 touchStartY; + f32 scrollY; + f32 contentHeight; + f32 touchStartY; }; extern bool (*gDjuiFlowLayoutScrollRender)(struct DjuiBase*); diff --git a/src/pc/djui/djui_interactable.c b/src/pc/djui/djui_interactable.c index be44f9e6b..6a4041dc6 100644 --- a/src/pc/djui/djui_interactable.c +++ b/src/pc/djui/djui_interactable.c @@ -339,13 +339,11 @@ void djui_interactable_on_text_editing(char* text, int cursorPos) { } void djui_interactable_on_scroll(float x, float y) { - // Priority: focused element (e.g. chat input) - if (gInteractableFocus && gInteractableFocus->interactable - && gInteractableFocus->interactable->on_scroll) { + if (gInteractableFocus && gInteractableFocus->interactable && gInteractableFocus->interactable->on_scroll) { gInteractableFocus->interactable->on_scroll(gInteractableFocus, x, y); return; } - // Bubble from hovered element up to ancestors + struct DjuiBase* base = gDjuiHovered; while (base) { if (base->interactable && base->interactable->on_scroll) { @@ -477,10 +475,7 @@ void djui_interactable_update(void) { // check if vertical drag exceeds threshold to steal touch for scrolling f32 dragDist = gCursorY - sCursorDownStartY; if (dragDist < 0) { dragDist = -dragDist; } - if (gInteractableMouseDown != NULL && dragDist > 10.0f - && gDjuiFlowLayoutScrollRender - && (!gInteractableMouseDown->interactable - || !gInteractableMouseDown->interactable->on_cursor_down)) { + if (gInteractableMouseDown != NULL && dragDist > 10.0f && (!gInteractableMouseDown->interactable || !gInteractableMouseDown->interactable->on_cursor_down)) { struct DjuiBase* parent = gInteractableMouseDown->parent; while (parent) { if (parent->render == gDjuiFlowLayoutScrollRender) { @@ -493,6 +488,7 @@ void djui_interactable_update(void) { } parent = parent->parent; } + if (!sDragScrollActive) { djui_interactable_on_cursor_down(gInteractableMouseDown); } From fa70ac5ad2cb9bad74be63f4ec7de952f5cb5e1a Mon Sep 17 00:00:00 2001 From: EmeraldLockdown <86802223+EmeraldLoc@users.noreply.github.com> Date: Sat, 9 May 2026 13:01:46 -0500 Subject: [PATCH 2/3] Fix issues caused by merge --- src/pc/djui/djui_cursor.c | 1 + src/pc/djui/djui_flow_layout.h | 3 +++ src/pc/djui/djui_interactable.c | 8 ++++++++ src/pc/djui/djui_panel_menu.c | 1 + 4 files changed, 13 insertions(+) diff --git a/src/pc/djui/djui_cursor.c b/src/pc/djui/djui_cursor.c index 5559f5d9f..608661c16 100644 --- a/src/pc/djui/djui_cursor.c +++ b/src/pc/djui/djui_cursor.c @@ -1,5 +1,6 @@ #include "djui.h" #include "djui_panel.h" +#include "djui_flow_layout.h" #include "pc/controller/controller_mouse.h" #include "pc/gfx/gfx_window_manager_api.h" #include "pc/debuglog.h" diff --git a/src/pc/djui/djui_flow_layout.h b/src/pc/djui/djui_flow_layout.h index a069ff0ed..48207b045 100644 --- a/src/pc/djui/djui_flow_layout.h +++ b/src/pc/djui/djui_flow_layout.h @@ -11,8 +11,11 @@ struct DjuiFlowLayout { f32 touchStartY; }; +extern bool (*gDjuiFlowLayoutScrollRender)(struct DjuiBase*); + void djui_flow_layout_set_flow_direction(struct DjuiFlowLayout* layout, enum DjuiFlowDirection flowDirection); void djui_flow_layout_set_margin(struct DjuiFlowLayout* layout, f32 margin); void djui_flow_layout_set_margin_type(struct DjuiFlowLayout* layout, enum DjuiScreenValueType marginType); +void djui_flow_layout_enable_scroll(struct DjuiFlowLayout* layout); struct DjuiFlowLayout* djui_flow_layout_create(struct DjuiBase* parent); diff --git a/src/pc/djui/djui_interactable.c b/src/pc/djui/djui_interactable.c index db2beb46e..72e4dfbe8 100644 --- a/src/pc/djui/djui_interactable.c +++ b/src/pc/djui/djui_interactable.c @@ -4,6 +4,7 @@ #include "djui_panel_pause.h" #include "djui_panel_modlist.h" #include "djui_panel_playerlist.h" +#include "djui_flow_layout.h" #include "pc/controller/controller_sdl.h" #include "pc/controller/controller_mouse.h" @@ -20,6 +21,8 @@ enum PadHoldDirection { PAD_HOLD_DIR_NONE, PAD_HOLD_DIR_UP, PAD_HOLD_DIR_DOWN, PAD_HOLD_DIR_LEFT, PAD_HOLD_DIR_RIGHT }; static enum PadHoldDirection sKeyboardHoldDirection = PAD_HOLD_DIR_NONE; static u16 sKeyboardButtons = 0; +static f32 sCursorDownStartY = 0; +static bool sDragScrollActive = false; static bool sIgnoreInteractableUntilCursorReleased = false; @@ -463,7 +466,11 @@ void djui_interactable_update(void) { if (gDjuiHovered != NULL) { gInteractableMouseDown = gDjuiHovered; gDjuiHovered = NULL; + sCursorDownStartY = gCursorY; + sDragScrollActive = false; djui_interactable_on_cursor_down_begin(gInteractableMouseDown, !mouseButtons); + } else if (sDragScrollActive) { + djui_interactable_on_cursor_down(gInteractableMouseDown); } else { // check if vertical drag exceeds threshold to steal touch for scrolling f32 dragDist = gCursorY - sCursorDownStartY; @@ -494,6 +501,7 @@ void djui_interactable_update(void) { if (gInteractableMouseDown != NULL) { djui_interactable_on_cursor_down_end(gInteractableMouseDown); gInteractableMouseDown = NULL; + sDragScrollActive = false; } struct DjuiBase* lastHovered = gDjuiHovered; gDjuiHovered = NULL; diff --git a/src/pc/djui/djui_panel_menu.c b/src/pc/djui/djui_panel_menu.c index 6ff2289a3..781cb8aef 100644 --- a/src/pc/djui/djui_panel_menu.c +++ b/src/pc/djui/djui_panel_menu.c @@ -101,6 +101,7 @@ struct DjuiThreePanel* djui_panel_menu_create(char* headerText, bool forcedLeftS djui_base_set_color(&body->base, 0, 0, 0, 0); djui_flow_layout_set_margin(body, 16); djui_flow_layout_set_flow_direction(body, DJUI_FLOW_DIR_DOWN); + djui_flow_layout_enable_scroll(body); } return panel; } From 22ac60ba120236fdee7f09ed3fe800418a0b82f8 Mon Sep 17 00:00:00 2001 From: EmeraldLockdown <86802223+EmeraldLoc@users.noreply.github.com> Date: Sun, 10 May 2026 21:52:17 -0500 Subject: [PATCH 3/3] Remove some logging --- src/pc/djui/djui_cursor.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pc/djui/djui_cursor.c b/src/pc/djui/djui_cursor.c index 608661c16..355449937 100644 --- a/src/pc/djui/djui_cursor.c +++ b/src/pc/djui/djui_cursor.c @@ -128,9 +128,6 @@ void djui_cursor_move(s8 xDir, s8 yDir) { f32 visibleTop = parent->clip.y; f32 visibleBottom = parent->clip.y + parent->clip.height; - LOG_CONSOLE("Element Y is %f, whereas clip y for flow is %f", targetTop, visibleTop) - LOG_CONSOLE("Clip Height is %f, whereas clip height for flow is %f", pick->clip.height, parent->clip.height) - if (targetTop < visibleTop) { layout->scrollY -= (visibleTop - targetTop); } else if (targetBottom > visibleBottom) {