380 lines
9.1 KiB
Lua
380 lines
9.1 KiB
Lua
--[[
|
|
This file is part of Ice Lua Components.
|
|
|
|
Ice Lua Components is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Ice Lua Components is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with Ice Lua Components. If not, see <http://www.gnu.org/licenses/>.
|
|
]]
|
|
|
|
dofile("pkg/base/lib_sdlkey.lua")
|
|
|
|
function string.split(s, sep, plain)
|
|
local start = 1
|
|
local done = false
|
|
local function pass(i, j, ...)
|
|
if i then
|
|
local seg = s:sub(start, i - 1)
|
|
start = j + 1
|
|
return seg, ...
|
|
else
|
|
done = true
|
|
return s:sub(start)
|
|
end
|
|
end
|
|
local result = {}
|
|
while not done do
|
|
if sep == '' then done = true result[#result+1]=s end
|
|
result[#result+1]=pass(s:find(sep, start, plain))
|
|
end
|
|
return result
|
|
end
|
|
|
|
gfx_font = common.img_load("pkg/iceball/halp/font-large.tga")
|
|
mus_rollb = common.mus_load_it("pkg/iceball/halp/gm-rollb-munch.it")
|
|
client.mus_vol_set(1.0)
|
|
client.mus_play(mus_rollb)
|
|
|
|
function unhex(s)
|
|
local htab = {
|
|
["0"] = 0x0,
|
|
["1"] = 0x1,
|
|
["2"] = 0x2,
|
|
["3"] = 0x3,
|
|
["4"] = 0x4,
|
|
["5"] = 0x5,
|
|
["6"] = 0x6,
|
|
["7"] = 0x7,
|
|
["8"] = 0x8,
|
|
["9"] = 0x9,
|
|
["A"] = 0xA,
|
|
["B"] = 0xB,
|
|
["C"] = 0xC,
|
|
["D"] = 0xD,
|
|
["E"] = 0xE,
|
|
["F"] = 0xF,
|
|
["a"] = 0xa,
|
|
["b"] = 0xb,
|
|
["c"] = 0xc,
|
|
["d"] = 0xd,
|
|
["e"] = 0xe,
|
|
["f"] = 0xf,
|
|
}
|
|
|
|
local v = 0
|
|
local i
|
|
for i=1,#s do
|
|
v = v*16 + htab[s:sub(i,i)]
|
|
end
|
|
return v
|
|
end
|
|
|
|
function tparse(s)
|
|
local l = string.split(s, "\n")
|
|
l[#l] = nil
|
|
|
|
local i
|
|
for i=1,#l do
|
|
local v = l[i]
|
|
local r = {data = v, color = 0xFFFFFFFF}
|
|
if v:sub(1,1) == "$" then
|
|
local c = v:sub(2,2)
|
|
if c == "-" then
|
|
r.data = "---------------------------------"
|
|
r.color = 0xFF888888
|
|
elseif c == "p" then
|
|
r.data = "* "..v:sub(3,#v)
|
|
r.color = 0xFFAAFFFF
|
|
elseif c == "c" then
|
|
r.data = v:sub(3+8,#v)
|
|
r.color = unhex(v:sub(3,2+8))
|
|
else
|
|
error("invalid text command: "..v)
|
|
end
|
|
end
|
|
l[i] = r
|
|
end
|
|
|
|
return {text = l, camy = 0}
|
|
end
|
|
|
|
function sprint(x, y, color, align, s, ...)
|
|
if not s then return end
|
|
local cx
|
|
if align == 0 then
|
|
cx = x
|
|
elseif align == 1 then
|
|
cx = x - #s * 4*6 / 2
|
|
else
|
|
cx = x - #s * 4*6
|
|
end
|
|
local i
|
|
for i=1,#s do
|
|
local c = s:sub(i,i):byte()
|
|
client.img_blit(gfx_font, cx, y, 4*6, 4*8, 4*6*(c-32), 0, color)
|
|
cx = cx + 4*6
|
|
end
|
|
sprint(x, y, color, align, ...)
|
|
end
|
|
|
|
blink_cursor = "_"
|
|
blink_time = 0
|
|
|
|
function client.hook_tick(sec_current, sec_delta)
|
|
if blink_time < sec_current then
|
|
if blink_cursor == "_" then
|
|
blink_cursor = " "
|
|
else
|
|
blink_cursor = "_"
|
|
end
|
|
blink_time = sec_current + 0.25
|
|
end
|
|
return 0.033
|
|
end
|
|
|
|
profile = common.json_load("clsave/pub/user.json")
|
|
config = common.json_load("clsave/config.json")
|
|
selected = 1
|
|
|
|
fields = {
|
|
{profile, "name", "Nickname", "string"},
|
|
{nil, nil, "Resolution", "resolution"},
|
|
{config["video"], "fullscreen", "Fullscreen", "boolean"},
|
|
{profile, "sensitivity", "Mouse Sensitivity", "float", 0.5, 4.0, 0.25},
|
|
{config["audio"], "mus_volume", "Music Volume", "float", 0, 1, 0.1},
|
|
{config["audio"], "volume", "Sound Volume", "float", 0, 1, 0.1},
|
|
{config["video"], "gl_vsync", "VSync", "boolean"},
|
|
{config["video"], "antialiasinglevel", "Anti-Aliasing", "select",
|
|
{0, 1, 2, 4, 8, 16}, {"Off", "1x", "2x", "4x", "8x", "16x"}},
|
|
{config["video"], "smoothlighting", "Lighting", "boolean", {"Flat", "Smooth"}},
|
|
{nil, nil, "Save and Exit", "action_save"},
|
|
{nil, nil, "Exit without Saving", "action_exit"}
|
|
}
|
|
|
|
function get_value_default(field)
|
|
if field[1] ~= nil and field[2] ~= nil then
|
|
return field[1][field[2]]
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
function set_value_default(field, value)
|
|
if field[1] ~= nil and field[2] ~= nil then
|
|
field[1][field[2]] = value
|
|
end
|
|
end
|
|
|
|
function print_value_default(field, value)
|
|
return value
|
|
end
|
|
|
|
function key_value_default()
|
|
end
|
|
|
|
function key_value_select(field, value, key, values)
|
|
for i=1,#values do
|
|
if values[i] == value then
|
|
if key == SDLK_RIGHT or key == SDLK_RETURN then
|
|
if i == #values then
|
|
return values[1]
|
|
else
|
|
return values[i + 1]
|
|
end
|
|
elseif key == SDLK_LEFT then
|
|
if i == 1 then
|
|
return values[#values]
|
|
else
|
|
return values[i - 1]
|
|
end
|
|
else
|
|
return values[i]
|
|
end
|
|
end
|
|
end
|
|
|
|
return values[1]
|
|
end
|
|
|
|
field_types = {}
|
|
|
|
-- TODO: Add actual resolution size check from SDL (Note: iceball requires at least 800x600, so check for that)
|
|
local resolution_list = {"800x600", "1024x600", "1024x768", "1280x720", "1280x800", "1280x960", "1280x1024",
|
|
"1366x768", "1440x900", "1600x900", "1600x1200", "1680x1050", "1920x1080", "1920x1200", "2560x1440", "2560x1600",
|
|
"3840x2160"}
|
|
|
|
field_types["resolution"] = {}
|
|
field_types["resolution"]["get"] =
|
|
function(field, value)
|
|
return config["video"]["width"] .. "x" .. config["video"]["height"]
|
|
end
|
|
field_types["resolution"]["set"] =
|
|
function(field, value)
|
|
local res = string.split(value, "x")
|
|
if #res == 2 and tonumber(res[1]) ~= nil and tonumber(res[2]) ~= nil then
|
|
config["video"]["width"] = tonumber(res[1])
|
|
config["video"]["height"] = tonumber(res[2])
|
|
end
|
|
end
|
|
field_types["resolution"]["key"] =
|
|
function(field, value, key)
|
|
return key_value_select(field, value, key, resolution_list)
|
|
end
|
|
|
|
field_types["boolean"] = {}
|
|
field_types["boolean"]["print"] =
|
|
function(field, value)
|
|
local values = field[5]
|
|
if values == nil then values = {"Off", "On"} end
|
|
if value then return values[2] else return values[1] end
|
|
end
|
|
field_types["boolean"]["key"] =
|
|
function(field, value, key, uni)
|
|
if key == SDLK_LEFT or key == SDLK_RIGHT or key == SDLK_RETURN then
|
|
return not value
|
|
else
|
|
return value
|
|
end
|
|
end
|
|
|
|
field_types["float"] = {}
|
|
field_types["float"]["print"] =
|
|
function(field, value)
|
|
return math.floor((value * 100) + 0.5) .. "%"
|
|
end
|
|
field_types["float"]["key"] =
|
|
function(field, value, key, uni)
|
|
local min = field[5]
|
|
local max = field[6]
|
|
local step = field[7]
|
|
if min == nil then min = 0 end
|
|
if max == nil then max = 1 end
|
|
if step == nil then step = (max - min) * 10 end
|
|
if key == SDLK_RIGHT then
|
|
return math.min(max, value + step)
|
|
elseif key == SDLK_LEFT then
|
|
return math.max(min, value - step)
|
|
end
|
|
end
|
|
|
|
field_types["select"] = {}
|
|
field_types["select"]["print"] =
|
|
function(field, value)
|
|
local values = field[5]
|
|
if field[6] ~= nil then
|
|
local i = 1
|
|
for j=1,#values do
|
|
if values[j] == value then
|
|
i = j
|
|
end
|
|
end
|
|
return field[6][i]
|
|
else
|
|
return value
|
|
end
|
|
end
|
|
field_types["select"]["key"] =
|
|
function(field, value, key, uni)
|
|
return key_value_select(field, value, key, field[5])
|
|
end
|
|
|
|
field_types["string"] = {}
|
|
field_types["string"]["key"] =
|
|
function(field, value, key, uni)
|
|
if key == SDLK_BACKSPACE then
|
|
return string.sub(value, 1, -2)
|
|
elseif key >= 32 and key <= 126 then
|
|
return value .. string.char(uni)
|
|
else
|
|
return value
|
|
end
|
|
end
|
|
|
|
for k,v in pairs(field_types) do
|
|
if v["get"] == nil then v["get"] = get_value_default end
|
|
if v["set"] == nil then v["set"] = set_value_default end
|
|
if v["print"] == nil then v["print"] = print_value_default end
|
|
if v["key"] == nil then v["key"] = key_value_default end
|
|
end
|
|
|
|
function client.hook_key(key, state, modif, uni)
|
|
local field = fields[selected]
|
|
local field_type = field_types[field[4]]
|
|
local value = nil
|
|
if field_type ~= nil then
|
|
value = field_type["get"](field)
|
|
end
|
|
|
|
if state then
|
|
if key == SDLK_RETURN and field[4]:find("action") then
|
|
if field[4] == "action_save" then
|
|
common.json_write("clsave/pub/user.json", profile)
|
|
common.json_write("clsave/config.json", config)
|
|
client.create_launcher("pkg/iceball/launch")
|
|
-- client.mk_sys_execv()
|
|
elseif field[4] == "action_exit" then
|
|
client.create_launcher("pkg/iceball/launch")
|
|
-- client.mk_sys_execv()
|
|
end
|
|
elseif key == SDLK_UP then
|
|
selected = selected - 1
|
|
if selected <= 0 then
|
|
selected = #fields
|
|
end
|
|
elseif key == SDLK_DOWN then
|
|
selected = selected + 1
|
|
if selected > #fields then
|
|
selected = 1
|
|
end
|
|
elseif field_type ~= nil then
|
|
value = field_type["key"](field, value, key, uni)
|
|
end
|
|
end
|
|
|
|
if field_type ~= nil then
|
|
field_type["set"](field, value)
|
|
end
|
|
|
|
end
|
|
|
|
function client.hook_render()
|
|
local sw, sh = client.screen_get_dims()
|
|
local xl = 10
|
|
local xr = sw - 30
|
|
local oy = 10
|
|
local oh = 50
|
|
-- TODO: Add scrolling/centering, for now we almost fill the screen on 800x600
|
|
for i=1,#fields do
|
|
local y = oy + ((i - 1) * oh)
|
|
local field = fields[i]
|
|
local field_type = field_types[field[4]]
|
|
local key = field[3]
|
|
if selected == i then
|
|
key = ">" .. key
|
|
if field[4] == "string" then
|
|
sprint(xr, y, 0xFFFFFFFF, 0, blink_cursor)
|
|
end
|
|
else
|
|
key = " " .. key
|
|
end
|
|
sprint(xl, y, 0xFFFFFFFF, 0, key)
|
|
if field_type ~= nil then
|
|
local value = field_type["get"](field)
|
|
if value ~= nil then
|
|
sprint(xr, y, 0xFFFFFFFF, -1, field_type["print"](field, value))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
client.map_fog_set(0, 35, 75, 30.0)
|
|
|