-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathformspec.lua
More file actions
183 lines (156 loc) · 5.94 KB
/
Copy pathformspec.lua
File metadata and controls
183 lines (156 loc) · 5.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
local S = technic_cnc.getter
-- Margin is hardcoded for some elements...
local margin = 0.5
local padding = 0.2
local grid_size = 1 + padding
local fs_prefix = "formspec_version[4]size[%d,%d]style_type[list;size=1,1;spacing=0.2,0.2]label[0.5,0.5;%s]"
local fs_slimhalf = "label[0.5,3.6;"..S("Slim Elements half / normal height:").."]"..
"image_button[0.5,4;1,0.49;technic_cnc_full%s.png;full; ]"..
"image_button[0.5,4.51;1,0.49;technic_cnc_half%s.png;half; ]"
-- TODO: These should be defined in programs.lua and provide API to register more
local slimhalf_buttons = {
"element_straight",
"element_end",
"element_cross",
"element_t",
"element_edge"
}
-- Create button grid that returns paging information (leftover button count).
-- WIP: Starting index could be easily added if needed to provide full paging.
local function image_button_grid(x_start, y_start, width, height, items, selected)
local result = ""
local count = 0
local row = 0
local column = 0
local max_row = math.floor(height / grid_size + 0.1)
local max_column = math.floor(math.min(#items, math.floor(width / grid_size) * max_row) / max_row + 0.1)
for _,name in ipairs(items) do
local x = x_start + column * grid_size
local y = y_start + row * grid_size
local modifier = selected == name and "^[invert:b" or ""
result = result .. ("image_button[%0.1f,%0.1f;1,1;technic_cnc_%s.png%s;%s;]"):format(x, y, name, modifier, name)
count = count + 1
if column + 1 < max_column then
column = column + 1
else
column = 0
row = row + 1
if row >= max_row then
return result, #items - count
end
end
end
return result, #items - count
end
local function label(x, y, text)
return ("label[%0.1f,%0.1f;%s]"):format(x, y, text)
end
local function list(name, x, y, w, h, text)
return (text and label(x, y - 0.5, text) or "") ..
("list[context;%s;%0.1f,%0.1f;%d,%d;]"):format(name, x, y, w, h) ..
("listring[current_player;main]listring[context;%s]"):format(name)
end
local function get_formspec(nodename, def, meta)
local width = grid_size * 11 + margin * 2
local height = 13
local fs = fs_prefix:format(width, height, S("Choose Milling Program:"))
local p = meta:get("program")
-- Programming buttons
local x = margin
local y = 1
local buttons1, leftover1 = image_button_grid(x, y, width - margin * 2, grid_size * 2, def.programs, p)
-- Slim / half / normal
x = margin + grid_size
y = 4
local buttons2, leftover2 = image_button_grid(x, y, width - grid_size - margin * 2, grid_size, slimhalf_buttons, p)
local half = meta:get("size") == "2"
fs = fs .. buttons1 .. fs_slimhalf:format(half and "" or "_active", half and "_active" or "") .. buttons2
-- Program paging controls
if leftover1 > 0 or leftover2 > 0 then
x = width - margin - grid_size * 2
fs = fs .. ("button[%0.1f,%0.1f;%0.1f,%0.1f;paging_prev;Previous]"):format(x, padding, grid_size, 0.6)
.. ("button[%0.1f,%0.1f;%0.1f,%0.1f;paging_next;Next]"):format(x + grid_size, padding, grid_size, 0.6)
end
-- Some filler for empty unused space
y = height - (grid_size * 4) - margin + padding
--fs = fs .. ("model[10,%0.1f;3,3;;node.obj;%s;0.1,0.1;true;false]"):format(y, table.concat(def.tiles, ","))
--fs = fs .. ("image[10,%0.1f;3,3;%s]"):format(y, def.tiles[6])
local size = grid_size * 3
fs = fs .. ("item_image[%0.1f,%0.1f;%0.1f,%0.1f;%s]"):format(grid_size * 8 + margin, y, size, size, nodename)
-- Player inventory
fs = fs .. ("list[current_player;main;%0.1f,%0.1f;8,4;]"):format(margin, y)
-- Input / output inventories
x = grid_size * def.input_size + grid_size + margin
y = 6
fs = fs .. list("src", margin, y, def.input_size, 1, S("In:")) .. list("dst", x, y, def.output_size, 1, S("Out:"))
x = grid_size * 8 + margin
-- Upgrades
if def.upgrade then
fs = fs .. list("upgrade1", x, y, 1, 1, S("Upgrade Slots")) .. list("upgrade2", x + grid_size, y, 1, 1)
end
-- Stack splitting toggle
if meta and def.tube and technic_cnc.pipeworks then
y = height - margin - grid_size * 4.5
fs = fs .. technic_cnc.pipeworks.cycling_button(meta, "splitstacks", margin, y)
end
-- Digilines channel field
if def.digilines then
y = height - grid_size - margin + padding + 0.3
local w = width - x - margin - grid_size
fs = fs .. ("field[%0.1f,%0.1f;%0.1f,%0.1f;channel;Channel;${channel}]"):format(x + padding, y, w, 0.7)
fs = fs .. ("button[%0.1f,%0.1f;%0.1f,%0.1f;setchannel;Set]"):format(x + w + padding, y, 1, 0.7)
end
return fs
end
local function on_receive_fields(pos, meta, fields, sender, update_formspec)
local name = sender:get_player_name()
if fields.quit or (meta:get_int("public") == 0 and minetest.is_protected(pos, name)) then
return true
end
-- Program for half/full size
if fields.full then
meta:set_int("size", 1)
update_formspec(meta)
return true
elseif fields.half then
meta:set_int("size", 2)
update_formspec(meta)
return true
elseif fields.paging_next or fields.paging_prev then
-- TODO: Page index should be capped between 0 and max based on button count
local page = meta:get_int("page")
meta:set_int("page", page + (fields.paging_next and 1 or -1))
return
end
-- Resolve the node name and the number of items to make
local program_selected
local products = technic_cnc.products
for program, _ in pairs(fields) do
if products[program] then
local update = meta:get("program") ~= program
technic_cnc.set_program(meta, program, meta:get_int("size"))
technic_cnc.enable(meta)
meta:set_string("cnc_user", name)
program_selected = true
if update then
update_formspec(meta)
end
break
end
end
if program_selected and not technic_cnc.use_technic then
local inv = meta:get_inventory()
technic_cnc.produce(meta, inv)
return true
end
local setchannel = fields.setchannel or (fields.key_enter and fields.key_enter_field == "channel")
if setchannel and not minetest.is_protected(pos, name) then
meta:set_string("channel", fields.channel)
return true
end
return program_selected
end
return {
get_formspec = get_formspec,
on_receive_fields = on_receive_fields,
}