Add WIP digistuff touchscreen exporting
This commit is contained in:
parent
3c52ddff9b
commit
c01a5fa734
|
@ -22,6 +22,8 @@ default (dynamically loaded when required).
|
|||
if you plan to import them again.
|
||||
- The ability to load existing formspecs (provided they are version 2 or
|
||||
above).
|
||||
- The ability to export to (but not import from) digistuff touchscreen
|
||||
formspecs.
|
||||
|
||||
## Limitations
|
||||
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
--
|
||||
-- Formspec AST to digistuff touchscreen converter
|
||||
--
|
||||
-- Copyright © 2020 by luk3yx.
|
||||
--
|
||||
-- This program is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU Affero General Public License as
|
||||
-- published by the Free Software Foundation, either version 3 of the
|
||||
-- License, or (at your option) any later version.
|
||||
--
|
||||
-- This program 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 Affero General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Affero General Public License
|
||||
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
--
|
||||
|
||||
local basic_types = {}
|
||||
for _, t in ipairs({'image', 'field', 'pwdfield', 'textarea', 'label',
|
||||
'vertlabel', 'button', 'button_exit'}) do
|
||||
basic_types[t] = true
|
||||
end
|
||||
|
||||
local function export(tree, backport_func)
|
||||
tree = formspec_ast.flatten(tree)
|
||||
|
||||
-- Modify box nodes before calling backport_func() to fix alignment
|
||||
for node in formspec_ast.find(tree, 'box') do
|
||||
-- Boxes can be partially emulated with images.
|
||||
node.type = 'image'
|
||||
node.texture_name = 'halo.png^[colorize:' .. node.color
|
||||
node.color = nil
|
||||
end
|
||||
|
||||
if backport_func then
|
||||
tree = backport_func(tree)
|
||||
end
|
||||
|
||||
local fs_v2 = (tree.formspec_version or 1) >= 2
|
||||
tree.formspec_version = nil
|
||||
if tree[1] and tree[1].type == 'size' then
|
||||
table.remove(tree, 1)
|
||||
end
|
||||
for _, node in ipairs(tree) do
|
||||
if node.type == 'dropdown' or node.type == 'textlist' then
|
||||
node.selected_id, node.selected_idx = node.selected_idx, nil
|
||||
node.choices, node.item = node.item, nil
|
||||
-- Later versions of the digustuff mod require a height field even
|
||||
-- for formspec version 1 (breaking dropdowns on older clients).
|
||||
node.h = node.h or 0.81
|
||||
elseif node.type == 'image_button' or
|
||||
node.type == 'image_button_exit' then
|
||||
node.image, node.texture_name = node.texture_name, nil
|
||||
elseif not basic_types[node.type] then
|
||||
return nil, 'Unsupported node type: ' .. node.type
|
||||
end
|
||||
|
||||
if not node.command then
|
||||
node.command = 'add' .. node.type
|
||||
end
|
||||
node.type = nil
|
||||
for _, i in ipairs({"x", "y", "w", "h"}) do
|
||||
if node[i] then
|
||||
node[i:upper()] = node[i]
|
||||
node[i] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(tree, 1, {command = 'clear'})
|
||||
table.insert(tree, 2, {command = 'realcoordinates', enabled = fs_v2})
|
||||
return tree
|
||||
end
|
||||
|
||||
local function very_basic_dump(obj)
|
||||
local obj_type = type(obj)
|
||||
if obj_type == 'string' then
|
||||
return ('%q'):format(obj)
|
||||
elseif obj_type ~= 'table' then
|
||||
return tostring(obj)
|
||||
end
|
||||
|
||||
local t = {}
|
||||
for k, v in pairs(obj) do
|
||||
if type(k) ~= 'string' or not k:match('^[A-Za-z_]+$') then
|
||||
k = '[' .. very_basic_dump(k) .. ']'
|
||||
end
|
||||
local line = k .. ' = ' .. very_basic_dump(v)
|
||||
if k == 'command' then
|
||||
table.insert(t, 1, line)
|
||||
else
|
||||
table.insert(t, line)
|
||||
end
|
||||
end
|
||||
|
||||
return '{' .. table.concat(t, ', ') .. '}'
|
||||
end
|
||||
|
||||
local function export_string(...)
|
||||
local res, err = export(...)
|
||||
if not res then
|
||||
return nil, err
|
||||
end
|
||||
for k, v in ipairs(res) do
|
||||
res[k] = very_basic_dump(v)
|
||||
end
|
||||
return '{' .. table.concat(res, ',\n') .. '}'
|
||||
end
|
||||
|
||||
return export, export_string
|
|
@ -74,7 +74,7 @@ fixers.item_image = fixers.image
|
|||
|
||||
function fixers.button(elem)
|
||||
elem.type = 'image_' .. elem.type
|
||||
elem.texture_name = ''
|
||||
elem.texture_name = 'blank.png'
|
||||
return fixers.image_button(elem)
|
||||
end
|
||||
fixers.button_exit = fixers.button
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<script src="https://unpkg.com/fengari-web/dist/fengari-web.js"></script>
|
||||
<script type="application/lua" src="index.lua?rev=3"></script>
|
||||
<script type="application/lua" src="index.lua?rev=4"></script>
|
||||
<style>
|
||||
body {
|
||||
background: #8CBAFA;
|
||||
|
|
49
index.lua
49
index.lua
|
@ -18,9 +18,11 @@
|
|||
--
|
||||
|
||||
-- Load the renderer
|
||||
dofile('renderer.lua?rev=3')
|
||||
dofile('renderer.lua?rev=4')
|
||||
local formspec_escape = formspec_ast.formspec_escape
|
||||
|
||||
local _, digistuff_ts_export = dofile('digistuff_ts.lua?rev=4')
|
||||
|
||||
-- Show the properties list
|
||||
local properties_elem
|
||||
local function get_properties_list(list_name)
|
||||
|
@ -132,10 +134,10 @@ local function show_properties(elem, node)
|
|||
local formspec = draw_elements_list(elem) ..
|
||||
'label[0.25,2.5;Properties for ' .. formspec_escape(node.type) .. ']'
|
||||
local y = 3.5
|
||||
for k, v in pairs(node) do
|
||||
if k == 'type' or k == '_transient' then goto continue end
|
||||
for k_, v in pairs(node) do
|
||||
if k_ == 'type' or k_ == '_transient' then goto continue end
|
||||
|
||||
local k = k
|
||||
local k = k_
|
||||
local value_type = type(v)
|
||||
if k == 'opt' or k == 'props' then
|
||||
assert(value_type == 'table')
|
||||
|
@ -143,7 +145,8 @@ local function show_properties(elem, node)
|
|||
formspec_escape(get_property_name(k)) .. ' (map)]'
|
||||
y = y + 0.1
|
||||
local i = 0
|
||||
for prop, value in pairs(v) do
|
||||
for prop_, value in pairs(v) do
|
||||
local prop = prop_
|
||||
i = i + 1
|
||||
formspec = formspec .. 'label[0.4,' .. y + 0.3 .. ';•]' ..
|
||||
'field[0.7,' .. y .. ';1.95,0.6;' ..
|
||||
|
@ -157,7 +160,6 @@ local function show_properties(elem, node)
|
|||
formspec_escape('map-' .. i .. ':' .. k) .. ';X]'
|
||||
y = y + 0.8
|
||||
|
||||
local prop = prop
|
||||
callbacks['map-' .. i .. ':' .. k] = function()
|
||||
node[k] = get_properties_map(k)
|
||||
node[k][prop] = nil
|
||||
|
@ -416,7 +418,7 @@ local load_save_opts = {}
|
|||
local function show_load_save_dialog()
|
||||
local callbacks = {}
|
||||
local formspec = [[
|
||||
formspec_version[2]size[6,9.5]button[0,0;1,0.6;back;←]
|
||||
formspec_version[2]size[6,10.75]button[0,0;1,0.6;back;←]
|
||||
label[1.25,0.3;Load / save formspec]
|
||||
checkbox[0.25,1.3;use_v1;Use formspec version 1;]] ..
|
||||
(load_save_opts.use_v1 and 'true' or 'false') .. [[]
|
||||
|
@ -431,6 +433,8 @@ local function show_load_save_dialog()
|
|||
label[0.75,5.8;handled automatically.]
|
||||
button[0.25,7;5.5,1;load;Load formspec]
|
||||
button[0.25,8.25;5.5,1;save;Save formspec]
|
||||
button[0.25,9.5;5.5,1;digistuff_ts;WIP]] .. '\n' ..
|
||||
[[Export to digistuff touchscreen]
|
||||
]]
|
||||
local function get_options()
|
||||
local elems = element_dialog.firstChild.firstChild.children
|
||||
|
@ -481,26 +485,35 @@ local function show_load_save_dialog()
|
|||
})
|
||||
end
|
||||
|
||||
function callbacks.save()
|
||||
get_options()
|
||||
local tree = renderer.elem_to_ast(element_dialog_base)
|
||||
local res, err = renderer.export(tree, load_save_opts)
|
||||
local function save_dialog(res, err)
|
||||
element_dialog.innerHTML = ''
|
||||
local fs = 'formspec_version[2]size[6,9.5]button[0,0;1,0.6;back;←]' ..
|
||||
'label[1.25,0.3;Save formspec]textarea[0.25,1.25;5.5,8;result;'
|
||||
local label, msg
|
||||
if res then
|
||||
fs = fs ..
|
||||
'Formspec exported successfully.;' .. formspec_escape(res)
|
||||
label, msg = 'Formspec exported successfully.', res
|
||||
else
|
||||
fs = fs ..
|
||||
'Error exporting formspec!;' .. formspec_escape(err)
|
||||
label, msg = 'Error exporting formspec!', err
|
||||
end
|
||||
fs = fs .. ']'
|
||||
local fs = 'formspec_version[2]size[6,9.5]button[0,0;1,0.6;back;←]' ..
|
||||
'label[1.25,0.3;Save formspec]textarea[0.25,1.25;5.5,8;result;' ..
|
||||
label .. ';' .. formspec_escape(msg) .. ']'
|
||||
render_into(element_dialog, fs, {
|
||||
back = show_load_save_dialog,
|
||||
})
|
||||
end
|
||||
|
||||
function callbacks.save()
|
||||
get_options()
|
||||
local tree = renderer.elem_to_ast(element_dialog_base)
|
||||
save_dialog(renderer.export(tree, load_save_opts))
|
||||
end
|
||||
|
||||
function callbacks.digistuff_ts()
|
||||
get_options()
|
||||
local tree = renderer.elem_to_ast(element_dialog_base)
|
||||
local f = load_save_opts.use_v1 and renderer.fs51_backport or nil
|
||||
save_dialog(digistuff_ts_export(tree, f))
|
||||
end
|
||||
|
||||
render_into(element_dialog, formspec, callbacks)
|
||||
end
|
||||
|
||||
|
|
25
renderer.lua
25
renderer.lua
|
@ -441,20 +441,25 @@ function renderer.import(fs, opts)
|
|||
return tree, err
|
||||
end
|
||||
|
||||
function renderer.export(tree, opts)
|
||||
if opts.use_v1 then
|
||||
tree = fs51.backport(tree)
|
||||
function renderer.fs51_backport(tree)
|
||||
tree = fs51.backport(tree)
|
||||
|
||||
-- Round numbers to 2 decimal places
|
||||
local c = {'x', 'y', 'w', 'h'}
|
||||
for node in formspec_ast.walk(tree) do
|
||||
for _, k in ipairs(c) do
|
||||
if type(node[k]) == 'number' then
|
||||
node[k] = math.floor((node[k] * 100) + 0.5) / 100
|
||||
end
|
||||
-- Round numbers to 2 decimal places
|
||||
local c = {'x', 'y', 'w', 'h'}
|
||||
for node in formspec_ast.walk(tree) do
|
||||
for _, k in ipairs(c) do
|
||||
if type(node[k]) == 'number' then
|
||||
node[k] = math.floor((node[k] * 100) + 0.5) / 100
|
||||
end
|
||||
end
|
||||
end
|
||||
return tree
|
||||
end
|
||||
|
||||
function renderer.export(tree, opts)
|
||||
if opts.use_v1 then
|
||||
tree = renderer.fs51_backport(tree)
|
||||
end
|
||||
|
||||
local fs, err = formspec_ast.unparse(tree)
|
||||
if not fs then return nil, err end
|
||||
|
|
Loading…
Reference in New Issue