aboutsummaryrefslogtreecommitdiff
path: root/font_api/fontform.lua
blob: 118d92d6dc13523595384ad119194263d65e2608 (plain)
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
--[[
    font_api mod for Minetest - Library to add font display capability
    to display_api mod.
    (c) Pierre-Yves Rollo

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
--]]

local modname = minetest.get_current_modname()

-- Context management functions (surely many improvements to do)

local contexts = {}

local function get_player_name(player)
	if type(player) == 'string' then return player end
	if type(player) == 'userdata' and player.get_player_name then
		return player:get_player_name()
	end
	minetest.log('warning',	'['..modname..'] get_player_name could not identify player.')
end

minetest.register_on_leaveplayer(function(player)
	local playername = get_player_name(player)
	if playername then contexts[playername] = nil end
end)

local function new_context(player, context)
	local playername = get_player_name(player)
	if playername then
		contexts[playername] = context
		contexts[playername].playername = playername
		return contexts[playername]
    end
end

local function get_context(player)
	local playername = get_player_name(player)
	if playername then
		if contexts[playername] then
			return contexts[playername]
		else
			minetest.log('warning', '['..modname..'] Context not found for player "'..playername..'"')
		end
	end
end

local function update_context(player, changes)
	local playername = get_player_name(player)
	if playername then
		if not contexts[playername] then
			contexts[playername] = { playername = playername }
		end
		for key, value in pairs(changes) do
			contexts[playername][key] = value
		end
	end
end

-- Show node formspec functions

local function show_node_formspec(player, pos)
	local meta = minetest.get_meta(pos)
	local playername = get_player_name(player)

	-- Decontextualize formspec
	local fs = meta:get_string('formspec')

	-- Change context and currrent_name references to nodemeta references
	fs = fs:gsub("current_name", "nodemeta:"..pos.x..","..pos.y..","..pos.z)
	fs = fs:gsub("context", "nodemeta:"..pos.x..","..pos.y..","..pos.z)

	-- Change all ${} to their corresponding metadata values
	local s, e
	repeat
		s, e = fs:find('%${.*}')
		if s and e then
			fs = fs:sub(1, s-1)..
				minetest.formspec_escape(meta:get_string(fs:sub(s+2,e-1)))..
				fs:sub(e+1)
		end
	until s == nil

	-- Find node on_receive_fields
	local ndef = minetest.registered_nodes[minetest.get_node(pos).name]

	if ndef and ndef.on_receive_fields then
		update_context(player, { on_receive_fields = ndef.on_receive_fields } )
	end
	update_context(player, { node_pos = pos } )

	-- Show formspec
	minetest.show_formspec(playername, modname..':context_formspec', fs)
end

minetest.register_on_player_receive_fields(function(player, formname, fields)
	if formname == modname..':context_formspec' then
		local context = get_context(player)
		if context == nil then return end

		if context.on_receive_fields then
			context.on_receive_fields(context.pos, '', fields, player)
		end
	end
end)

-- Specific functions

local function font_list_prepare()
	local list = {}
	for name, _ in pairs(font_api.registered_fonts) do
		list[#list+1] = name
	end
	table.sort(list)
	return list
end

local function show_fs(player)
	local context = get_context(player)
	if context == nil then return end
	local fonts = font_list_prepare()

	local fs = 'size[4,'..(#fonts + 0.8)..']'
		..default.gui_bg..default.gui_bg_img..default.gui_slots
		..'button_exit[0,'..(#fonts)..';4,1;cancel;Cancel]'

	for line = 1, #fonts do
		local font = font_api.get_font(fonts[line])
		fs = fs..'image[0.1,'..(line-0.9)..';4.5,0.8;'
		..font:make_text_texture(font.name, font:get_height()*5,
			font:get_height()*1.2, 1, "center", "top", "#fff")
		..']button_exit[0,'..(line-1)..';4,1;font_'..font.name..';]'
	end
	minetest.show_formspec(context.playername, modname..':font_list', fs)
end

minetest.register_on_player_receive_fields(function(player, formname, fields)
	if formname == modname..':font_list' then
		local context = get_context(player)
		if context == nil then return end

		if fields.quit == 'true' then
			for name, _ in pairs(font_api.registered_fonts) do
				if fields['font_'..name] then
					local meta = minetest.get_meta(context.pos)
					meta:set_string("font", name)
					display_api.update_entities(context.pos)
				end
			end

			-- Using after to avoid the "double close" bug
			minetest.after(0, show_node_formspec, player, context.pos)
		end
	end
end)

function font_api.show_font_list(player, pos)
	new_context(player, { pos = pos })
	show_fs(player)
end