mobile support
This commit is contained in:
+141
-132
@@ -80,7 +80,7 @@
|
||||
labels = {},
|
||||
label_gradients = {},
|
||||
|
||||
is_mobile = uis.TouchEnabled and not uis.KeyboardEnabled,
|
||||
is_mobile = uis.TouchEnabled,
|
||||
|
||||
colorpicker_open = false;
|
||||
gui;
|
||||
@@ -279,57 +279,78 @@
|
||||
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)
|
||||
local dragging = false
|
||||
local touch_input -- the finger driving this drag, nil while on mouse
|
||||
|
||||
local function drives(input, mouse_type)
|
||||
if touch_input then return input == touch_input end
|
||||
return input.UserInputType == mouse_type
|
||||
end
|
||||
|
||||
trigger.InputBegan:Connect(function(input)
|
||||
local kind = input.UserInputType
|
||||
if kind ~= Enum.UserInputType.MouseButton1 and kind ~= Enum.UserInputType.Touch then return end
|
||||
if dragging then return end
|
||||
|
||||
dragging = true
|
||||
touch_input = (kind == Enum.UserInputType.Touch) and input or nil
|
||||
on_begin(input)
|
||||
end)
|
||||
|
||||
library:connection(uis.InputChanged, function(input)
|
||||
if not dragging then return end
|
||||
if not drives(input, Enum.UserInputType.MouseMovement) then return end
|
||||
|
||||
on_move(input)
|
||||
end)
|
||||
|
||||
-- released anywhere, not just over the trigger, or a drag can get stuck on
|
||||
library:connection(uis.InputEnded, function(input)
|
||||
if not dragging then return end
|
||||
if not drives(input, Enum.UserInputType.MouseButton1) then return end
|
||||
|
||||
dragging = false
|
||||
touch_input = nil
|
||||
if on_end then on_end(input) end
|
||||
end)
|
||||
end
|
||||
|
||||
function library:resizify(frame)
|
||||
-- a 10px corner is unhittable with a finger
|
||||
local grip = library.is_mobile and 24 or 10
|
||||
|
||||
local Frame = Instance.new("TextButton")
|
||||
Frame.Position = dim2(1, -10, 1, -10)
|
||||
Frame.Position = dim2(1, -grip, 1, -grip)
|
||||
Frame.BorderColor3 = rgb(0, 0, 0)
|
||||
Frame.Size = dim2(0, 10, 0, 10)
|
||||
Frame.Size = dim2(0, grip, 0, grip)
|
||||
Frame.BorderSizePixel = 0
|
||||
Frame.BackgroundColor3 = rgb(255, 255, 255)
|
||||
Frame.Parent = frame
|
||||
Frame.BackgroundTransparency = 1
|
||||
Frame.Text = ""
|
||||
Frame.AutoButtonColor = false
|
||||
Frame.Active = true
|
||||
|
||||
local resizing = false
|
||||
local start_size
|
||||
local start
|
||||
local og_size = frame.Size
|
||||
|
||||
Frame.InputBegan:Connect(function(input)
|
||||
if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
||||
resizing = true
|
||||
library:pointer_drag(Frame, function(input)
|
||||
start = input.Position
|
||||
start_size = frame.Size
|
||||
end
|
||||
end)
|
||||
end, function(input)
|
||||
local delta = input.Position - start
|
||||
|
||||
Frame.InputEnded:Connect(function(input)
|
||||
if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
||||
resizing = false
|
||||
end
|
||||
end)
|
||||
|
||||
library:connection(uis.InputChanged, function(input, game_event)
|
||||
if resizing and input.UserInputType == Enum.UserInputType.MouseMovement then
|
||||
local viewport_x = camera.ViewportSize.X
|
||||
local viewport_y = camera.ViewportSize.Y
|
||||
|
||||
local current_size = dim2(
|
||||
frame.Size = dim2(
|
||||
start_size.X.Scale,
|
||||
math.clamp(
|
||||
start_size.X.Offset + (input.Position.X - start.X),
|
||||
og_size.X.Offset,
|
||||
viewport_x
|
||||
),
|
||||
clamp(start_size.X.Offset + delta.X, og_size.X.Offset, camera.ViewportSize.X),
|
||||
start_size.Y.Scale,
|
||||
math.clamp(
|
||||
start_size.Y.Offset + (input.Position.Y - start.Y),
|
||||
og_size.Y.Offset,
|
||||
viewport_y
|
||||
clamp(start_size.Y.Offset + delta.Y, og_size.Y.Offset, camera.ViewportSize.Y)
|
||||
)
|
||||
)
|
||||
frame.Size = current_size
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -340,6 +361,16 @@
|
||||
return (y_cond and x_cond)
|
||||
end
|
||||
|
||||
-- point is optional, so mouse callers keep the old behaviour and touch can pass a finger
|
||||
function library:point_in_frame(uiobject, point)
|
||||
if not point then return library:mouse_in_frame(uiobject) end
|
||||
|
||||
local pos, size = uiobject.AbsolutePosition, uiobject.AbsoluteSize
|
||||
|
||||
return point.X >= pos.X and point.X <= pos.X + size.X
|
||||
and point.Y >= pos.Y and point.Y <= pos.Y + size.Y
|
||||
end
|
||||
|
||||
library.lerp = function(start, finish, t)
|
||||
t = t or 1 / 8
|
||||
|
||||
@@ -347,49 +378,25 @@
|
||||
end
|
||||
|
||||
function library:draggify(frame)
|
||||
local dragging = false
|
||||
local start_size = frame.Position
|
||||
local start
|
||||
|
||||
frame.InputBegan:Connect(function(input)
|
||||
if input.UserInputType == Enum.UserInputType.MouseButton1
|
||||
or input.UserInputType == Enum.UserInputType.Touch then
|
||||
dragging = true
|
||||
-- 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
|
||||
|
||||
library:pointer_drag(frame, function(input)
|
||||
start = input.Position
|
||||
start_size = frame.Position
|
||||
end
|
||||
end)
|
||||
end, function(input)
|
||||
local delta = input.Position - start
|
||||
-- measured size, so AutomaticSize frames clamp against their real width
|
||||
local size = frame.AbsoluteSize
|
||||
|
||||
frame.InputEnded:Connect(function(input)
|
||||
if input.UserInputType == Enum.UserInputType.MouseButton1
|
||||
or input.UserInputType == Enum.UserInputType.Touch then
|
||||
dragging = false
|
||||
end
|
||||
end)
|
||||
|
||||
library:connection(uis.InputChanged, function(input, game_event)
|
||||
if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement
|
||||
or input.UserInputType == Enum.UserInputType.Touch) then
|
||||
local viewport_x = camera.ViewportSize.X
|
||||
local viewport_y = camera.ViewportSize.Y
|
||||
|
||||
local current_position = dim2(
|
||||
0,
|
||||
clamp(
|
||||
start_size.X.Offset + (input.Position.X - start.X),
|
||||
0,
|
||||
viewport_x - frame.Size.X.Offset
|
||||
),
|
||||
0,
|
||||
math.clamp(
|
||||
start_size.Y.Offset + (input.Position.Y - start.Y),
|
||||
0,
|
||||
viewport_y - frame.Size.Y.Offset
|
||||
frame.Position = dim2(
|
||||
0, clamp(start_size.X.Offset + delta.X, 0, camera.ViewportSize.X - size.X),
|
||||
0, clamp(start_size.Y.Offset + delta.Y, 0, camera.ViewportSize.Y - size.Y)
|
||||
)
|
||||
)
|
||||
|
||||
frame.Position = current_position
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -1019,6 +1026,7 @@
|
||||
Text = "";
|
||||
AutoButtonColor = false;
|
||||
BorderSizePixel = 0;
|
||||
Active = true;
|
||||
ZIndex = 5
|
||||
});
|
||||
--
|
||||
@@ -1053,24 +1061,16 @@
|
||||
state.callback = value
|
||||
end
|
||||
|
||||
-- drag, with a tap fallback -- a touch that barely moves is a click, not a drag
|
||||
local dragging, drag_start, drag_origin, travelled = false, nil, nil, 0
|
||||
-- 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 tap_slop = library.is_mobile and 12 or 6
|
||||
|
||||
hitbox.InputBegan:Connect(function(input)
|
||||
if input.UserInputType ~= Enum.UserInputType.MouseButton1
|
||||
and input.UserInputType ~= Enum.UserInputType.Touch then return end
|
||||
|
||||
dragging = true
|
||||
library:pointer_drag(hitbox, function(input)
|
||||
travelled = 0
|
||||
drag_start = input.Position
|
||||
drag_origin = outline.Position
|
||||
end)
|
||||
|
||||
library:connection(uis.InputChanged, function(input)
|
||||
if not dragging then return end
|
||||
if input.UserInputType ~= Enum.UserInputType.MouseMovement
|
||||
and input.UserInputType ~= Enum.UserInputType.Touch then return end
|
||||
|
||||
end, function(input)
|
||||
local delta = input.Position - drag_start
|
||||
travelled = max(travelled, abs(delta.X) + abs(delta.Y))
|
||||
|
||||
@@ -1079,16 +1079,8 @@
|
||||
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)
|
||||
))
|
||||
end)
|
||||
|
||||
library:connection(uis.InputEnded, function(input)
|
||||
if not dragging then return end
|
||||
if input.UserInputType ~= Enum.UserInputType.MouseButton1
|
||||
and input.UserInputType ~= Enum.UserInputType.Touch then return end
|
||||
|
||||
dragging = false
|
||||
|
||||
if travelled <= 6 and state.callback then
|
||||
end, function()
|
||||
if travelled <= tap_slop and state.callback then
|
||||
state.callback(proxy)
|
||||
end
|
||||
end)
|
||||
@@ -1674,23 +1666,18 @@
|
||||
--
|
||||
|
||||
-- Connections
|
||||
outline.MouseButton1Down:Connect(function()
|
||||
cfg.dragging = true
|
||||
end)
|
||||
|
||||
library:connection(uis.InputChanged, function(input)
|
||||
if cfg.dragging and input.UserInputType == Enum.UserInputType.MouseMovement then
|
||||
local function slide_to(input)
|
||||
local size_x = (input.Position.X - inline.AbsolutePosition.X) / inline.AbsoluteSize.X
|
||||
local value = ((cfg.max - cfg.min) * size_x) + cfg.min
|
||||
|
||||
cfg.set(value)
|
||||
cfg.set(((cfg.max - cfg.min) * size_x) + cfg.min)
|
||||
end
|
||||
end)
|
||||
|
||||
library:connection(uis.InputEnded, function(input)
|
||||
if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
||||
-- setting on press as well as on move, since a tap has nowhere to move to
|
||||
library:pointer_drag(outline, function(input)
|
||||
cfg.dragging = true
|
||||
slide_to(input)
|
||||
end, slide_to, function()
|
||||
cfg.dragging = false
|
||||
end
|
||||
end)
|
||||
--
|
||||
|
||||
@@ -1929,13 +1916,17 @@
|
||||
cfg.set_visible(cfg.open)
|
||||
end)
|
||||
|
||||
uis.InputEnded:Connect(function(input)
|
||||
if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
||||
if not (library:mouse_in_frame(accent) or library:mouse_in_frame(dropdown)) then
|
||||
library:connection(uis.InputEnded, function(input)
|
||||
local kind = input.UserInputType
|
||||
if kind ~= Enum.UserInputType.MouseButton1 and kind ~= Enum.UserInputType.Touch then return end
|
||||
|
||||
local at = (kind == Enum.UserInputType.Touch)
|
||||
and vec2(input.Position.X, input.Position.Y) or nil
|
||||
|
||||
if not (library:point_in_frame(accent, at) or library:point_in_frame(dropdown, at)) then
|
||||
cfg.open = false
|
||||
cfg.set_visible(false)
|
||||
end
|
||||
end
|
||||
end)
|
||||
--
|
||||
|
||||
@@ -2273,9 +2264,15 @@
|
||||
cfg.callback(Color, a)
|
||||
end
|
||||
|
||||
function cfg.update_color()
|
||||
-- position is only supplied for touch, where there is no mouse to query.
|
||||
-- it arrives already in AbsolutePosition space, same as the slider uses
|
||||
function cfg.update_color(position)
|
||||
local offset = position
|
||||
|
||||
if not offset then
|
||||
local mouse = uis:GetMouseLocation()
|
||||
local offset = vec2(mouse.X, mouse.Y - gui_offset)
|
||||
offset = vec2(mouse.X, mouse.Y - gui_offset)
|
||||
end
|
||||
|
||||
if dragging_sat then
|
||||
s = math.clamp((offset - saturation_value_button.AbsolutePosition).X / saturation_value_button.AbsoluteSize.X, 0, 1)
|
||||
@@ -2301,36 +2298,43 @@
|
||||
cfg.set_visible(cfg.open)
|
||||
end)
|
||||
|
||||
uis.InputChanged:Connect(function(input)
|
||||
if (dragging_sat or dragging_hue or dragging_alpha) and input.UserInputType == Enum.UserInputType.MouseMovement then
|
||||
cfg.update_color()
|
||||
-- mouse keeps querying GetMouseLocation, a finger has to report itself
|
||||
local function pointer_at(input)
|
||||
if input.UserInputType == Enum.UserInputType.Touch then
|
||||
return vec2(input.Position.X, input.Position.Y)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function handle(button, set_dragging)
|
||||
library:pointer_drag(button, function(input)
|
||||
set_dragging(true)
|
||||
cfg.update_color(pointer_at(input))
|
||||
end, function(input)
|
||||
cfg.update_color(pointer_at(input))
|
||||
end, function()
|
||||
set_dragging(false)
|
||||
end)
|
||||
end
|
||||
|
||||
handle(saturation_button, function(v) dragging_sat = v end)
|
||||
handle(hue_button, function(v) dragging_hue = v end)
|
||||
handle(alpha_button, function(v) dragging_alpha = v end)
|
||||
|
||||
library:connection(uis.InputEnded, function(input)
|
||||
if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
||||
local kind = input.UserInputType
|
||||
if kind ~= Enum.UserInputType.MouseButton1 and kind ~= Enum.UserInputType.Touch then return end
|
||||
|
||||
dragging_sat = false
|
||||
dragging_hue = false
|
||||
dragging_alpha = false
|
||||
|
||||
if not (library:mouse_in_frame(colorpicker_element) or library:mouse_in_frame(colorpicker)) then
|
||||
local at = pointer_at(input)
|
||||
|
||||
if not (library:point_in_frame(colorpicker_element, at) or library:point_in_frame(colorpicker, at)) then
|
||||
cfg.open = false
|
||||
cfg.set_visible(false)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
alpha_button.MouseButton1Down:Connect(function()
|
||||
dragging_alpha = true
|
||||
end)
|
||||
|
||||
hue_button.MouseButton1Down:Connect(function()
|
||||
dragging_hue = true
|
||||
end)
|
||||
|
||||
saturation_button.MouseButton1Down:Connect(function()
|
||||
print("hiu")
|
||||
dragging_sat = true
|
||||
end)
|
||||
|
||||
textbox.FocusLost:Connect(function()
|
||||
@@ -2706,8 +2710,13 @@
|
||||
end
|
||||
end
|
||||
|
||||
if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
||||
if not (library:mouse_in_frame(keybind_holder) or library:mouse_in_frame(accent)) then
|
||||
local kind = input.UserInputType
|
||||
|
||||
if kind == Enum.UserInputType.MouseButton1 or kind == Enum.UserInputType.Touch then
|
||||
local at = (kind == Enum.UserInputType.Touch)
|
||||
and vec2(input.Position.X, input.Position.Y) or nil
|
||||
|
||||
if not (library:point_in_frame(keybind_holder, at) or library:point_in_frame(accent, at)) then
|
||||
cfg.open = false
|
||||
cfg.set_visible(false)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user