dpi scale
This commit is contained in:
+38
-49
@@ -282,9 +282,6 @@
|
|||||||
end
|
end
|
||||||
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)
|
function library:apply_scale(frame)
|
||||||
local scale = library:create("UIScale", {
|
local scale = library:create("UIScale", {
|
||||||
Parent = frame,
|
Parent = frame,
|
||||||
@@ -304,12 +301,9 @@
|
|||||||
end
|
end
|
||||||
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.
|
|
||||||
function library:pointer_drag(trigger, on_begin, on_move, on_end)
|
function library:pointer_drag(trigger, on_begin, on_move, on_end)
|
||||||
local dragging = false
|
local dragging = false
|
||||||
local touch_input -- the finger driving this drag, nil while on mouse
|
local touch_input
|
||||||
|
|
||||||
local function drives(input, mouse_type)
|
local function drives(input, mouse_type)
|
||||||
if touch_input then return input == touch_input end
|
if touch_input then return input == touch_input end
|
||||||
@@ -333,7 +327,6 @@
|
|||||||
on_move(input)
|
on_move(input)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- released anywhere, not just over the trigger, or a drag can get stuck on
|
|
||||||
library:connection(uis.InputEnded, function(input)
|
library:connection(uis.InputEnded, function(input)
|
||||||
if not dragging then return end
|
if not dragging then return end
|
||||||
if not drives(input, Enum.UserInputType.MouseButton1) then return end
|
if not drives(input, Enum.UserInputType.MouseButton1) then return end
|
||||||
@@ -345,8 +338,6 @@
|
|||||||
end
|
end
|
||||||
|
|
||||||
function library:resizify(frame)
|
function library:resizify(frame)
|
||||||
-- 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 grip = (library.is_mobile and 24 or 10) / library.ui_scale
|
||||||
|
|
||||||
local Frame = Instance.new("TextButton")
|
local Frame = Instance.new("TextButton")
|
||||||
@@ -369,8 +360,6 @@
|
|||||||
start = input.Position
|
start = input.Position
|
||||||
start_size = frame.Size
|
start_size = frame.Size
|
||||||
end, function(input)
|
end, function(input)
|
||||||
-- 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
|
local delta = (input.Position - start) / library.ui_scale
|
||||||
|
|
||||||
frame.Size = dim2(
|
frame.Size = dim2(
|
||||||
@@ -389,7 +378,6 @@
|
|||||||
return (y_cond and x_cond)
|
return (y_cond and x_cond)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- point is optional, so mouse callers keep the old behaviour and touch can pass a finger
|
|
||||||
function library:point_in_frame(uiobject, point)
|
function library:point_in_frame(uiobject, point)
|
||||||
if not point then return library:mouse_in_frame(uiobject) end
|
if not point then return library:mouse_in_frame(uiobject) end
|
||||||
|
|
||||||
@@ -409,8 +397,6 @@
|
|||||||
local start_size = frame.Position
|
local start_size = frame.Position
|
||||||
local start
|
local start
|
||||||
|
|
||||||
-- without this a touch falls straight through to the camera controls and the
|
|
||||||
-- frame never sees the drag, which is why mobile could not move anything
|
|
||||||
frame.Active = true
|
frame.Active = true
|
||||||
|
|
||||||
library:pointer_drag(frame, function(input)
|
library:pointer_drag(frame, function(input)
|
||||||
@@ -418,7 +404,6 @@
|
|||||||
start_size = frame.Position
|
start_size = frame.Position
|
||||||
end, function(input)
|
end, function(input)
|
||||||
local delta = input.Position - start
|
local delta = input.Position - start
|
||||||
-- measured size, so AutomaticSize frames clamp against their real width
|
|
||||||
local size = frame.AbsoluteSize
|
local size = frame.AbsoluteSize
|
||||||
|
|
||||||
frame.Position = dim2(
|
frame.Position = dim2(
|
||||||
@@ -614,7 +599,6 @@
|
|||||||
themes.preset[theme] = color
|
themes.preset[theme] = color
|
||||||
end
|
end
|
||||||
|
|
||||||
-- repaints the window gradient plus every floating label made by library.label
|
|
||||||
function library:refresh_gradients()
|
function library:refresh_gradients()
|
||||||
local seq = rgbseq{
|
local seq = rgbseq{
|
||||||
rgbkey(0, themes.preset["1"]),
|
rgbkey(0, themes.preset["1"]),
|
||||||
@@ -707,7 +691,18 @@
|
|||||||
BorderSizePixel = 0;
|
BorderSizePixel = 0;
|
||||||
BackgroundColor3 = rgb(255, 255, 255)
|
BackgroundColor3 = rgb(255, 255, 255)
|
||||||
});
|
});
|
||||||
window_outline.Position = dim2(0, window_outline.AbsolutePosition.Y, 0, window_outline.AbsolutePosition.Y)
|
|
||||||
|
do
|
||||||
|
local viewport = camera.ViewportSize
|
||||||
|
local rendered_x = cfg.size.X.Offset * library.ui_scale
|
||||||
|
local rendered_y = cfg.size.Y.Offset * library.ui_scale
|
||||||
|
|
||||||
|
window_outline.Position = dim2(
|
||||||
|
0, max(floor((viewport.X - rendered_x) / 2), 0),
|
||||||
|
0, max(floor((viewport.Y - rendered_y) / 2), 0)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
cfg.main_outline = window_outline
|
cfg.main_outline = window_outline
|
||||||
|
|
||||||
library:apply_scale(window_outline)
|
library:apply_scale(window_outline)
|
||||||
@@ -773,7 +768,6 @@
|
|||||||
window_outline.Visible = bool
|
window_outline.Visible = bool
|
||||||
end
|
end
|
||||||
|
|
||||||
-- the mobile toggle needs a handle on the menu it is toggling
|
|
||||||
library.main_window = cfg
|
library.main_window = cfg
|
||||||
|
|
||||||
return setmetatable(cfg, library)
|
return setmetatable(cfg, library)
|
||||||
@@ -977,16 +971,7 @@
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- standalone floating panel -- the watermark's look, but reusable from anywhere.
|
|
||||||
-- writes go through the proxy, so `label.text = "hi"` updates the ui immediately:
|
|
||||||
--
|
|
||||||
-- local label = library.label()
|
|
||||||
-- label.text = "hi"
|
|
||||||
-- label.position = Vector2.new(500, 500)
|
|
||||||
--
|
|
||||||
-- pass a callback to make it tappable (dragging never counts as a tap).
|
|
||||||
function library.label(options)
|
function library.label(options)
|
||||||
-- tolerate library:label{} as well as library.label{}
|
|
||||||
if options == library then options = nil end
|
if options == library then options = nil end
|
||||||
options = options or {}
|
options = options or {}
|
||||||
|
|
||||||
@@ -1050,7 +1035,6 @@
|
|||||||
|
|
||||||
library:apply_scale(outline)
|
library:apply_scale(outline)
|
||||||
|
|
||||||
-- transparent lid so touch and mouse land on one instance
|
|
||||||
local hitbox = library:create("TextButton", {
|
local hitbox = library:create("TextButton", {
|
||||||
Parent = outline;
|
Parent = outline;
|
||||||
BackgroundTransparency = 1;
|
BackgroundTransparency = 1;
|
||||||
@@ -1070,7 +1054,6 @@
|
|||||||
callback = options.callback,
|
callback = options.callback,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- declared up front so the handlers below close over the local, not a global
|
|
||||||
local proxy
|
local proxy
|
||||||
local setters = {}
|
local setters = {}
|
||||||
|
|
||||||
@@ -1093,8 +1076,6 @@
|
|||||||
state.callback = value
|
state.callback = value
|
||||||
end
|
end
|
||||||
|
|
||||||
-- drag, with a tap fallback -- a pointer that barely moves is a click, not a drag.
|
|
||||||
-- fingers wobble far more than a mouse, so touch gets a looser threshold
|
|
||||||
local drag_start, drag_origin, travelled = nil, nil, 0
|
local drag_start, drag_origin, travelled = nil, nil, 0
|
||||||
local tap_slop = library.is_mobile and 12 or 6
|
local tap_slop = library.is_mobile and 12 or 6
|
||||||
|
|
||||||
@@ -1106,7 +1087,6 @@
|
|||||||
local delta = input.Position - drag_start
|
local delta = input.Position - drag_start
|
||||||
travelled = max(travelled, abs(delta.X) + abs(delta.Y))
|
travelled = max(travelled, abs(delta.X) + abs(delta.Y))
|
||||||
|
|
||||||
-- AutomaticSize leaves Size.X.Offset at 0, so clamp against the measured width
|
|
||||||
setters.position(dim_offset(
|
setters.position(dim_offset(
|
||||||
clamp(drag_origin.X.Offset + delta.X, 0, camera.ViewportSize.X - outline.AbsoluteSize.X),
|
clamp(drag_origin.X.Offset + delta.X, 0, camera.ViewportSize.X - outline.AbsoluteSize.X),
|
||||||
clamp(drag_origin.Y.Offset + delta.Y, 0, camera.ViewportSize.Y - outline.AbsoluteSize.Y)
|
clamp(drag_origin.Y.Offset + delta.Y, 0, camera.ViewportSize.Y - outline.AbsoluteSize.Y)
|
||||||
@@ -1196,10 +1176,6 @@
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- mobile has no keyboard, so the menu keybind is unreachable -- hand it a tappable
|
|
||||||
-- stand-in that sits under the watermark and toggles the same thing the bind does.
|
|
||||||
-- reads the live visibility rather than tracking its own flag, so tapping stays in
|
|
||||||
-- sync with anyone who toggled the menu by keybind
|
|
||||||
library.mobile_toggle = library.label({
|
library.mobile_toggle = library.label({
|
||||||
text = "toggle ui",
|
text = "toggle ui",
|
||||||
position = vec2(50, 82),
|
position = vec2(50, 82),
|
||||||
@@ -1214,15 +1190,6 @@
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
--[[
|
|
||||||
local pingTimeSec = game.Players.LocalPlayer:GetNetworkPing()
|
|
||||||
local pingTimeMs = pingTimeSec * 1000
|
|
||||||
pingLabel.Text = "Ping: " .. tostring(math.floor(pingTimeMs)) .. "ms"
|
|
||||||
|
|
||||||
local realFPS = workspace:GetRealPhysicsFPS()
|
|
||||||
fpsLabel.Text = "FPS: " .. tostring(math.floor(realFPS))
|
|
||||||
]]
|
|
||||||
|
|
||||||
function library:column(properties)
|
function library:column(properties)
|
||||||
self.count += 1
|
self.count += 1
|
||||||
@@ -1608,8 +1575,12 @@
|
|||||||
name = options.name or nil,
|
name = options.name or nil,
|
||||||
suffix = options.suffix or "",
|
suffix = options.suffix or "",
|
||||||
flag = options.flag or options.name or "Flag",
|
flag = options.flag or options.name or "Flag",
|
||||||
callback = options.callback or function() end,
|
callback = options.callback or function() end,
|
||||||
|
|
||||||
|
-- fires once on release instead of every step, for work too heavy to
|
||||||
|
-- run mid-drag. never fires for a programmatic set, only real input
|
||||||
|
released = options.released or options.on_release or function() end,
|
||||||
|
|
||||||
min = options.min or options.minimum or 0,
|
min = options.min or options.minimum or 0,
|
||||||
max = options.max or options.maximum or 100,
|
max = options.max or options.maximum or 100,
|
||||||
intervals = options.interval or options.decimal or 1,
|
intervals = options.interval or options.decimal or 1,
|
||||||
@@ -1710,6 +1681,7 @@
|
|||||||
slide_to(input)
|
slide_to(input)
|
||||||
end, slide_to, function()
|
end, slide_to, function()
|
||||||
cfg.dragging = false
|
cfg.dragging = false
|
||||||
|
cfg.released(cfg.value)
|
||||||
end)
|
end)
|
||||||
--
|
--
|
||||||
|
|
||||||
@@ -2847,11 +2819,28 @@
|
|||||||
config_holder = section:dropdown({name = "configs", options = {"report", "this", "error", "to", "dev"}, callback = function(option) if textbox then textbox.set(option) end end, flag = "config_name_list"}); library:update_config_list()
|
config_holder = section:dropdown({name = "configs", options = {"report", "this", "error", "to", "dev"}, callback = function(option) if textbox then textbox.set(option) end end, flag = "config_name_list"}); library:update_config_list()
|
||||||
textbox = section:textbox({name = "config name:", flag = "config_name_text"})
|
textbox = section:textbox({name = "config name:", flag = "config_name_text"})
|
||||||
section:button({name = "save", callback = function() writefile(library:config_path(flags["config_name_text"]), library:get_config()) library:update_config_list() end})
|
section:button({name = "save", callback = function() writefile(library:config_path(flags["config_name_text"]), library:get_config()) library:update_config_list() end})
|
||||||
section:button({name = "load", callback = function() library:load_config(readfile(library:config_path(flags["config_name_text"]))) library:update_config_list() end})
|
section:button({name = "load", callback = function()
|
||||||
|
library:load_config(readfile(library:config_path(flags["config_name_text"])))
|
||||||
|
library:update_config_list()
|
||||||
|
|
||||||
|
-- sliders restore through set, which skips the release hook on purpose,
|
||||||
|
-- so the saved scale has to be pushed through by hand
|
||||||
|
local dpi = tonumber(flags["dpi_scale"])
|
||||||
|
if dpi then library:set_ui_scale(dpi / 100) end
|
||||||
|
end})
|
||||||
section:button({name = "delete", callback = function() delfile(library:config_path(flags["config_name_text"])) library:update_config_list() end})
|
section:button({name = "delete", callback = function() delfile(library:config_path(flags["config_name_text"])) library:update_config_list() end})
|
||||||
|
|
||||||
local section = main:column({}):section({name = "other", size = 1, default = true})
|
local section = main:column({}):section({name = "other", size = 1, default = true})
|
||||||
section:keybind({name = "menu bind", callback = function(bool) window.toggle_menu(bool) end, default = true})
|
section:keybind({name = "menu bind", callback = function(bool) window.toggle_menu(bool) end, default = true})
|
||||||
|
|
||||||
|
-- rescaling relays out every element, so it waits for release rather than
|
||||||
|
-- thrashing the whole menu on each step of the drag
|
||||||
|
section:slider({
|
||||||
|
name = "dpi scale", min = 50, max = 150, default = library.ui_scale * 100,
|
||||||
|
interval = 1, suffix = "%", flag = "dpi_scale",
|
||||||
|
released = function(value) library:set_ui_scale(value / 100) end
|
||||||
|
})
|
||||||
|
|
||||||
section:colorpicker({name = "gradient 1", callback = function(color)
|
section:colorpicker({name = "gradient 1", callback = function(color)
|
||||||
library:update_theme("1", color)
|
library:update_theme("1", color)
|
||||||
library:refresh_gradients()
|
library:refresh_gradients()
|
||||||
|
|||||||
Reference in New Issue
Block a user