aboutsummaryrefslogtreecommitdiff
path: root/builtin/mainmenu/textures.lua
blob: 56992c0c5cca0fe1ff857894377b1a222a2901ea (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
--Minetest
--Copyright (C) 2013 sapier
--
--This program 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 2.1 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 Lesser General Public License for more details.
--
--You should have received a copy of the GNU Lesser General Public License along
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.


mm_texture = {}

--------------------------------------------------------------------------------
function mm_texture.init()
	mm_texture.defaulttexturedir = core.get_texturepath() .. DIR_DELIM .. "base" ..
						DIR_DELIM .. "pack" .. DIR_DELIM
	mm_texture.basetexturedir = mm_texture.defaulttexturedir
	
	mm_texture.texturepack = core.setting_get("texture_path")
	
	mm_texture.gameid = nil
end

--------------------------------------------------------------------------------
function mm_texture.update(tab,gamedetails)
	if tab ~= "singleplayer" then
		mm_texture.reset()
		return
	end

	if gamedetails == nil then
		return
	end
	
	mm_texture.update_game(gamedetails)
end

--------------------------------------------------------------------------------
function mm_texture.reset()
	mm_texture.gameid = nil
	local have_bg      = false
	local have_overlay = mm_texture.set_generic("overlay")
	
	if not have_overlay then
		have_bg = mm_texture.set_generic("background")
	end
	
	mm_texture.clear("header")
	mm_texture.clear("footer")
	core.set_clouds(false)
	
	mm_texture.set_generic("footer")
	mm_texture.set_generic("header")
	
	if not have_bg then
		if core.setting_getbool("menu_clouds") then
			core.set_clouds(true)
		else
			mm_texture.set_dirt_bg()
		end
	end
end

--------------------------------------------------------------------------------
function mm_texture.update_game(gamedetails)
	if mm_texture.gameid == gamedetails.id then
		return
	end
	
	local have_bg      = false
	local have_overlay = mm_texture.set_game("overlay",gamedetails)
	
	if not have_overlay then
		have_bg = mm_texture.set_game("background",gamedetails)
	end
	
	mm_texture.clear("header")
	mm_texture.clear("footer")
	core.set_clouds(false)
	
	if not have_bg then
		
		if core.setting_getbool("menu_clouds") then
			core.set_clouds(true)
		else
			mm_texture.set_dirt_bg()
		end
	end
	
	mm_texture.set_game("footer",gamedetails)
	mm_texture.set_game("header",gamedetails)
	
	mm_texture.gameid = gamedetails.id
end

--------------------------------------------------------------------------------
function mm_texture.clear(identifier)
	core.set_background(identifier,"")
end

--------------------------------------------------------------------------------
function mm_texture.set_generic(identifier)
	--try texture pack first
	if mm_texture.texturepack ~= nil then
		local path = mm_texture.texturepack .. DIR_DELIM .."menu_" ..
										identifier .. ".png"
		if core.set_background(identifier,path) then
			return true
		end
	end
	
	if mm_texture.defaulttexturedir ~= nil then
		local path = mm_texture.defaulttexturedir .. DIR_DELIM .."menu_" ..
										identifier .. ".png"
		if core.set_background(identifier,path) then
			return true
		end
	end
	
	return false
end

--------------------------------------------------------------------------------
function mm_texture.set_game(identifier,gamedetails)
	
	if gamedetails == nil then
		return false
	end

	if mm_texture.texturepack ~= nil then
		local path = mm_texture.texturepack .. DIR_DELIM ..
						gamedetails.id .. "_menu_" .. identifier .. ".png"
		if core.set_background(identifier,path) then
			return true
		end
	end
	
	local path = gamedetails.path .. DIR_DELIM .."menu" ..
									 DIR_DELIM .. identifier .. ".png"
	if core.set_background(identifier,path) then
		return true
	end
	
	return false
end

function mm_texture.set_dirt_bg()
	if mm_texture.texturepack ~= nil then
		local path = mm_texture.texturepack .. DIR_DELIM .."default_dirt.png"
		if core.set_background("background", path, true, 128) then
			return true
		end
	end
	
	--use base pack
	local minimalpath = defaulttexturedir .. "dirt_bg.png"
	core.set_background("background", minimalpath, true, 128)
end
"hl num">2, y=0}, } local dir_angle_tbl={} for d,v in pairs(dir_trans_tbl) do local uvec = vector.normalize(v) dir_angle_tbl[d] = math.atan2(-uvec.x, uvec.z) end function advtrains.dir_to_angle(dir) return dir_angle_tbl[dir] or error("advtrains: in helpers.lua/dir_to_angle() given dir="..(dir or "nil")) end function advtrains.dirCoordSet(coord, dir) return vector.add(coord, advtrains.dirToCoord(dir)) end advtrains.pos_add_dir = advtrains.dirCoordSet function advtrains.pos_add_angle(pos, ang) -- 0 is +Z -> meaning of sin/cos swapped return vector.add(pos, {x = -math.sin(ang), y = 0, z = math.cos(ang)}) end function advtrains.dirToCoord(dir) return dir_trans_tbl[dir] or error("advtrains: in helpers.lua/dir_to_vector() given dir="..(dir or "nil")) end advtrains.dir_to_vector = advtrains.dirToCoord function advtrains.maxN(list, expectstart) local n=expectstart or 0 while list[n] do n=n+1 end return n-1 end function advtrains.minN(list, expectstart) local n=expectstart or 0 while list[n] do n=n-1 end return n+1 end function atround(number) return math.floor(number+0.5) end atfloor = math.floor function advtrains.round_vector_floor_y(vec) return {x=math.floor(vec.x+0.5), y=math.floor(vec.y), z=math.floor(vec.z+0.5)} end function advtrains.yawToDirection(yaw, conn1, conn2) if not conn1 or not conn2 then error("given nil to yawToDirection: conn1="..(conn1 or "nil").." conn2="..(conn1 or "nil")) end local yaw1 = advtrains.dir_to_angle(conn1) local yaw2 = advtrains.dir_to_angle(conn2) local adiff1 = advtrains.minAngleDiffRad(yaw, yaw1) local adiff2 = advtrains.minAngleDiffRad(yaw, yaw2) if math.abs(adiff2)<math.abs(adiff1) then return conn2 else return conn1 end end function advtrains.yawToAnyDir(yaw) local min_conn, min_diff=0, 10 for conn, vec in pairs(advtrains.dir_trans_tbl) do local yaw1 = advtrains.dir_to_angle(conn) local diff = math.abs(advtrains.minAngleDiffRad(yaw, yaw1)) if diff < min_diff then min_conn = conn min_diff = diff end end return min_conn end function advtrains.yawToClosestConn(yaw, conns) local min_connid, min_diff=1, 10 for connid, conn in ipairs(conns) do local yaw1 = advtrains.dir_to_angle(conn.c) local diff = math.abs(advtrains.minAngleDiffRad(yaw, yaw1)) if diff < min_diff then min_connid = connid min_diff = diff end end return min_connid end local pi, pi2 = math.pi, 2*math.pi function advtrains.minAngleDiffRad(r1, r2) while r1>pi2 do r1=r1-pi2 end while r1<0 do r1=r1+pi2 end while r2>pi2 do r2=r2-pi2 end while r1<0 do r2=r2+pi2 end local try1=r2-r1 local try2=r2+pi2-r1 local try3=r2-pi2-r1 local minabs = math.min(math.abs(try1), math.abs(try2), math.abs(try3)) if minabs==math.abs(try1) then return try1 end if minabs==math.abs(try2) then return try2 end if minabs==math.abs(try3) then return try3 end end -- Takes 2 connections (0...AT_CMAX) as argument -- Returns the angle median of those 2 positions from the pov -- of standing on the cdir1 side and looking towards cdir2 -- cdir1 - >NODE> - cdir2 function advtrains.conn_angle_median(cdir1, cdir2) local ang1 = advtrains.dir_to_angle(advtrains.oppd(cdir1)) local ang2 = advtrains.dir_to_angle(cdir2) return ang1 + advtrains.minAngleDiffRad(ang1, ang2)/2 end function advtrains.merge_tables(a, ...) local new={} for _,t in ipairs({a,...}) do for k,v in pairs(t) do new[k]=v end end return new end function advtrains.save_keys(tbl, keys) local new={} for _,key in ipairs(keys) do new[key] = tbl[key] end return new end function advtrains.get_real_index_position(path, index) if not path or not index then return end local first_pos=path[math.floor(index)] local second_pos=path[math.floor(index)+1] if not first_pos or not second_pos then return nil end local factor=index-math.floor(index) local actual_pos={x=first_pos.x-(first_pos.x-second_pos.x)*factor, y=first_pos.y-(first_pos.y-second_pos.y)*factor, z=first_pos.z-(first_pos.z-second_pos.z)*factor,} return actual_pos end function advtrains.pos_median(pos1, pos2) return {x=pos1.x-(pos1.x-pos2.x)*0.5, y=pos1.y-(pos1.y-pos2.y)*0.5, z=pos1.z-(pos1.z-pos2.z)*0.5} end function advtrains.abs_ceil(i) return math.ceil(math.abs(i))*math.sign(i) end function advtrains.serialize_inventory(inv) local ser={} local liszts=inv:get_lists() for lisztname, liszt in pairs(liszts) do ser[lisztname]={} for idx, item in ipairs(liszt) do local istring=item:to_string() if istring~="" then ser[lisztname][idx]=istring end end end return minetest.serialize(ser) end function advtrains.deserialize_inventory(sers, inv) local ser=minetest.deserialize(sers) if ser then inv:set_lists(ser) return true end return false end --is_protected wrapper that checks for protection_bypass privilege function advtrains.is_protected(pos, name) if not name then error("advtrains.is_protected() called without name parameter!") end if minetest.check_player_privs(name, {protection_bypass=true}) then --player can bypass protection return false end return minetest.is_protected(pos, name) end function advtrains.is_creative(name) if not name then error("advtrains.is_creative() called without name parameter!") end if minetest.check_player_privs(name, {creative=true}) then return true end return minetest.settings:get_bool("creative_mode") end function advtrains.is_damage_enabled(name) if not name then error("advtrains.is_damage_enabled() called without name parameter!") end if minetest.check_player_privs(name, "train_admin") then return false end return minetest.settings:get_bool("enable_damage") end function advtrains.ms_to_kmh(speed) return speed * 3.6 end -- 4 possible inputs: -- integer: just do that modulo calculation -- table with c set: rotate c -- table with tables: rotate each -- table with integers: rotate each (probably no use case) function advtrains.rotate_conn_by(conn, rotate) if tonumber(conn) then return (conn+rotate)%AT_CMAX elseif conn.c then return { c = (conn.c+rotate)%AT_CMAX, y = conn.y} end local tmp={} for connid, data in ipairs(conn) do tmp[connid]=advtrains.rotate_conn_by(data, rotate) end return tmp end function advtrains.oppd(dir) return advtrains.rotate_conn_by(dir, AT_CMAX/2) end --conn_to_match like rotate_conn_by --other_conns have to be a table of conn tables! function advtrains.conn_matches_to(conn, other_conns) if tonumber(conn) then for connid, data in ipairs(other_conns) do if advtrains.oppd(conn) == data.c then return connid end end return false elseif conn.c then for connid, data in ipairs(other_conns) do local cmp = advtrains.oppd(conn) if cmp.c == data.c and (cmp.y or 0) == (data.y or 0) then return connid end end return false end local tmp={} for connid, data in ipairs(conn) do local backmatch = advtrains.conn_matches_to(data, other_conns) if backmatch then return backmatch, connid end --returns <connid of other rail> <connid of this rail> end return false end -- Going from the rail at pos (does not need to be rounded) along connection with id conn_idx, if there is a matching rail, return it and the matching connid -- returns: <adjacent pos>, <conn index of adjacent>, <my conn index>, <railheight of adjacent> -- parameter this_conns_p is connection table of this rail and is optional, is determined by get_rail_info_at if not provided. function advtrains.get_adjacent_rail(this_posnr, this_conns_p, conn_idx, drives_on) local this_pos = advtrains.round_vector_floor_y(this_posnr) local this_conns = this_conns_p if not this_conns then _, this_conns = advtrains.get_rail_info_at(this_pos) end if not conn_idx then for coni, _ in ipairs(this_conns) do local adj_pos, adj_conn_idx, _, nry, nco = advtrains.get_adjacent_rail(this_pos, this_conns, coni) if adj_pos then return adj_pos,adj_conn_idx,coni,nry, nco end end return nil end local conn = this_conns[conn_idx] local conn_y = conn.y or 0 local adj_pos = advtrains.dirCoordSet(this_pos, conn.c); while conn_y>=1 do conn_y = conn_y - 1 adj_pos.y = adj_pos.y + 1 end local nextnode_ok, nextconns, nextrail_y=advtrains.get_rail_info_at(adj_pos, drives_on) if not nextnode_ok then adj_pos.y = adj_pos.y - 1 conn_y = conn_y + 1 nextnode_ok, nextconns, nextrail_y=advtrains.get_rail_info_at(adj_pos, drives_on) if not nextnode_ok then return nil end end local adj_connid = advtrains.conn_matches_to({c=conn.c, y=conn_y}, nextconns) if adj_connid then return adj_pos, adj_connid, conn_idx, nextrail_y, nextconns end return nil end -- when a train enters a rail on connid 'conn', which connid will it go out? -- nconns: number of connections in connection table: -- 2 = straight rail; 3 = turnout, 4 = crossing, 5 = three-way turnout (5th entry is a stub) -- returns: connid_out local connlku={[2]={2,1}, [3]={2,1,1}, [4]={2,1,4,3}, [5]={2,1,1,1}} function advtrains.get_matching_conn(conn, nconns) return connlku[nconns][conn] end function advtrains.random_id() local idst="" for i=0,5 do idst=idst..(math.random(0,9)) end return idst end -- Shorthand for pos_to_string and round_vector_floor_y function advtrains.roundfloorpts(pos) return minetest.pos_to_string(advtrains.round_vector_floor_y(pos)) end -- insert an element into a table if it does not yet exist there -- equalfunc is a function to compare equality, defaults to == -- returns true if the element was inserted function advtrains.insert_once(tab, elem, equalfunc) for _,e in pairs(tab) do if equalfunc and equalfunc(elem, e) or e==elem then return false end end tab[#tab+1] = elem return true end