Another change
This commit is contained in:
279
libs/binser.lua
279
libs/binser.lua
@@ -1,7 +1,7 @@
|
|||||||
-- binser.lua
|
-- binser.lua
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Copyright (c) 2016 Calvin Rose
|
Copyright (c) 2016-2019 Calvin Rose
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
@@ -27,7 +27,6 @@ local select = select
|
|||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
local getmetatable = getmetatable
|
local getmetatable = getmetatable
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
local tonumber = tonumber
|
|
||||||
local type = type
|
local type = type
|
||||||
local loadstring = loadstring or load
|
local loadstring = loadstring or load
|
||||||
local concat = table.concat
|
local concat = table.concat
|
||||||
@@ -52,25 +51,6 @@ if not frexp then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- NIL = 202
|
|
||||||
-- FLOAT = 203
|
|
||||||
-- TRUE = 204
|
|
||||||
-- FALSE = 205
|
|
||||||
-- STRING = 206
|
|
||||||
-- TABLE = 207
|
|
||||||
-- REFERENCE = 208
|
|
||||||
-- CONSTRUCTOR = 209
|
|
||||||
-- FUNCTION = 210
|
|
||||||
-- RESOURCE = 211
|
|
||||||
-- INT64 = 212
|
|
||||||
|
|
||||||
local mts = {}
|
|
||||||
local ids = {}
|
|
||||||
local serializers = {}
|
|
||||||
local deserializers = {}
|
|
||||||
local resources = {}
|
|
||||||
local resources_by_name = {}
|
|
||||||
|
|
||||||
local function pack(...)
|
local function pack(...)
|
||||||
return {...}, select("#", ...)
|
return {...}, select("#", ...)
|
||||||
end
|
end
|
||||||
@@ -166,25 +146,36 @@ end
|
|||||||
-- number deserialization code also modified from https://github.com/fperrad/lua-MessagePack
|
-- number deserialization code also modified from https://github.com/fperrad/lua-MessagePack
|
||||||
local function number_from_str(str, index)
|
local function number_from_str(str, index)
|
||||||
local b = byte(str, index)
|
local b = byte(str, index)
|
||||||
|
if not b then error("Expected more bytes of input.") end
|
||||||
if b < 128 then
|
if b < 128 then
|
||||||
return b - 27, index + 1
|
return b - 27, index + 1
|
||||||
elseif b < 192 then
|
elseif b < 192 then
|
||||||
return byte(str, index + 1) + 0x100 * (b - 128) - 8192, index + 2
|
local b2 = byte(str, index + 1)
|
||||||
|
if not b2 then error("Expected more bytes of input.") end
|
||||||
|
return b2 + 0x100 * (b - 128) - 8192, index + 2
|
||||||
end
|
end
|
||||||
local b1, b2, b3, b4, b5, b6, b7, b8 = byte(str, index + 1, index + 8)
|
local b1, b2, b3, b4, b5, b6, b7, b8 = byte(str, index + 1, index + 8)
|
||||||
|
if (not b1) or (not b2) or (not b3) or (not b4) or
|
||||||
|
(not b5) or (not b6) or (not b7) or (not b8) then
|
||||||
|
error("Expected more bytes of input.")
|
||||||
|
end
|
||||||
if b == 212 then
|
if b == 212 then
|
||||||
local flip = b1 >= 128
|
local flip = b1 >= 128
|
||||||
if flip then -- negative
|
if flip then -- negative
|
||||||
b1, b2, b3, b4 = 0xFF - b1, 0xFF - b2, 0xFF - b3, 0xFF - b4
|
b1, b2, b3, b4 = 0xFF - b1, 0xFF - b2, 0xFF - b3, 0xFF - b4
|
||||||
b5, b6, b7, b8 = 0xFF - b5, 0xFF - b6, 0xFF - b7, 0xFF - b8
|
b5, b6, b7, b8 = 0xFF - b5, 0xFF - b6, 0xFF - b7, 0xFF - b8
|
||||||
end
|
end
|
||||||
local n = ((((((b1 * 0x100 + b2) * 0x100 + b3) * 0x100 + b4) * 0x100 + b5) * 0x100 + b6) * 0x100 + b7) * 0x100 + b8
|
local n = ((((((b1 * 0x100 + b2) * 0x100 + b3) * 0x100 + b4) *
|
||||||
|
0x100 + b5) * 0x100 + b6) * 0x100 + b7) * 0x100 + b8
|
||||||
if flip then
|
if flip then
|
||||||
return (-n) - 1, index + 9
|
return (-n) - 1, index + 9
|
||||||
else
|
else
|
||||||
return n, index + 9
|
return n, index + 9
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if b ~= 203 then
|
||||||
|
error("Expected number")
|
||||||
|
end
|
||||||
local sign = b1 > 0x7F and -1 or 1
|
local sign = b1 > 0x7F and -1 or 1
|
||||||
local e = (b1 % 0x80) * 0x10 + floor(b2 / 0x10)
|
local e = (b1 % 0x80) * 0x10 + floor(b2 / 0x10)
|
||||||
local m = ((((((b2 % 0x10) * 0x100 + b3) * 0x100 + b4) * 0x100 + b5) * 0x100 + b6) * 0x100 + b7) * 0x100 + b8
|
local m = ((((((b2 % 0x10) * 0x100 + b3) * 0x100 + b4) * 0x100 + b5) * 0x100 + b6) * 0x100 + b7) * 0x100 + b8
|
||||||
@@ -207,6 +198,32 @@ local function number_from_str(str, index)
|
|||||||
return n, index + 9
|
return n, index + 9
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function newbinser()
|
||||||
|
|
||||||
|
-- unique table key for getting next value
|
||||||
|
local NEXT = {}
|
||||||
|
local CTORSTACK = {}
|
||||||
|
|
||||||
|
-- NIL = 202
|
||||||
|
-- FLOAT = 203
|
||||||
|
-- TRUE = 204
|
||||||
|
-- FALSE = 205
|
||||||
|
-- STRING = 206
|
||||||
|
-- TABLE = 207
|
||||||
|
-- REFERENCE = 208
|
||||||
|
-- CONSTRUCTOR = 209
|
||||||
|
-- FUNCTION = 210
|
||||||
|
-- RESOURCE = 211
|
||||||
|
-- INT64 = 212
|
||||||
|
-- TABLE WITH META = 213
|
||||||
|
|
||||||
|
local mts = {}
|
||||||
|
local ids = {}
|
||||||
|
local serializers = {}
|
||||||
|
local deserializers = {}
|
||||||
|
local resources = {}
|
||||||
|
local resources_by_name = {}
|
||||||
local types = {}
|
local types = {}
|
||||||
|
|
||||||
types["nil"] = function(x, visited, accum)
|
types["nil"] = function(x, visited, accum)
|
||||||
@@ -227,8 +244,8 @@ function types.string(x, visited, accum)
|
|||||||
accum[alen + 1] = "\208"
|
accum[alen + 1] = "\208"
|
||||||
accum[alen + 2] = number_to_str(visited[x])
|
accum[alen + 2] = number_to_str(visited[x])
|
||||||
else
|
else
|
||||||
visited[x] = visited.next
|
visited[x] = visited[NEXT]
|
||||||
visited.next = visited.next + 1
|
visited[NEXT] = visited[NEXT] + 1
|
||||||
accum[alen + 1] = "\206"
|
accum[alen + 1] = "\206"
|
||||||
accum[alen + 2] = number_to_str(#x)
|
accum[alen + 2] = number_to_str(#x)
|
||||||
accum[alen + 3] = x
|
accum[alen + 3] = x
|
||||||
@@ -245,10 +262,11 @@ local function check_custom_type(x, visited, accum)
|
|||||||
local mt = getmetatable(x)
|
local mt = getmetatable(x)
|
||||||
local id = mt and ids[mt]
|
local id = mt and ids[mt]
|
||||||
if id then
|
if id then
|
||||||
if x == visited.temp then
|
local constructing = visited[CTORSTACK]
|
||||||
|
if constructing[x] then
|
||||||
error("Infinite loop in constructor.")
|
error("Infinite loop in constructor.")
|
||||||
end
|
end
|
||||||
visited.temp = x
|
constructing[x] = true
|
||||||
accum[#accum + 1] = "\209"
|
accum[#accum + 1] = "\209"
|
||||||
types[type(id)](id, visited, accum)
|
types[type(id)](id, visited, accum)
|
||||||
local args, len = pack(serializers[id](x))
|
local args, len = pack(serializers[id](x))
|
||||||
@@ -257,8 +275,10 @@ local function check_custom_type(x, visited, accum)
|
|||||||
local arg = args[i]
|
local arg = args[i]
|
||||||
types[type(arg)](arg, visited, accum)
|
types[type(arg)](arg, visited, accum)
|
||||||
end
|
end
|
||||||
visited[x] = visited.next
|
visited[x] = visited[NEXT]
|
||||||
visited.next = visited.next + 1
|
visited[NEXT] = visited[NEXT] + 1
|
||||||
|
-- We finished constructing
|
||||||
|
constructing[x] = nil
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -279,10 +299,16 @@ function types.table(x, visited, accum)
|
|||||||
accum[#accum + 1] = number_to_str(visited[x])
|
accum[#accum + 1] = number_to_str(visited[x])
|
||||||
else
|
else
|
||||||
if check_custom_type(x, visited, accum) then return end
|
if check_custom_type(x, visited, accum) then return end
|
||||||
visited[x] = visited.next
|
visited[x] = visited[NEXT]
|
||||||
visited.next = visited.next + 1
|
visited[NEXT] = visited[NEXT] + 1
|
||||||
local xlen = #x
|
local xlen = #x
|
||||||
|
local mt = getmetatable(x)
|
||||||
|
if mt then
|
||||||
|
accum[#accum + 1] = "\213"
|
||||||
|
types.table(mt, visited, accum)
|
||||||
|
else
|
||||||
accum[#accum + 1] = "\207"
|
accum[#accum + 1] = "\207"
|
||||||
|
end
|
||||||
accum[#accum + 1] = number_to_str(xlen)
|
accum[#accum + 1] = number_to_str(xlen)
|
||||||
for i = 1, xlen do
|
for i = 1, xlen do
|
||||||
local v = x[i]
|
local v = x[i]
|
||||||
@@ -310,8 +336,8 @@ types["function"] = function(x, visited, accum)
|
|||||||
accum[#accum + 1] = number_to_str(visited[x])
|
accum[#accum + 1] = number_to_str(visited[x])
|
||||||
else
|
else
|
||||||
if check_custom_type(x, visited, accum) then return end
|
if check_custom_type(x, visited, accum) then return end
|
||||||
visited[x] = visited.next
|
visited[x] = visited[NEXT]
|
||||||
visited.next = visited.next + 1
|
visited[NEXT] = visited[NEXT] + 1
|
||||||
local str = dump(x)
|
local str = dump(x)
|
||||||
accum[#accum + 1] = "\210"
|
accum[#accum + 1] = "\210"
|
||||||
accum[#accum + 1] = number_to_str(#str)
|
accum[#accum + 1] = number_to_str(#str)
|
||||||
@@ -333,39 +359,57 @@ types.thread = function() error("Cannot serialize threads.") end
|
|||||||
|
|
||||||
local function deserialize_value(str, index, visited)
|
local function deserialize_value(str, index, visited)
|
||||||
local t = byte(str, index)
|
local t = byte(str, index)
|
||||||
if not t then return end
|
if not t then return nil, index end
|
||||||
if t < 128 then
|
if t < 128 then
|
||||||
return t - 27, index + 1
|
return t - 27, index + 1
|
||||||
elseif t < 192 then
|
elseif t < 192 then
|
||||||
return byte(str, index + 1) + 0x100 * (t - 128) - 8192, index + 2
|
local b2 = byte(str, index + 1)
|
||||||
|
if not b2 then error("Expected more bytes of input.") end
|
||||||
|
return b2 + 0x100 * (t - 128) - 8192, index + 2
|
||||||
elseif t == 202 then
|
elseif t == 202 then
|
||||||
return nil, index + 1
|
return nil, index + 1
|
||||||
elseif t == 203 then
|
elseif t == 203 or t == 212 then
|
||||||
return number_from_str(str, index)
|
return number_from_str(str, index)
|
||||||
elseif t == 204 then
|
elseif t == 204 then
|
||||||
return true, index + 1
|
return true, index + 1
|
||||||
elseif t == 205 then
|
elseif t == 205 then
|
||||||
return false, index + 1
|
return false, index + 1
|
||||||
elseif t == 206 then
|
elseif t == 206 then
|
||||||
local length, dataindex = deserialize_value(str, index + 1, visited)
|
local length, dataindex = number_from_str(str, index + 1)
|
||||||
local nextindex = dataindex + length
|
local nextindex = dataindex + length
|
||||||
|
if not (length >= 0) then error("Bad string length") end
|
||||||
|
if #str < nextindex - 1 then error("Expected more bytes of string") end
|
||||||
local substr = sub(str, dataindex, nextindex - 1)
|
local substr = sub(str, dataindex, nextindex - 1)
|
||||||
visited[#visited + 1] = substr
|
visited[#visited + 1] = substr
|
||||||
return substr, nextindex
|
return substr, nextindex
|
||||||
elseif t == 207 then
|
elseif t == 207 or t == 213 then
|
||||||
local count, nextindex = number_from_str(str, index + 1)
|
local mt, count, nextindex
|
||||||
local ret = {}
|
local ret = {}
|
||||||
visited[#visited + 1] = ret
|
visited[#visited + 1] = ret
|
||||||
|
nextindex = index + 1
|
||||||
|
if t == 213 then
|
||||||
|
mt, nextindex = deserialize_value(str, nextindex, visited)
|
||||||
|
if type(mt) ~= "table" then error("Expected table metatable") end
|
||||||
|
end
|
||||||
|
count, nextindex = number_from_str(str, nextindex)
|
||||||
for i = 1, count do
|
for i = 1, count do
|
||||||
|
local oldindex = nextindex
|
||||||
ret[i], nextindex = deserialize_value(str, nextindex, visited)
|
ret[i], nextindex = deserialize_value(str, nextindex, visited)
|
||||||
|
if nextindex == oldindex then error("Expected more bytes of input.") end
|
||||||
end
|
end
|
||||||
count, nextindex = number_from_str(str, nextindex)
|
count, nextindex = number_from_str(str, nextindex)
|
||||||
for i = 1, count do
|
for i = 1, count do
|
||||||
local k, v
|
local k, v
|
||||||
|
local oldindex = nextindex
|
||||||
k, nextindex = deserialize_value(str, nextindex, visited)
|
k, nextindex = deserialize_value(str, nextindex, visited)
|
||||||
|
if nextindex == oldindex then error("Expected more bytes of input.") end
|
||||||
|
oldindex = nextindex
|
||||||
v, nextindex = deserialize_value(str, nextindex, visited)
|
v, nextindex = deserialize_value(str, nextindex, visited)
|
||||||
|
if nextindex == oldindex then error("Expected more bytes of input.") end
|
||||||
|
if k == nil then error("Can't have nil table keys") end
|
||||||
ret[k] = v
|
ret[k] = v
|
||||||
end
|
end
|
||||||
|
if mt then setmetatable(ret, mt) end
|
||||||
return ret, nextindex
|
return ret, nextindex
|
||||||
elseif t == 208 then
|
elseif t == 208 then
|
||||||
local ref, nextindex = number_from_str(str, index + 1)
|
local ref, nextindex = number_from_str(str, index + 1)
|
||||||
@@ -376,29 +420,39 @@ local function deserialize_value(str, index, visited)
|
|||||||
count, nextindex = number_from_str(str, nextindex)
|
count, nextindex = number_from_str(str, nextindex)
|
||||||
local args = {}
|
local args = {}
|
||||||
for i = 1, count do
|
for i = 1, count do
|
||||||
|
local oldindex = nextindex
|
||||||
args[i], nextindex = deserialize_value(str, nextindex, visited)
|
args[i], nextindex = deserialize_value(str, nextindex, visited)
|
||||||
|
if nextindex == oldindex then error("Expected more bytes of input.") end
|
||||||
|
end
|
||||||
|
if not name or not deserializers[name] then
|
||||||
|
error(("Cannot deserialize class '%s'"):format(tostring(name)))
|
||||||
end
|
end
|
||||||
local ret = deserializers[name](unpack(args))
|
local ret = deserializers[name](unpack(args))
|
||||||
visited[#visited + 1] = ret
|
visited[#visited + 1] = ret
|
||||||
return ret, nextindex
|
return ret, nextindex
|
||||||
elseif t == 210 then
|
elseif t == 210 then
|
||||||
local length, dataindex = deserialize_value(str, index + 1, visited)
|
local length, dataindex = number_from_str(str, index + 1)
|
||||||
local nextindex = dataindex + length
|
local nextindex = dataindex + length
|
||||||
|
if not (length >= 0) then error("Bad string length") end
|
||||||
|
if #str < nextindex - 1 then error("Expected more bytes of string") end
|
||||||
local ret = loadstring(sub(str, dataindex, nextindex - 1))
|
local ret = loadstring(sub(str, dataindex, nextindex - 1))
|
||||||
visited[#visited + 1] = ret
|
visited[#visited + 1] = ret
|
||||||
return ret, nextindex
|
return ret, nextindex
|
||||||
elseif t == 211 then
|
elseif t == 211 then
|
||||||
local res, nextindex = deserialize_value(str, index + 1, visited)
|
local resname, nextindex = deserialize_value(str, index + 1, visited)
|
||||||
return resources_by_name[res], nextindex
|
if resname == nil then error("Got nil resource name") end
|
||||||
elseif t == 212 then
|
local res = resources_by_name[resname]
|
||||||
return number_from_str(str, index)
|
if res == nil then
|
||||||
|
error(("No resources found for name '%s'"):format(tostring(resname)))
|
||||||
|
end
|
||||||
|
return res, nextindex
|
||||||
else
|
else
|
||||||
error("Could not deserialize type byte " .. t .. ".")
|
error("Could not deserialize type byte " .. t .. ".")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function serialize(...)
|
local function serialize(...)
|
||||||
local visited = {next = 1}
|
local visited = {[NEXT] = 1, [CTORSTACK] = {}}
|
||||||
local accum = {}
|
local accum = {}
|
||||||
for i = 1, select("#", ...) do
|
for i = 1, select("#", ...) do
|
||||||
local x = select(i, ...)
|
local x = select(i, ...)
|
||||||
@@ -418,7 +472,7 @@ end
|
|||||||
local function serialize_to_file(path, mode, ...)
|
local function serialize_to_file(path, mode, ...)
|
||||||
local file, err = io.open(path, mode)
|
local file, err = io.open(path, mode)
|
||||||
assert(file, err)
|
assert(file, err)
|
||||||
local visited = {next = 1}
|
local visited = {[NEXT] = 1, [CTORSTACK] = {}}
|
||||||
local accum = make_file_writer(file)
|
local accum = make_file_writer(file)
|
||||||
for i = 1, select("#", ...) do
|
for i = 1, select("#", ...) do
|
||||||
local x = select(i, ...)
|
local x = select(i, ...)
|
||||||
@@ -444,11 +498,15 @@ local function deserialize(str, index)
|
|||||||
local visited = {}
|
local visited = {}
|
||||||
local len = 0
|
local len = 0
|
||||||
local val
|
local val
|
||||||
while index do
|
while true do
|
||||||
val, index = deserialize_value(str, index, visited)
|
local nextindex
|
||||||
if index then
|
val, nextindex = deserialize_value(str, index, visited)
|
||||||
|
if nextindex > index then
|
||||||
len = len + 1
|
len = len + 1
|
||||||
vals[len] = val
|
vals[len] = val
|
||||||
|
index = nextindex
|
||||||
|
else
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return vals, len
|
return vals, len
|
||||||
@@ -464,11 +522,15 @@ local function deserializeN(str, n, index)
|
|||||||
local visited = {}
|
local visited = {}
|
||||||
local len = 0
|
local len = 0
|
||||||
local val
|
local val
|
||||||
while index and len < n do
|
while len < n do
|
||||||
val, index = deserialize_value(str, index, visited)
|
local nextindex
|
||||||
if index then
|
val, nextindex = deserialize_value(str, index, visited)
|
||||||
|
if nextindex > index then
|
||||||
len = len + 1
|
len = len + 1
|
||||||
vals[len] = val
|
vals[len] = val
|
||||||
|
index = nextindex
|
||||||
|
else
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
vals[len + 1] = index
|
vals[len + 1] = index
|
||||||
@@ -477,34 +539,32 @@ end
|
|||||||
|
|
||||||
local function readFile(path)
|
local function readFile(path)
|
||||||
local file, err = io.open(path, "rb")
|
local file, err = io.open(path, "rb")
|
||||||
if file == nil then
|
assert(file, err)
|
||||||
return nil, 0
|
|
||||||
end
|
|
||||||
local str = file:read("*all")
|
local str = file:read("*all")
|
||||||
file:close()
|
file:close()
|
||||||
return deserialize(str)
|
return deserialize(str)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function default_deserialize(metatable)
|
-- Resources
|
||||||
return function(...)
|
|
||||||
local ret = {}
|
local function registerResource(resource, name)
|
||||||
for i = 1, select("#", ...), 2 do
|
type_check(name, "string", "name")
|
||||||
ret[select(i, ...)] = select(i + 1, ...)
|
assert(not resources[resource],
|
||||||
end
|
"Resource already registered.")
|
||||||
return setmetatable(ret, metatable)
|
assert(not resources_by_name[name],
|
||||||
end
|
format("Resource %q already exists.", name))
|
||||||
|
resources_by_name[name] = resource
|
||||||
|
resources[resource] = name
|
||||||
|
return resource
|
||||||
end
|
end
|
||||||
|
|
||||||
local function default_serialize(x)
|
local function unregisterResource(name)
|
||||||
assert(type(x) == "table",
|
type_check(name, "string", "name")
|
||||||
"Default serialization for custom types only works for tables.")
|
assert(resources_by_name[name], format("Resource %q does not exist.", name))
|
||||||
local args = {}
|
local resource = resources_by_name[name]
|
||||||
local len = 0
|
resources_by_name[name] = nil
|
||||||
for k, v in pairs(x) do
|
resources[resource] = nil
|
||||||
args[len + 1], args[len + 2] = k, v
|
return resource
|
||||||
len = len + 2
|
|
||||||
end
|
|
||||||
return unpack(args, 1, len)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Templating
|
-- Templating
|
||||||
@@ -539,15 +599,19 @@ local function templatepart_serialize(part, argaccum, x, len)
|
|||||||
extracount = extracount + 1
|
extracount = extracount + 1
|
||||||
end
|
end
|
||||||
for i = 1, #part do
|
for i = 1, #part do
|
||||||
extracount = extracount - 1
|
local name
|
||||||
if type(part[i]) == "table" then
|
if type(part[i]) == "table" then
|
||||||
extras[part[i][1]] = nil
|
name = part[i][1]
|
||||||
len = templatepart_serialize(part[i][2], argaccum, x[part[i][1]], len)
|
len = templatepart_serialize(part[i][2], argaccum, x[name], len)
|
||||||
else
|
else
|
||||||
extras[part[i]] = nil
|
name = part[i]
|
||||||
len = len + 1
|
len = len + 1
|
||||||
argaccum[len] = x[part[i]]
|
argaccum[len] = x[part[i]]
|
||||||
end
|
end
|
||||||
|
if extras[name] ~= nil then
|
||||||
|
extracount = extracount - 1
|
||||||
|
extras[name] = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if extracount > 0 then
|
if extracount > 0 then
|
||||||
argaccum[len + 1] = extras
|
argaccum[len + 1] = extras
|
||||||
@@ -580,39 +644,47 @@ end
|
|||||||
|
|
||||||
local function template_serializer_and_deserializer(metatable, template)
|
local function template_serializer_and_deserializer(metatable, template)
|
||||||
return function(x)
|
return function(x)
|
||||||
argaccum = {}
|
local argaccum = {}
|
||||||
local len = templatepart_serialize(template, argaccum, x, 0)
|
local len = templatepart_serialize(template, argaccum, x, 0)
|
||||||
return unpack(argaccum, 1, len)
|
return unpack(argaccum, 1, len)
|
||||||
end, function(...)
|
end, function(...)
|
||||||
local ret = {}
|
local ret = {}
|
||||||
local len = select("#", ...)
|
|
||||||
local args = {...}
|
local args = {...}
|
||||||
templatepart_deserialize(ret, template, args, 1)
|
templatepart_deserialize(ret, template, args, 1)
|
||||||
return setmetatable(ret, metatable)
|
return setmetatable(ret, metatable)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Used to serialize classes withh custom serializers and deserializers.
|
||||||
|
-- If no _serialize or _deserialize (or no _template) value is found in the
|
||||||
|
-- metatable, then the metatable is registered as a resources.
|
||||||
local function register(metatable, name, serialize, deserialize)
|
local function register(metatable, name, serialize, deserialize)
|
||||||
|
if type(metatable) == "table" then
|
||||||
name = name or metatable.name
|
name = name or metatable.name
|
||||||
serialize = serialize or metatable._serialize
|
serialize = serialize or metatable._serialize
|
||||||
deserialize = deserialize or metatable._deserialize
|
deserialize = deserialize or metatable._deserialize
|
||||||
if not serialize then
|
if (not serialize) or (not deserialize) then
|
||||||
if metatable._template then
|
if metatable._template then
|
||||||
|
-- Register as template
|
||||||
local t = normalize_template(metatable._template)
|
local t = normalize_template(metatable._template)
|
||||||
serialize, deserialize = template_serializer_and_deserializer(metatable, t)
|
serialize, deserialize = template_serializer_and_deserializer(metatable, t)
|
||||||
elseif not deserialize then
|
|
||||||
serialize = default_serialize
|
|
||||||
deserialize = default_deserialize(metatable)
|
|
||||||
else
|
else
|
||||||
serialize = metatable
|
-- Register the metatable as a resource. This is semantically
|
||||||
|
-- similar and more flexible (handles cycles).
|
||||||
|
registerResource(metatable, name)
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
type_check(metatable, "table", "metatable")
|
elseif type(metatable) == "string" then
|
||||||
|
name = name or metatable
|
||||||
|
end
|
||||||
type_check(name, "string", "name")
|
type_check(name, "string", "name")
|
||||||
type_check(serialize, "function", "serialize")
|
type_check(serialize, "function", "serialize")
|
||||||
type_check(deserialize, "function", "deserialize")
|
type_check(deserialize, "function", "deserialize")
|
||||||
assert(not ids[metatable], "Metatable already registered.")
|
assert((not ids[metatable]) and (not resources[metatable]),
|
||||||
assert(not mts[name], ("Name %q already registered."):format(name))
|
"Metatable already registered.")
|
||||||
|
assert((not mts[name]) and (not resources_by_name[name]),
|
||||||
|
("Name %q already registered."):format(name))
|
||||||
mts[name] = metatable
|
mts[name] = metatable
|
||||||
ids[metatable] = name
|
ids[metatable] = name
|
||||||
serializers[name] = serialize
|
serializers[name] = serialize
|
||||||
@@ -628,11 +700,14 @@ local function unregister(item)
|
|||||||
name, metatable = ids[item], item
|
name, metatable = ids[item], item
|
||||||
end
|
end
|
||||||
type_check(name, "string", "name")
|
type_check(name, "string", "name")
|
||||||
type_check(metatable, "table", "metatable")
|
|
||||||
mts[name] = nil
|
mts[name] = nil
|
||||||
|
if (metatable) then
|
||||||
|
resources[metatable] = nil
|
||||||
ids[metatable] = nil
|
ids[metatable] = nil
|
||||||
|
end
|
||||||
serializers[name] = nil
|
serializers[name] = nil
|
||||||
deserializers[name] = nil
|
deserializers[name] = nil
|
||||||
|
resources_by_name[name] = nil;
|
||||||
return metatable
|
return metatable
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -646,27 +721,8 @@ local function registerClass(class, name)
|
|||||||
return class
|
return class
|
||||||
end
|
end
|
||||||
|
|
||||||
local function registerResource(resource, name)
|
|
||||||
type_check(name, "string", "name")
|
|
||||||
assert(not resources[resource],
|
|
||||||
"Resource already registered.")
|
|
||||||
assert(not resources_by_name[name],
|
|
||||||
format("Resource %q already exists.", name))
|
|
||||||
resources_by_name[name] = resource
|
|
||||||
resources[resource] = name
|
|
||||||
return resource
|
|
||||||
end
|
|
||||||
|
|
||||||
local function unregisterResource(name)
|
|
||||||
type_check(name, "string", "name")
|
|
||||||
assert(resources_by_name[name], format("Resource %q does not exist.", name))
|
|
||||||
local resource = resources_by_name[name]
|
|
||||||
resources_by_name[name] = nil
|
|
||||||
resources[resource] = nil
|
|
||||||
return resource
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
VERSION = "0.0-8",
|
||||||
-- aliases
|
-- aliases
|
||||||
s = serialize,
|
s = serialize,
|
||||||
d = deserialize,
|
d = deserialize,
|
||||||
@@ -685,5 +741,10 @@ return {
|
|||||||
unregister = unregister,
|
unregister = unregister,
|
||||||
registerResource = registerResource,
|
registerResource = registerResource,
|
||||||
unregisterResource = unregisterResource,
|
unregisterResource = unregisterResource,
|
||||||
registerClass = registerClass
|
registerClass = registerClass,
|
||||||
|
|
||||||
|
newbinser = newbinser
|
||||||
}
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return newbinser()
|
||||||
|
|||||||
46
main.lua
46
main.lua
@@ -17,7 +17,7 @@ function love.load()
|
|||||||
require "load.version"
|
require "load.version"
|
||||||
|
|
||||||
require "funcs"
|
require "funcs"
|
||||||
TOUCH_SETTINGS = require 'mobile_libs.settings'
|
TOUCH_SETTINGS = require 'mobile_libs.touch_settings'
|
||||||
BUTTON = require 'mobile_libs.simple-button'
|
BUTTON = require 'mobile_libs.simple-button'
|
||||||
BUTTON.setDefaultOption{
|
BUTTON.setDefaultOption{
|
||||||
draw = function(self)
|
draw = function(self)
|
||||||
@@ -62,6 +62,8 @@ function love.load()
|
|||||||
font=font_3x5_2,
|
font=font_3x5_2,
|
||||||
}
|
}
|
||||||
require 'mobile_libs.vctrl'
|
require 'mobile_libs.vctrl'
|
||||||
|
VCTRL.new(TOUCH_SETTINGS.bind[1])
|
||||||
|
VCTRL.toggle(true)
|
||||||
|
|
||||||
loadSave()
|
loadSave()
|
||||||
require "scene"
|
require "scene"
|
||||||
@@ -136,6 +138,7 @@ function love.draw()
|
|||||||
love.graphics.scale(scale_factor)
|
love.graphics.scale(scale_factor)
|
||||||
|
|
||||||
scene:render()
|
scene:render()
|
||||||
|
if scene.title ~= TouchConfigScene.title then VCTRL.draw() end
|
||||||
|
|
||||||
if config.gamesettings.display_gamemode == 1 or scene.title == "Title" then
|
if config.gamesettings.display_gamemode == 1 or scene.title == "Title" then
|
||||||
love.graphics.setFont(font_3x5_2)
|
love.graphics.setFont(font_3x5_2)
|
||||||
@@ -335,10 +338,51 @@ function love.joystickhat(joystick, hat, direction)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function love.mousepressed(x, y, b, isTouch, presses)
|
||||||
|
if isTouch then return end
|
||||||
|
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
|
||||||
|
if scene.title ~= 'Touchscreen configuration' and VCTRL.press(x, y, 1) then
|
||||||
|
return -- Avoid duplicate
|
||||||
|
end
|
||||||
|
scene:onInputPress{type = "mouse", x = x, y = y, presses = presses}
|
||||||
|
end
|
||||||
|
function love.mousereleased(x, y, b, isTouch, presses)
|
||||||
|
if isTouch then return end
|
||||||
|
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
|
||||||
|
if scene.title ~= 'Touchscreen configuration' and VCTRL.release(1) then
|
||||||
|
return -- Avoid duplicate
|
||||||
|
end
|
||||||
|
scene:onInputRelease{type = "mouse", x = x, y = y, presses = presses}
|
||||||
|
end
|
||||||
|
function love.mousemoved(x, y, dx, dy, isTouch)
|
||||||
|
if isTouch then return end
|
||||||
|
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
|
||||||
|
local dx,dy=dx/SCREEN_SCALE_FACTOR,dy/SCREEN_SCALE_FACTOR
|
||||||
|
scene:onInputMove{type = "mouse", x = x, y = y, dx = dx, dy = dy}
|
||||||
|
end
|
||||||
function love.wheelmoved(x, y)
|
function love.wheelmoved(x, y)
|
||||||
scene:onInputPress({input=nil, type="wheel", x=x, y=y})
|
scene:onInputPress({input=nil, type="wheel", x=x, y=y})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function love.touchpressed(id,x,y)
|
||||||
|
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
|
||||||
|
if scene.title ~= 'Touchscreen configuration' and VCTRL.press(x, y, id) then
|
||||||
|
return -- Avoid duplicate
|
||||||
|
end
|
||||||
|
scene:onInputPress{type = "touch", x = x, y = y, dx = 0, dy = 0, id = id}
|
||||||
|
end
|
||||||
|
function love.touchreleased(id,x,y)
|
||||||
|
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
|
||||||
|
if scene.title ~= 'Touchscreen configuration' and VCTRL.release(id) then
|
||||||
|
return -- Avoid duplicate
|
||||||
|
end
|
||||||
|
scene:onInputRelease{type = "touch", x = x, y = y, dx = 0, dy = 0, id = id}
|
||||||
|
end
|
||||||
|
function love.touchmoved(id,x,y,dx,dy)
|
||||||
|
local x,y=GLOBAL_TRANSFORM:inverseTransformPoint(x,y)
|
||||||
|
scene:onInputMove{type = "touch", x = x, y = y, dx = dx, dy = dy, id = id}
|
||||||
|
end
|
||||||
|
|
||||||
function love.resize(w, h)
|
function love.resize(w, h)
|
||||||
GLOBAL_CANVAS:release()
|
GLOBAL_CANVAS:release()
|
||||||
GLOBAL_CANVAS = love.graphics.newCanvas(w, h)
|
GLOBAL_CANVAS = love.graphics.newCanvas(w, h)
|
||||||
|
|||||||
496
mobile_libs/bitser.lua
Normal file
496
mobile_libs/bitser.lua
Normal file
@@ -0,0 +1,496 @@
|
|||||||
|
--[[
|
||||||
|
Copyright (c) 2020, Jasmijn Wellner
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local VERSION = '1.1'
|
||||||
|
|
||||||
|
local floor = math.floor
|
||||||
|
local pairs = pairs
|
||||||
|
local type = type
|
||||||
|
local insert = table.insert
|
||||||
|
local getmetatable = getmetatable
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
|
local ffi = require("ffi")
|
||||||
|
local buf_pos = 0
|
||||||
|
local buf_size = -1
|
||||||
|
local buf = nil
|
||||||
|
local buf_is_writable = true
|
||||||
|
local writable_buf = nil
|
||||||
|
local writable_buf_size = nil
|
||||||
|
local includeMetatables = true -- togglable with bitser.includeMetatables(false)
|
||||||
|
local SEEN_LEN = {}
|
||||||
|
|
||||||
|
local function Buffer_prereserve(min_size)
|
||||||
|
if buf_size < min_size then
|
||||||
|
buf_size = min_size
|
||||||
|
buf = ffi.new("uint8_t[?]", buf_size)
|
||||||
|
buf_is_writable = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_clear()
|
||||||
|
buf_size = -1
|
||||||
|
buf = nil
|
||||||
|
buf_is_writable = true
|
||||||
|
writable_buf = nil
|
||||||
|
writable_buf_size = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_makeBuffer(size)
|
||||||
|
if not buf_is_writable then
|
||||||
|
buf = writable_buf
|
||||||
|
buf_size = writable_buf_size
|
||||||
|
writable_buf = nil
|
||||||
|
writable_buf_size = nil
|
||||||
|
buf_is_writable = true
|
||||||
|
end
|
||||||
|
buf_pos = 0
|
||||||
|
Buffer_prereserve(size)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_newReader(str)
|
||||||
|
Buffer_makeBuffer(#str)
|
||||||
|
ffi.copy(buf, str, #str)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_newDataReader(data, size)
|
||||||
|
if buf_is_writable then
|
||||||
|
writable_buf = buf
|
||||||
|
writable_buf_size = buf_size
|
||||||
|
end
|
||||||
|
buf_is_writable = false
|
||||||
|
buf_pos = 0
|
||||||
|
buf_size = size
|
||||||
|
buf = ffi.cast("uint8_t*", data)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_reserve(additional_size)
|
||||||
|
while buf_pos + additional_size > buf_size do
|
||||||
|
buf_size = buf_size * 2
|
||||||
|
local oldbuf = buf
|
||||||
|
buf = ffi.new("uint8_t[?]", buf_size)
|
||||||
|
buf_is_writable = true
|
||||||
|
ffi.copy(buf, oldbuf, buf_pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_write_byte(x)
|
||||||
|
Buffer_reserve(1)
|
||||||
|
buf[buf_pos] = x
|
||||||
|
buf_pos = buf_pos + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_write_raw(data, len)
|
||||||
|
Buffer_reserve(len)
|
||||||
|
ffi.copy(buf + buf_pos, data, len)
|
||||||
|
buf_pos = buf_pos + len
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_write_string(s)
|
||||||
|
Buffer_write_raw(s, #s)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_write_data(ct, len, ...)
|
||||||
|
Buffer_write_raw(ffi.new(ct, ...), len)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_ensure(numbytes)
|
||||||
|
if buf_pos + numbytes > buf_size then
|
||||||
|
error("malformed serialized data")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_read_byte()
|
||||||
|
Buffer_ensure(1)
|
||||||
|
local x = buf[buf_pos]
|
||||||
|
buf_pos = buf_pos + 1
|
||||||
|
return x
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_read_string(len)
|
||||||
|
Buffer_ensure(len)
|
||||||
|
local x = ffi.string(buf + buf_pos, len)
|
||||||
|
buf_pos = buf_pos + len
|
||||||
|
return x
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_read_raw(data, len)
|
||||||
|
ffi.copy(data, buf + buf_pos, len)
|
||||||
|
buf_pos = buf_pos + len
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
local function Buffer_read_data(ct, len)
|
||||||
|
return Buffer_read_raw(ffi.new(ct), len)
|
||||||
|
end
|
||||||
|
|
||||||
|
local resource_registry = {}
|
||||||
|
local resource_name_registry = {}
|
||||||
|
local class_registry = {}
|
||||||
|
local class_name_registry = {}
|
||||||
|
local classkey_registry = {}
|
||||||
|
local class_deserialize_registry = {}
|
||||||
|
|
||||||
|
local serialize_value
|
||||||
|
|
||||||
|
local function write_number(value, _)
|
||||||
|
if floor(value) == value and value >= -2147483648 and value <= 2147483647 then
|
||||||
|
if value >= -27 and value <= 100 then
|
||||||
|
--small int
|
||||||
|
Buffer_write_byte(value + 27)
|
||||||
|
elseif value >= -32768 and value <= 32767 then
|
||||||
|
--short int
|
||||||
|
Buffer_write_byte(250)
|
||||||
|
Buffer_write_data("int16_t[1]", 2, value)
|
||||||
|
else
|
||||||
|
--long int
|
||||||
|
Buffer_write_byte(245)
|
||||||
|
Buffer_write_data("int32_t[1]", 4, value)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
--double
|
||||||
|
Buffer_write_byte(246)
|
||||||
|
Buffer_write_data("double[1]", 8, value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function write_string(value, _)
|
||||||
|
if #value < 32 then
|
||||||
|
--short string
|
||||||
|
Buffer_write_byte(192 + #value)
|
||||||
|
else
|
||||||
|
--long string
|
||||||
|
Buffer_write_byte(244)
|
||||||
|
write_number(#value)
|
||||||
|
end
|
||||||
|
Buffer_write_string(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function write_nil(_, _)
|
||||||
|
Buffer_write_byte(247)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function write_boolean(value, _)
|
||||||
|
Buffer_write_byte(value and 249 or 248)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function write_table(value, seen)
|
||||||
|
local classkey
|
||||||
|
local metatable = getmetatable(value)
|
||||||
|
local classname = (class_name_registry[value.class] -- MiddleClass
|
||||||
|
or class_name_registry[value.__baseclass] -- SECL
|
||||||
|
or class_name_registry[metatable] -- hump.class
|
||||||
|
or class_name_registry[value.__class__] -- Slither
|
||||||
|
or class_name_registry[value.__class]) -- Moonscript class
|
||||||
|
if classname then
|
||||||
|
classkey = classkey_registry[classname]
|
||||||
|
Buffer_write_byte(242)
|
||||||
|
serialize_value(classname, seen)
|
||||||
|
elseif includeMetatables and metatable then
|
||||||
|
Buffer_write_byte(253)
|
||||||
|
else
|
||||||
|
Buffer_write_byte(240)
|
||||||
|
end
|
||||||
|
local len = #value
|
||||||
|
write_number(len, seen)
|
||||||
|
for i = 1, len do
|
||||||
|
serialize_value(value[i], seen)
|
||||||
|
end
|
||||||
|
local klen = 0
|
||||||
|
for k in pairs(value) do
|
||||||
|
if (type(k) ~= 'number' or floor(k) ~= k or k > len or k < 1) and k ~= classkey then
|
||||||
|
klen = klen + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
write_number(klen, seen)
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if (type(k) ~= 'number' or floor(k) ~= k or k > len or k < 1) and k ~= classkey then
|
||||||
|
serialize_value(k, seen)
|
||||||
|
serialize_value(v, seen)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if includeMetatables and metatable and not classname then
|
||||||
|
serialize_value(metatable, seen)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function write_cdata(value, seen)
|
||||||
|
local ty = ffi.typeof(value)
|
||||||
|
if ty == value then
|
||||||
|
-- ctype
|
||||||
|
Buffer_write_byte(251)
|
||||||
|
serialize_value(tostring(ty):sub(7, -2), seen)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- cdata
|
||||||
|
Buffer_write_byte(252)
|
||||||
|
serialize_value(ty, seen)
|
||||||
|
local len = ffi.sizeof(value)
|
||||||
|
write_number(len)
|
||||||
|
Buffer_write_raw(ffi.typeof('$[1]', ty)(value), len)
|
||||||
|
end
|
||||||
|
|
||||||
|
local types = {number = write_number, string = write_string, table = write_table, boolean = write_boolean, ["nil"] = write_nil, cdata = write_cdata}
|
||||||
|
|
||||||
|
serialize_value = function(value, seen)
|
||||||
|
if seen[value] then
|
||||||
|
local ref = seen[value]
|
||||||
|
if ref < 64 then
|
||||||
|
--small reference
|
||||||
|
Buffer_write_byte(128 + ref)
|
||||||
|
else
|
||||||
|
--long reference
|
||||||
|
Buffer_write_byte(243)
|
||||||
|
write_number(ref, seen)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local t = type(value)
|
||||||
|
if t ~= 'number' and t ~= 'boolean' and t ~= 'nil' and t ~= 'cdata' then
|
||||||
|
seen[value] = seen[SEEN_LEN]
|
||||||
|
seen[SEEN_LEN] = seen[SEEN_LEN] + 1
|
||||||
|
end
|
||||||
|
if resource_name_registry[value] then
|
||||||
|
local name = resource_name_registry[value]
|
||||||
|
if #name < 16 then
|
||||||
|
--small resource
|
||||||
|
Buffer_write_byte(224 + #name)
|
||||||
|
Buffer_write_string(name)
|
||||||
|
else
|
||||||
|
--long resource
|
||||||
|
Buffer_write_byte(241)
|
||||||
|
write_string(name, seen)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
(types[t] or
|
||||||
|
error("cannot serialize type " .. t)
|
||||||
|
)(value, seen)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function serialize(value)
|
||||||
|
Buffer_makeBuffer(4096)
|
||||||
|
local seen = {[SEEN_LEN] = 0}
|
||||||
|
serialize_value(value, seen)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function add_to_seen(value, seen)
|
||||||
|
insert(seen, value)
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
|
||||||
|
local function reserve_seen(seen)
|
||||||
|
insert(seen, 42)
|
||||||
|
return #seen
|
||||||
|
end
|
||||||
|
|
||||||
|
local function deserialize_value(seen)
|
||||||
|
local t = Buffer_read_byte()
|
||||||
|
if t < 128 then
|
||||||
|
--small int
|
||||||
|
return t - 27
|
||||||
|
elseif t < 192 then
|
||||||
|
--small reference
|
||||||
|
return seen[t - 127]
|
||||||
|
elseif t < 224 then
|
||||||
|
--small string
|
||||||
|
return add_to_seen(Buffer_read_string(t - 192), seen)
|
||||||
|
elseif t < 240 then
|
||||||
|
--small resource
|
||||||
|
return add_to_seen(resource_registry[Buffer_read_string(t - 224)], seen)
|
||||||
|
elseif t == 240 or t == 253 then
|
||||||
|
--table
|
||||||
|
local v = add_to_seen({}, seen)
|
||||||
|
local len = deserialize_value(seen)
|
||||||
|
for i = 1, len do
|
||||||
|
v[i] = deserialize_value(seen)
|
||||||
|
end
|
||||||
|
len = deserialize_value(seen)
|
||||||
|
for _ = 1, len do
|
||||||
|
local key = deserialize_value(seen)
|
||||||
|
v[key] = deserialize_value(seen)
|
||||||
|
end
|
||||||
|
if t == 253 then
|
||||||
|
if includeMetatables then
|
||||||
|
setmetatable(v, deserialize_value(seen))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return v
|
||||||
|
elseif t == 241 then
|
||||||
|
--long resource
|
||||||
|
local idx = reserve_seen(seen)
|
||||||
|
local value = resource_registry[deserialize_value(seen)]
|
||||||
|
seen[idx] = value
|
||||||
|
return value
|
||||||
|
elseif t == 242 then
|
||||||
|
--instance
|
||||||
|
local instance = add_to_seen({}, seen)
|
||||||
|
local classname = deserialize_value(seen)
|
||||||
|
local class = class_registry[classname]
|
||||||
|
local classkey = classkey_registry[classname]
|
||||||
|
local deserializer = class_deserialize_registry[classname]
|
||||||
|
local len = deserialize_value(seen)
|
||||||
|
for i = 1, len do
|
||||||
|
instance[i] = deserialize_value(seen)
|
||||||
|
end
|
||||||
|
len = deserialize_value(seen)
|
||||||
|
for _ = 1, len do
|
||||||
|
local key = deserialize_value(seen)
|
||||||
|
instance[key] = deserialize_value(seen)
|
||||||
|
end
|
||||||
|
if classkey then
|
||||||
|
instance[classkey] = class
|
||||||
|
end
|
||||||
|
return deserializer(instance, class)
|
||||||
|
elseif t == 243 then
|
||||||
|
--reference
|
||||||
|
return seen[deserialize_value(seen) + 1]
|
||||||
|
elseif t == 244 then
|
||||||
|
--long string
|
||||||
|
return add_to_seen(Buffer_read_string(deserialize_value(seen)), seen)
|
||||||
|
elseif t == 245 then
|
||||||
|
--long int
|
||||||
|
return Buffer_read_data("int32_t[1]", 4)[0]
|
||||||
|
elseif t == 246 then
|
||||||
|
--double
|
||||||
|
return Buffer_read_data("double[1]", 8)[0]
|
||||||
|
elseif t == 247 then
|
||||||
|
--nil
|
||||||
|
return nil
|
||||||
|
elseif t == 248 then
|
||||||
|
--false
|
||||||
|
return false
|
||||||
|
elseif t == 249 then
|
||||||
|
--true
|
||||||
|
return true
|
||||||
|
elseif t == 250 then
|
||||||
|
--short int
|
||||||
|
return Buffer_read_data("int16_t[1]", 2)[0]
|
||||||
|
elseif t == 251 then
|
||||||
|
--ctype
|
||||||
|
return ffi.typeof(deserialize_value(seen))
|
||||||
|
elseif t == 252 then
|
||||||
|
local ctype = deserialize_value(seen)
|
||||||
|
local len = deserialize_value(seen)
|
||||||
|
local read_into = ffi.typeof('$[1]', ctype)()
|
||||||
|
Buffer_read_raw(read_into, len)
|
||||||
|
return ctype(read_into[0])
|
||||||
|
else
|
||||||
|
error("unsupported serialized type " .. t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function deserialize_MiddleClass(instance, class)
|
||||||
|
return setmetatable(instance, class.__instanceDict)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function deserialize_SECL(instance, class)
|
||||||
|
return setmetatable(instance, getmetatable(class))
|
||||||
|
end
|
||||||
|
|
||||||
|
local deserialize_humpclass = setmetatable
|
||||||
|
|
||||||
|
local function deserialize_Slither(instance, class)
|
||||||
|
return getmetatable(class).allocate(instance)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function deserialize_Moonscript(instance, class)
|
||||||
|
return setmetatable(instance, class.__base)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {dumps = function(value)
|
||||||
|
serialize(value)
|
||||||
|
return ffi.string(buf, buf_pos)
|
||||||
|
end, dumpLoveFile = function(fname, value)
|
||||||
|
serialize(value)
|
||||||
|
assert(love.filesystem.write(fname, ffi.string(buf, buf_pos)))
|
||||||
|
end, loadLoveFile = function(fname)
|
||||||
|
local serializedData, error = love.filesystem.newFileData(fname)
|
||||||
|
assert(serializedData, error)
|
||||||
|
Buffer_newDataReader(serializedData:getPointer(), serializedData:getSize())
|
||||||
|
local value = deserialize_value({})
|
||||||
|
-- serializedData needs to not be collected early in a tail-call
|
||||||
|
-- so make sure deserialize_value returns before loadLoveFile does
|
||||||
|
return value
|
||||||
|
end, loadData = function(data, size)
|
||||||
|
if size == 0 then
|
||||||
|
error('cannot load value from empty data')
|
||||||
|
end
|
||||||
|
Buffer_newDataReader(data, size)
|
||||||
|
return deserialize_value({})
|
||||||
|
end, loads = function(str)
|
||||||
|
if #str == 0 then
|
||||||
|
error('cannot load value from empty string')
|
||||||
|
end
|
||||||
|
Buffer_newReader(str)
|
||||||
|
return deserialize_value({})
|
||||||
|
end, includeMetatables = function(bool)
|
||||||
|
includeMetatables = not not bool
|
||||||
|
end, register = function(name, resource)
|
||||||
|
assert(not resource_registry[name], name .. " already registered")
|
||||||
|
resource_registry[name] = resource
|
||||||
|
resource_name_registry[resource] = name
|
||||||
|
return resource
|
||||||
|
end, unregister = function(name)
|
||||||
|
resource_name_registry[resource_registry[name]] = nil
|
||||||
|
resource_registry[name] = nil
|
||||||
|
end, registerClass = function(name, class, classkey, deserializer)
|
||||||
|
if not class then
|
||||||
|
class = name
|
||||||
|
name = class.__name__ or class.name or class.__name
|
||||||
|
end
|
||||||
|
if not classkey then
|
||||||
|
if class.__instanceDict then
|
||||||
|
-- assume MiddleClass
|
||||||
|
classkey = 'class'
|
||||||
|
elseif class.__baseclass then
|
||||||
|
-- assume SECL
|
||||||
|
classkey = '__baseclass'
|
||||||
|
end
|
||||||
|
-- assume hump.class, Slither, Moonscript class or something else that doesn't store the
|
||||||
|
-- class directly on the instance
|
||||||
|
end
|
||||||
|
if not deserializer then
|
||||||
|
if class.__instanceDict then
|
||||||
|
-- assume MiddleClass
|
||||||
|
deserializer = deserialize_MiddleClass
|
||||||
|
elseif class.__baseclass then
|
||||||
|
-- assume SECL
|
||||||
|
deserializer = deserialize_SECL
|
||||||
|
elseif class.__index == class then
|
||||||
|
-- assume hump.class
|
||||||
|
deserializer = deserialize_humpclass
|
||||||
|
elseif class.__name__ then
|
||||||
|
-- assume Slither
|
||||||
|
deserializer = deserialize_Slither
|
||||||
|
elseif class.__base then
|
||||||
|
-- assume Moonscript class
|
||||||
|
deserializer = deserialize_Moonscript
|
||||||
|
else
|
||||||
|
error("no deserializer given for unsupported class library")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class_registry[name] = class
|
||||||
|
classkey_registry[name] = classkey
|
||||||
|
class_deserialize_registry[name] = deserializer
|
||||||
|
class_name_registry[class] = name
|
||||||
|
return class
|
||||||
|
end, unregisterClass = function(name)
|
||||||
|
class_name_registry[class_registry[name]] = nil
|
||||||
|
classkey_registry[name] = nil
|
||||||
|
class_deserialize_registry[name] = nil
|
||||||
|
class_registry[name] = nil
|
||||||
|
end, reserveBuffer = Buffer_prereserve, clearBuffer = Buffer_clear, version = VERSION}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
local FILE = {}
|
local FILE = {}
|
||||||
local binser = require "libs.binser"
|
local binser = require "libs.binser"
|
||||||
-- local bitser = require "libs.bitser"
|
local bitser = require "mobile_libs.bitser"
|
||||||
|
|
||||||
local serializer_used
|
local serializer_used
|
||||||
|
|
||||||
@@ -37,5 +37,5 @@ end
|
|||||||
return function(lib_name)
|
return function(lib_name)
|
||||||
assert(lib_name == 'bitser' or lib_name == 'binser', '[lib_name] must be "bitser" or "binser"')
|
assert(lib_name == 'bitser' or lib_name == 'binser', '[lib_name] must be "bitser" or "binser"')
|
||||||
serializer_used = lib_name
|
serializer_used = lib_name
|
||||||
_G.FILE = FILE
|
return FILE
|
||||||
end
|
end
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
local fs = love.filesystem
|
|
||||||
|
|
||||||
local CONFIG_FILE = '/mobile/touch_config.txt'
|
|
||||||
local _settings = fs.read(CONFIG_FILE) ~= nil and FILE.read(CONFIG_FILE) or {}
|
|
||||||
local _defaultSettings = {
|
|
||||||
firstTime = true,
|
|
||||||
__default__={
|
|
||||||
{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, y=420,key= 'restart',r=35,iconSize=60,alpha=0.4},
|
|
||||||
},
|
|
||||||
|
|
||||||
---@type table<string,string>[]
|
|
||||||
bind = {},
|
|
||||||
}
|
|
||||||
|
|
||||||
return setmetatable(
|
|
||||||
{__default__ = _defaultSettings},
|
|
||||||
{
|
|
||||||
__index = function(_, k)
|
|
||||||
if _settings[k] == nil then
|
|
||||||
_settings[k] = _defaultSettings[k]
|
|
||||||
FILE.write(CONFIG_FILE,_settings)
|
|
||||||
end
|
|
||||||
return _settings[k]
|
|
||||||
end,
|
|
||||||
__newindex = function(_, k, v)
|
|
||||||
_settings[k] = v
|
|
||||||
FILE.write(CONFIG_FILE,_settings)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
)
|
|
||||||
67
mobile_libs/touch_settings.lua
Normal file
67
mobile_libs/touch_settings.lua
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
local fs = love.filesystem
|
||||||
|
local FILE=require'mobile_libs.file''binser'
|
||||||
|
|
||||||
|
local CONFIG_FILE = 'mobile/touch_config.txt'
|
||||||
|
love.filesystem.createDirectory('mobile')
|
||||||
|
local _settings = fs.read(CONFIG_FILE) ~= nil and FILE.read(CONFIG_FILE) or {}
|
||||||
|
local _defaultSettings = {
|
||||||
|
firstTime = true,
|
||||||
|
|
||||||
|
---@type table<string,string>[]
|
||||||
|
bind = {
|
||||||
|
{
|
||||||
|
{type='button',x= 1 * 70 + 120,y = 1 * 70 + 120, r = 30, key= 'up',iconSize=50},
|
||||||
|
{type='button',x= 2 * 70 + 120,y = 1 * 70 + 120, r = 30, key= 'down',iconSize=50},
|
||||||
|
{type='button',x= 3 * 70 + 120,y = 1 * 70 + 120, r = 30, key= 'left',iconSize=50},
|
||||||
|
{type='button',x= 4 * 70 + 120,y = 1 * 70 + 120, r = 30, key= 'right',iconSize=50},
|
||||||
|
{type='button',x= 5 * 70 + 120,y = 1 * 70 + 120, r = 30, key= 'menu_decide',iconSize=50},
|
||||||
|
|
||||||
|
{type='button',x= 1 * 70 + 120,y = 2 * 70 + 120, r = 30, key= 'rotate_left',iconSize=50},
|
||||||
|
{type='button',x= 2 * 70 + 120,y = 2 * 70 + 120, r = 30, key= 'rotate_left2',iconSize=50},
|
||||||
|
{type='button',x= 3 * 70 + 120,y = 2 * 70 + 120, r = 30, key= 'rotate_right',iconSize=50},
|
||||||
|
{type='button',x= 4 * 70 + 120,y = 2 * 70 + 120, r = 30, key= 'rotate_right2',iconSize=50},
|
||||||
|
{type='button',x= 5 * 70 + 120,y = 2 * 70 + 120, r = 30, key= 'retry',iconSize=50},
|
||||||
|
|
||||||
|
{type='button',x= 1 * 70 + 120,y = 3 * 70 + 120, r = 30, key= '1',iconSize=50},
|
||||||
|
{type='button',x= 2 * 70 + 120,y = 3 * 70 + 120, r = 30, key= '2',iconSize=50},
|
||||||
|
{type='button',x= 3 * 70 + 120,y = 3 * 70 + 120, r = 30, key= '3',iconSize=50},
|
||||||
|
{type='button',x= 4 * 70 + 120,y = 3 * 70 + 120, r = 30, key= '4',iconSize=50},
|
||||||
|
{type='button',x= 5 * 70 + 120,y = 3 * 70 + 120, r = 30, key= '5',iconSize=50},
|
||||||
|
|
||||||
|
-- {type='button',x= 1 * 70 + 120,y = 4 * 70 + 120, r = 30, key= 'up',iconSize=50},
|
||||||
|
{type='button',x= 2 * 70 + 120,y = 4 * 70 + 120, r = 30, key='touch_settings',iconSize=50},
|
||||||
|
{type='button',x= 3 * 70 + 120,y = 4 * 70 + 120, r = 30, key= 'align_view',iconSize=50},
|
||||||
|
{type='button',x= 4 * 70 + 120,y = 4 * 70 + 120, r = 30, key= 'menu_back',iconSize=50},
|
||||||
|
-- {type='button',x= 5 * 70 + 120,y = 4 * 70 + 120, r = 30, key= 'up',iconSize=50},
|
||||||
|
|
||||||
|
}, -- 1
|
||||||
|
{
|
||||||
|
{type='button',x= 70,y=280,key= 'up',r=45,iconSize=60,alpha=0.4,shape='circle'},
|
||||||
|
{type='button',x= 70,y=430,key= 'down',r=45,iconSize=60,alpha=0.4,shape='circle'},
|
||||||
|
{type='button',x= -5,y=355,key= 'left',r=45,iconSize=60,alpha=0.4,shape='circle'},
|
||||||
|
{type='button',x= 145,y=355,key= 'right',r=45,iconSize=60,alpha=0.4,shape='circle'},
|
||||||
|
{type='button',x=640- -5,y=355,key= 'rotate_left',r=45,iconSize=60,alpha=0.4,shape='circle'},
|
||||||
|
{type='button',x=640-145,y=355,key= 'rotate_left2',r=45,iconSize=60,alpha=0.4,shape='circle'},
|
||||||
|
{type='button',x=640- 70,y=430,key= 'rotate_right',r=45,iconSize=60,alpha=0.4,shape='circle'},
|
||||||
|
{type='button',x=640- 70,y=280,key='rotate_right2',r=45,iconSize=60,alpha=0.4,shape='circle'},
|
||||||
|
{type='button',x=320, y=420,key= 'retry',r=35,iconSize=60,alpha=0.4,shape='circle'},
|
||||||
|
} -- 2
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(
|
||||||
|
{__default__ = _defaultSettings},
|
||||||
|
{
|
||||||
|
__index = function(_, k)
|
||||||
|
if _settings[k] == nil then
|
||||||
|
_settings[k] = _defaultSettings[k]
|
||||||
|
FILE.write(CONFIG_FILE,_settings)
|
||||||
|
end
|
||||||
|
return _settings[k]
|
||||||
|
end,
|
||||||
|
__newindex = function(_, k, v)
|
||||||
|
_settings[k] = v
|
||||||
|
FILE.write(CONFIG_FILE,_settings)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -15,34 +15,34 @@ local function mDrawQ(obj,quad,x,y,a,k)
|
|||||||
love.graphics.draw(obj,quad,x,y,a,k,nil,w*.5,h*.5)
|
love.graphics.draw(obj,quad,x,y,a,k,nil,w*.5,h*.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
local empty_quad
|
local alternativePfunction={}
|
||||||
|
local alternativeRfunction={
|
||||||
|
touch_settings=function()
|
||||||
|
if (
|
||||||
|
scene.title ~= 'Game' and
|
||||||
|
scene.title ~= TouchConfigScene.title
|
||||||
|
) then
|
||||||
|
scene = TouchConfigScene()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
local empty_quad=gc_newQuad(1,1,1,1,1,1)
|
||||||
-- A table containing quads used to draw icons for virtual control system.
|
-- A table containing quads used to draw icons for virtual control system.
|
||||||
-- local virtual_quad=setmetatable((function()
|
|
||||||
-- local t={}
|
|
||||||
-- local w=180
|
|
||||||
-- empty_quad=gc_newQuad(0,0,1,1,5*w,7*w)
|
|
||||||
-- for i,name in next,{
|
|
||||||
-- 'left','right','up','down','',
|
|
||||||
-- 'rotate_right','rotate_left','','','',
|
|
||||||
-- '','','','','',
|
|
||||||
-- '','','','','',
|
|
||||||
-- '','','menu_back','','',
|
|
||||||
-- '','','','','',
|
|
||||||
-- '','','','','menu_decide',
|
|
||||||
-- } do if #name>0 then t[name]=gc_newQuad((i-1)%5*w,math.floor((i-1)/5)*w,w,w,5*w,7*w) end end
|
|
||||||
-- t.rotate_right2, t.rotate_left2 = t.rotate_right, t.rotate_left
|
|
||||||
-- return t
|
|
||||||
-- end)(),{
|
|
||||||
-- __index=function() return empty_quad end
|
|
||||||
-- })
|
|
||||||
local virtual_quad=setmetatable((function()
|
local virtual_quad=setmetatable((function()
|
||||||
local t={}
|
local t={}
|
||||||
local w=180
|
local w=180
|
||||||
empty_quad=gc_newQuad(0,0,1,1,5*w,2*w)
|
empty_quad=gc_newQuad(0,0,1,1,5*w,7*w)
|
||||||
for i,name in next,{
|
for i,name in next,{
|
||||||
'left','right','up','down','restart',
|
'left','right','up','down','',
|
||||||
'rotate_right','rotate_left','rotate_right2','rotate_left2'
|
'rotate_right','rotate_left','rotate_180','hold','align_view',
|
||||||
} do if #name>0 then t[name]=gc_newQuad((i-1)%5*w,math.floor((i-1)/5)*w,w,w,5*w,2*w) end end
|
'','','','','',
|
||||||
|
'1','2','3','4','5',
|
||||||
|
'','retry','','menu_back','',
|
||||||
|
'touch_settings','','','','',
|
||||||
|
'','','','','menu_decide',
|
||||||
|
} do if #name>0 then t[name]=gc_newQuad((i-1)%5*w,math.floor((i-1)/5)*w,w,w,5*w,7*w) end end
|
||||||
|
t.rotate_right2, t.rotate_left2 = t.rotate_right, t.rotate_left
|
||||||
return t
|
return t
|
||||||
end)(),{
|
end)(),{
|
||||||
__index=function() return empty_quad end
|
__index=function() return empty_quad end
|
||||||
@@ -61,11 +61,11 @@ function control_type.button:new(data)
|
|||||||
x=data.x or 320,
|
x=data.x or 320,
|
||||||
y=data.y or 240,
|
y=data.y or 240,
|
||||||
r=data.r or 80, -- size
|
r=data.r or 80, -- size
|
||||||
shape=data.shape or 'circle',
|
shape=data.shape or 'square',
|
||||||
key=data.key or 'X',
|
key=data.key or 'X',
|
||||||
iconSize=data.iconSize or 60,
|
iconSize=data.iconSize or 60,
|
||||||
alpha=data.alpha or 0.75,
|
alpha=data.alpha or 0.75,
|
||||||
quad=virtual_quad[data.key]
|
quad=virtual_quad[data.key],
|
||||||
},self)
|
},self)
|
||||||
end
|
end
|
||||||
function control_type.button:export()
|
function control_type.button:export()
|
||||||
@@ -78,7 +78,7 @@ function control_type.button:export()
|
|||||||
shape = self.shape,
|
shape = self.shape,
|
||||||
key = self.key,
|
key = self.key,
|
||||||
iconSize = self.iconSize,
|
iconSize = self.iconSize,
|
||||||
alpha = self.alpha
|
alpha = self.alpha,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
function control_type.button:reset()
|
function control_type.button:reset()
|
||||||
@@ -91,13 +91,21 @@ function control_type.button:press(_,_,id)
|
|||||||
self.lastPressTime=love.timer.getTime()
|
self.lastPressTime=love.timer.getTime()
|
||||||
self.pressingID=id
|
self.pressingID=id
|
||||||
-- love.keypressed(self.key, love.keyboard.getScancodeFromKey(self.key))
|
-- love.keypressed(self.key, love.keyboard.getScancodeFromKey(self.key))
|
||||||
SCENE:onInputPress{input=self.key,type="virtual"}
|
if alternativePfunction[self.key] then
|
||||||
|
alternativePfunction[self.key]()
|
||||||
|
else
|
||||||
|
scene:onInputPress{input=self.key,type="virtual"}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
function control_type.button:release()
|
function control_type.button:release()
|
||||||
self.pressed=false
|
self.pressed=false
|
||||||
self.pressingID=false
|
self.pressingID=false
|
||||||
-- love.keyreleased(self.key,love.keyboard.getScancodeFromKey(self.key))
|
-- love.keyreleased(self.key,love.keyboard.getScancodeFromKey(self.key))
|
||||||
SCENE:onInputRelease{input=self.key,type="virtual"}
|
if alternativeRfunction[self.key] then
|
||||||
|
alternativeRfunction[self.key]()
|
||||||
|
else
|
||||||
|
scene:onInputRelease{input=self.key,type="virtual"}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
function control_type.button:drag(dx,dy)
|
function control_type.button:drag(dx,dy)
|
||||||
self.x,self.y=self.x+dx,self.y+dy
|
self.x,self.y=self.x+dx,self.y+dy
|
||||||
@@ -158,6 +166,8 @@ VCTRL.hasChanged = false
|
|||||||
---@field iconSize? number
|
---@field iconSize? number
|
||||||
---@field alpha? number
|
---@field alpha? number
|
||||||
---@field show? boolean
|
---@field show? boolean
|
||||||
|
---@field pressFunc function|nil
|
||||||
|
---@field releaseFunc function|nil
|
||||||
|
|
||||||
---@param ... VCTRL.data[]
|
---@param ... VCTRL.data[]
|
||||||
---Adding (multiple) virtual button(s)
|
---Adding (multiple) virtual button(s)
|
||||||
@@ -165,6 +175,14 @@ function VCTRL.new(...)
|
|||||||
for _,d in pairs(...) do table.insert(VCTRL,control_type[d.type]:new(d)) end
|
for _,d in pairs(...) do table.insert(VCTRL,control_type[d.type]:new(d)) end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param key string
|
||||||
|
---@param pfunc function|nil
|
||||||
|
---@param rfunc function|nil
|
||||||
|
function VCTRL.setAltFunction(key,pfunc,rfunc)
|
||||||
|
alternativePfunction[key] = pfunc
|
||||||
|
alternativeRfunction[key] = rfunc
|
||||||
|
end
|
||||||
|
|
||||||
---@param toggle boolean|false
|
---@param toggle boolean|false
|
||||||
---Enabling virtual control or not
|
---Enabling virtual control or not
|
||||||
function VCTRL.toggle(toggle)
|
function VCTRL.toggle(toggle)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 46 KiB |
@@ -1,6 +1,6 @@
|
|||||||
---@diagnostic disable: cast-local-type
|
---@diagnostic disable: cast-local-type
|
||||||
local TouchConfigScene = Scene:extend()
|
local TouchConfigScene = Scene:extend()
|
||||||
TouchConfigScene.title = "Touchscreen config"
|
TouchConfigScene.title = "Touchscreen configuration"
|
||||||
|
|
||||||
local function roundUnit(n,u)
|
local function roundUnit(n,u)
|
||||||
local u = u or 1
|
local u = u or 1
|
||||||
@@ -12,6 +12,12 @@ local function drawText(text, x, y, size, orientation, color)
|
|||||||
love.graphics.setColor(color)
|
love.graphics.setColor(color)
|
||||||
love.graphics.printf(text, x, y, size*2, orientation, nil, 0.5)
|
love.graphics.printf(text, x, y, size*2, orientation, nil, 0.5)
|
||||||
end
|
end
|
||||||
|
local function math_clamp(x, min, max)
|
||||||
|
if max < min then
|
||||||
|
min, max = max, min
|
||||||
|
end
|
||||||
|
return x < min and min or (x > max and max or x)
|
||||||
|
end
|
||||||
|
|
||||||
local buttonList
|
local buttonList
|
||||||
local sliderList = {}
|
local sliderList = {}
|
||||||
@@ -25,9 +31,9 @@ local function exitSceneFunc(saved)
|
|||||||
VCTRL.release()
|
VCTRL.release()
|
||||||
BUTTON.release(buttonList)
|
BUTTON.release(buttonList)
|
||||||
if TOUCH_SETTINGS.firstTime and not saved then
|
if TOUCH_SETTINGS.firstTime and not saved then
|
||||||
SCENE = InputConfigScene(true)
|
scene = InputConfigScene(true)
|
||||||
else
|
else
|
||||||
SCENE = TitleScene()
|
scene = TitleScene()
|
||||||
TOUCH_SETTINGS.firstTime = false
|
TOUCH_SETTINGS.firstTime = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -56,7 +62,7 @@ buttonList = {
|
|||||||
-- codeWhenReleased = function()
|
-- codeWhenReleased = function()
|
||||||
-- VCTRL.release()
|
-- VCTRL.release()
|
||||||
-- BUTTON.release(buttonList)
|
-- BUTTON.release(buttonList)
|
||||||
-- SCENE = TouchConfigPreviewScene()
|
-- scene = TouchConfigPreviewScene()
|
||||||
-- end
|
-- end
|
||||||
-- },
|
-- },
|
||||||
resetAll = BUTTON.new{
|
resetAll = BUTTON.new{
|
||||||
@@ -72,8 +78,8 @@ buttonList = {
|
|||||||
VCTRL.focus = nil; focusingButton = nil
|
VCTRL.focus = nil; focusingButton = nil
|
||||||
VCTRL.hasChanged = false
|
VCTRL.hasChanged = false
|
||||||
VCTRL.clearAll()
|
VCTRL.clearAll()
|
||||||
VCTRL.new(TOUCH_SETTINGS.__default__)
|
VCTRL.new(TOUCH_SETTINGS.__default__.bind[1])
|
||||||
TOUCH_SETTINGS.bind[1] = TOUCH_SETTINGS.__default__
|
TOUCH_SETTINGS.bind[1] = TOUCH_SETTINGS.__default__.bind[1]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
@@ -94,7 +100,7 @@ buttonList = {
|
|||||||
exitSceneFunc(true)
|
exitSceneFunc(true)
|
||||||
elseif selection == 2 then
|
elseif selection == 2 then
|
||||||
VCTRL.clearAll()
|
VCTRL.clearAll()
|
||||||
VCTRL.new(TOUCH_SETTINGS.bind[1])
|
VCTRL.new(TOUCH_SETTINGS.bind[1] or {})
|
||||||
-- love.window.showMessageBox("Discarded!", "Your changes was discarded!")
|
-- love.window.showMessageBox("Discarded!", "Your changes was discarded!")
|
||||||
|
|
||||||
exitSceneFunc()
|
exitSceneFunc()
|
||||||
@@ -239,16 +245,12 @@ function TouchConfigScene:render()
|
|||||||
|
|
||||||
for _, v in ipairs(VCTRL) do
|
for _, v in ipairs(VCTRL) do
|
||||||
if v ~= focusingButton then
|
if v ~= focusingButton then
|
||||||
v:draw(
|
v:draw(v.alpha * (focusingButton and 0.25 or 1))
|
||||||
focusingButton and
|
|
||||||
(v.show and 0.5 or 0.1) or
|
|
||||||
(v.show and 1 or 0.5)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if focusingButton then
|
if focusingButton then
|
||||||
focusingButton:draw(
|
focusingButton:draw(
|
||||||
math.clamp(
|
math_clamp(
|
||||||
math.sin(love.timer.getTime()*4)*.5+0.1,
|
math.sin(love.timer.getTime()*4)*.5+0.1,
|
||||||
focusingButton.show and 1 or 0.1, 1
|
focusingButton.show and 1 or 0.1, 1
|
||||||
)
|
)
|
||||||
@@ -259,7 +261,7 @@ function TouchConfigScene:render()
|
|||||||
BUTTON.draw(buttonList)
|
BUTTON.draw(buttonList)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param e SCENE_onInput
|
|
||||||
function TouchConfigScene:onInputMove(e)
|
function TouchConfigScene:onInputMove(e)
|
||||||
if e.type == "touch" or (e.type == "mouse" and love.mouse.isDown(1)) then
|
if e.type == "touch" or (e.type == "mouse" and love.mouse.isDown(1)) then
|
||||||
if VCTRL.drag(e.dx, e.dy, e.id or 1) then VCTRL.hasChanged = true end
|
if VCTRL.drag(e.dx, e.dy, e.id or 1) then VCTRL.hasChanged = true end
|
||||||
@@ -267,7 +269,7 @@ function TouchConfigScene:onInputMove(e)
|
|||||||
BUTTON.checkHovering(buttonList, e.x, e.y)
|
BUTTON.checkHovering(buttonList, e.x, e.y)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---@param e SCENE_onInput
|
|
||||||
function TouchConfigScene:onInputPress(e)
|
function TouchConfigScene:onInputPress(e)
|
||||||
if e.type == "mouse" or e.type == "touch" then
|
if e.type == "mouse" or e.type == "touch" then
|
||||||
if not (
|
if not (
|
||||||
@@ -281,7 +283,7 @@ function TouchConfigScene:onInputPress(e)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
---@param e SCENE_onInput
|
|
||||||
function TouchConfigScene:onInputRelease(e)
|
function TouchConfigScene:onInputRelease(e)
|
||||||
if e.type == "mouse" or e.type == "touch" then
|
if e.type == "mouse" or e.type == "touch" then
|
||||||
if not BUTTON.release(buttonList, e.x, e.y, e.id) then
|
if not BUTTON.release(buttonList, e.x, e.y, e.id) then
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ Scene = Object:extend()
|
|||||||
function Scene:new() end
|
function Scene:new() end
|
||||||
function Scene:update() end
|
function Scene:update() end
|
||||||
function Scene:render() end
|
function Scene:render() end
|
||||||
function Scene:onInputPress() end
|
function Scene:onInputMove(e) end
|
||||||
function Scene:onInputRelease() end
|
function Scene:onInputPress(e) end
|
||||||
|
function Scene:onInputRelease(e) end
|
||||||
|
|
||||||
ExitScene = require "scene.exit"
|
ExitScene = require "scene.exit"
|
||||||
GameScene = require "scene.game"
|
GameScene = require "scene.game"
|
||||||
|
|||||||
Reference in New Issue
Block a user