Final update for touch configuration scene

This commit is contained in:
Squishy (C6H12O6+NaCl+H2O)
2024-05-23 23:44:25 +07:00
parent ffe1bf5049
commit b14fe9c86c
5 changed files with 262 additions and 80 deletions

View File

@@ -46,7 +46,7 @@ control_type.button.__index=control_type.button
function control_type.button:new(data)
local data=data or {}
return setmetatable({
show=data.show or true,
show=data.show~=nil and data.show or true,
x=data.x or 320,
y=data.y or 240,
r=data.r or 80, -- size
@@ -137,7 +137,6 @@ local global_toggle=false
VCTRL={}
VCTRL.focus=nil -- Focusing buttons
---@type table
---@class VCTRL.data
---@field type 'button'
---@field x number
@@ -148,14 +147,10 @@ VCTRL.focus=nil -- Focusing buttons
---@field alpha? number
---@field show? boolean
---@param ... VCTRL.data
---@param ... VCTRL.data[]
---Adding (multiple) virtual button(s)
function VCTRL.new(...)
for _,d in pairs(...) do
local t=d.type
d.type=nil
table.insert(VCTRL,control_type[t]:new(d))
end
for _,d in pairs(...) do table.insert(VCTRL,control_type[d.type]:new(d)) end
end
---@param toggle boolean|false
@@ -180,11 +175,12 @@ function VCTRL.clearAll()
collectgarbage()
end
function VCTRL.press(x,y,id)
---@param force? boolean Forcing click on hidden widgets?
function VCTRL.press(x,y,id,force)
if not global_toggle then return end
local obj,closestDist=false,1e99
for _, w in ipairs(VCTRL) do
if w.show then
if w.show or force then
local d=w:getDistance(x,y)
if d<=1 and d<closestDist then
obj,closestDist=w,d
@@ -212,6 +208,7 @@ function VCTRL.drag(dx,dy,id)
if not global_toggle then return end
if touches[id] then
touches[id]:drag(dx,dy)
return true
end
end

View File

@@ -62,6 +62,7 @@ local button = {
codeWhenPressed = NULL,
codeWhenReleased = NULL,
update = NULL,
_hovering = false,
_pressed = false,
@@ -121,24 +122,33 @@ function button:press(x, y, touchID)
self._touchID = touchID
self._pressed = true
return true
end
end
---Trigger release action, don't need ``self._hovering`` to ``true``
function button:release(x, y, touchID)
local valid = true
if touchID then valid = touchID == self._touchID end
if touchID then
valid = touchID == self._touchID
elseif x and y then
valid = true
end
if valid then
self.codeWhenReleased()
self._pressed = false
self._touchID = false
if touchID then
self._hovering = false
else
self._hovering = self:isHovering(x, y)
end
if self:isHovering(x, y) then
self.codeWhenReleased()
return true
end
end
end
@@ -243,6 +253,11 @@ end
function BUTTON.draw(list)
for _, v in pairs(list) do v:draw() end
end
---Update all buttons in provided list
---@param list table<any,BUTTON.button>
function BUTTON.update(list)
for _, v in pairs(list) do v:update() end
end
---Check if current mouse position is inside button<br>
---Calling BUTTON.press will trigger this, but you can call it when moving mouse so button can be highlighted when being hovered
@@ -258,13 +273,13 @@ end
---@param x number # Mouse position
---@param y number # Mouse position
function BUTTON.press(list, x, y, touchID)
for _, v in pairs(list) do v:press(x, y, touchID) end
for _, v in pairs(list) do if v:press(x, y, touchID) then return true end end
end
---Trigger the release action
---@param list table<BUTTON.button>
function BUTTON.release(list, x, y, touchID)
for _, v in pairs(list) do v:release(x, y, touchID) end
for _, v in pairs(list) do if v:release(x, y, touchID) then return true end end
end
return BUTTON

View File

@@ -32,9 +32,9 @@ BUTTON.setDefaultOption{
do
local _, t
if need_big_font then
_, t = FONT_big:getWrap(text, self.w * 2)
_, t = FONT_big:getWrap(text, (self.w - 10) * 2)
else
_, t = FONT_tromi:getWrap(text, self.w * 2)
_, t = FONT_tromi:getWrap(text, (self.w - 10) * 2)
end
lineAmount = #t
end
@@ -45,17 +45,18 @@ BUTTON.setDefaultOption{
local textPos = self.y + (self.h * 0.5) - textHeight
if need_big_font then
drawBigText(text, self.x, textPos, self.w, 'center')
drawBigText(text, self.x + 5, textPos, self.w - 10, self.textOrientation, self.textColor)
else
drawText(text, self.x, textPos, self.w, 'center')
drawText(text, self.x + 5, textPos, self.w - 10, self.textOrientation, self.textColor)
end
love.graphics.setColor(1, 1, 1, 0.8)
love.graphics.setColor(self.borderColor)
love.graphics.setLineWidth(1)
love.graphics.rectangle('line', self.x, self.y, self.w, self.h, self.r)
end,
backgroundColor = {0, 0, 0, 0.8},
pressColor = {0.4, 1, 1, 0.5}
pressColor = {0.4, 1, 1, 0.5},
borderColor = {1, 1, 1, 0.8},
}
-- Graphics

View File

@@ -35,6 +35,21 @@ function love.load()
math.randomseed(os.time())
require "settings"
if SETTINGS.input.virtual == nil then
SETTINGS.input.virtual = {
{type='button',x= 70,y=280,key= 'up',r=45,iconSize=60,alpha=0.4},
{type='button',x= 70,y=430,key= 'down',r=45,iconSize=60,alpha=0.4},
{type='button',x= -5,y=355,key= 'left',r=45,iconSize=60,alpha=0.4},
{type='button',x= 145,y=355,key= 'right',r=45,iconSize=60,alpha=0.4},
{type='button',x=640- -5,y=355,key= 'rotate_left',r=45,iconSize=60,alpha=0.4},
{type='button',x=640-145,y=355,key= 'rotate_left2',r=45,iconSize=60,alpha=0.4},
{type='button',x=640- 70,y=430,key= 'rotate_right',r=45,iconSize=60,alpha=0.4},
{type='button',x=640- 70,y=280,key='rotate_right2',r=45,iconSize=60,alpha=0.4},
{type='button',x=320- 40,y=420,key= 'menu_decide',r=35,iconSize=60,alpha=0.4},
{type='button',x=320+ 40,y=420,key= 'menu_back',r=35,iconSize=60,alpha=0.4},
}
end
-- Window stuffs
love.window.setMode(love.graphics.getWidth(), love.graphics.getHeight(), {resizable = true});
love.window.setFullscreen(SETTINGS["fullscreen"])
@@ -45,8 +60,8 @@ function love.load()
-- Now it's real time to load all stuffs!
require "load" -- Most game's resources are loaded in here
require "scene"
require "game.vctrl" -- VCTRL
require "scene"
function SCENE.update()
SCENE = SETTINGS.firstTime and InputConfigScene(true) or TitleScene()
@@ -78,8 +93,9 @@ function love.load()
}
end
local scale_factor
function love.resize(w, h)
local scale_factor = math.min(w / 640, h / 480)
scale_factor = math.min(w / 640, h / 480)
GLOBAL_TRANSFORM:setTransformation(
(w - scale_factor * 640) / 2,
(h - scale_factor * 480) / 2,
@@ -123,16 +139,17 @@ end
function love.mousepressed(x, y, b, isTouch, presses)
if isTouch then return end
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
SCENE:onInputPress{type = "mouse", x = x, y = y, button = b, presses = presses}
SCENE:onInputPress{type = "mouse", x = x, y = y, id = b, presses = presses}
end
function love.mousereleased(x, y, b, isTouch, presses)
if isTouch then return end
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
SCENE:onInputRelease{type = "mouse", x = x, y = y, button = b, presses = presses}
SCENE:onInputRelease{type = "mouse", x = x, y = y, id = b, presses = presses}
end
function love.mousemoved(x, y, dx, dy)
function love.mousemoved(x, y, dx, dy, isTouch)
if isTouch then return end
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
local dx,dy=GLOBAL_TRANSFORM:inverseTransformPoint(dx,dy)
local dx,dy=dx/scale_factor,dy/scale_factor
SCENE:onInputMove{type = "mouse", x = x, y = y, dx = dx, dy = dy}
end
function love.wheelmoved(dx, dy)
@@ -141,7 +158,7 @@ end
function love.touchpressed(id,x,y)
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
SCENE:onInputPress{type = "touch", x = x, y = y, dx = 0, dy = 0, id = id}
SCENE:onInputPress{type = "touch", x = x, y = y, dx = 0, dy = 0, id = id}
end
function love.touchdragged(id,x,y,dx,dy)
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
@@ -161,7 +178,7 @@ function love.keypressed(key, scancode)
love.window.setFullscreen(SETTINGS["fullscreen"])
elseif scancode == "f2" and SCENE.title ~= "Input Config" and SCENE.title ~= "Game" then
SCENE = InputConfigScene()
elseif scancode == "f12" then REQUEST_BREAK()
elseif scancode == "f12" then LLDEBUGGER.requestBreak()
-- function keys are reserved
elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f1[0-2]+$") then
return

View File

@@ -1,5 +1,6 @@
---@diagnostic disable: cast-local-type
local TouchConfigScene = SCENE:extend()
TouchConfigScene.title = "Touchscreen config\n(you can tap anywhere on touch screen to select this)"
TouchConfigScene.title = "Touchscreen config"
--[[
TODO:
@@ -7,90 +8,241 @@ TouchConfigScene.title = "Touchscreen config\n(you can tap anywhere on touch scr
2. Add behaviors
]]
local buttonList
local sliderList
---@class VCTRL.data
local focusingButton
local selectingButton
---@type boolean
local previewMode
---@type boolean
local isSelectingButton
---@type number
local gridSize = 1
local buttonList = {
select_button = BUTTON.new{
text = "Select key\n[Rotate right 2]",
x = 10, y = 10, w = 120, h = 110
},
---@type function
local exitSceneFunc = function()
VCTRL.release()
BUTTON.release(buttonList)
SCENE = TitleScene()
end
zoom_negat = BUTTON.new{
text = "[—]\nSmaller",
x = 145, y = 10, w = 100, h = 50,
buttonList = {
showToggle = BUTTON.new{
text = function()
if focusingButton then
return string.format("Show / Hide\n[%s]", focusingButton.show and "Show" or "Hide")
else
return "Show / Hide\n[----]"
end
end,
x = 240, y = 5, w = 90, h = 50,
codeWhenReleased = function ()
if focusingButton then focusingButton.show = not focusingButton.show end
end,
update = function(self) self.textColor = focusingButton and {1, 1, 1} or {0.5, 0.5, 0.5} end
},
zoom_reset = BUTTON.new{
text = "Size: 50\nTap to reset",
x = 255, y = 10, w = 100, h = 50,
},
zoom_posit = BUTTON.new{
text = "[+]\nBigger",
x = 365, y = 10, w = 100, h = 50,
previewToggle = BUTTON.new{
text = function ()
return string.format("Preview\n[%s]", previewMode and "On" or "Off")
end,
x = 520, y = 5, w = 60, h = 50,
codeWhenReleased = function() previewMode = not previewMode end
},
menuScreen = BUTTON.new{
text = "MENU",
x = 585, y = 5, w = 50, h = 50,
codeWhenReleased = function()
local selection = love.window.showMessageBox(
"Save config?",
"Are you sure you want to save your changes?",
{
"Save", "Discard", "Cont. editing",
escapebutton = 2, enterbutton = 1
},
"info",
true
)
if selection == 1 then
SETTINGS.input.virtual = VCTRL.exportAll()
love.window.showMessageBox("Saved!", "Your changes was saved!")
exitSceneFunc()
elseif selection == 2 then
VCTRL.clearAll()
VCTRL.new(SETTINGS.input.virtual)
love.window.showMessageBox("Discarded!", "Your changes was discarded!")
opact_negat = BUTTON.new{
text = "[—]\nCan't see",
x = 145, y = 70, w = 100, h = 50,
},
opact_reset = BUTTON.new{
text = "Opacity: 50%\nTap to reset",
x = 255, y = 70, w = 100, h = 50,
codeWhenReleased = function() PlaySE("autopromote") end
},
opact_posit = BUTTON.new{
text = "[+]\nTotally see",
x = 365, y = 70, w = 100, h = 50,
},
menu_back = BUTTON.new{
text = "SAVE and\nback to MENU",
x = 480, y = 10, w = 150, h = 50,
codeWhenReleased = function() SCENE = TitleScene() end
},
BUTTON.new{
text = "DISCARD\nchanges",
x = 480, y = 70, w = 70, h = 50,
},
BUTTON.new{
text = "RESET to\nDEFAULT",
x = 560, y = 70, w = 70, h = 50,
},
exitSceneFunc()
end
end
}
}
sliderList = {}
sliderList.opacity = newSlider(
130, 20-1, 100, 100, 0, 100,
function()
local v
if focusingButton then
v = math.roundUnit(sliderList.opacity.value, 0.01)
focusingButton.alpha = v
sliderList.opacity.value = v
end
end,
{width = 10, knob = 'circle', track = 'roundrect'}
)
sliderList.size = newSlider(
130, 40-1, 100, 45, 0, 120,
function(v)
if focusingButton then
local v = math.roundUnit(v, 5)
focusingButton.r = v
sliderList.size.value = v / 120
end
end,
{width = 10, knob = 'circle', track = 'roundrect'}
)
local gridSizeTable = {1, 2, 5, 10, 20, 50, 100}
sliderList.gridSize = newSlider(
400, 40-1, 100, 1, 1, #gridSizeTable - 1,
function()
local v = math.roundUnit(sliderList.gridSize.value, 1 / 6)
sliderList.gridSize.value = v
gridSize = gridSizeTable[math.roundUnit(v * (#gridSizeTable - 1) + 1, 1)]
end,
{width = 10, knob = 'circle', track = 'roundrect'}
); sliderList.gridSize.forceLight = true
local function sliderList_draw()
for _, s in pairs(sliderList) do
if s.forceLight then
love.graphics.setColor(1, 1, 1)
else
love.graphics.setColor(focusingButton and {1, 1, 1} or {0.5, 0.5, 0.5})
end
love.graphics.setLineWidth(1)
s:draw()
end
end
local function sliderList_update()
local x, y = GLOBAL_TRANSFORM:inverseTransformPoint(love.mouse.getPosition())
for _, s in pairs(sliderList) do
s:update(x, y)
end
end
function TouchConfigScene:new()
VCTRL.toggle(true)
focusingButton = false
selectingButton = nil
VCTRL.focus = nil
focusingButton = nil
previewMode = false
-- TODO
end
function TouchConfigScene:update()
-- TODO
if VCTRL.focus~=focusingButton then
focusingButton = VCTRL.focus
sliderList.opacity.value = focusingButton.alpha
sliderList.size.value = focusingButton.r / 120
end
BUTTON.update(buttonList)
sliderList_update()
end
function TouchConfigScene:render()
MainBackground()
if gridSize >= 10 then
love.graphics.setColor(1,1,1,0.5)
love.graphics.setLineWidth(1)
-- From 0 to X
for ix=0,math.floor(640 / gridSize) do
love.graphics.line(gridSize * ix, 0 , gridSize * ix, 480)
end
-- From 0 to Y
for iy=0,math.floor(480 / gridSize) do
love.graphics.line(0, gridSize * iy, 640, gridSize * iy)
end
end
love.graphics.setColor(0, 0, 0, 0.7)
-- Opacity and Size
love.graphics.rectangle("fill", 10, 5, 227, 50)
-- Snap to grid
love.graphics.rectangle("fill", 335, 5, 130, 50)
-- Opacity
drawText("Opacity", 20, 10, 100, "left")
drawText(string.format("%3.1d%%", focusingButton and focusingButton.alpha * 100 or 0), 190, 10, 40, "left")
-- Size
drawText("Size", 20, 30, 100, "left")
drawText(string.format("%3.1dpx", focusingButton and focusingButton.r or 0), 190, 30, 40, "left")
-- Snap to grid
drawText(string.format("Snap to grid: %3s", gridSize), 340, 10, 140, "left")
if previewMode then
VCTRL.draw()
else
for _, v in ipairs(VCTRL) do
if v ~= focusingButton then
v:draw(
focusingButton and
(v.show and 0.5 or 0.1) or
(v.show and 0.5 or 0.25)
)
end
end
if focusingButton then
focusingButton:draw(
math.clamp(
math.abs(math.sin(love.timer.getTime()*4)),
focusingButton.show and 0.5 or 0.1, 1
)
)
end
end
sliderList_draw()
BUTTON.draw(buttonList)
drawBigText(buttonList.opact_reset._pressed and "okay" or "not", 400, 400, 100, "left")
end
---@param e SCENE_onInput
function TouchConfigScene:onInputMove(e)
if e.type == "mouse" or e.type == "touch" then
if love.mouse.isDown(1) then
VCTRL.drag(e.dx, e.dy, e.id or 1)
end
end
if e.type == "mouse" then
BUTTON.checkHovering(buttonList, e.x, e.y)
end
end
---@param e SCENE_onInput
function TouchConfigScene:onInputPress(e)
if e.input == 'menu_back' then SCENE = InputConfigScene() end
if e.type ~= "virtual" and e.input == 'menu_back' then SCENE = InputConfigScene() end
if e.type == "mouse" or e.type == "touch" then
BUTTON.press(buttonList, e.x, e.y, e.type == "touch")
if not (
VCTRL.press(e.x, e.y, e.id and e.id or 1, true) or
BUTTON.press(buttonList, e.x, e.y, e.id) or
(e.x >= 75 and e.x <= 185 and e.y >= 12 and e.y <= 44)
) then
VCTRL.focus = nil
focusingButton = nil
end
end
end
---@param e SCENE_onInput
function TouchConfigScene:onInputRelease(e)
if e.type == "mouse" or e.type == "touch" then
BUTTON.release(buttonList, e.x, e.y, e.type == "touch")
if not BUTTON.release(buttonList, e.x, e.y, e.id) then
if focusingButton and VCTRL.release(e.id) then
love.window.showMessageBox("Okay","")
focusingButton.x = math.roundUnit(focusingButton.x, gridSize)
focusingButton.y = math.roundUnit(focusingButton.y, gridSize)
end
end
end
end