mirror of
https://github.com/minetest/minetest.git
synced 2024-06-30 21:20:36 +02:00
Compare commits
23 Commits
448083aabc
...
bb360d6ec1
Author | SHA1 | Date | |
---|---|---|---|
|
bb360d6ec1 | ||
|
9a1501ae89 | ||
|
514e106414 | ||
|
4c001bd248 | ||
|
fb6ceb2664 | ||
|
50da26da91 | ||
|
28857841aa | ||
|
157d129e30 | ||
|
7bf61ed9c7 | ||
|
1588eab2f7 | ||
|
34bd7dcde1 | ||
|
8b11c73994 | ||
|
7f1105cd47 | ||
|
b74c36961b | ||
|
b3d957127c | ||
|
c1a76bc7db | ||
|
ed11b33430 | ||
|
a509aad6b2 | ||
|
f06364e6a5 | ||
|
8c11c12c69 | ||
|
67810800ad | ||
|
9375f66c48 | ||
|
a73b4f27cb |
@ -240,12 +240,15 @@ function math.factorial(x)
|
||||
return v
|
||||
end
|
||||
|
||||
|
||||
function math.round(x)
|
||||
if x >= 0 then
|
||||
return math.floor(x + 0.5)
|
||||
if x < 0 then
|
||||
local int = math.ceil(x)
|
||||
local frac = x - int
|
||||
return int - ((frac <= -0.5) and 1 or 0)
|
||||
end
|
||||
return math.ceil(x - 0.5)
|
||||
local int = math.floor(x)
|
||||
local frac = x - int
|
||||
return int + ((frac >= 0.5) and 1 or 0)
|
||||
end
|
||||
|
||||
local formspec_escapes = {
|
||||
|
@ -176,3 +176,17 @@ describe("formspec_escape", function()
|
||||
assert.equal("\\[Hello\\\\\\[", core.formspec_escape("[Hello\\["))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("math", function()
|
||||
it("round()", function()
|
||||
assert.equal(0, math.round(0))
|
||||
assert.equal(10, math.round(10.3))
|
||||
assert.equal(11, math.round(10.5))
|
||||
assert.equal(11, math.round(10.7))
|
||||
assert.equal(-10, math.round(-10.3))
|
||||
assert.equal(-11, math.round(-10.5))
|
||||
assert.equal(-11, math.round(-10.7))
|
||||
assert.equal(0, math.round(0.49999999999999994))
|
||||
assert.equal(0, math.round(-0.49999999999999994))
|
||||
end)
|
||||
end)
|
||||
|
@ -133,6 +133,8 @@ local function start_install(package, reason)
|
||||
conf:set("release", package.release)
|
||||
conf:write()
|
||||
end
|
||||
|
||||
pkgmgr.reload_by_type(package.type)
|
||||
end
|
||||
end
|
||||
|
||||
@ -146,7 +148,6 @@ local function start_install(package, reason)
|
||||
|
||||
start_install(next.package, next.reason)
|
||||
end
|
||||
|
||||
ui.update()
|
||||
end
|
||||
|
||||
@ -427,8 +428,9 @@ end
|
||||
|
||||
|
||||
function contentdb.update_paths()
|
||||
pkgmgr.load_all()
|
||||
|
||||
local mod_hash = {}
|
||||
pkgmgr.refresh_globals()
|
||||
for _, mod in pairs(pkgmgr.global_mods:get_list()) do
|
||||
local cdb_id = pkgmgr.get_contentdb_id(mod)
|
||||
if cdb_id then
|
||||
@ -437,7 +439,6 @@ function contentdb.update_paths()
|
||||
end
|
||||
|
||||
local game_hash = {}
|
||||
pkgmgr.update_gamelist()
|
||||
for _, game in pairs(pkgmgr.games) do
|
||||
local cdb_id = pkgmgr.get_contentdb_id(game)
|
||||
if cdb_id then
|
||||
@ -446,7 +447,7 @@ function contentdb.update_paths()
|
||||
end
|
||||
|
||||
local txp_hash = {}
|
||||
for _, txp in pairs(pkgmgr.get_texture_packs()) do
|
||||
for _, txp in pairs(pkgmgr.texture_packs) do
|
||||
local cdb_id = pkgmgr.get_contentdb_id(txp)
|
||||
if cdb_id then
|
||||
txp_hash[contentdb.aliases[cdb_id] or cdb_id] = txp
|
||||
|
@ -110,7 +110,7 @@ pkgmgr = {}
|
||||
-- @param modpack Currently processing modpack or nil/"" if none (recursion)
|
||||
function pkgmgr.get_mods(path, virtual_path, listing, modpack)
|
||||
local mods = core.get_dir_list(path, true)
|
||||
|
||||
local added = {}
|
||||
for _, name in ipairs(mods) do
|
||||
if name:sub(1, 1) ~= "." then
|
||||
local mod_path = path .. DIR_DELIM .. name
|
||||
@ -120,6 +120,7 @@ function pkgmgr.get_mods(path, virtual_path, listing, modpack)
|
||||
parent_dir = path,
|
||||
}
|
||||
listing[#listing + 1] = toadd
|
||||
added[#added + 1] = toadd
|
||||
|
||||
-- Get config file
|
||||
local mod_conf
|
||||
@ -150,8 +151,6 @@ function pkgmgr.get_mods(path, virtual_path, listing, modpack)
|
||||
toadd.virtual_path = mod_virtual_path
|
||||
toadd.type = "mod"
|
||||
|
||||
pkgmgr.update_translations({ toadd })
|
||||
|
||||
-- Check modpack.txt
|
||||
-- Note: modpack.conf is already checked above
|
||||
local modpackfile = io.open(mod_path .. DIR_DELIM .. "modpack.txt")
|
||||
@ -171,6 +170,8 @@ function pkgmgr.get_mods(path, virtual_path, listing, modpack)
|
||||
end
|
||||
end
|
||||
|
||||
pkgmgr.update_translations(added)
|
||||
|
||||
if not modpack then
|
||||
-- Sort all when the recursion is done
|
||||
table.sort(listing, function(a, b)
|
||||
@ -180,12 +181,13 @@ function pkgmgr.get_mods(path, virtual_path, listing, modpack)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function pkgmgr.get_texture_packs()
|
||||
function pkgmgr.reload_texture_packs()
|
||||
local txtpath = core.get_texturepath()
|
||||
local txtpath_system = core.get_texturepath_share()
|
||||
local retval = {}
|
||||
|
||||
load_texture_packs(txtpath, retval)
|
||||
|
||||
-- on portable versions these two paths coincide. It avoids loading the path twice
|
||||
if txtpath ~= txtpath_system then
|
||||
load_texture_packs(txtpath_system, retval)
|
||||
@ -197,11 +199,13 @@ function pkgmgr.get_texture_packs()
|
||||
return a.title:lower() < b.title:lower()
|
||||
end)
|
||||
|
||||
return retval
|
||||
pkgmgr.texture_packs = retval
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function pkgmgr.get_all()
|
||||
pkgmgr.load_all()
|
||||
|
||||
local result = {}
|
||||
|
||||
for _, mod in pairs(pkgmgr.global_mods:get_list()) do
|
||||
@ -210,7 +214,7 @@ function pkgmgr.get_all()
|
||||
for _, game in pairs(pkgmgr.games) do
|
||||
result[#result + 1] = game
|
||||
end
|
||||
for _, txp in pairs(pkgmgr.get_texture_packs()) do
|
||||
for _, txp in pairs(pkgmgr.texture_packs) do
|
||||
result[#result + 1] = txp
|
||||
end
|
||||
|
||||
@ -288,7 +292,7 @@ end
|
||||
function pkgmgr.render_packagelist(render_list, use_technical_names, with_icon)
|
||||
if not render_list then
|
||||
if not pkgmgr.global_mods then
|
||||
pkgmgr.refresh_globals()
|
||||
pkgmgr.reload_global_mods()
|
||||
end
|
||||
render_list = pkgmgr.global_mods
|
||||
end
|
||||
@ -549,6 +553,7 @@ function pkgmgr.get_worldconfig(worldpath)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Caller is responsible for reloading content types (see reload_by_type)
|
||||
function pkgmgr.install_dir(expected_type, path, basename, targetpath)
|
||||
assert(type(expected_type) == "string")
|
||||
assert(type(path) == "string")
|
||||
@ -615,12 +620,6 @@ function pkgmgr.install_dir(expected_type, path, basename, targetpath)
|
||||
fgettext_ne("Failed to install $1 to $2", basename, targetpath)
|
||||
end
|
||||
|
||||
if basefolder.type == "game" then
|
||||
pkgmgr.update_gamelist()
|
||||
else
|
||||
pkgmgr.refresh_globals()
|
||||
end
|
||||
|
||||
return targetpath, nil
|
||||
end
|
||||
|
||||
@ -742,7 +741,7 @@ function pkgmgr.comparemod(elem1,elem2)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function pkgmgr.refresh_globals()
|
||||
function pkgmgr.reload_global_mods()
|
||||
local function is_equal(element,uid) --uid match
|
||||
if element.name == uid then
|
||||
return true
|
||||
@ -774,7 +773,7 @@ function pkgmgr.get_game_mods(gamespec, retval)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function pkgmgr.update_gamelist()
|
||||
function pkgmgr.reload_games()
|
||||
pkgmgr.games = core.get_games()
|
||||
table.sort(pkgmgr.games, function(a, b)
|
||||
return a.title:lower() < b.title:lower()
|
||||
@ -782,6 +781,32 @@ function pkgmgr.update_gamelist()
|
||||
pkgmgr.update_translations(pkgmgr.games)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function pkgmgr.reload_by_type(type)
|
||||
if type == "game" then
|
||||
pkgmgr.reload_games()
|
||||
elseif type == "txp" then
|
||||
pkgmgr.reload_texture_packs()
|
||||
elseif type == "mod" or type == "modpack" then
|
||||
pkgmgr.reload_global_mods()
|
||||
else
|
||||
error("Unknown package type: " .. type)
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function pkgmgr.load_all()
|
||||
if not pkgmgr.global_mods then
|
||||
pkgmgr.reload_global_mods()
|
||||
end
|
||||
if not pkgmgr.games then
|
||||
pkgmgr.reload_games()
|
||||
end
|
||||
if not pkgmgr.texture_packs then
|
||||
pkgmgr.reload_texture_packs()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
function pkgmgr.update_translations(list)
|
||||
for _, item in ipairs(list) do
|
||||
@ -831,4 +856,4 @@ end
|
||||
--------------------------------------------------------------------------------
|
||||
-- read initial data
|
||||
--------------------------------------------------------------------------------
|
||||
pkgmgr.update_gamelist()
|
||||
pkgmgr.reload_games()
|
||||
|
@ -46,6 +46,9 @@ local function reset()
|
||||
function core.get_texturepath()
|
||||
return txp_dir
|
||||
end
|
||||
function core.get_texturepath_share()
|
||||
return txp_dir
|
||||
end
|
||||
function core.get_modpath()
|
||||
return mods_dir
|
||||
end
|
||||
@ -59,13 +62,6 @@ local function reset()
|
||||
setfenv(loadfile("builtin/common/misc_helpers.lua"), env)()
|
||||
setfenv(loadfile("builtin/mainmenu/content/pkgmgr.lua"), env)()
|
||||
|
||||
function env.pkgmgr.update_gamelist()
|
||||
table.insert(calls, { "update_gamelist" })
|
||||
end
|
||||
function env.pkgmgr.refresh_globals()
|
||||
table.insert(calls, { "refresh_globals" })
|
||||
end
|
||||
|
||||
function env.assert_calls(list)
|
||||
assert.are.same(list, calls)
|
||||
end
|
||||
@ -113,7 +109,6 @@ describe("install_dir", function()
|
||||
env.assert_calls({
|
||||
{ "delete_dir", mods_dir .. "/mymod" },
|
||||
{ "copy_dir", "/tmp/123", mods_dir .. "/mymod", false },
|
||||
{ "refresh_globals" },
|
||||
})
|
||||
end)
|
||||
|
||||
@ -129,7 +124,6 @@ describe("install_dir", function()
|
||||
env.assert_calls({
|
||||
{ "delete_dir", mods_dir .. "/mymod" },
|
||||
{ "copy_dir", "/tmp/123", mods_dir .. "/mymod", false },
|
||||
{ "refresh_globals" },
|
||||
})
|
||||
end)
|
||||
|
||||
@ -145,7 +139,6 @@ describe("install_dir", function()
|
||||
env.assert_calls({
|
||||
{ "delete_dir", games_dir .. "/mygame" },
|
||||
{ "copy_dir", "/tmp/123", games_dir .. "/mygame", false },
|
||||
{ "update_gamelist" },
|
||||
})
|
||||
end)
|
||||
|
||||
@ -161,7 +154,6 @@ describe("install_dir", function()
|
||||
env.assert_calls({
|
||||
{ "delete_dir", mods_dir .. "/123" },
|
||||
{ "copy_dir", "/tmp/123", mods_dir .. "/123", false },
|
||||
{ "refresh_globals" },
|
||||
})
|
||||
end)
|
||||
|
||||
@ -188,7 +180,6 @@ describe("install_dir", function()
|
||||
env.assert_calls({
|
||||
{ "delete_dir", "/tmp/alt-target" },
|
||||
{ "copy_dir", "/tmp/123", "/tmp/alt-target", false },
|
||||
{ "refresh_globals" },
|
||||
})
|
||||
end)
|
||||
|
||||
@ -238,6 +229,5 @@ describe("install_dir", function()
|
||||
path, message = env.pkgmgr.install_dir("txp", "/tmp/123", "name", nil)
|
||||
assert.is._not._nil(path)
|
||||
assert.is._nil(message)
|
||||
|
||||
end)
|
||||
end)
|
||||
|
@ -72,9 +72,6 @@ end
|
||||
|
||||
|
||||
local function has_packages_from_cdb()
|
||||
pkgmgr.refresh_globals()
|
||||
pkgmgr.update_gamelist()
|
||||
|
||||
for _, content in pairs(pkgmgr.get_all()) do
|
||||
if pkgmgr.get_contentdb_id(content) then
|
||||
return true
|
||||
@ -127,9 +124,6 @@ function update_detector.get_all()
|
||||
return {}
|
||||
end
|
||||
|
||||
pkgmgr.refresh_globals()
|
||||
pkgmgr.update_gamelist()
|
||||
|
||||
local ret = {}
|
||||
local all_content = pkgmgr.get_all()
|
||||
for _, content in ipairs(all_content) do
|
||||
|
@ -37,11 +37,7 @@ local function delete_content_buttonhandler(this, fields)
|
||||
gamedata.errormessage = fgettext_ne("pkgmgr: failed to delete \"$1\"", this.data.content.path)
|
||||
end
|
||||
|
||||
if this.data.content.type == "game" then
|
||||
pkgmgr.update_gamelist()
|
||||
else
|
||||
pkgmgr.refresh_globals()
|
||||
end
|
||||
pkgmgr.reload_by_type(this.data.content.type)
|
||||
else
|
||||
gamedata.errormessage = fgettext_ne("pkgmgr: invalid path \"$1\"", this.data.content.path)
|
||||
end
|
||||
|
@ -45,7 +45,7 @@ local function rename_modpack_buttonhandler(this, fields)
|
||||
local oldpath = this.data.mod.path
|
||||
local targetpath = this.data.mod.parent_dir .. DIR_DELIM .. fields["te_modpack_name"]
|
||||
os.rename(oldpath, targetpath)
|
||||
pkgmgr.refresh_globals()
|
||||
pkgmgr.reload_global_mods()
|
||||
pkgmgr.selected_mod = pkgmgr.global_mods:get_current_index(
|
||||
pkgmgr.global_mods:raw_index_by_uid(fields["te_modpack_name"]))
|
||||
|
||||
|
@ -22,16 +22,27 @@ local component_funcs = dofile(core.get_mainmenu_path() .. DIR_DELIM ..
|
||||
local shadows_component = dofile(core.get_mainmenu_path() .. DIR_DELIM ..
|
||||
"settings" .. DIR_DELIM .. "shadows_component.lua")
|
||||
|
||||
|
||||
local full_settings = settingtypes.parse_config_file(false, true)
|
||||
local loaded = false
|
||||
local full_settings
|
||||
local info_icon_path = core.formspec_escape(defaulttexturedir .. "settings_info.png")
|
||||
local reset_icon_path = core.formspec_escape(defaulttexturedir .. "settings_reset.png")
|
||||
|
||||
local all_pages = {}
|
||||
local page_by_id = {}
|
||||
local filtered_pages = all_pages
|
||||
local filtered_page_by_id = page_by_id
|
||||
|
||||
|
||||
local function get_setting_info(name)
|
||||
for _, entry in ipairs(full_settings) do
|
||||
if entry.type ~= "category" and entry.name == name then
|
||||
return entry
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
local function add_page(page)
|
||||
assert(type(page.id) == "string")
|
||||
assert(type(page.title) == "string")
|
||||
@ -46,49 +57,6 @@ local function add_page(page)
|
||||
end
|
||||
|
||||
|
||||
local change_keys = {
|
||||
query_text = "Controls",
|
||||
requires = {
|
||||
keyboard_mouse = true,
|
||||
},
|
||||
get_formspec = function(self, avail_w)
|
||||
local btn_w = math.min(avail_w, 3)
|
||||
return ("button[0,0;%f,0.8;btn_change_keys;%s]"):format(btn_w, fgettext("Controls")), 0.8
|
||||
end,
|
||||
on_submit = function(self, fields)
|
||||
if fields.btn_change_keys then
|
||||
core.show_keys_menu()
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
|
||||
add_page({
|
||||
id = "accessibility",
|
||||
title = fgettext_ne("Accessibility"),
|
||||
content = {
|
||||
"language",
|
||||
{ heading = fgettext_ne("General") },
|
||||
"font_size",
|
||||
"chat_font_size",
|
||||
"gui_scaling",
|
||||
"hud_scaling",
|
||||
"show_nametag_backgrounds",
|
||||
{ heading = fgettext_ne("Chat") },
|
||||
"console_height",
|
||||
"console_alpha",
|
||||
"console_color",
|
||||
{ heading = fgettext_ne("Controls") },
|
||||
"autojump",
|
||||
"safe_dig_and_place",
|
||||
{ heading = fgettext_ne("Movement") },
|
||||
"arm_inertia",
|
||||
"view_bobbing_amount",
|
||||
"fall_bobbing_amount",
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
local function load_settingtypes()
|
||||
local page = nil
|
||||
local section = nil
|
||||
@ -129,94 +97,134 @@ local function load_settingtypes()
|
||||
end
|
||||
end
|
||||
end
|
||||
load_settingtypes()
|
||||
|
||||
table.insert(page_by_id.controls_keyboard_and_mouse.content, 1, change_keys)
|
||||
do
|
||||
local content = page_by_id.graphics_and_audio_shaders.content
|
||||
local idx = table.indexof(content, "enable_dynamic_shadows")
|
||||
table.insert(content, idx, shadows_component)
|
||||
end
|
||||
|
||||
|
||||
local function get_setting_info(name)
|
||||
for _, entry in ipairs(full_settings) do
|
||||
if entry.type ~= "category" and entry.name == name then
|
||||
return entry
|
||||
end
|
||||
local function load()
|
||||
if loaded then
|
||||
return
|
||||
end
|
||||
loaded = true
|
||||
|
||||
full_settings = settingtypes.parse_config_file(false, true)
|
||||
|
||||
local change_keys = {
|
||||
query_text = "Controls",
|
||||
requires = {
|
||||
keyboard_mouse = true,
|
||||
},
|
||||
get_formspec = function(self, avail_w)
|
||||
local btn_w = math.min(avail_w, 3)
|
||||
return ("button[0,0;%f,0.8;btn_change_keys;%s]"):format(btn_w, fgettext("Controls")), 0.8
|
||||
end,
|
||||
on_submit = function(self, fields)
|
||||
if fields.btn_change_keys then
|
||||
core.show_keys_menu()
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
add_page({
|
||||
id = "accessibility",
|
||||
title = fgettext_ne("Accessibility"),
|
||||
content = {
|
||||
"language",
|
||||
{ heading = fgettext_ne("General") },
|
||||
"font_size",
|
||||
"chat_font_size",
|
||||
"gui_scaling",
|
||||
"hud_scaling",
|
||||
"show_nametag_backgrounds",
|
||||
{ heading = fgettext_ne("Chat") },
|
||||
"console_height",
|
||||
"console_alpha",
|
||||
"console_color",
|
||||
{ heading = fgettext_ne("Controls") },
|
||||
"autojump",
|
||||
"safe_dig_and_place",
|
||||
{ heading = fgettext_ne("Movement") },
|
||||
"arm_inertia",
|
||||
"view_bobbing_amount",
|
||||
"fall_bobbing_amount",
|
||||
},
|
||||
})
|
||||
|
||||
load_settingtypes()
|
||||
|
||||
table.insert(page_by_id.controls_keyboard_and_mouse.content, 1, change_keys)
|
||||
do
|
||||
local content = page_by_id.graphics_and_audio_shaders.content
|
||||
local idx = table.indexof(content, "enable_dynamic_shadows")
|
||||
table.insert(content, idx, shadows_component)
|
||||
end
|
||||
|
||||
return nil
|
||||
-- These must not be translated, as they need to show in the local
|
||||
-- language no matter the user's current language.
|
||||
-- This list must be kept in sync with src/unsupported_language_list.txt.
|
||||
get_setting_info("language").option_labels = {
|
||||
[""] = fgettext_ne("(Use system language)"),
|
||||
--ar = " [ar]", blacklisted
|
||||
be = "Беларуская [be]",
|
||||
bg = "Български [bg]",
|
||||
ca = "Català [ca]",
|
||||
cs = "Česky [cs]",
|
||||
cy = "Cymraeg [cy]",
|
||||
da = "Dansk [da]",
|
||||
de = "Deutsch [de]",
|
||||
--dv = " [dv]", blacklisted
|
||||
el = "Ελληνικά [el]",
|
||||
en = "English [en]",
|
||||
eo = "Esperanto [eo]",
|
||||
es = "Español [es]",
|
||||
et = "Eesti [et]",
|
||||
eu = "Euskara [eu]",
|
||||
fi = "Suomi [fi]",
|
||||
fil = "Wikang Filipino [fil]",
|
||||
fr = "Français [fr]",
|
||||
gd = "Gàidhlig [gd]",
|
||||
gl = "Galego [gl]",
|
||||
--he = " [he]", blacklisted
|
||||
--hi = " [hi]", blacklisted
|
||||
hu = "Magyar [hu]",
|
||||
id = "Bahasa Indonesia [id]",
|
||||
it = "Italiano [it]",
|
||||
ja = "日本語 [ja]",
|
||||
jbo = "Lojban [jbo]",
|
||||
kk = "Қазақша [kk]",
|
||||
--kn = " [kn]", blacklisted
|
||||
ko = "한국어 [ko]",
|
||||
ky = "Kırgızca / Кыргызча [ky]",
|
||||
lt = "Lietuvių [lt]",
|
||||
lv = "Latviešu [lv]",
|
||||
mn = "Монгол [mn]",
|
||||
mr = "मराठी [mr]",
|
||||
ms = "Bahasa Melayu [ms]",
|
||||
--ms_Arab = " [ms_Arab]", blacklisted
|
||||
nb = "Norsk Bokmål [nb]",
|
||||
nl = "Nederlands [nl]",
|
||||
nn = "Norsk Nynorsk [nn]",
|
||||
oc = "Occitan [oc]",
|
||||
pl = "Polski [pl]",
|
||||
pt = "Português [pt]",
|
||||
pt_BR = "Português do Brasil [pt_BR]",
|
||||
ro = "Română [ro]",
|
||||
ru = "Русский [ru]",
|
||||
sk = "Slovenčina [sk]",
|
||||
sl = "Slovenščina [sl]",
|
||||
sr_Cyrl = "Српски [sr_Cyrl]",
|
||||
sr_Latn = "Srpski (Latinica) [sr_Latn]",
|
||||
sv = "Svenska [sv]",
|
||||
sw = "Kiswahili [sw]",
|
||||
--th = " [th]", blacklisted
|
||||
tr = "Türkçe [tr]",
|
||||
tt = "Tatarça [tt]",
|
||||
uk = "Українська [uk]",
|
||||
vi = "Tiếng Việt [vi]",
|
||||
zh_CN = "中文 (简体) [zh_CN]",
|
||||
zh_TW = "正體中文 (繁體) [zh_TW]",
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
-- These must not be translated, as they need to show in the local
|
||||
-- language no matter the user's current language.
|
||||
-- This list must be kept in sync with src/unsupported_language_list.txt.
|
||||
get_setting_info("language").option_labels = {
|
||||
[""] = fgettext_ne("(Use system language)"),
|
||||
--ar = " [ar]", blacklisted
|
||||
be = "Беларуская [be]",
|
||||
bg = "Български [bg]",
|
||||
ca = "Català [ca]",
|
||||
cs = "Česky [cs]",
|
||||
cy = "Cymraeg [cy]",
|
||||
da = "Dansk [da]",
|
||||
de = "Deutsch [de]",
|
||||
--dv = " [dv]", blacklisted
|
||||
el = "Ελληνικά [el]",
|
||||
en = "English [en]",
|
||||
eo = "Esperanto [eo]",
|
||||
es = "Español [es]",
|
||||
et = "Eesti [et]",
|
||||
eu = "Euskara [eu]",
|
||||
fi = "Suomi [fi]",
|
||||
fil = "Wikang Filipino [fil]",
|
||||
fr = "Français [fr]",
|
||||
gd = "Gàidhlig [gd]",
|
||||
gl = "Galego [gl]",
|
||||
--he = " [he]", blacklisted
|
||||
--hi = " [hi]", blacklisted
|
||||
hu = "Magyar [hu]",
|
||||
id = "Bahasa Indonesia [id]",
|
||||
it = "Italiano [it]",
|
||||
ja = "日本語 [ja]",
|
||||
jbo = "Lojban [jbo]",
|
||||
kk = "Қазақша [kk]",
|
||||
--kn = " [kn]", blacklisted
|
||||
ko = "한국어 [ko]",
|
||||
ky = "Kırgızca / Кыргызча [ky]",
|
||||
lt = "Lietuvių [lt]",
|
||||
lv = "Latviešu [lv]",
|
||||
mn = "Монгол [mn]",
|
||||
mr = "मराठी [mr]",
|
||||
ms = "Bahasa Melayu [ms]",
|
||||
--ms_Arab = " [ms_Arab]", blacklisted
|
||||
nb = "Norsk Bokmål [nb]",
|
||||
nl = "Nederlands [nl]",
|
||||
nn = "Norsk Nynorsk [nn]",
|
||||
oc = "Occitan [oc]",
|
||||
pl = "Polski [pl]",
|
||||
pt = "Português [pt]",
|
||||
pt_BR = "Português do Brasil [pt_BR]",
|
||||
ro = "Română [ro]",
|
||||
ru = "Русский [ru]",
|
||||
sk = "Slovenčina [sk]",
|
||||
sl = "Slovenščina [sl]",
|
||||
sr_Cyrl = "Српски [sr_Cyrl]",
|
||||
sr_Latn = "Srpski (Latinica) [sr_Latn]",
|
||||
sv = "Svenska [sv]",
|
||||
sw = "Kiswahili [sw]",
|
||||
--th = " [th]", blacklisted
|
||||
tr = "Türkçe [tr]",
|
||||
tt = "Tatarça [tt]",
|
||||
uk = "Українська [uk]",
|
||||
vi = "Tiếng Việt [vi]",
|
||||
zh_CN = "中文 (简体) [zh_CN]",
|
||||
zh_TW = "正體中文 (繁體) [zh_TW]",
|
||||
}
|
||||
|
||||
|
||||
-- See if setting matches keywords
|
||||
local function get_setting_match_weight(entry, query_keywords)
|
||||
local setting_score = 0
|
||||
@ -734,6 +742,7 @@ end
|
||||
|
||||
|
||||
function create_settings_dlg()
|
||||
load()
|
||||
local dlg = dialog_create("dlg_settings", get_formspec, buttonhandler, eventhandler)
|
||||
|
||||
dlg.data.page_id = update_filtered_pages("")
|
||||
|
@ -439,9 +439,9 @@ function settingtypes.parse_config_file(read_all, parse_mods)
|
||||
end
|
||||
|
||||
-- Parse mods
|
||||
pkgmgr.load_all()
|
||||
local mods_category_initialized = false
|
||||
local mods = {}
|
||||
pkgmgr.get_mods(core.get_modpath(), "mods", mods)
|
||||
local mods = pkgmgr.global_mods:get_list()
|
||||
table.sort(mods, function(a, b) return a.name < b.name end)
|
||||
|
||||
for _, mod in ipairs(mods) do
|
||||
|
@ -29,16 +29,11 @@ end
|
||||
local packages_raw, packages
|
||||
|
||||
local function update_packages()
|
||||
if not pkgmgr.global_mods then
|
||||
pkgmgr.refresh_globals()
|
||||
end
|
||||
if not pkgmgr.games then
|
||||
pkgmgr.update_gamelist()
|
||||
end
|
||||
pkgmgr.load_all()
|
||||
|
||||
packages_raw = {}
|
||||
table.insert_all(packages_raw, pkgmgr.games)
|
||||
table.insert_all(packages_raw, pkgmgr.get_texture_packs())
|
||||
table.insert_all(packages_raw, pkgmgr.texture_packs)
|
||||
table.insert_all(packages_raw, pkgmgr.global_mods:get_list())
|
||||
|
||||
local function get_data()
|
||||
@ -207,6 +202,7 @@ local function handle_doubleclick(pkg)
|
||||
core.settings:set("texture_path", pkg.path)
|
||||
end
|
||||
packages = nil
|
||||
pkgmgr.reload_texture_packs()
|
||||
|
||||
mm_game_theme.init()
|
||||
mm_game_theme.set_engine()
|
||||
@ -271,6 +267,7 @@ local function handle_buttons(tabview, fields, tabname, tabdata)
|
||||
|
||||
core.settings:set("texture_path", txp_path)
|
||||
packages = nil
|
||||
pkgmgr.reload_texture_packs()
|
||||
|
||||
mm_game_theme.init()
|
||||
mm_game_theme.set_engine()
|
||||
|
@ -3902,6 +3902,7 @@ Operators
|
||||
---------
|
||||
|
||||
Operators can be used if all of the involved vectors have metatables:
|
||||
|
||||
* `v1 == v2`:
|
||||
* Returns whether `v1` and `v2` are identical.
|
||||
* `-v`:
|
||||
@ -4007,8 +4008,9 @@ Helper functions
|
||||
* X1, Y1, ... Z2 are coordinates
|
||||
* `relative_to`: Optional. If set to a position, each coordinate
|
||||
can use the tilde notation for relative positions
|
||||
* Tilde notation: "~": Relative coordinate
|
||||
"~<number>": Relative coordinate plus <number>
|
||||
* Tilde notation
|
||||
* `"~"`: Relative coordinate
|
||||
* `"~<number>"`: Relative coordinate plus `<number>`
|
||||
* Example: `minetest.string_to_area("(1,2,3) (~5,~-5,~)", {x=10,y=10,z=10})`
|
||||
returns `{x=1,y=2,z=3}, {x=15,y=5,z=10}`
|
||||
* `minetest.formspec_escape(string)`: returns a string
|
||||
@ -4346,6 +4348,8 @@ the previous octave.
|
||||
This may need to be tuned when altering `lacunarity`; when doing so consider
|
||||
that a common medium value is 1 / lacunarity.
|
||||
|
||||
Instead of `persistence`, the key `persist` may be used to the same effect.
|
||||
|
||||
### `lacunarity`
|
||||
|
||||
Each additional octave has a 'wavelength' that is the 'wavelength' of the
|
||||
|
@ -157,7 +157,7 @@ minetest.register_node("basenodes:water_flowing", {
|
||||
"Drowning damage: 1",
|
||||
drawtype = "flowingliquid",
|
||||
waving = 3,
|
||||
tiles = {"default_water_flowing.png"},
|
||||
tiles = {"default_water_flowing.png"..WATER_ALPHA},
|
||||
special_tiles = {
|
||||
{name = "default_water_flowing.png"..WATER_ALPHA,
|
||||
backface_culling = false},
|
||||
|
@ -105,3 +105,9 @@ minetest.register_craftitem("testitems:telescope_stick", {
|
||||
return itemstack
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("testitems:translucent_item", {
|
||||
description = S("Translucent item (translucent inventory & wield image)"),
|
||||
inventory_image = "testitems_translucent.png",
|
||||
wield_image = "testitems_translucent.png",
|
||||
})
|
BIN
games/devtest/mods/testitems/textures/testitems_translucent.png
Normal file
BIN
games/devtest/mods/testitems/textures/testitems_translucent.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 208 B |
@ -2,29 +2,22 @@
|
||||
|
||||
local S = minetest.get_translator("testnodes")
|
||||
|
||||
-- Complex mesh
|
||||
minetest.register_node("testnodes:performance_mesh_clip", {
|
||||
description = S("Performance Test Node") .. "\n" .. S("Marble with 'clip' transparency"),
|
||||
drawtype = "mesh",
|
||||
mesh = "testnodes_marble_glass.obj",
|
||||
tiles = {"testnodes_marble_glass.png"},
|
||||
paramtype = "light",
|
||||
use_texture_alpha = "clip",
|
||||
for use_texture_alpha, description in pairs({
|
||||
opaque = S("Marble with 'opaque' transparency"),
|
||||
clip = S("Marble with 'clip' transparency"),
|
||||
blend = S("Marble with 'blend' transparency"),
|
||||
}) do
|
||||
minetest.register_node("testnodes:performance_mesh_" .. use_texture_alpha, {
|
||||
description = S("Performance Test Node") .. "\n" .. description,
|
||||
drawtype = "mesh",
|
||||
mesh = "testnodes_marble_glass.obj",
|
||||
tiles = {"testnodes_marble_glass.png"},
|
||||
paramtype = "light",
|
||||
use_texture_alpha = use_texture_alpha,
|
||||
|
||||
groups = {dig_immediate=3},
|
||||
})
|
||||
|
||||
-- Complex mesh, alpha blending
|
||||
minetest.register_node("testnodes:performance_mesh_blend", {
|
||||
description = S("Performance Test Node") .. "\n" .. S("Marble with 'blend' transparency"),
|
||||
drawtype = "mesh",
|
||||
mesh = "testnodes_marble_glass.obj",
|
||||
tiles = {"testnodes_marble_glass.png"},
|
||||
paramtype = "light",
|
||||
use_texture_alpha = "blend",
|
||||
|
||||
groups = {dig_immediate=3},
|
||||
})
|
||||
groups = {dig_immediate=3},
|
||||
})
|
||||
end
|
||||
|
||||
-- Overlay
|
||||
minetest.register_node("testnodes:performance_overlay_clip", {
|
||||
|
@ -200,7 +200,7 @@ class IGUIButton : public IGUIElement
|
||||
\param loop: True if the animation should loop, false if not
|
||||
\param scale: True if the sprite should scale to button size, false if not */
|
||||
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
|
||||
video::SColor color = video::SColor(255, 255, 255, 255), bool loop = false, bool scale = false) = 0;
|
||||
video::SColor color = video::SColor(255, 255, 255, 255), bool loop = false) = 0;
|
||||
|
||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||
virtual s32 getSpriteIndex(EGUI_BUTTON_STATE state) const = 0;
|
||||
@ -211,9 +211,6 @@ class IGUIButton : public IGUIElement
|
||||
//! Returns if the sprite in the given state does loop
|
||||
virtual bool getSpriteLoop(EGUI_BUTTON_STATE state) const = 0;
|
||||
|
||||
//! Returns if the sprite in the given state is scaled
|
||||
virtual bool getSpriteScale(EGUI_BUTTON_STATE state) const = 0;
|
||||
|
||||
//! Sets if the button should behave like a push button.
|
||||
/** Which means it can be in two states: Normal or Pressed. With a click on the button,
|
||||
the user can change the state of the button. */
|
||||
|
@ -374,6 +374,12 @@ const c8 *const GUISkinFontNames[EGDF_COUNT + 1] = {
|
||||
class IGUISkin : virtual public IReferenceCounted
|
||||
{
|
||||
public:
|
||||
//! returns display density scaling factor
|
||||
virtual float getScale() const = 0;
|
||||
|
||||
//! sets display density scaling factor
|
||||
virtual void setScale(float scale) = 0;
|
||||
|
||||
//! returns default color
|
||||
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const = 0;
|
||||
|
||||
|
@ -75,12 +75,11 @@ void CGUIButton::setSpriteBank(IGUISpriteBank *sprites)
|
||||
SpriteBank = sprites;
|
||||
}
|
||||
|
||||
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale)
|
||||
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
|
||||
{
|
||||
ButtonSprites[(u32)state].Index = index;
|
||||
ButtonSprites[(u32)state].Color = color;
|
||||
ButtonSprites[(u32)state].Loop = loop;
|
||||
ButtonSprites[(u32)state].Scale = scale;
|
||||
}
|
||||
|
||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||
@ -101,12 +100,6 @@ bool CGUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const
|
||||
return ButtonSprites[(u32)state].Loop;
|
||||
}
|
||||
|
||||
//! Returns if the sprite in the given state is scaled
|
||||
bool CGUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const
|
||||
{
|
||||
return ButtonSprites[(u32)state].Scale;
|
||||
}
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIButton::OnEvent(const SEvent &event)
|
||||
{
|
||||
@ -294,19 +287,26 @@ void CGUIButton::draw()
|
||||
void CGUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di ¢er)
|
||||
{
|
||||
u32 stateIdx = (u32)state;
|
||||
s32 spriteIdx = ButtonSprites[stateIdx].Index;
|
||||
if (spriteIdx == -1)
|
||||
return;
|
||||
|
||||
if (ButtonSprites[stateIdx].Index != -1) {
|
||||
if (ButtonSprites[stateIdx].Scale) {
|
||||
const video::SColor colors[] = {ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color};
|
||||
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect,
|
||||
&AbsoluteClippingRect, colors,
|
||||
os::Timer::getTime() - startTime, ButtonSprites[stateIdx].Loop);
|
||||
} else {
|
||||
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
|
||||
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, os::Timer::getTime(),
|
||||
ButtonSprites[stateIdx].Loop, true);
|
||||
}
|
||||
}
|
||||
u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber;
|
||||
core::rect<s32> srcRect = SpriteBank->getPositions()[rectIdx];
|
||||
|
||||
IGUISkin *skin = Environment->getSkin();
|
||||
s32 scale = std::max(std::floor(skin->getScale()), 1.0f);
|
||||
core::rect<s32> rect(center, srcRect.getSize() * scale);
|
||||
rect -= rect.getSize() / 2;
|
||||
|
||||
const video::SColor colors[] = {
|
||||
ButtonSprites[stateIdx].Color,
|
||||
ButtonSprites[stateIdx].Color,
|
||||
ButtonSprites[stateIdx].Color,
|
||||
ButtonSprites[stateIdx].Color,
|
||||
};
|
||||
SpriteBank->draw2DSprite(spriteIdx, rect, &AbsoluteClippingRect, colors,
|
||||
os::Timer::getTime() - startTime, ButtonSprites[stateIdx].Loop);
|
||||
}
|
||||
|
||||
EGUI_BUTTON_IMAGE_STATE CGUIButton::getImageState(bool pressed) const
|
||||
|
@ -92,7 +92,7 @@ class CGUIButton : public IGUIButton
|
||||
*/
|
||||
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
|
||||
video::SColor color = video::SColor(255, 255, 255, 255),
|
||||
bool loop = false, bool scale = false) override;
|
||||
bool loop = false) override;
|
||||
|
||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||
s32 getSpriteIndex(EGUI_BUTTON_STATE state) const override;
|
||||
@ -103,9 +103,6 @@ class CGUIButton : public IGUIButton
|
||||
//! Returns if the sprite in the given state does loop
|
||||
bool getSpriteLoop(EGUI_BUTTON_STATE state) const override;
|
||||
|
||||
//! Returns if the sprite in the given state is scaled
|
||||
bool getSpriteScale(EGUI_BUTTON_STATE state) const override;
|
||||
|
||||
//! Sets if the button should behave like a push button. Which means it
|
||||
//! can be in two states: Normal or Pressed. With a click on the button,
|
||||
//! the user can change the state of the button.
|
||||
@ -158,19 +155,18 @@ class CGUIButton : public IGUIButton
|
||||
struct ButtonSprite
|
||||
{
|
||||
ButtonSprite() :
|
||||
Index(-1), Loop(false), Scale(false)
|
||||
Index(-1), Loop(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const ButtonSprite &other) const
|
||||
{
|
||||
return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;
|
||||
return Index == other.Index && Color == other.Color && Loop == other.Loop;
|
||||
}
|
||||
|
||||
s32 Index;
|
||||
video::SColor Color;
|
||||
bool Loop;
|
||||
bool Scale;
|
||||
};
|
||||
|
||||
ButtonSprite ButtonSprites[EGBS_COUNT];
|
||||
|
@ -24,6 +24,12 @@ class CGUISkin : public IGUISkin
|
||||
//! destructor
|
||||
virtual ~CGUISkin();
|
||||
|
||||
//! returns display density scaling factor
|
||||
virtual float getScale() const override { return Scale; }
|
||||
|
||||
//! sets display density scaling factor
|
||||
virtual void setScale(float scale) override { Scale = scale; }
|
||||
|
||||
//! returns default color
|
||||
video::SColor getColor(EGUI_DEFAULT_COLOR color) const override;
|
||||
|
||||
@ -210,6 +216,7 @@ class CGUISkin : public IGUISkin
|
||||
EGUI_SKIN_TYPE getType() const override;
|
||||
|
||||
private:
|
||||
float Scale = 1.0f;
|
||||
video::SColor Colors[EGDC_COUNT];
|
||||
s32 Sizes[EGDS_COUNT];
|
||||
u32 Icons[EGDI_COUNT];
|
||||
|
@ -129,9 +129,9 @@ EM_BOOL CIrrDeviceSDL::MouseLeaveCallback(int eventType, const EmscriptenMouseEv
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key)
|
||||
bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE irrlichtKey)
|
||||
{
|
||||
switch (key) {
|
||||
switch (irrlichtKey) {
|
||||
// keys which are known to have safe special character interpretation
|
||||
// could need changes over time (removals and additions!)
|
||||
case KEY_RETURN:
|
||||
@ -189,24 +189,68 @@ bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key)
|
||||
}
|
||||
}
|
||||
|
||||
int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key)
|
||||
int CIrrDeviceSDL::findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock)
|
||||
{
|
||||
switch (irrlichtKey) {
|
||||
// special cases that always return a char regardless of how the SDL keycode
|
||||
// looks
|
||||
switch (key) {
|
||||
case KEY_RETURN:
|
||||
case KEY_ESCAPE:
|
||||
return (int)key;
|
||||
return (int)irrlichtKey;
|
||||
|
||||
// This is necessary for keys on the numpad because they don't use the same
|
||||
// keycodes as their non-numpad versions (whose keycodes correspond to chars),
|
||||
// but have their own SDL keycodes and their own Irrlicht keycodes (which
|
||||
// don't correspond to chars).
|
||||
case KEY_MULTIPLY:
|
||||
return '*';
|
||||
case KEY_ADD:
|
||||
return '+';
|
||||
case KEY_SUBTRACT:
|
||||
return '-';
|
||||
case KEY_DIVIDE:
|
||||
return '/';
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (numlock) {
|
||||
// Number keys on the numpad are also affected, but we only want them
|
||||
// to produce number chars when numlock is enabled.
|
||||
switch (irrlichtKey) {
|
||||
case KEY_NUMPAD0:
|
||||
return '0';
|
||||
case KEY_NUMPAD1:
|
||||
return '1';
|
||||
case KEY_NUMPAD2:
|
||||
return '2';
|
||||
case KEY_NUMPAD3:
|
||||
return '3';
|
||||
case KEY_NUMPAD4:
|
||||
return '4';
|
||||
case KEY_NUMPAD5:
|
||||
return '5';
|
||||
case KEY_NUMPAD6:
|
||||
return '6';
|
||||
case KEY_NUMPAD7:
|
||||
return '7';
|
||||
case KEY_NUMPAD8:
|
||||
return '8';
|
||||
case KEY_NUMPAD9:
|
||||
return '9';
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// SDL in-place ORs values with no character representation with 1<<30
|
||||
// https://wiki.libsdl.org/SDL2/SDLKeycodeLookup
|
||||
if (assumedChar & (1 << 30))
|
||||
// This also affects the numpad keys btw.
|
||||
if (sdlKey & (1 << 30))
|
||||
return 0;
|
||||
|
||||
switch (key) {
|
||||
switch (irrlichtKey) {
|
||||
case KEY_PRIOR:
|
||||
case KEY_NEXT:
|
||||
case KEY_HOME:
|
||||
@ -218,7 +262,7 @@ int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key)
|
||||
case KEY_NUMLOCK:
|
||||
return 0;
|
||||
default:
|
||||
return assumedChar;
|
||||
return sdlKey;
|
||||
}
|
||||
}
|
||||
|
||||
@ -825,7 +869,8 @@ bool CIrrDeviceSDL::run()
|
||||
irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN);
|
||||
irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0;
|
||||
irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL) != 0;
|
||||
irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key);
|
||||
irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key,
|
||||
(SDL_event.key.keysym.mod & KMOD_NUM) != 0);
|
||||
postEventFromUser(irrevent);
|
||||
} break;
|
||||
|
||||
|
@ -273,10 +273,10 @@ class CIrrDeviceSDL : public CIrrDeviceStub
|
||||
|
||||
#endif
|
||||
// Check if a key is a known special character with no side effects on text boxes.
|
||||
static bool keyIsKnownSpecial(EKEY_CODE key);
|
||||
static bool keyIsKnownSpecial(EKEY_CODE irrlichtKey);
|
||||
|
||||
// Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).
|
||||
static int findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key);
|
||||
static int findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock);
|
||||
|
||||
// Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
|
||||
void resetReceiveTextInputEvents();
|
||||
|
@ -352,6 +352,7 @@ void ClientLauncher::config_guienv()
|
||||
|
||||
float density = rangelim(g_settings->getFloat("gui_scaling"), 0.5f, 20) *
|
||||
RenderingEngine::getDisplayDensity();
|
||||
skin->setScale(density);
|
||||
skin->setSize(gui::EGDS_CHECK_BOX_WIDTH, (s32)(17.0f * density));
|
||||
skin->setSize(gui::EGDS_SCROLLBAR_SIZE, (s32)(21.0f * density));
|
||||
skin->setSize(gui::EGDS_WINDOW_BUTTON_WIDTH, (s32)(15.0f * density));
|
||||
|
@ -1145,7 +1145,6 @@ void drawItemStack(
|
||||
}
|
||||
|
||||
video::SMaterial &material = buf->getMaterial();
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
material.Lighting = false;
|
||||
driver->setMaterial(material);
|
||||
driver->drawMeshBuffer(buf);
|
||||
|
@ -526,26 +526,7 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
|
||||
shaderinfo.name = name;
|
||||
shaderinfo.material_type = material_type;
|
||||
shaderinfo.drawtype = drawtype;
|
||||
switch (material_type) {
|
||||
case TILE_MATERIAL_OPAQUE:
|
||||
case TILE_MATERIAL_LIQUID_OPAQUE:
|
||||
case TILE_MATERIAL_WAVING_LIQUID_OPAQUE:
|
||||
shaderinfo.base_material = video::EMT_SOLID;
|
||||
break;
|
||||
case TILE_MATERIAL_ALPHA:
|
||||
case TILE_MATERIAL_PLAIN_ALPHA:
|
||||
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
||||
case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT:
|
||||
shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
break;
|
||||
case TILE_MATERIAL_BASIC:
|
||||
case TILE_MATERIAL_PLAIN:
|
||||
case TILE_MATERIAL_WAVING_LEAVES:
|
||||
case TILE_MATERIAL_WAVING_PLANTS:
|
||||
case TILE_MATERIAL_WAVING_LIQUID_BASIC:
|
||||
shaderinfo.base_material = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
break;
|
||||
}
|
||||
shaderinfo.base_material = MaterialType_to_irr(material_type);
|
||||
shaderinfo.material = shaderinfo.base_material;
|
||||
|
||||
bool enable_shaders = g_settings->getBool("enable_shaders");
|
||||
|
@ -18,31 +18,54 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "tile.h"
|
||||
#include "EMaterialTypes.h"
|
||||
#include "SMaterial.h"
|
||||
|
||||
// Sets everything else except the texture in the material
|
||||
void TileLayer::applyMaterialOptions(video::SMaterial &material) const
|
||||
void MaterialType_to_irr(MaterialType material_type,
|
||||
video::E_MATERIAL_TYPE &irr_mat_type, f32 &irr_mat_param)
|
||||
{
|
||||
switch (material_type) {
|
||||
case TILE_MATERIAL_OPAQUE:
|
||||
case TILE_MATERIAL_LIQUID_OPAQUE:
|
||||
case TILE_MATERIAL_WAVING_LIQUID_OPAQUE:
|
||||
material.MaterialType = video::EMT_SOLID;
|
||||
irr_mat_type = video::EMT_SOLID;
|
||||
irr_mat_param = 0.0f;
|
||||
break;
|
||||
case TILE_MATERIAL_ALPHA:
|
||||
case TILE_MATERIAL_PLAIN_ALPHA:
|
||||
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
||||
case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT:
|
||||
default:
|
||||
irr_mat_type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
irr_mat_param = 0.0f;
|
||||
break;
|
||||
case TILE_MATERIAL_BASIC:
|
||||
case TILE_MATERIAL_PLAIN:
|
||||
case TILE_MATERIAL_WAVING_LEAVES:
|
||||
case TILE_MATERIAL_WAVING_PLANTS:
|
||||
case TILE_MATERIAL_WAVING_LIQUID_BASIC:
|
||||
material.MaterialTypeParam = 0.5;
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
break;
|
||||
case TILE_MATERIAL_ALPHA:
|
||||
case TILE_MATERIAL_LIQUID_TRANSPARENT:
|
||||
case TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT:
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
break;
|
||||
default:
|
||||
irr_mat_type = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
irr_mat_param = 0.5f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
video::E_MATERIAL_TYPE MaterialType_to_irr(MaterialType material_type) {
|
||||
video::E_MATERIAL_TYPE res;
|
||||
f32 unused;
|
||||
MaterialType_to_irr(material_type, res, unused);
|
||||
return res;
|
||||
}
|
||||
|
||||
void MaterialType_to_irr(MaterialType material_type, video::SMaterial &material) {
|
||||
MaterialType_to_irr(material_type,
|
||||
material.MaterialType, material.MaterialTypeParam);
|
||||
}
|
||||
|
||||
// Sets everything else except the texture in the material
|
||||
void TileLayer::applyMaterialOptions(video::SMaterial &material) const
|
||||
{
|
||||
MaterialType_to_irr(static_cast<MaterialType>(material_type), material);
|
||||
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) != 0;
|
||||
if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) {
|
||||
material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
|
||||
|
@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "EMaterialTypes.h"
|
||||
#include "irrlichttypes.h"
|
||||
#include <ITexture.h>
|
||||
#include <vector>
|
||||
@ -39,6 +40,11 @@ enum MaterialType{
|
||||
TILE_MATERIAL_PLAIN_ALPHA
|
||||
};
|
||||
|
||||
void MaterialType_to_irr(MaterialType material_type,
|
||||
video::E_MATERIAL_TYPE &irr_mat_type, f32 &irr_mat_param);
|
||||
video::E_MATERIAL_TYPE MaterialType_to_irr(MaterialType material_type);
|
||||
void MaterialType_to_irr(MaterialType material_type, video::SMaterial &mat);
|
||||
|
||||
// Material flags
|
||||
// Should backface culling be enabled?
|
||||
#define MATERIAL_FLAG_BACKFACE_CULLING 0x01
|
||||
|
@ -18,8 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "wieldmesh.h"
|
||||
#include "EMaterialTypes.h"
|
||||
#include "SMaterial.h"
|
||||
#include "settings.h"
|
||||
#include "shader.h"
|
||||
#include "inventory.h"
|
||||
#include "client.h"
|
||||
#include "itemdef.h"
|
||||
@ -29,7 +30,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "mapblock_mesh.h"
|
||||
#include "client/meshgen/collector.h"
|
||||
#include "client/tile.h"
|
||||
#include "log.h"
|
||||
#include "util/numeric.h"
|
||||
#include <map>
|
||||
#include <IMeshManipulator.h>
|
||||
@ -41,6 +41,56 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define MIN_EXTRUSION_MESH_RESOLUTION 16
|
||||
#define MAX_EXTRUSION_MESH_RESOLUTION 512
|
||||
|
||||
/*!
|
||||
* Applies overlays, textures and optionally materials to the given mesh and
|
||||
* extracts tile colors for colorization.
|
||||
* \param mattype overrides the buffer's material type, but can also
|
||||
* be NULL to leave the original material.
|
||||
* \param colors returns the colors of the mesh buffers in the mesh.
|
||||
*/
|
||||
static void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f,
|
||||
std::vector<ItemPartColor> *colors)
|
||||
{
|
||||
const u32 mc = mesh->getMeshBufferCount();
|
||||
// Allocate colors for existing buffers
|
||||
colors->clear();
|
||||
colors->resize(mc);
|
||||
|
||||
for (u32 i = 0; i < mc; ++i) {
|
||||
const TileSpec *tile = &(f.tiles[i]);
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
||||
for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) {
|
||||
const TileLayer *layer = &tile->layers[layernum];
|
||||
if (layer->texture_id == 0)
|
||||
continue;
|
||||
if (layernum != 0) {
|
||||
scene::IMeshBuffer *copy = cloneMeshBuffer(buf);
|
||||
copy->getMaterial() = buf->getMaterial();
|
||||
mesh->addMeshBuffer(copy);
|
||||
copy->drop();
|
||||
buf = copy;
|
||||
colors->emplace_back(layer->has_color, layer->color);
|
||||
} else {
|
||||
(*colors)[i] = ItemPartColor(layer->has_color, layer->color);
|
||||
}
|
||||
|
||||
video::SMaterial &material = buf->getMaterial();
|
||||
if (layer->animation_frame_count > 1) {
|
||||
const FrameSpec &animation_frame = (*layer->frames)[0];
|
||||
material.setTexture(0, animation_frame.texture);
|
||||
} else {
|
||||
material.setTexture(0, layer->texture);
|
||||
}
|
||||
|
||||
if (tile->world_aligned) {
|
||||
u32 n = buf->getVertexCount();
|
||||
for (u32 k = 0; k != n; ++k)
|
||||
buf->getTCoords(k) /= layer->scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y)
|
||||
{
|
||||
const f32 r = 0.5;
|
||||
@ -193,10 +243,55 @@ class ExtrusionMeshCache: public IReferenceCounted
|
||||
|
||||
static ExtrusionMeshCache *g_extrusion_mesh_cache = nullptr;
|
||||
|
||||
static scene::SMesh *getExtrudedMesh(ITextureSource *tsrc,
|
||||
const std::string &imagename, const std::string &overlay_name)
|
||||
{
|
||||
// check textures
|
||||
video::ITexture *texture = tsrc->getTextureForMesh(imagename);
|
||||
if (!texture) {
|
||||
return NULL;
|
||||
}
|
||||
video::ITexture *overlay_texture =
|
||||
(overlay_name.empty()) ? NULL : tsrc->getTexture(overlay_name);
|
||||
|
||||
// get mesh
|
||||
core::dimension2d<u32> dim = texture->getSize();
|
||||
scene::IMesh *original = g_extrusion_mesh_cache->create(dim);
|
||||
scene::SMesh *mesh = cloneMesh(original);
|
||||
original->drop();
|
||||
|
||||
//set texture
|
||||
mesh->getMeshBuffer(0)->getMaterial().setTexture(0,
|
||||
tsrc->getTexture(imagename));
|
||||
if (overlay_texture) {
|
||||
scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0));
|
||||
copy->getMaterial().setTexture(0, overlay_texture);
|
||||
mesh->addMeshBuffer(copy);
|
||||
copy->drop();
|
||||
}
|
||||
// Customize materials
|
||||
for (u32 layer = 0; layer < mesh->getMeshBufferCount(); layer++) {
|
||||
video::SMaterial &material = mesh->getMeshBuffer(layer)->getMaterial();
|
||||
material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
|
||||
material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
|
||||
material.forEachTexture([] (auto &tex) {
|
||||
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
|
||||
tex.MagFilter = video::ETMAGF_NEAREST;
|
||||
});
|
||||
material.BackfaceCulling = true;
|
||||
material.Lighting = false;
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
material.MaterialTypeParam = 0.0f; // render everything with alpha > 0
|
||||
material.ZWriteEnable = video::EZW_ON;
|
||||
}
|
||||
scaleMesh(mesh, v3f(2.0, 2.0, 2.0));
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting):
|
||||
scene::ISceneNode(mgr->getRootSceneNode(), mgr, id),
|
||||
m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF),
|
||||
m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL),
|
||||
m_lighting(lighting)
|
||||
{
|
||||
m_enable_shaders = g_settings->getBool("enable_shaders");
|
||||
@ -248,7 +343,17 @@ void WieldMeshSceneNode::setCube(const ContentFeatures &f,
|
||||
scene::IMesh *cubemesh = g_extrusion_mesh_cache->createCube();
|
||||
scene::SMesh *copy = cloneMesh(cubemesh);
|
||||
cubemesh->drop();
|
||||
postProcessNodeMesh(copy, f, false, true, &m_material_type, &m_colors, true);
|
||||
postProcessNodeMesh(copy, f, &m_colors);
|
||||
|
||||
// Customize materials
|
||||
for (u32 i = 0; i < cubemesh->getMeshBufferCount(); ++i) {
|
||||
// It suffices to look at the first layer;
|
||||
// a special overlay layer needs to be consistent with it -
|
||||
// otherwise we would be overwriting the material options of the fist layer
|
||||
scene::IMeshBuffer *buf = cubemesh->getMeshBuffer(i);
|
||||
f.tiles[i].layers[0].applyMaterialOptions(buf->getMaterial());
|
||||
}
|
||||
|
||||
changeToMesh(copy);
|
||||
copy->drop();
|
||||
m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR);
|
||||
@ -295,7 +400,8 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename,
|
||||
material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
|
||||
material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
|
||||
material.MaterialType = m_material_type;
|
||||
material.MaterialTypeParam = 0.5f;
|
||||
material.MaterialTypeParam = m_material_type_param;
|
||||
material.ZWriteEnable = video::EZW_ON;
|
||||
material.BackfaceCulling = true;
|
||||
// Enable bi/trilinear filtering only for high resolution textures
|
||||
bool bilinear_filter = dim.Width > 32 && m_bilinear_filter;
|
||||
@ -350,13 +456,11 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n,
|
||||
}
|
||||
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
||||
buf->Material.setTexture(0, p.layer.texture);
|
||||
p.layer.applyMaterialOptions(buf->Material);
|
||||
mesh->addMeshBuffer(buf);
|
||||
buf->append(&p.vertices[0], p.vertices.size(),
|
||||
&p.indices[0], p.indices.size());
|
||||
buf->drop();
|
||||
colors->push_back(
|
||||
ItemPartColor(p.layer.has_color, p.layer.color));
|
||||
colors->emplace_back(p.layer.has_color, p.layer.color);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
@ -365,7 +469,6 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
||||
{
|
||||
ITextureSource *tsrc = client->getTextureSource();
|
||||
IItemDefManager *idef = client->getItemDefManager();
|
||||
IShaderSource *shdrsrc = client->getShaderSource();
|
||||
const NodeDefManager *ndef = client->getNodeDefManager();
|
||||
const ItemDefinition &def = item.getDefinition(idef);
|
||||
const ContentFeatures &f = ndef->get(def.name);
|
||||
@ -373,8 +476,16 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
||||
|
||||
scene::SMesh *mesh = nullptr;
|
||||
|
||||
const auto material_type = def.type == ITEM_NODE
|
||||
? f.getMaterialType() : TILE_MATERIAL_ALPHA;
|
||||
MaterialType_to_irr(material_type, m_material_type, m_material_type_param);
|
||||
if (m_enable_shaders) {
|
||||
u32 shader_id = shdrsrc->getShader("object_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
|
||||
IShaderSource *shdrsrc = client->getShaderSource();
|
||||
u32 shader_id = shdrsrc->getShader("object_shader",
|
||||
material_type, def.type == ITEM_NODE ? f.drawtype : NDT_MESH);
|
||||
// The shader gives a material ID (different from our material type) back.
|
||||
// Strictly speaking, "m_material type" is a misnomer,
|
||||
// since either a material type or ID is stored.
|
||||
m_material_type = shdrsrc->getShaderInfo(shader_id).material;
|
||||
}
|
||||
|
||||
@ -463,7 +574,8 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
||||
for (u32 i = 0; i < material_count; ++i) {
|
||||
video::SMaterial &material = m_meshnode->getMaterial(i);
|
||||
material.MaterialType = m_material_type;
|
||||
material.MaterialTypeParam = 0.5f;
|
||||
material.MaterialTypeParam = m_material_type_param;
|
||||
material.ZWriteEnable = video::EZW_ON;
|
||||
material.BackfaceCulling = cull_backface;
|
||||
material.forEachTexture([this] (auto &tex) {
|
||||
setMaterialFilters(tex, m_bilinear_filter, m_trilinear_filter,
|
||||
@ -624,8 +736,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
||||
} else
|
||||
scaleMesh(mesh, v3f(1.2, 1.2, 1.2));
|
||||
// add overlays
|
||||
postProcessNodeMesh(mesh, f, false, false, nullptr,
|
||||
&result->buffer_colors, true);
|
||||
postProcessNodeMesh(mesh, f, &result->buffer_colors);
|
||||
if (f.drawtype == NDT_ALLFACES)
|
||||
scaleMesh(mesh, v3f(f.visual_scale));
|
||||
break;
|
||||
@ -664,14 +775,17 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
||||
for (u32 i = 0; i < mesh->getMeshBufferCount(); ++i) {
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
||||
video::SMaterial &material = buf->getMaterial();
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
material.MaterialTypeParam = 0.5f;
|
||||
// Note: This overwrites material types / type params
|
||||
// of plantlike extrusion meshes for alpha blending consistency.
|
||||
// It suffices to look at the first layer; overlays need to be consistent.
|
||||
f.tiles[i].layers[0].applyMaterialOptions(material);
|
||||
material.ZWriteEnable = video::EZW_ON;
|
||||
material.forEachTexture([] (auto &tex) {
|
||||
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
|
||||
tex.MagFilter = video::ETMAGF_NEAREST;
|
||||
});
|
||||
material.BackfaceCulling = cull_backface;
|
||||
material.Lighting = false;
|
||||
material.Lighting = false; // no lighting in the inventory
|
||||
}
|
||||
|
||||
rotateMeshXZby(mesh, -45);
|
||||
@ -685,109 +799,3 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
||||
}
|
||||
result->mesh = mesh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
scene::SMesh *getExtrudedMesh(ITextureSource *tsrc,
|
||||
const std::string &imagename, const std::string &overlay_name)
|
||||
{
|
||||
// check textures
|
||||
video::ITexture *texture = tsrc->getTextureForMesh(imagename);
|
||||
if (!texture) {
|
||||
return NULL;
|
||||
}
|
||||
video::ITexture *overlay_texture =
|
||||
(overlay_name.empty()) ? NULL : tsrc->getTexture(overlay_name);
|
||||
|
||||
// get mesh
|
||||
core::dimension2d<u32> dim = texture->getSize();
|
||||
scene::IMesh *original = g_extrusion_mesh_cache->create(dim);
|
||||
scene::SMesh *mesh = cloneMesh(original);
|
||||
original->drop();
|
||||
|
||||
//set texture
|
||||
mesh->getMeshBuffer(0)->getMaterial().setTexture(0,
|
||||
tsrc->getTexture(imagename));
|
||||
if (overlay_texture) {
|
||||
scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0));
|
||||
copy->getMaterial().setTexture(0, overlay_texture);
|
||||
mesh->addMeshBuffer(copy);
|
||||
copy->drop();
|
||||
}
|
||||
// Customize materials
|
||||
for (u32 layer = 0; layer < mesh->getMeshBufferCount(); layer++) {
|
||||
video::SMaterial &material = mesh->getMeshBuffer(layer)->getMaterial();
|
||||
material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
|
||||
material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
|
||||
material.forEachTexture([] (auto &tex) {
|
||||
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
|
||||
tex.MagFilter = video::ETMAGF_NEAREST;
|
||||
});
|
||||
material.BackfaceCulling = true;
|
||||
material.Lighting = false;
|
||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
material.MaterialTypeParam = 0.5f;
|
||||
}
|
||||
scaleMesh(mesh, v3f(2.0, 2.0, 2.0));
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f,
|
||||
bool use_shaders, bool set_material, const video::E_MATERIAL_TYPE *mattype,
|
||||
std::vector<ItemPartColor> *colors, bool apply_scale)
|
||||
{
|
||||
const u32 mc = mesh->getMeshBufferCount();
|
||||
// Allocate colors for existing buffers
|
||||
colors->clear();
|
||||
colors->resize(mc);
|
||||
|
||||
for (u32 i = 0; i < mc; ++i) {
|
||||
const TileSpec *tile = &(f.tiles[i]);
|
||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
||||
for (int layernum = 0; layernum < MAX_TILE_LAYERS; layernum++) {
|
||||
const TileLayer *layer = &tile->layers[layernum];
|
||||
if (layer->texture_id == 0)
|
||||
continue;
|
||||
if (layernum != 0) {
|
||||
scene::IMeshBuffer *copy = cloneMeshBuffer(buf);
|
||||
copy->getMaterial() = buf->getMaterial();
|
||||
mesh->addMeshBuffer(copy);
|
||||
copy->drop();
|
||||
buf = copy;
|
||||
colors->emplace_back(layer->has_color, layer->color);
|
||||
} else {
|
||||
(*colors)[i] = ItemPartColor(layer->has_color, layer->color);
|
||||
}
|
||||
|
||||
video::SMaterial &material = buf->getMaterial();
|
||||
if (set_material)
|
||||
layer->applyMaterialOptions(material);
|
||||
if (mattype) {
|
||||
material.MaterialType = *mattype;
|
||||
}
|
||||
if (layer->animation_frame_count > 1) {
|
||||
const FrameSpec &animation_frame = (*layer->frames)[0];
|
||||
material.setTexture(0, animation_frame.texture);
|
||||
} else {
|
||||
material.setTexture(0, layer->texture);
|
||||
}
|
||||
if (use_shaders) {
|
||||
if (layer->normal_texture) {
|
||||
if (layer->animation_frame_count > 1) {
|
||||
const FrameSpec &animation_frame = (*layer->frames)[0];
|
||||
material.setTexture(1, animation_frame.normal_texture);
|
||||
} else
|
||||
material.setTexture(1, layer->normal_texture);
|
||||
}
|
||||
material.setTexture(2, layer->flags_texture);
|
||||
}
|
||||
|
||||
if (apply_scale && tile->world_aligned) {
|
||||
u32 n = buf->getVertexCount();
|
||||
for (u32 k = 0; k != n; ++k)
|
||||
buf->getTCoords(k) /= layer->scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +118,7 @@ class WieldMeshSceneNode : public scene::ISceneNode
|
||||
// Child scene node with the current wield mesh
|
||||
scene::IMeshSceneNode *m_meshnode = nullptr;
|
||||
video::E_MATERIAL_TYPE m_material_type;
|
||||
f32 m_material_type_param = 0.0f;
|
||||
|
||||
// True if SMaterial::Lighting should be enabled.
|
||||
bool m_lighting;
|
||||
@ -146,17 +147,3 @@ class WieldMeshSceneNode : public scene::ISceneNode
|
||||
};
|
||||
|
||||
void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result);
|
||||
|
||||
scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename,
|
||||
const std::string &overlay_name);
|
||||
|
||||
/*!
|
||||
* Applies overlays, textures and optionally materials to the given mesh and
|
||||
* extracts tile colors for colorization.
|
||||
* \param mattype overrides the buffer's material type, but can also
|
||||
* be NULL to leave the original material.
|
||||
* \param colors returns the colors of the mesh buffers in the mesh.
|
||||
*/
|
||||
void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f, bool use_shaders,
|
||||
bool set_material, const video::E_MATERIAL_TYPE *mattype,
|
||||
std::vector<ItemPartColor> *colors, bool apply_scale = false);
|
||||
|
@ -89,12 +89,11 @@ void GUIButton::setSpriteBank(IGUISpriteBank* sprites)
|
||||
SpriteBank = sprites;
|
||||
}
|
||||
|
||||
void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale)
|
||||
void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
|
||||
{
|
||||
ButtonSprites[(u32)state].Index = index;
|
||||
ButtonSprites[(u32)state].Color = color;
|
||||
ButtonSprites[(u32)state].Loop = loop;
|
||||
ButtonSprites[(u32)state].Scale = scale;
|
||||
}
|
||||
|
||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||
@ -115,12 +114,6 @@ bool GUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const
|
||||
return ButtonSprites[(u32)state].Loop;
|
||||
}
|
||||
|
||||
//! Returns if the sprite in the given state is scaled
|
||||
bool GUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const
|
||||
{
|
||||
return ButtonSprites[(u32)state].Scale;
|
||||
}
|
||||
|
||||
//! called if an event happened.
|
||||
bool GUIButton::OnEvent(const SEvent& event)
|
||||
{
|
||||
@ -354,23 +347,26 @@ void GUIButton::draw()
|
||||
void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center)
|
||||
{
|
||||
u32 stateIdx = (u32)state;
|
||||
s32 spriteIdx = ButtonSprites[stateIdx].Index;
|
||||
if (spriteIdx == -1)
|
||||
return;
|
||||
|
||||
if (ButtonSprites[stateIdx].Index != -1)
|
||||
{
|
||||
if ( ButtonSprites[stateIdx].Scale )
|
||||
{
|
||||
const video::SColor colors[] = {ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color};
|
||||
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect.UpperLeftCorner,
|
||||
&AbsoluteClippingRect, colors[0], // FIXME: remove [0]
|
||||
porting::getTimeMs()-startTime, ButtonSprites[stateIdx].Loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
|
||||
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, porting::getTimeMs(),
|
||||
ButtonSprites[stateIdx].Loop, true);
|
||||
}
|
||||
}
|
||||
u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber;
|
||||
core::rect<s32> srcRect = SpriteBank->getPositions()[rectIdx];
|
||||
|
||||
IGUISkin *skin = Environment->getSkin();
|
||||
s32 scale = std::max(std::floor(skin->getScale()), 1.0f);
|
||||
core::rect<s32> rect(center, srcRect.getSize() * scale);
|
||||
rect -= rect.getSize() / 2;
|
||||
|
||||
const video::SColor colors[] = {
|
||||
ButtonSprites[stateIdx].Color,
|
||||
ButtonSprites[stateIdx].Color,
|
||||
ButtonSprites[stateIdx].Color,
|
||||
ButtonSprites[stateIdx].Color,
|
||||
};
|
||||
SpriteBank->draw2DSprite(spriteIdx, rect, &AbsoluteClippingRect, colors,
|
||||
porting::getTimeMs() - startTime, ButtonSprites[stateIdx].Loop);
|
||||
}
|
||||
|
||||
EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const
|
||||
|
@ -92,7 +92,7 @@ class GUIButton : public gui::IGUIButton
|
||||
*/
|
||||
virtual void setSprite(gui::EGUI_BUTTON_STATE state, s32 index,
|
||||
video::SColor color=video::SColor(255,255,255,255),
|
||||
bool loop=false, bool scale=false) override;
|
||||
bool loop=false) override;
|
||||
|
||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||
virtual s32 getSpriteIndex(gui::EGUI_BUTTON_STATE state) const override;
|
||||
@ -103,9 +103,6 @@ class GUIButton : public gui::IGUIButton
|
||||
//! Returns if the sprite in the given state does loop
|
||||
virtual bool getSpriteLoop(gui::EGUI_BUTTON_STATE state) const override;
|
||||
|
||||
//! Returns if the sprite in the given state is scaled
|
||||
virtual bool getSpriteScale(gui::EGUI_BUTTON_STATE state) const override;
|
||||
|
||||
//! Sets if the button should behave like a push button. Which means it
|
||||
//! can be in two states: Normal or Pressed. With a click on the button,
|
||||
//! the user can change the state of the button.
|
||||
@ -230,13 +227,12 @@ class GUIButton : public gui::IGUIButton
|
||||
{
|
||||
bool operator==(const ButtonSprite &other) const
|
||||
{
|
||||
return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;
|
||||
return Index == other.Index && Color == other.Color && Loop == other.Loop;
|
||||
}
|
||||
|
||||
s32 Index = -1;
|
||||
video::SColor Color;
|
||||
bool Loop = false;
|
||||
bool Scale = false;
|
||||
};
|
||||
|
||||
ButtonSprite ButtonSprites[gui::EGBS_COUNT];
|
||||
|
@ -27,6 +27,12 @@ namespace gui
|
||||
//! destructor
|
||||
virtual ~GUISkin();
|
||||
|
||||
//! returns display density scaling factor
|
||||
virtual float getScale() const { return Scale; }
|
||||
|
||||
//! sets display density scaling factor
|
||||
virtual void setScale(float scale) { Scale = scale; }
|
||||
|
||||
//! returns default color
|
||||
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const;
|
||||
|
||||
@ -292,6 +298,7 @@ namespace gui
|
||||
|
||||
private:
|
||||
|
||||
float Scale = 1.0f;
|
||||
video::SColor Colors[EGDC_COUNT];
|
||||
s32 Sizes[EGDS_COUNT];
|
||||
u32 Icons[EGDI_COUNT];
|
||||
|
112
src/nodedef.cpp
112
src/nodedef.cpp
@ -784,6 +784,80 @@ bool isWorldAligned(AlignStyle style, WorldAlignMode mode, NodeDrawType drawtype
|
||||
return false;
|
||||
}
|
||||
|
||||
void ContentFeatures::updateAlpha(bool translucent_liquids) {
|
||||
if ((drawtype == NDT_LIQUID || drawtype == NDT_FLOWINGLIQUID) &&
|
||||
!translucent_liquids)
|
||||
alpha = ALPHAMODE_OPAQUE;
|
||||
}
|
||||
|
||||
MaterialType ContentFeatures::getMaterialType() const
|
||||
{
|
||||
MaterialType material_type;
|
||||
switch (alpha) {
|
||||
case ALPHAMODE_OPAQUE:
|
||||
material_type = TILE_MATERIAL_OPAQUE;
|
||||
break;
|
||||
case ALPHAMODE_CLIP:
|
||||
material_type = TILE_MATERIAL_BASIC;
|
||||
break;
|
||||
case ALPHAMODE_BLEND:
|
||||
default:
|
||||
material_type = TILE_MATERIAL_ALPHA;
|
||||
break;
|
||||
}
|
||||
switch (drawtype) {
|
||||
case NDT_LIQUID:
|
||||
case NDT_FLOWINGLIQUID:
|
||||
switch (alpha) {
|
||||
case ALPHAMODE_OPAQUE:
|
||||
return (waving == 3)
|
||||
? TILE_MATERIAL_WAVING_LIQUID_OPAQUE
|
||||
: TILE_MATERIAL_LIQUID_OPAQUE;
|
||||
case ALPHAMODE_CLIP:
|
||||
return (waving == 3)
|
||||
? TILE_MATERIAL_WAVING_LIQUID_BASIC
|
||||
: TILE_MATERIAL_LIQUID_TRANSPARENT;
|
||||
case ALPHAMODE_BLEND:
|
||||
default:
|
||||
return (waving == 3)
|
||||
? TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT
|
||||
: TILE_MATERIAL_LIQUID_TRANSPARENT;
|
||||
}
|
||||
break;
|
||||
case NDT_ALLFACES_OPTIONAL:
|
||||
if (waving >= 1)
|
||||
return TILE_MATERIAL_WAVING_LEAVES;
|
||||
break;
|
||||
case NDT_PLANTLIKE:
|
||||
if (waving >= 1)
|
||||
return TILE_MATERIAL_WAVING_PLANTS;
|
||||
break;
|
||||
case NDT_MESH:
|
||||
case NDT_NODEBOX:
|
||||
switch (waving) {
|
||||
case 1:
|
||||
return TILE_MATERIAL_WAVING_PLANTS;
|
||||
case 2:
|
||||
return TILE_MATERIAL_WAVING_LEAVES;
|
||||
case 3:
|
||||
switch (alpha) {
|
||||
case ALPHAMODE_OPAQUE:
|
||||
return TILE_MATERIAL_WAVING_LIQUID_OPAQUE;
|
||||
case ALPHAMODE_CLIP:
|
||||
return TILE_MATERIAL_WAVING_LIQUID_BASIC;
|
||||
case ALPHAMODE_BLEND:
|
||||
return TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return material_type;
|
||||
}
|
||||
|
||||
void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc,
|
||||
scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings)
|
||||
{
|
||||
@ -810,11 +884,8 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||
tdef_spec[j] = tiledef_special[j];
|
||||
}
|
||||
|
||||
bool is_liquid = false;
|
||||
|
||||
MaterialType material_type = alpha == ALPHAMODE_OPAQUE ?
|
||||
TILE_MATERIAL_OPAQUE : (alpha == ALPHAMODE_CLIP ? TILE_MATERIAL_BASIC :
|
||||
TILE_MATERIAL_ALPHA);
|
||||
updateAlpha(tsettings.translucent_liquids);
|
||||
MaterialType material_type = getMaterialType();
|
||||
|
||||
switch (drawtype) {
|
||||
default:
|
||||
@ -825,16 +896,10 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||
solidness = 0;
|
||||
break;
|
||||
case NDT_LIQUID:
|
||||
if (!tsettings.translucent_liquids)
|
||||
alpha = ALPHAMODE_OPAQUE;
|
||||
solidness = 1;
|
||||
is_liquid = true;
|
||||
break;
|
||||
case NDT_FLOWINGLIQUID:
|
||||
solidness = 0;
|
||||
if (!tsettings.translucent_liquids)
|
||||
alpha = ALPHAMODE_OPAQUE;
|
||||
is_liquid = true;
|
||||
break;
|
||||
case NDT_GLASSLIKE:
|
||||
solidness = 0;
|
||||
@ -879,13 +944,9 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||
for (TileDef &td : tdef)
|
||||
td.name += std::string("^[noalpha");
|
||||
}
|
||||
if (waving >= 1)
|
||||
material_type = TILE_MATERIAL_WAVING_LEAVES;
|
||||
break;
|
||||
case NDT_PLANTLIKE:
|
||||
solidness = 0;
|
||||
if (waving >= 1)
|
||||
material_type = TILE_MATERIAL_WAVING_PLANTS;
|
||||
break;
|
||||
case NDT_FIRELIKE:
|
||||
solidness = 0;
|
||||
@ -893,15 +954,6 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||
case NDT_MESH:
|
||||
case NDT_NODEBOX:
|
||||
solidness = 0;
|
||||
if (waving == 1) {
|
||||
material_type = TILE_MATERIAL_WAVING_PLANTS;
|
||||
} else if (waving == 2) {
|
||||
material_type = TILE_MATERIAL_WAVING_LEAVES;
|
||||
} else if (waving == 3) {
|
||||
material_type = alpha == ALPHAMODE_OPAQUE ?
|
||||
TILE_MATERIAL_WAVING_LIQUID_OPAQUE : (alpha == ALPHAMODE_CLIP ?
|
||||
TILE_MATERIAL_WAVING_LIQUID_BASIC : TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT);
|
||||
}
|
||||
break;
|
||||
case NDT_TORCHLIKE:
|
||||
case NDT_SIGNLIKE:
|
||||
@ -914,17 +966,6 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_liquid) {
|
||||
if (waving == 3) {
|
||||
material_type = alpha == ALPHAMODE_OPAQUE ?
|
||||
TILE_MATERIAL_WAVING_LIQUID_OPAQUE : (alpha == ALPHAMODE_CLIP ?
|
||||
TILE_MATERIAL_WAVING_LIQUID_BASIC : TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT);
|
||||
} else {
|
||||
material_type = alpha == ALPHAMODE_OPAQUE ? TILE_MATERIAL_LIQUID_OPAQUE :
|
||||
TILE_MATERIAL_LIQUID_TRANSPARENT;
|
||||
}
|
||||
}
|
||||
|
||||
u32 tile_shader = shdsrc->getShader("nodes_shader", material_type, drawtype);
|
||||
|
||||
MaterialType overlay_material = material_type;
|
||||
@ -1082,6 +1123,7 @@ void NodeDefManager::clear()
|
||||
f.name = "air";
|
||||
f.drawtype = NDT_AIRLIKE;
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.alpha = ALPHAMODE_CLIP;
|
||||
f.light_propagates = true;
|
||||
f.sunlight_propagates = true;
|
||||
f.walkable = false;
|
||||
|
@ -531,6 +531,8 @@ struct ContentFeatures
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
void updateAlpha(bool translucent_liquids);
|
||||
MaterialType getMaterialType() const;
|
||||
void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc,
|
||||
scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user