Merge branch 'main' of https://github.com/26F-Studio/Techmino into mod-patch
This commit is contained in:
103
Zframework/clipboard.lua
Normal file
103
Zframework/clipboard.lua
Normal file
@@ -0,0 +1,103 @@
|
||||
local function _sanitize(content)
|
||||
if type(content)=='boolean' then
|
||||
content=content and 'true' or 'false'
|
||||
end
|
||||
if type(content)=='nil' then
|
||||
content=''
|
||||
end
|
||||
if type(content)=='number' then
|
||||
content=tostring(content)
|
||||
end
|
||||
if type(content)~='string' then
|
||||
MES.new('error',"Invalid content type!")
|
||||
MES.traceback()
|
||||
return ''
|
||||
end
|
||||
return content
|
||||
end
|
||||
|
||||
if SYSTEM~='Web' then
|
||||
local get=love.system.getClipboardText
|
||||
local set=love.system.setClipboardText
|
||||
return {
|
||||
get=function() return get() or '' end,
|
||||
set=function(content) set(_sanitize(content)) end,
|
||||
setFreshInterval=NULL,
|
||||
_update=NULL,
|
||||
}
|
||||
end
|
||||
|
||||
if WEB_COMPAT_MODE then
|
||||
local _clipboardBuffer=''
|
||||
return {
|
||||
get=function()
|
||||
JS.newPromiseRequest(
|
||||
JS.stringFunc(
|
||||
[[
|
||||
window.navigator.clipboard
|
||||
.readText()
|
||||
.then((text) => _$_(text))
|
||||
.catch((e) => {
|
||||
console.warn(e);
|
||||
_$_('');
|
||||
});
|
||||
]]
|
||||
),
|
||||
function(data) _clipboardBuffer=data end,
|
||||
function() _clipboardBuffer='' end,
|
||||
3,
|
||||
'getClipboardText'
|
||||
)
|
||||
if TASK.lock('clipboard_compat_interval',2.6) then
|
||||
_clipboardBuffer=''
|
||||
MES.new('warn',"Web-Compat mode, paste again to confirm",2.6)
|
||||
end
|
||||
return _clipboardBuffer
|
||||
end,
|
||||
set=function(str)
|
||||
JS.callJS(JS.stringFunc(
|
||||
[[
|
||||
window.navigator.clipboard
|
||||
.writeText('%s')
|
||||
.then(() => console.log('Copied to clipboard'))
|
||||
.catch((e) => console.warn(e));
|
||||
]],
|
||||
_sanitize(str)
|
||||
))
|
||||
end,
|
||||
setFreshInterval=NULL,
|
||||
_update=NULL,
|
||||
}
|
||||
end
|
||||
|
||||
local getCHN=love.thread.getChannel('CLIP_get')
|
||||
local setCHN=love.thread.getChannel('CLIP_set')
|
||||
local trigCHN=love.thread.getChannel('CLIP_trig')
|
||||
|
||||
local clipboard_thread=love.thread.newThread('Zframework/clipboard_thread.lua')
|
||||
local isStarted,errorMessage=clipboard_thread:start()
|
||||
|
||||
if not isStarted then
|
||||
MES.new("error",errorMessage,26)
|
||||
end
|
||||
|
||||
local freshInterval=1
|
||||
local timer=-.626
|
||||
return {
|
||||
get=function() return getCHN:peek() or '' end,
|
||||
set=function(content) setCHN:push(_sanitize(content)) end,
|
||||
setFreshInterval=function(val)
|
||||
freshInterval=val
|
||||
end,
|
||||
_update=function(dt)
|
||||
timer=timer+dt
|
||||
if timer>freshInterval then
|
||||
if isStarted and not clipboard_thread:isRunning() then
|
||||
MES.new("warn",clipboard_thread:getError(),26)
|
||||
isStarted=false
|
||||
end
|
||||
trigCHN:push(timer)
|
||||
timer=0
|
||||
end
|
||||
end,
|
||||
}
|
||||
48
Zframework/clipboard_thread.lua
Normal file
48
Zframework/clipboard_thread.lua
Normal file
@@ -0,0 +1,48 @@
|
||||
local getCHN=love.thread.getChannel('CLIP_get')
|
||||
local setCHN=love.thread.getChannel('CLIP_set')
|
||||
local trigCHN=love.thread.getChannel('CLIP_trig')
|
||||
|
||||
JS=require'Zframework.js'
|
||||
local sleep=require'love.timer'.sleep
|
||||
|
||||
local retrieving=false
|
||||
while true do
|
||||
if trigCHN:getCount()>0 then
|
||||
local dt=trigCHN:pop()
|
||||
if setCHN:getCount()>0 then
|
||||
while setCHN:getCount()>1 do setCHN:pop() end
|
||||
-- Set Clipboard
|
||||
JS.callJS(JS.stringFunc(
|
||||
[[
|
||||
window.navigator.clipboard
|
||||
.writeText('%s')
|
||||
.then(() => console.log('Copied to clipboard'))
|
||||
.catch((e) => console.warn(e));
|
||||
]],
|
||||
setCHN:pop()
|
||||
))
|
||||
end
|
||||
-- Get Clipboard
|
||||
if not retrieving then
|
||||
JS.newPromiseRequest(
|
||||
JS.stringFunc[[
|
||||
window.navigator.clipboard
|
||||
.readText()
|
||||
.then((text) => _$_(text))
|
||||
.catch((e)=>{});
|
||||
]],
|
||||
function(data)
|
||||
while getCHN:getCount()>0 do getCHN:pop() end
|
||||
getCHN:push(data)
|
||||
retrieving=false
|
||||
end,
|
||||
function() retrieving=false end,
|
||||
1,
|
||||
'getClipboardText'
|
||||
)
|
||||
retrieving=true
|
||||
end
|
||||
JS.retrieveData(dt)
|
||||
end
|
||||
sleep(.001)
|
||||
end
|
||||
@@ -1,5 +1,5 @@
|
||||
local sendCHN=love.thread.getChannel('inputChannel')
|
||||
local recvCHN=love.thread.getChannel('outputChannel')
|
||||
local sendCHN=love.thread.getChannel('HTTP_inputChannel')
|
||||
local recvCHN=love.thread.getChannel('HTTP_outputChannel')
|
||||
|
||||
local threads={}
|
||||
local threadCount=0
|
||||
@@ -9,11 +9,15 @@ local threadCode=[[
|
||||
local http=require'socket.http'
|
||||
local ltn12=require'ltn12'
|
||||
|
||||
local sendCHN=love.thread.getChannel('inputChannel')
|
||||
local recvCHN=love.thread.getChannel('outputChannel')
|
||||
local sendCHN=love.thread.getChannel('HTTP_inputChannel')
|
||||
local recvCHN=love.thread.getChannel('HTTP_outputChannel')
|
||||
local sleep=require'love.timer'.sleep
|
||||
|
||||
while true do
|
||||
local arg=sendCHN:demand()
|
||||
-- local arg=sendCHN:demand()
|
||||
-- Warning: workaround for love.js
|
||||
while sendCHN:getCount()==0 do sleep(.0626) end
|
||||
local arg=sendCHN:pop()
|
||||
|
||||
if arg._destroy then
|
||||
recvCHN:push{
|
||||
|
||||
@@ -3,8 +3,16 @@
|
||||
NONE={}function NULL() end PAPER=love.graphics.newCanvas(1,1)
|
||||
EDITING=""
|
||||
LOADED=false
|
||||
|
||||
---@type 'Windows'|'Android'|'Linux'|'iOS'|'macOS'|'Web'
|
||||
SYSTEM=love.system.getOS()
|
||||
if SYSTEM=='OS X' then SYSTEM='macOS' end
|
||||
WEB_COMPAT_MODE=false
|
||||
if SYSTEM=='OS X' then
|
||||
SYSTEM='macOS'
|
||||
elseif SYSTEM=='Web' then
|
||||
WEB_COMPAT_MODE=not love.thread.newThread('\n'):start()
|
||||
print('Web compatible mode: ', WEB_COMPAT_MODE)
|
||||
end
|
||||
|
||||
-- Bit module
|
||||
local success
|
||||
@@ -72,6 +80,7 @@ do
|
||||
end
|
||||
|
||||
-- Love-based modules (basic)
|
||||
CLIPBOARD= require'Zframework.clipboard'
|
||||
HTTP= require'Zframework.http'
|
||||
WS= require'Zframework.websocket'
|
||||
FILE= require'Zframework.file'
|
||||
@@ -94,6 +103,10 @@ IMG= require'Zframework.image'
|
||||
BGM= require'Zframework.bgm'
|
||||
VOC= require'Zframework.voice'
|
||||
|
||||
if SYSTEM=='Web' then
|
||||
JS=require'Zframework.js'
|
||||
end
|
||||
|
||||
local ms,kb=love.mouse,love.keyboard
|
||||
local KBisDown=kb.isDown
|
||||
|
||||
@@ -174,6 +187,7 @@ local function updatePowerInfo()
|
||||
gc_pop()
|
||||
gc.setCanvas()
|
||||
end
|
||||
|
||||
-------------------------------------------------------------
|
||||
local lastX,lastY=0,0-- Last click pos
|
||||
local function _updateMousePos(x,y,dx,dy)
|
||||
@@ -423,38 +437,38 @@ local dPadToKey={
|
||||
start='return',
|
||||
back='escape',
|
||||
}
|
||||
function love.joystickadded(JS)
|
||||
function love.joystickadded(joystick)
|
||||
table.insert(jsState,{
|
||||
_id=JS:getID(),
|
||||
_jsObj=JS,
|
||||
_id=joystick:getID(),
|
||||
_jsObj=joystick,
|
||||
leftx=0,lefty=0,
|
||||
rightx=0,righty=0,
|
||||
triggerleft=0,triggerright=0
|
||||
})
|
||||
MES.new('info',"Joystick added")
|
||||
end
|
||||
function love.joystickremoved(JS)
|
||||
function love.joystickremoved(joystick)
|
||||
for i=1,#jsState do
|
||||
if jsState[i]._jsObj==JS then
|
||||
if jsState[i]._jsObj==joystick then
|
||||
for j=1,#gamePadKeys do
|
||||
if JS:isGamepadDown(gamePadKeys[j]) then
|
||||
love.gamepadreleased(JS,gamePadKeys[j])
|
||||
if joystick:isGamepadDown(gamePadKeys[j]) then
|
||||
love.gamepadreleased(joystick,gamePadKeys[j])
|
||||
end
|
||||
end
|
||||
love.gamepadaxis(JS,'leftx',0)
|
||||
love.gamepadaxis(JS,'lefty',0)
|
||||
love.gamepadaxis(JS,'rightx',0)
|
||||
love.gamepadaxis(JS,'righty',0)
|
||||
love.gamepadaxis(JS,'triggerleft',-1)
|
||||
love.gamepadaxis(JS,'triggerright',-1)
|
||||
love.gamepadaxis(joystick,'leftx',0)
|
||||
love.gamepadaxis(joystick,'lefty',0)
|
||||
love.gamepadaxis(joystick,'rightx',0)
|
||||
love.gamepadaxis(joystick,'righty',0)
|
||||
love.gamepadaxis(joystick,'triggerleft',-1)
|
||||
love.gamepadaxis(joystick,'triggerright',-1)
|
||||
MES.new('info',"Joystick removed")
|
||||
table.remove(jsState,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
function love.gamepadaxis(JS,axis,val)
|
||||
if jsState[1] and JS==jsState[1]._jsObj then
|
||||
function love.gamepadaxis(joystick,axis,val)
|
||||
if jsState[1] and joystick==jsState[1]._jsObj then
|
||||
local js=jsState[1]
|
||||
if axis=='leftx' or axis=='lefty' or axis=='rightx' or axis=='righty' then
|
||||
local newVal=-- range: [0,1]
|
||||
@@ -463,14 +477,14 @@ function love.gamepadaxis(JS,axis,val)
|
||||
0
|
||||
if newVal~=js[axis] then
|
||||
if js[axis]==-1 then
|
||||
love.gamepadreleased(JS,jsAxisEventName[axis][1])
|
||||
love.gamepadreleased(joystick,jsAxisEventName[axis][1])
|
||||
elseif js[axis]~=0 then
|
||||
love.gamepadreleased(JS,jsAxisEventName[axis][2])
|
||||
love.gamepadreleased(joystick,jsAxisEventName[axis][2])
|
||||
end
|
||||
if newVal==-1 then
|
||||
love.gamepadpressed(JS,jsAxisEventName[axis][1])
|
||||
love.gamepadpressed(joystick,jsAxisEventName[axis][1])
|
||||
elseif newVal==1 then
|
||||
love.gamepadpressed(JS,jsAxisEventName[axis][2])
|
||||
love.gamepadpressed(joystick,jsAxisEventName[axis][2])
|
||||
end
|
||||
js[axis]=newVal
|
||||
end
|
||||
@@ -478,9 +492,9 @@ function love.gamepadaxis(JS,axis,val)
|
||||
local newVal=val>.3 and 1 or 0-- range: [0,1]
|
||||
if newVal~=js[axis] then
|
||||
if newVal==1 then
|
||||
love.gamepadpressed(JS,jsAxisEventName[axis])
|
||||
love.gamepadpressed(joystick,jsAxisEventName[axis])
|
||||
else
|
||||
love.gamepadreleased(JS,jsAxisEventName[axis])
|
||||
love.gamepadreleased(joystick,jsAxisEventName[axis])
|
||||
end
|
||||
js[axis]=newVal
|
||||
end
|
||||
@@ -720,6 +734,10 @@ function love.run()
|
||||
|
||||
-- UPDATE
|
||||
STEP()
|
||||
if SYSTEM == 'Web' then
|
||||
JS.retrieveData(dt)
|
||||
CLIPBOARD._update(dt)
|
||||
end
|
||||
if mouseShow then mouse_update(dt) end
|
||||
if next(jsState) then gp_update(jsState[1],dt) end
|
||||
VOC.update()
|
||||
|
||||
142
Zframework/js.lua
Normal file
142
Zframework/js.lua
Normal file
@@ -0,0 +1,142 @@
|
||||
local __requestQueue={}
|
||||
local _requestCount=0
|
||||
local _Request={
|
||||
command="",
|
||||
currentTime=0,
|
||||
timeOut=2,
|
||||
id='0',
|
||||
}
|
||||
local __defaultErrorFunction=nil
|
||||
local isDebugActive=false
|
||||
|
||||
local JS={}
|
||||
|
||||
function JS.callJS(funcToCall)
|
||||
print("callJavascriptFunction "..funcToCall)
|
||||
end
|
||||
|
||||
--You can pass a set of commands here and, it is a syntactic sugar for executing many commands inside callJS, as it only calls a function
|
||||
--If you pass arguments to the func beyond the string, it will perform automatically string.format
|
||||
--Return statement is possible inside this structure
|
||||
--This will return a string containing a function to be called by JS.callJS
|
||||
function JS.stringFunc(str,...)
|
||||
str="(function(){"..str.."})()"
|
||||
if (#arg>0) then
|
||||
str=str:format(unpack(arg))
|
||||
end
|
||||
str=str:gsub("[\n\t]","")
|
||||
return str
|
||||
end
|
||||
|
||||
--The call will store in the webDB the return value from the function passed it timeouts
|
||||
local function retrieveJS(funcToCall,filename)
|
||||
--Used for retrieveData function
|
||||
JS.callJS(("FS.writeFile('%s/%s',%s);"):format(love.filesystem.getSaveDirectory(),filename,funcToCall))
|
||||
end
|
||||
|
||||
--Call JS.newRequest instead
|
||||
function _Request:new(isPromise,command,onDataLoaded,onError,timeout,id)
|
||||
local obj={}
|
||||
setmetatable(obj,self)
|
||||
obj.command=command
|
||||
obj.onError=onError or __defaultErrorFunction
|
||||
if not isPromise then
|
||||
retrieveJS(command,self.filename)
|
||||
else
|
||||
JS.callJS(command)
|
||||
end
|
||||
obj.onDataLoaded=onDataLoaded
|
||||
obj.timeOut=(timeout==nil) and obj.timeOut or timeout
|
||||
obj.id=id
|
||||
obj.filename="__temp"..id
|
||||
|
||||
|
||||
function obj:getData()
|
||||
--Try to read from webdb
|
||||
if love.filesystem.getInfo(self.filename) then
|
||||
return love.filesystem.read(self.filename)
|
||||
end
|
||||
end
|
||||
|
||||
function obj:purgeData()
|
||||
--Data must be purged for not allowing old data to be retrieved
|
||||
love.filesystem.remove(self.filename)
|
||||
end
|
||||
|
||||
function obj:update(dt)
|
||||
self.timeOut=self.timeOut-dt
|
||||
local retData=self:getData()
|
||||
|
||||
if ((retData~=nil and retData~="nil") or self.timeOut<=0) then
|
||||
if (retData~=nil and retData:match("ERROR")==nil) then
|
||||
if isDebugActive then
|
||||
print("Data has been retrieved "..retData)
|
||||
end
|
||||
self.onDataLoaded(retData)
|
||||
else
|
||||
self.onError(self.id,retData)
|
||||
end
|
||||
self:purgeData()
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
return obj
|
||||
end
|
||||
|
||||
--Place this function on love.update and set it to return if it returns false (This API is synchronous)
|
||||
function JS.retrieveData(dt)
|
||||
local isRetrieving=#__requestQueue~=0
|
||||
local deadRequests={}
|
||||
for i=1,#__requestQueue do
|
||||
local isUpdating=__requestQueue[i]:update(dt)
|
||||
if not isUpdating then
|
||||
table.insert(deadRequests,i)
|
||||
end
|
||||
end
|
||||
for i=1,#deadRequests do
|
||||
if (isDebugActive) then
|
||||
print("Request died: "..deadRequests[i])
|
||||
end
|
||||
table.remove(__requestQueue,deadRequests[i])
|
||||
end
|
||||
return isRetrieving
|
||||
end
|
||||
|
||||
--May only be used for functions that don't return a promise
|
||||
function JS.newRequest(funcToCall,onDataLoaded,onError,timeout,optionalId)
|
||||
table.insert(__requestQueue,_Request:new(false,funcToCall,onDataLoaded,onError,timeout or 5,optionalId or _requestCount))
|
||||
end
|
||||
|
||||
--This function can be handled manually (in JS code)
|
||||
--How to: add the function call when your events resolve: FS.writeFile("Put love.filesystem.getSaveDirectory here", "Pass a string here (NUMBER DONT WORK"))
|
||||
--Or it can be handled by Lua, it auto sets your data if you write the following command:
|
||||
-- _$_(yourStringOrFunctionHere)
|
||||
function JS.newPromiseRequest(funcToCall,onDataLoaded,onError,timeout,optionalId)
|
||||
optionalId=optionalId or _requestCount
|
||||
funcToCall=funcToCall:gsub("_$_%(","FS.writeFile('"..love.filesystem.getSaveDirectory().."/__temp"..optionalId.."', ")
|
||||
table.insert(__requestQueue,_Request:new(true,funcToCall,onDataLoaded,onError,timeout or 5,optionalId))
|
||||
end
|
||||
|
||||
|
||||
--It receives the ID from ther request
|
||||
--Don't try printing the request.command, as it will execute the javascript command
|
||||
function JS.setDefaultErrorFunction(func)
|
||||
__defaultErrorFunction=func
|
||||
end
|
||||
|
||||
JS.setDefaultErrorFunction(function(id,error)
|
||||
if (isDebugActive) then
|
||||
local msg="Data could not be loaded for id:'"..id.."'"
|
||||
if (error) then
|
||||
msg=msg.."\nError: "..error
|
||||
end
|
||||
print(msg)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
JS.callJS(JS.stringFunc("__getWebDB('%s');","__LuaJSDB"))
|
||||
|
||||
return JS
|
||||
@@ -140,7 +140,7 @@ function profile.switch()
|
||||
switch=not switch
|
||||
if not switch then
|
||||
profile.stop()
|
||||
love.system.setClipboardText(profile.report())
|
||||
CLIPBOARD.set(profile.report())
|
||||
profile.reset()
|
||||
return false
|
||||
else
|
||||
|
||||
@@ -131,9 +131,8 @@ function STRING.time_short(t)
|
||||
-- floor seconds
|
||||
timeUnits[#timeUnits]=floorint(timeUnits[#timeUnits])
|
||||
|
||||
local outputStr=''
|
||||
for i=1,#timeUnits do
|
||||
if timeUnits>0 then
|
||||
if timeUnits[i]>0 then
|
||||
return timeUnits[i]..timeLetters[i]..' '..timeUnits[i+1]..timeLetters[i+1]
|
||||
end
|
||||
end
|
||||
@@ -190,7 +189,7 @@ do-- functions to shorted big numbers
|
||||
function STRING.bigInt(t)
|
||||
if t<1000 then
|
||||
return tostring(t)
|
||||
elseif t~=1e999 then
|
||||
elseif t~=1/0 then
|
||||
local e=floorint(lg(t)/3)
|
||||
return(t/10^(e*3))..units[e+1]
|
||||
else
|
||||
|
||||
@@ -8,8 +8,6 @@ local path=''
|
||||
|
||||
local type=type
|
||||
local timer=love.timer.getTime
|
||||
local TRD=love.thread.newThread("\n")
|
||||
local TRD_isRunning=TRD.isRunning
|
||||
|
||||
local WS={}
|
||||
local wsList=setmetatable({},{
|
||||
@@ -151,7 +149,7 @@ function WS.update(dt)
|
||||
local time=timer()
|
||||
for name,ws in next,wsList do
|
||||
if ws.real and ws.status~='dead' then
|
||||
if TRD_isRunning(ws.thread) then
|
||||
if ws.thread:isRunning() then
|
||||
if ws.triggerCHN:getCount()==0 then
|
||||
ws.triggerCHN:push(0)
|
||||
end
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
---@type love.Channel,love.Channel,love.Channel
|
||||
local triggerCHN,sendCHN,readCHN=...
|
||||
|
||||
local CHN_demand,CHN_getCount=triggerCHN.demand,triggerCHN.getCount
|
||||
@@ -5,16 +6,20 @@ local CHN_push,CHN_pop=triggerCHN.push,triggerCHN.pop
|
||||
|
||||
local SOCK=require'socket'.tcp()
|
||||
local JSON=require'Zframework.json'
|
||||
local sleep=require'love.timer'.sleep
|
||||
|
||||
do-- Connect
|
||||
local host=CHN_demand(sendCHN)
|
||||
local port=CHN_demand(sendCHN)
|
||||
local path=CHN_demand(sendCHN)
|
||||
local head=CHN_demand(sendCHN)
|
||||
local timeout=CHN_demand(sendCHN)
|
||||
-- Warning: workaround for love.js, used to use CHN_demand instead
|
||||
while CHN_getCount(sendCHN)<5 do sleep(.0626) end
|
||||
local host=CHN_pop(sendCHN)
|
||||
local port=CHN_pop(sendCHN)
|
||||
local path=CHN_pop(sendCHN)
|
||||
local head=CHN_pop(sendCHN)
|
||||
local timeout=CHN_pop(sendCHN)
|
||||
|
||||
SOCK:settimeout(timeout)
|
||||
local res,err=SOCK:connect(host,port)
|
||||
-- print('C0',res,err)
|
||||
assert(res,err)
|
||||
|
||||
-- WebSocket handshake
|
||||
@@ -31,6 +36,7 @@ do-- Connect
|
||||
|
||||
-- First line of HTTP
|
||||
res,err=SOCK:receive('*l')
|
||||
-- print('C',res,err)
|
||||
assert(res,err)
|
||||
local code,ctLen
|
||||
code=res:find(' ')
|
||||
@@ -39,22 +45,28 @@ do-- Connect
|
||||
-- Get body length from headers and remove headers
|
||||
repeat
|
||||
res,err=SOCK:receive('*l')
|
||||
-- print('H',res,err)
|
||||
assert(res,err)
|
||||
if not ctLen and res:find('length') then
|
||||
ctLen=tonumber(res:match('%d+'))
|
||||
if not ctLen and res:find('content-length') then
|
||||
ctLen=tonumber(res:match('%d+')) or 0
|
||||
end
|
||||
until res==''
|
||||
|
||||
-- Result
|
||||
if code=='101' then
|
||||
CHN_push(readCHN,'success')
|
||||
end
|
||||
|
||||
-- Content(?)
|
||||
if ctLen then
|
||||
if code=='101' then
|
||||
CHN_push(readCHN,'success')
|
||||
else
|
||||
res,err=SOCK:receive(ctLen)
|
||||
res,err=SOCK:receive(ctLen)
|
||||
-- print('R',res,err)
|
||||
if code~='101' then
|
||||
res=JSON.decode(assert(res,err))
|
||||
error((code or "XXX")..":"..(res and res.reason or "Server Error"))
|
||||
end
|
||||
end
|
||||
|
||||
SOCK:settimeout(0)
|
||||
end
|
||||
|
||||
@@ -136,10 +148,10 @@ local readThread=coroutine.wrap(function()
|
||||
assert(res,err)
|
||||
length=shl(byte(res,1),8)+byte(res,2)
|
||||
elseif length==127 then
|
||||
local lenData
|
||||
lenData,err=_receive(SOCK,8)
|
||||
-- 'res' is 'lenData' here
|
||||
res,err=_receive(SOCK,8)
|
||||
assert(res,err)
|
||||
local _,_,_,_,_5,_6,_7,_8=byte(lenData,1,8)
|
||||
local _,_,_,_,_5,_6,_7,_8=byte(res,1,8)
|
||||
length=shl(_5,24)+shl(_6,16)+shl(_7,8)+_8
|
||||
end
|
||||
res,err=_receive(SOCK,length)
|
||||
@@ -158,12 +170,14 @@ local readThread=coroutine.wrap(function()
|
||||
lBuffer=lBuffer..res
|
||||
if fin then
|
||||
CHN_push(readCHN,lBuffer)
|
||||
-- print('M',lBuffer)
|
||||
lBuffer=""
|
||||
end
|
||||
else
|
||||
CHN_push(readCHN,op)
|
||||
if fin then
|
||||
CHN_push(readCHN,res)
|
||||
-- print('S',res)
|
||||
lBuffer=""
|
||||
else
|
||||
lBuffer=res
|
||||
@@ -176,7 +190,8 @@ end)
|
||||
local success,err
|
||||
|
||||
while true do-- Running
|
||||
CHN_demand(triggerCHN)
|
||||
while CHN_getCount(triggerCHN)==0 do sleep(.0626) end
|
||||
CHN_pop(triggerCHN)
|
||||
success,err=pcall(sendThread)
|
||||
if not success or err then break end
|
||||
success,err=pcall(readThread)
|
||||
|
||||
@@ -15,6 +15,7 @@ local timer=love.timer.getTime
|
||||
local next=next
|
||||
local floor,ceil=math.floor,math.ceil
|
||||
local max,min=math.max,math.min
|
||||
local match=string.match
|
||||
local sub,ins,rem=string.sub,table.insert,table.remove
|
||||
local xOy=SCR.xOy
|
||||
local FONT=FONT
|
||||
@@ -142,13 +143,21 @@ local button={
|
||||
type='button',
|
||||
mustHaveText=true,
|
||||
ATV=0,-- Activating time(0~8)
|
||||
textAlreadyWrapped=false,-- Text already wrapped? (Managed by :setObject, can be override, this will be true if obj has a '\n')
|
||||
}
|
||||
function button:reset()
|
||||
self.ATV=0
|
||||
end
|
||||
function button:setObject(obj)
|
||||
if type(obj)=='string' or type(obj)=='number' then
|
||||
self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
|
||||
if match(obj,"\n") then
|
||||
self.textAlreadyWrapped=true
|
||||
self.obj=gc.newText(FONT.get(self.font,self.fType))
|
||||
self.obj:addf(obj,self.w-self.edge*2,(self.align=='L' and 'left') or (self.align=='R' and 'right') or 'center')
|
||||
else
|
||||
self.textAlreadyWrapped=false
|
||||
self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
|
||||
end
|
||||
elseif obj then
|
||||
self.obj=obj
|
||||
end
|
||||
@@ -194,16 +203,7 @@ function button:draw()
|
||||
local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5
|
||||
local y0=y+h*.5
|
||||
gc_setColor(1,1,1,.2+ATV*.05)
|
||||
if self.align=='M' then
|
||||
local x0=x+w*.5
|
||||
local kx=obj:type()=='Text' and min(w/ox/2,1) or 1
|
||||
gc_draw(obj,x0-1,y0-1,nil,kx,1,ox,oy)
|
||||
gc_draw(obj,x0-1,y0+1,nil,kx,1,ox,oy)
|
||||
gc_draw(obj,x0+1,y0-1,nil,kx,1,ox,oy)
|
||||
gc_draw(obj,x0+1,y0+1,nil,kx,1,ox,oy)
|
||||
gc_setColor(r*.55,g*.55,b*.55)
|
||||
gc_draw(obj,x0,y0,nil,kx,1,ox,oy)
|
||||
elseif self.align=='L' then
|
||||
if self.align=='L' or self.textAlreadyWrapped then
|
||||
local edge=self.edge
|
||||
gc_draw(obj,x+edge-1,y0-1-oy)
|
||||
gc_draw(obj,x+edge-1,y0+1-oy)
|
||||
@@ -219,6 +219,15 @@ function button:draw()
|
||||
gc_draw(obj,x0+1,y0+1-oy)
|
||||
gc_setColor(r*.55,g*.55,b*.55)
|
||||
gc_draw(obj,x0,y0-oy)
|
||||
else--if self.align=='M' then
|
||||
local x0=x+w*.5
|
||||
local kx=obj:type()=='Text' and min(w/ox/2,1) or 1
|
||||
gc_draw(obj,x0-1,y0-1,nil,kx,1,ox,oy)
|
||||
gc_draw(obj,x0-1,y0+1,nil,kx,1,ox,oy)
|
||||
gc_draw(obj,x0+1,y0-1,nil,kx,1,ox,oy)
|
||||
gc_draw(obj,x0+1,y0+1,nil,kx,1,ox,oy)
|
||||
gc_setColor(r*.55,g*.55,b*.55)
|
||||
gc_draw(obj,x0,y0,nil,kx,1,ox,oy)
|
||||
end
|
||||
end
|
||||
function button:getInfo()
|
||||
@@ -290,13 +299,21 @@ local key={
|
||||
type='key',
|
||||
mustHaveText=true,
|
||||
ATV=0,-- Activating time(0~4)
|
||||
textAlreadyWrapped=false,---See button.setObject (line 146)
|
||||
}
|
||||
function key:reset()
|
||||
self.ATV=0
|
||||
end
|
||||
function key:setObject(obj)
|
||||
if type(obj)=='string' or type(obj)=='number' then
|
||||
self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
|
||||
if match(obj,"\n") then
|
||||
self.textAlreadyWrapped=true
|
||||
self.obj=gc.newText(FONT.get(self.font,self.fType))
|
||||
self.obj:addf(obj,self.w-self.edge*2,(self.align=='L' and 'left') or (self.align=='R' and 'right') or 'center')
|
||||
else
|
||||
self.textAlreadyWrapped=false
|
||||
self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
|
||||
end
|
||||
elseif obj then
|
||||
self.obj=obj
|
||||
end
|
||||
@@ -354,14 +371,15 @@ function key:draw()
|
||||
-- Drawable
|
||||
local obj=self.obj
|
||||
local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5
|
||||
|
||||
gc_setColor(r,g,b)
|
||||
if align=='M' then
|
||||
local kx=obj:type()=='Text' and min(w/ox/2,1) or 1
|
||||
gc_draw(obj,x+w*.5,y+h*.5,nil,kx,1,ox,oy)
|
||||
elseif align=='L' then
|
||||
gc_draw(obj,x+self.edge,y-oy+h*.5)
|
||||
if align=='L' or self.textAlreadyWrapped then
|
||||
gc_draw(obj,x+self.edge,y+h*.5-oy)
|
||||
elseif align=='R' then
|
||||
gc_draw(obj,x+w-self.edge-ox*2,y-oy+h*.5)
|
||||
else--if align=='M' then
|
||||
local kx=obj:type()=='Text' and min(w/ox/2,1) or 1
|
||||
gc_draw(obj,x+w*.5,y+h*.5,nil,kx,1,ox,oy)
|
||||
end
|
||||
end
|
||||
function key:getInfo()
|
||||
@@ -1382,10 +1400,13 @@ function WIDGET.setLang(widgetText)
|
||||
t=W.name or "##"
|
||||
W.color=COLOR.dV
|
||||
end
|
||||
if type(t)=='string' and W.font then
|
||||
t=gc.newText(FONT.get(W.font),t)
|
||||
if type(W.setObject)=='function' then
|
||||
W:setObject(t)
|
||||
elseif type(t)=='string' and W.font then
|
||||
W.obj=gc.newText(FONT.get(W.font or 30),t)
|
||||
else
|
||||
W.obj=t
|
||||
end
|
||||
W.obj=t
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user