From f2648c002bb4a380126a44f9dbfbf5e41da36b99 Mon Sep 17 00:00:00 2001 From: tul <27+tul@noreply.localhost> Date: Tue, 4 Aug 2026 15:50:45 +0000 Subject: [PATCH] mobile sizedown --- UI/library.lua | 73 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/UI/library.lua b/UI/library.lua index 995748f..b4539ab 100644 --- a/UI/library.lua +++ b/UI/library.lua @@ -82,6 +82,9 @@ is_mobile = uis.TouchEnabled, + ui_scale = uis.TouchEnabled and 0.75 or 1, + ui_scales = {}, + colorpicker_open = false; gui; } @@ -279,6 +282,28 @@ end end + -- scales a floating root and its whole subtree. UIScale grows from the anchor + -- point, so with the default (0, 0) anchor AbsolutePosition is untouched and only + -- AbsoluteSize shrinks -- which keeps every drag and ratio calculation honest + function library:apply_scale(frame) + local scale = library:create("UIScale", { + Parent = frame, + Scale = library.ui_scale, + }) + + library.ui_scales[#library.ui_scales + 1] = scale + + return scale + end + + function library:set_ui_scale(value) + library.ui_scale = value + + for _, scale in next, library.ui_scales do + scale.Scale = value + end + end + -- one pointer-drag helper behind the window, the resize grip and every label. -- a touch is tracked by its input object rather than its type, so a second finger -- (moving, shooting, another panel) can never hijack a drag that is already running. @@ -320,8 +345,9 @@ end function library:resizify(frame) - -- a 10px corner is unhittable with a finger - local grip = library.is_mobile and 24 or 10 + -- a 10px corner is unhittable with a finger. divided by the scale so the grip + -- stays that size on screen instead of shrinking along with the menu + local grip = (library.is_mobile and 24 or 10) / library.ui_scale local Frame = Instance.new("TextButton") Frame.Position = dim2(1, -grip, 1, -grip) @@ -343,7 +369,9 @@ start = input.Position start_size = frame.Size end, function(input) - local delta = input.Position - start + -- Size is in unscaled units while the pointer moves in screen pixels, so + -- the delta has to be converted or the corner drifts away from the finger + local delta = (input.Position - start) / library.ui_scale frame.Size = dim2( start_size.X.Scale, @@ -682,6 +710,8 @@ window_outline.Position = dim2(0, window_outline.AbsolutePosition.Y, 0, window_outline.AbsolutePosition.Y) cfg.main_outline = window_outline + library:apply_scale(window_outline) + library:resizify(window_outline) library:draggify(window_outline) @@ -1018,6 +1048,8 @@ library.label_gradients[#library.label_gradients + 1] = gradient + library:apply_scale(outline) + -- transparent lid so touch and mouse land on one instance local hitbox = library:create("TextButton", { Parent = outline; @@ -1784,6 +1816,10 @@ BackgroundColor3 = themes.preset[tostring(self.count)] }); library:apply_theme(accent, tostring(self.count), "BackgroundColor3") + -- floats on the ScreenGui rather than inside the window, so it needs + -- its own scale to match the menu it belongs to + library:apply_scale(accent) + local inline = library:create("Frame", { Parent = accent; Size = dim2(1, -2, 1, -2); @@ -1910,8 +1946,12 @@ dropdown_holder.MouseButton1Click:Connect(function() cfg.open = not cfg.open - accent.Size = dim2(0, dropdown_holder.AbsoluteSize.X, 0, accent.Size.Y.Offset) - accent.Position = dim2(0, dropdown_holder.AbsolutePosition.X, 0, dropdown_holder.AbsolutePosition.Y + 77) + -- AbsoluteSize already has the scale baked in, and so will this frame + -- once its own UIScale applies, so divide it back out first + local scale = library.ui_scale + + accent.Size = dim2(0, dropdown_holder.AbsoluteSize.X / scale, 0, accent.Size.Y.Offset) + accent.Position = dim2(0, dropdown_holder.AbsolutePosition.X, 0, dropdown_holder.AbsolutePosition.Y + 77 * scale) cfg.set_visible(cfg.open) end) @@ -2006,6 +2046,10 @@ BackgroundColor3 = themes.preset[tostring(self.count)] }); library:apply_theme(colorpicker, tostring(self.count), "BackgroundColor3") + -- floats on the ScreenGui rather than inside the window, so it needs + -- its own scale to match the menu it belongs to + library:apply_scale(colorpicker) + local a = library:create("Frame", { Parent = colorpicker; BorderColor3 = rgb(0, 0, 0); @@ -2228,7 +2272,12 @@ function cfg.set_visible(bool) colorpicker.Visible = bool - colorpicker.Position = dim_offset(colorpicker_element_color.AbsolutePosition.X - 1, colorpicker_element_color.AbsolutePosition.Y + colorpicker_element_color.AbsoluteSize.Y + 65) + -- the drop below the swatch is a fixed pixel gap, so it has to shrink + -- with the menu or the panel detaches from the row that opened it + colorpicker.Position = dim_offset( + colorpicker_element_color.AbsolutePosition.X - 1, + colorpicker_element_color.AbsolutePosition.Y + colorpicker_element_color.AbsoluteSize.Y + 65 * library.ui_scale + ) end function cfg.set(color, alpha) @@ -2520,6 +2569,10 @@ BackgroundColor3 = themes.preset[tostring(self.count)] }); library:apply_theme(accent, tostring(self.count), "BackgroundColor3") + -- floats on the ScreenGui rather than inside the window, so it needs + -- its own scale to match the menu it belongs to + library:apply_scale(accent) + local inline = library:create("Frame", { Parent = accent; Size = dim2(1, -2, 1, -2); @@ -2660,8 +2713,12 @@ function cfg.set_visible(bool) accent.Visible = bool - accent.Size = dim2(0, keybind_holder.AbsoluteSize.X, 0, accent.Size.Y.Offset) - accent.Position = dim2(0, keybind_holder.AbsolutePosition.X, 0, keybind_holder.AbsolutePosition.Y + 77) + -- AbsoluteSize already has the scale baked in, and so will this frame + -- once its own UIScale applies, so divide it back out first + local scale = library.ui_scale + + accent.Size = dim2(0, keybind_holder.AbsoluteSize.X / scale, 0, accent.Size.Y.Offset) + accent.Position = dim2(0, keybind_holder.AbsolutePosition.X, 0, keybind_holder.AbsolutePosition.Y + 77 * scale) end --