mirror of
https://github.com/minetest/minetest.git
synced 2024-07-04 15:05:27 +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
|
return v
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function math.round(x)
|
function math.round(x)
|
||||||
if x >= 0 then
|
if x < 0 then
|
||||||
return math.floor(x + 0.5)
|
local int = math.ceil(x)
|
||||||
|
local frac = x - int
|
||||||
|
return int - ((frac <= -0.5) and 1 or 0)
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
local formspec_escapes = {
|
local formspec_escapes = {
|
||||||
|
@ -176,3 +176,17 @@ describe("formspec_escape", function()
|
|||||||
assert.equal("\\[Hello\\\\\\[", core.formspec_escape("[Hello\\["))
|
assert.equal("\\[Hello\\\\\\[", core.formspec_escape("[Hello\\["))
|
||||||
end)
|
end)
|
||||||
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:set("release", package.release)
|
||||||
conf:write()
|
conf:write()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
pkgmgr.reload_by_type(package.type)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -146,7 +148,6 @@ local function start_install(package, reason)
|
|||||||
|
|
||||||
start_install(next.package, next.reason)
|
start_install(next.package, next.reason)
|
||||||
end
|
end
|
||||||
|
|
||||||
ui.update()
|
ui.update()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -427,8 +428,9 @@ end
|
|||||||
|
|
||||||
|
|
||||||
function contentdb.update_paths()
|
function contentdb.update_paths()
|
||||||
|
pkgmgr.load_all()
|
||||||
|
|
||||||
local mod_hash = {}
|
local mod_hash = {}
|
||||||
pkgmgr.refresh_globals()
|
|
||||||
for _, mod in pairs(pkgmgr.global_mods:get_list()) do
|
for _, mod in pairs(pkgmgr.global_mods:get_list()) do
|
||||||
local cdb_id = pkgmgr.get_contentdb_id(mod)
|
local cdb_id = pkgmgr.get_contentdb_id(mod)
|
||||||
if cdb_id then
|
if cdb_id then
|
||||||
@ -437,7 +439,6 @@ function contentdb.update_paths()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local game_hash = {}
|
local game_hash = {}
|
||||||
pkgmgr.update_gamelist()
|
|
||||||
for _, game in pairs(pkgmgr.games) do
|
for _, game in pairs(pkgmgr.games) do
|
||||||
local cdb_id = pkgmgr.get_contentdb_id(game)
|
local cdb_id = pkgmgr.get_contentdb_id(game)
|
||||||
if cdb_id then
|
if cdb_id then
|
||||||
@ -446,7 +447,7 @@ function contentdb.update_paths()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local txp_hash = {}
|
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)
|
local cdb_id = pkgmgr.get_contentdb_id(txp)
|
||||||
if cdb_id then
|
if cdb_id then
|
||||||
txp_hash[contentdb.aliases[cdb_id] or cdb_id] = txp
|
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)
|
-- @param modpack Currently processing modpack or nil/"" if none (recursion)
|
||||||
function pkgmgr.get_mods(path, virtual_path, listing, modpack)
|
function pkgmgr.get_mods(path, virtual_path, listing, modpack)
|
||||||
local mods = core.get_dir_list(path, true)
|
local mods = core.get_dir_list(path, true)
|
||||||
|
local added = {}
|
||||||
for _, name in ipairs(mods) do
|
for _, name in ipairs(mods) do
|
||||||
if name:sub(1, 1) ~= "." then
|
if name:sub(1, 1) ~= "." then
|
||||||
local mod_path = path .. DIR_DELIM .. name
|
local mod_path = path .. DIR_DELIM .. name
|
||||||
@ -120,6 +120,7 @@ function pkgmgr.get_mods(path, virtual_path, listing, modpack)
|
|||||||
parent_dir = path,
|
parent_dir = path,
|
||||||
}
|
}
|
||||||
listing[#listing + 1] = toadd
|
listing[#listing + 1] = toadd
|
||||||
|
added[#added + 1] = toadd
|
||||||
|
|
||||||
-- Get config file
|
-- Get config file
|
||||||
local mod_conf
|
local mod_conf
|
||||||
@ -150,8 +151,6 @@ function pkgmgr.get_mods(path, virtual_path, listing, modpack)
|
|||||||
toadd.virtual_path = mod_virtual_path
|
toadd.virtual_path = mod_virtual_path
|
||||||
toadd.type = "mod"
|
toadd.type = "mod"
|
||||||
|
|
||||||
pkgmgr.update_translations({ toadd })
|
|
||||||
|
|
||||||
-- Check modpack.txt
|
-- Check modpack.txt
|
||||||
-- Note: modpack.conf is already checked above
|
-- Note: modpack.conf is already checked above
|
||||||
local modpackfile = io.open(mod_path .. DIR_DELIM .. "modpack.txt")
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
pkgmgr.update_translations(added)
|
||||||
|
|
||||||
if not modpack then
|
if not modpack then
|
||||||
-- Sort all when the recursion is done
|
-- Sort all when the recursion is done
|
||||||
table.sort(listing, function(a, b)
|
table.sort(listing, function(a, b)
|
||||||
@ -180,12 +181,13 @@ function pkgmgr.get_mods(path, virtual_path, listing, modpack)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function pkgmgr.get_texture_packs()
|
function pkgmgr.reload_texture_packs()
|
||||||
local txtpath = core.get_texturepath()
|
local txtpath = core.get_texturepath()
|
||||||
local txtpath_system = core.get_texturepath_share()
|
local txtpath_system = core.get_texturepath_share()
|
||||||
local retval = {}
|
local retval = {}
|
||||||
|
|
||||||
load_texture_packs(txtpath, retval)
|
load_texture_packs(txtpath, retval)
|
||||||
|
|
||||||
-- on portable versions these two paths coincide. It avoids loading the path twice
|
-- on portable versions these two paths coincide. It avoids loading the path twice
|
||||||
if txtpath ~= txtpath_system then
|
if txtpath ~= txtpath_system then
|
||||||
load_texture_packs(txtpath_system, retval)
|
load_texture_packs(txtpath_system, retval)
|
||||||
@ -197,11 +199,13 @@ function pkgmgr.get_texture_packs()
|
|||||||
return a.title:lower() < b.title:lower()
|
return a.title:lower() < b.title:lower()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
return retval
|
pkgmgr.texture_packs = retval
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function pkgmgr.get_all()
|
function pkgmgr.get_all()
|
||||||
|
pkgmgr.load_all()
|
||||||
|
|
||||||
local result = {}
|
local result = {}
|
||||||
|
|
||||||
for _, mod in pairs(pkgmgr.global_mods:get_list()) do
|
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
|
for _, game in pairs(pkgmgr.games) do
|
||||||
result[#result + 1] = game
|
result[#result + 1] = game
|
||||||
end
|
end
|
||||||
for _, txp in pairs(pkgmgr.get_texture_packs()) do
|
for _, txp in pairs(pkgmgr.texture_packs) do
|
||||||
result[#result + 1] = txp
|
result[#result + 1] = txp
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -288,7 +292,7 @@ end
|
|||||||
function pkgmgr.render_packagelist(render_list, use_technical_names, with_icon)
|
function pkgmgr.render_packagelist(render_list, use_technical_names, with_icon)
|
||||||
if not render_list then
|
if not render_list then
|
||||||
if not pkgmgr.global_mods then
|
if not pkgmgr.global_mods then
|
||||||
pkgmgr.refresh_globals()
|
pkgmgr.reload_global_mods()
|
||||||
end
|
end
|
||||||
render_list = pkgmgr.global_mods
|
render_list = pkgmgr.global_mods
|
||||||
end
|
end
|
||||||
@ -549,6 +553,7 @@ function pkgmgr.get_worldconfig(worldpath)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
-- Caller is responsible for reloading content types (see reload_by_type)
|
||||||
function pkgmgr.install_dir(expected_type, path, basename, targetpath)
|
function pkgmgr.install_dir(expected_type, path, basename, targetpath)
|
||||||
assert(type(expected_type) == "string")
|
assert(type(expected_type) == "string")
|
||||||
assert(type(path) == "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)
|
fgettext_ne("Failed to install $1 to $2", basename, targetpath)
|
||||||
end
|
end
|
||||||
|
|
||||||
if basefolder.type == "game" then
|
|
||||||
pkgmgr.update_gamelist()
|
|
||||||
else
|
|
||||||
pkgmgr.refresh_globals()
|
|
||||||
end
|
|
||||||
|
|
||||||
return targetpath, nil
|
return targetpath, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -742,7 +741,7 @@ function pkgmgr.comparemod(elem1,elem2)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function pkgmgr.refresh_globals()
|
function pkgmgr.reload_global_mods()
|
||||||
local function is_equal(element,uid) --uid match
|
local function is_equal(element,uid) --uid match
|
||||||
if element.name == uid then
|
if element.name == uid then
|
||||||
return true
|
return true
|
||||||
@ -774,7 +773,7 @@ function pkgmgr.get_game_mods(gamespec, retval)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function pkgmgr.update_gamelist()
|
function pkgmgr.reload_games()
|
||||||
pkgmgr.games = core.get_games()
|
pkgmgr.games = core.get_games()
|
||||||
table.sort(pkgmgr.games, function(a, b)
|
table.sort(pkgmgr.games, function(a, b)
|
||||||
return a.title:lower() < b.title:lower()
|
return a.title:lower() < b.title:lower()
|
||||||
@ -782,6 +781,32 @@ function pkgmgr.update_gamelist()
|
|||||||
pkgmgr.update_translations(pkgmgr.games)
|
pkgmgr.update_translations(pkgmgr.games)
|
||||||
end
|
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)
|
function pkgmgr.update_translations(list)
|
||||||
for _, item in ipairs(list) do
|
for _, item in ipairs(list) do
|
||||||
@ -831,4 +856,4 @@ end
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- read initial data
|
-- read initial data
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
pkgmgr.update_gamelist()
|
pkgmgr.reload_games()
|
||||||
|
@ -46,6 +46,9 @@ local function reset()
|
|||||||
function core.get_texturepath()
|
function core.get_texturepath()
|
||||||
return txp_dir
|
return txp_dir
|
||||||
end
|
end
|
||||||
|
function core.get_texturepath_share()
|
||||||
|
return txp_dir
|
||||||
|
end
|
||||||
function core.get_modpath()
|
function core.get_modpath()
|
||||||
return mods_dir
|
return mods_dir
|
||||||
end
|
end
|
||||||
@ -59,13 +62,6 @@ local function reset()
|
|||||||
setfenv(loadfile("builtin/common/misc_helpers.lua"), env)()
|
setfenv(loadfile("builtin/common/misc_helpers.lua"), env)()
|
||||||
setfenv(loadfile("builtin/mainmenu/content/pkgmgr.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)
|
function env.assert_calls(list)
|
||||||
assert.are.same(list, calls)
|
assert.are.same(list, calls)
|
||||||
end
|
end
|
||||||
@ -113,7 +109,6 @@ describe("install_dir", function()
|
|||||||
env.assert_calls({
|
env.assert_calls({
|
||||||
{ "delete_dir", mods_dir .. "/mymod" },
|
{ "delete_dir", mods_dir .. "/mymod" },
|
||||||
{ "copy_dir", "/tmp/123", mods_dir .. "/mymod", false },
|
{ "copy_dir", "/tmp/123", mods_dir .. "/mymod", false },
|
||||||
{ "refresh_globals" },
|
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -129,7 +124,6 @@ describe("install_dir", function()
|
|||||||
env.assert_calls({
|
env.assert_calls({
|
||||||
{ "delete_dir", mods_dir .. "/mymod" },
|
{ "delete_dir", mods_dir .. "/mymod" },
|
||||||
{ "copy_dir", "/tmp/123", mods_dir .. "/mymod", false },
|
{ "copy_dir", "/tmp/123", mods_dir .. "/mymod", false },
|
||||||
{ "refresh_globals" },
|
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -145,7 +139,6 @@ describe("install_dir", function()
|
|||||||
env.assert_calls({
|
env.assert_calls({
|
||||||
{ "delete_dir", games_dir .. "/mygame" },
|
{ "delete_dir", games_dir .. "/mygame" },
|
||||||
{ "copy_dir", "/tmp/123", games_dir .. "/mygame", false },
|
{ "copy_dir", "/tmp/123", games_dir .. "/mygame", false },
|
||||||
{ "update_gamelist" },
|
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -161,7 +154,6 @@ describe("install_dir", function()
|
|||||||
env.assert_calls({
|
env.assert_calls({
|
||||||
{ "delete_dir", mods_dir .. "/123" },
|
{ "delete_dir", mods_dir .. "/123" },
|
||||||
{ "copy_dir", "/tmp/123", mods_dir .. "/123", false },
|
{ "copy_dir", "/tmp/123", mods_dir .. "/123", false },
|
||||||
{ "refresh_globals" },
|
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -188,7 +180,6 @@ describe("install_dir", function()
|
|||||||
env.assert_calls({
|
env.assert_calls({
|
||||||
{ "delete_dir", "/tmp/alt-target" },
|
{ "delete_dir", "/tmp/alt-target" },
|
||||||
{ "copy_dir", "/tmp/123", "/tmp/alt-target", false },
|
{ "copy_dir", "/tmp/123", "/tmp/alt-target", false },
|
||||||
{ "refresh_globals" },
|
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -238,6 +229,5 @@ describe("install_dir", function()
|
|||||||
path, message = env.pkgmgr.install_dir("txp", "/tmp/123", "name", nil)
|
path, message = env.pkgmgr.install_dir("txp", "/tmp/123", "name", nil)
|
||||||
assert.is._not._nil(path)
|
assert.is._not._nil(path)
|
||||||
assert.is._nil(message)
|
assert.is._nil(message)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -72,9 +72,6 @@ end
|
|||||||
|
|
||||||
|
|
||||||
local function has_packages_from_cdb()
|
local function has_packages_from_cdb()
|
||||||
pkgmgr.refresh_globals()
|
|
||||||
pkgmgr.update_gamelist()
|
|
||||||
|
|
||||||
for _, content in pairs(pkgmgr.get_all()) do
|
for _, content in pairs(pkgmgr.get_all()) do
|
||||||
if pkgmgr.get_contentdb_id(content) then
|
if pkgmgr.get_contentdb_id(content) then
|
||||||
return true
|
return true
|
||||||
@ -127,9 +124,6 @@ function update_detector.get_all()
|
|||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
pkgmgr.refresh_globals()
|
|
||||||
pkgmgr.update_gamelist()
|
|
||||||
|
|
||||||
local ret = {}
|
local ret = {}
|
||||||
local all_content = pkgmgr.get_all()
|
local all_content = pkgmgr.get_all()
|
||||||
for _, content in ipairs(all_content) do
|
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)
|
gamedata.errormessage = fgettext_ne("pkgmgr: failed to delete \"$1\"", this.data.content.path)
|
||||||
end
|
end
|
||||||
|
|
||||||
if this.data.content.type == "game" then
|
pkgmgr.reload_by_type(this.data.content.type)
|
||||||
pkgmgr.update_gamelist()
|
|
||||||
else
|
|
||||||
pkgmgr.refresh_globals()
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
gamedata.errormessage = fgettext_ne("pkgmgr: invalid path \"$1\"", this.data.content.path)
|
gamedata.errormessage = fgettext_ne("pkgmgr: invalid path \"$1\"", this.data.content.path)
|
||||||
end
|
end
|
||||||
|
@ -45,7 +45,7 @@ local function rename_modpack_buttonhandler(this, fields)
|
|||||||
local oldpath = this.data.mod.path
|
local oldpath = this.data.mod.path
|
||||||
local targetpath = this.data.mod.parent_dir .. DIR_DELIM .. fields["te_modpack_name"]
|
local targetpath = this.data.mod.parent_dir .. DIR_DELIM .. fields["te_modpack_name"]
|
||||||
os.rename(oldpath, targetpath)
|
os.rename(oldpath, targetpath)
|
||||||
pkgmgr.refresh_globals()
|
pkgmgr.reload_global_mods()
|
||||||
pkgmgr.selected_mod = pkgmgr.global_mods:get_current_index(
|
pkgmgr.selected_mod = pkgmgr.global_mods:get_current_index(
|
||||||
pkgmgr.global_mods:raw_index_by_uid(fields["te_modpack_name"]))
|
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 ..
|
local shadows_component = dofile(core.get_mainmenu_path() .. DIR_DELIM ..
|
||||||
"settings" .. DIR_DELIM .. "shadows_component.lua")
|
"settings" .. DIR_DELIM .. "shadows_component.lua")
|
||||||
|
|
||||||
|
local loaded = false
|
||||||
local full_settings = settingtypes.parse_config_file(false, true)
|
local full_settings
|
||||||
local info_icon_path = core.formspec_escape(defaulttexturedir .. "settings_info.png")
|
local info_icon_path = core.formspec_escape(defaulttexturedir .. "settings_info.png")
|
||||||
local reset_icon_path = core.formspec_escape(defaulttexturedir .. "settings_reset.png")
|
local reset_icon_path = core.formspec_escape(defaulttexturedir .. "settings_reset.png")
|
||||||
|
|
||||||
local all_pages = {}
|
local all_pages = {}
|
||||||
local page_by_id = {}
|
local page_by_id = {}
|
||||||
local filtered_pages = all_pages
|
local filtered_pages = all_pages
|
||||||
local filtered_page_by_id = page_by_id
|
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)
|
local function add_page(page)
|
||||||
assert(type(page.id) == "string")
|
assert(type(page.id) == "string")
|
||||||
assert(type(page.title) == "string")
|
assert(type(page.title) == "string")
|
||||||
@ -46,49 +57,6 @@ local function add_page(page)
|
|||||||
end
|
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 function load_settingtypes()
|
||||||
local page = nil
|
local page = nil
|
||||||
local section = nil
|
local section = nil
|
||||||
@ -129,31 +97,70 @@ local function load_settingtypes()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
load_settingtypes()
|
|
||||||
|
|
||||||
table.insert(page_by_id.controls_keyboard_and_mouse.content, 1, change_keys)
|
|
||||||
do
|
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 content = page_by_id.graphics_and_audio_shaders.content
|
||||||
local idx = table.indexof(content, "enable_dynamic_shadows")
|
local idx = table.indexof(content, "enable_dynamic_shadows")
|
||||||
table.insert(content, idx, shadows_component)
|
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
-- These must not be translated, as they need to show in the local
|
||||||
end
|
-- 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 = {
|
||||||
-- 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)"),
|
[""] = fgettext_ne("(Use system language)"),
|
||||||
--ar = " [ar]", blacklisted
|
--ar = " [ar]", blacklisted
|
||||||
be = "Беларуская [be]",
|
be = "Беларуская [be]",
|
||||||
@ -214,7 +221,8 @@ get_setting_info("language").option_labels = {
|
|||||||
vi = "Tiếng Việt [vi]",
|
vi = "Tiếng Việt [vi]",
|
||||||
zh_CN = "中文 (简体) [zh_CN]",
|
zh_CN = "中文 (简体) [zh_CN]",
|
||||||
zh_TW = "正體中文 (繁體) [zh_TW]",
|
zh_TW = "正體中文 (繁體) [zh_TW]",
|
||||||
}
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- See if setting matches keywords
|
-- See if setting matches keywords
|
||||||
@ -734,6 +742,7 @@ end
|
|||||||
|
|
||||||
|
|
||||||
function create_settings_dlg()
|
function create_settings_dlg()
|
||||||
|
load()
|
||||||
local dlg = dialog_create("dlg_settings", get_formspec, buttonhandler, eventhandler)
|
local dlg = dialog_create("dlg_settings", get_formspec, buttonhandler, eventhandler)
|
||||||
|
|
||||||
dlg.data.page_id = update_filtered_pages("")
|
dlg.data.page_id = update_filtered_pages("")
|
||||||
|
@ -439,9 +439,9 @@ function settingtypes.parse_config_file(read_all, parse_mods)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Parse mods
|
-- Parse mods
|
||||||
|
pkgmgr.load_all()
|
||||||
local mods_category_initialized = false
|
local mods_category_initialized = false
|
||||||
local mods = {}
|
local mods = pkgmgr.global_mods:get_list()
|
||||||
pkgmgr.get_mods(core.get_modpath(), "mods", mods)
|
|
||||||
table.sort(mods, function(a, b) return a.name < b.name end)
|
table.sort(mods, function(a, b) return a.name < b.name end)
|
||||||
|
|
||||||
for _, mod in ipairs(mods) do
|
for _, mod in ipairs(mods) do
|
||||||
|
@ -29,16 +29,11 @@ end
|
|||||||
local packages_raw, packages
|
local packages_raw, packages
|
||||||
|
|
||||||
local function update_packages()
|
local function update_packages()
|
||||||
if not pkgmgr.global_mods then
|
pkgmgr.load_all()
|
||||||
pkgmgr.refresh_globals()
|
|
||||||
end
|
|
||||||
if not pkgmgr.games then
|
|
||||||
pkgmgr.update_gamelist()
|
|
||||||
end
|
|
||||||
|
|
||||||
packages_raw = {}
|
packages_raw = {}
|
||||||
table.insert_all(packages_raw, pkgmgr.games)
|
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())
|
table.insert_all(packages_raw, pkgmgr.global_mods:get_list())
|
||||||
|
|
||||||
local function get_data()
|
local function get_data()
|
||||||
@ -207,6 +202,7 @@ local function handle_doubleclick(pkg)
|
|||||||
core.settings:set("texture_path", pkg.path)
|
core.settings:set("texture_path", pkg.path)
|
||||||
end
|
end
|
||||||
packages = nil
|
packages = nil
|
||||||
|
pkgmgr.reload_texture_packs()
|
||||||
|
|
||||||
mm_game_theme.init()
|
mm_game_theme.init()
|
||||||
mm_game_theme.set_engine()
|
mm_game_theme.set_engine()
|
||||||
@ -271,6 +267,7 @@ local function handle_buttons(tabview, fields, tabname, tabdata)
|
|||||||
|
|
||||||
core.settings:set("texture_path", txp_path)
|
core.settings:set("texture_path", txp_path)
|
||||||
packages = nil
|
packages = nil
|
||||||
|
pkgmgr.reload_texture_packs()
|
||||||
|
|
||||||
mm_game_theme.init()
|
mm_game_theme.init()
|
||||||
mm_game_theme.set_engine()
|
mm_game_theme.set_engine()
|
||||||
|
@ -3902,6 +3902,7 @@ Operators
|
|||||||
---------
|
---------
|
||||||
|
|
||||||
Operators can be used if all of the involved vectors have metatables:
|
Operators can be used if all of the involved vectors have metatables:
|
||||||
|
|
||||||
* `v1 == v2`:
|
* `v1 == v2`:
|
||||||
* Returns whether `v1` and `v2` are identical.
|
* Returns whether `v1` and `v2` are identical.
|
||||||
* `-v`:
|
* `-v`:
|
||||||
@ -4007,8 +4008,9 @@ Helper functions
|
|||||||
* X1, Y1, ... Z2 are coordinates
|
* X1, Y1, ... Z2 are coordinates
|
||||||
* `relative_to`: Optional. If set to a position, each coordinate
|
* `relative_to`: Optional. If set to a position, each coordinate
|
||||||
can use the tilde notation for relative positions
|
can use the tilde notation for relative positions
|
||||||
* Tilde notation: "~": Relative coordinate
|
* Tilde notation
|
||||||
"~<number>": Relative coordinate plus <number>
|
* `"~"`: Relative coordinate
|
||||||
|
* `"~<number>"`: Relative coordinate plus `<number>`
|
||||||
* Example: `minetest.string_to_area("(1,2,3) (~5,~-5,~)", {x=10,y=10,z=10})`
|
* 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}`
|
returns `{x=1,y=2,z=3}, {x=15,y=5,z=10}`
|
||||||
* `minetest.formspec_escape(string)`: returns a string
|
* `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
|
This may need to be tuned when altering `lacunarity`; when doing so consider
|
||||||
that a common medium value is 1 / lacunarity.
|
that a common medium value is 1 / lacunarity.
|
||||||
|
|
||||||
|
Instead of `persistence`, the key `persist` may be used to the same effect.
|
||||||
|
|
||||||
### `lacunarity`
|
### `lacunarity`
|
||||||
|
|
||||||
Each additional octave has a 'wavelength' that is the 'wavelength' of the
|
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",
|
"Drowning damage: 1",
|
||||||
drawtype = "flowingliquid",
|
drawtype = "flowingliquid",
|
||||||
waving = 3,
|
waving = 3,
|
||||||
tiles = {"default_water_flowing.png"},
|
tiles = {"default_water_flowing.png"..WATER_ALPHA},
|
||||||
special_tiles = {
|
special_tiles = {
|
||||||
{name = "default_water_flowing.png"..WATER_ALPHA,
|
{name = "default_water_flowing.png"..WATER_ALPHA,
|
||||||
backface_culling = false},
|
backface_culling = false},
|
||||||
|
@ -105,3 +105,9 @@ minetest.register_craftitem("testitems:telescope_stick", {
|
|||||||
return itemstack
|
return itemstack
|
||||||
end,
|
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")
|
local S = minetest.get_translator("testnodes")
|
||||||
|
|
||||||
-- Complex mesh
|
for use_texture_alpha, description in pairs({
|
||||||
minetest.register_node("testnodes:performance_mesh_clip", {
|
opaque = S("Marble with 'opaque' transparency"),
|
||||||
description = S("Performance Test Node") .. "\n" .. S("Marble with 'clip' 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",
|
drawtype = "mesh",
|
||||||
mesh = "testnodes_marble_glass.obj",
|
mesh = "testnodes_marble_glass.obj",
|
||||||
tiles = {"testnodes_marble_glass.png"},
|
tiles = {"testnodes_marble_glass.png"},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
use_texture_alpha = "clip",
|
use_texture_alpha = use_texture_alpha,
|
||||||
|
|
||||||
groups = {dig_immediate=3},
|
groups = {dig_immediate=3},
|
||||||
})
|
})
|
||||||
|
end
|
||||||
-- 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},
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Overlay
|
-- Overlay
|
||||||
minetest.register_node("testnodes:performance_overlay_clip", {
|
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 loop: True if the animation should loop, false if not
|
||||||
\param scale: True if the sprite should scale to button size, 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,
|
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
|
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||||
virtual s32 getSpriteIndex(EGUI_BUTTON_STATE state) const = 0;
|
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
|
//! Returns if the sprite in the given state does loop
|
||||||
virtual bool getSpriteLoop(EGUI_BUTTON_STATE state) const = 0;
|
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.
|
//! 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,
|
/** 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. */
|
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
|
class IGUISkin : virtual public IReferenceCounted
|
||||||
{
|
{
|
||||||
public:
|
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
|
//! returns default color
|
||||||
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const = 0;
|
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const = 0;
|
||||||
|
|
||||||
|
@ -75,12 +75,11 @@ void CGUIButton::setSpriteBank(IGUISpriteBank *sprites)
|
|||||||
SpriteBank = 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].Index = index;
|
||||||
ButtonSprites[(u32)state].Color = color;
|
ButtonSprites[(u32)state].Color = color;
|
||||||
ButtonSprites[(u32)state].Loop = loop;
|
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
|
//! 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;
|
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.
|
//! called if an event happened.
|
||||||
bool CGUIButton::OnEvent(const SEvent &event)
|
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)
|
void CGUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di ¢er)
|
||||||
{
|
{
|
||||||
u32 stateIdx = (u32)state;
|
u32 stateIdx = (u32)state;
|
||||||
|
s32 spriteIdx = ButtonSprites[stateIdx].Index;
|
||||||
|
if (spriteIdx == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
if (ButtonSprites[stateIdx].Index != -1) {
|
u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber;
|
||||||
if (ButtonSprites[stateIdx].Scale) {
|
core::rect<s32> srcRect = SpriteBank->getPositions()[rectIdx];
|
||||||
const video::SColor colors[] = {ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color};
|
|
||||||
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect,
|
IGUISkin *skin = Environment->getSkin();
|
||||||
&AbsoluteClippingRect, colors,
|
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);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EGUI_BUTTON_IMAGE_STATE CGUIButton::getImageState(bool pressed) const
|
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,
|
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
|
||||||
video::SColor color = video::SColor(255, 255, 255, 255),
|
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
|
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||||
s32 getSpriteIndex(EGUI_BUTTON_STATE state) const override;
|
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
|
//! Returns if the sprite in the given state does loop
|
||||||
bool getSpriteLoop(EGUI_BUTTON_STATE state) const override;
|
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
|
//! 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,
|
//! can be in two states: Normal or Pressed. With a click on the button,
|
||||||
//! the user can change the state of the button.
|
//! the user can change the state of the button.
|
||||||
@ -158,19 +155,18 @@ class CGUIButton : public IGUIButton
|
|||||||
struct ButtonSprite
|
struct ButtonSprite
|
||||||
{
|
{
|
||||||
ButtonSprite() :
|
ButtonSprite() :
|
||||||
Index(-1), Loop(false), Scale(false)
|
Index(-1), Loop(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const ButtonSprite &other) const
|
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;
|
s32 Index;
|
||||||
video::SColor Color;
|
video::SColor Color;
|
||||||
bool Loop;
|
bool Loop;
|
||||||
bool Scale;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ButtonSprite ButtonSprites[EGBS_COUNT];
|
ButtonSprite ButtonSprites[EGBS_COUNT];
|
||||||
|
@ -24,6 +24,12 @@ class CGUISkin : public IGUISkin
|
|||||||
//! destructor
|
//! destructor
|
||||||
virtual ~CGUISkin();
|
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
|
//! returns default color
|
||||||
video::SColor getColor(EGUI_DEFAULT_COLOR color) const override;
|
video::SColor getColor(EGUI_DEFAULT_COLOR color) const override;
|
||||||
|
|
||||||
@ -210,6 +216,7 @@ class CGUISkin : public IGUISkin
|
|||||||
EGUI_SKIN_TYPE getType() const override;
|
EGUI_SKIN_TYPE getType() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
float Scale = 1.0f;
|
||||||
video::SColor Colors[EGDC_COUNT];
|
video::SColor Colors[EGDC_COUNT];
|
||||||
s32 Sizes[EGDS_COUNT];
|
s32 Sizes[EGDS_COUNT];
|
||||||
u32 Icons[EGDI_COUNT];
|
u32 Icons[EGDI_COUNT];
|
||||||
|
@ -129,9 +129,9 @@ EM_BOOL CIrrDeviceSDL::MouseLeaveCallback(int eventType, const EmscriptenMouseEv
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
// keys which are known to have safe special character interpretation
|
||||||
// could need changes over time (removals and additions!)
|
// could need changes over time (removals and additions!)
|
||||||
case KEY_RETURN:
|
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
|
// special cases that always return a char regardless of how the SDL keycode
|
||||||
// looks
|
// looks
|
||||||
switch (key) {
|
|
||||||
case KEY_RETURN:
|
case KEY_RETURN:
|
||||||
case KEY_ESCAPE:
|
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:
|
default:
|
||||||
break;
|
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
|
// SDL in-place ORs values with no character representation with 1<<30
|
||||||
// https://wiki.libsdl.org/SDL2/SDLKeycodeLookup
|
// https://wiki.libsdl.org/SDL2/SDLKeycodeLookup
|
||||||
if (assumedChar & (1 << 30))
|
// This also affects the numpad keys btw.
|
||||||
|
if (sdlKey & (1 << 30))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (key) {
|
switch (irrlichtKey) {
|
||||||
case KEY_PRIOR:
|
case KEY_PRIOR:
|
||||||
case KEY_NEXT:
|
case KEY_NEXT:
|
||||||
case KEY_HOME:
|
case KEY_HOME:
|
||||||
@ -218,7 +262,7 @@ int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key)
|
|||||||
case KEY_NUMLOCK:
|
case KEY_NUMLOCK:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return assumedChar;
|
return sdlKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,7 +869,8 @@ bool CIrrDeviceSDL::run()
|
|||||||
irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN);
|
irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN);
|
||||||
irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0;
|
irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0;
|
||||||
irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL) != 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);
|
postEventFromUser(irrevent);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -273,10 +273,10 @@ class CIrrDeviceSDL : public CIrrDeviceStub
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
// Check if a key is a known special character with no side effects on text boxes.
|
// 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).
|
// 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.
|
// Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
|
||||||
void resetReceiveTextInputEvents();
|
void resetReceiveTextInputEvents();
|
||||||
|
@ -352,6 +352,7 @@ void ClientLauncher::config_guienv()
|
|||||||
|
|
||||||
float density = rangelim(g_settings->getFloat("gui_scaling"), 0.5f, 20) *
|
float density = rangelim(g_settings->getFloat("gui_scaling"), 0.5f, 20) *
|
||||||
RenderingEngine::getDisplayDensity();
|
RenderingEngine::getDisplayDensity();
|
||||||
|
skin->setScale(density);
|
||||||
skin->setSize(gui::EGDS_CHECK_BOX_WIDTH, (s32)(17.0f * 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_SCROLLBAR_SIZE, (s32)(21.0f * density));
|
||||||
skin->setSize(gui::EGDS_WINDOW_BUTTON_WIDTH, (s32)(15.0f * density));
|
skin->setSize(gui::EGDS_WINDOW_BUTTON_WIDTH, (s32)(15.0f * density));
|
||||||
|
@ -1145,7 +1145,6 @@ void drawItemStack(
|
|||||||
}
|
}
|
||||||
|
|
||||||
video::SMaterial &material = buf->getMaterial();
|
video::SMaterial &material = buf->getMaterial();
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
|
||||||
material.Lighting = false;
|
material.Lighting = false;
|
||||||
driver->setMaterial(material);
|
driver->setMaterial(material);
|
||||||
driver->drawMeshBuffer(buf);
|
driver->drawMeshBuffer(buf);
|
||||||
|
@ -526,26 +526,7 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
|
|||||||
shaderinfo.name = name;
|
shaderinfo.name = name;
|
||||||
shaderinfo.material_type = material_type;
|
shaderinfo.material_type = material_type;
|
||||||
shaderinfo.drawtype = drawtype;
|
shaderinfo.drawtype = drawtype;
|
||||||
switch (material_type) {
|
shaderinfo.base_material = MaterialType_to_irr(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.material = shaderinfo.base_material;
|
shaderinfo.material = shaderinfo.base_material;
|
||||||
|
|
||||||
bool enable_shaders = g_settings->getBool("enable_shaders");
|
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 "tile.h"
|
||||||
|
#include "EMaterialTypes.h"
|
||||||
|
#include "SMaterial.h"
|
||||||
|
|
||||||
// Sets everything else except the texture in the material
|
void MaterialType_to_irr(MaterialType material_type,
|
||||||
void TileLayer::applyMaterialOptions(video::SMaterial &material) const
|
video::E_MATERIAL_TYPE &irr_mat_type, f32 &irr_mat_param)
|
||||||
{
|
{
|
||||||
switch (material_type) {
|
switch (material_type) {
|
||||||
case TILE_MATERIAL_OPAQUE:
|
case TILE_MATERIAL_OPAQUE:
|
||||||
case TILE_MATERIAL_LIQUID_OPAQUE:
|
case TILE_MATERIAL_LIQUID_OPAQUE:
|
||||||
case TILE_MATERIAL_WAVING_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;
|
break;
|
||||||
case TILE_MATERIAL_BASIC:
|
case TILE_MATERIAL_BASIC:
|
||||||
|
case TILE_MATERIAL_PLAIN:
|
||||||
case TILE_MATERIAL_WAVING_LEAVES:
|
case TILE_MATERIAL_WAVING_LEAVES:
|
||||||
case TILE_MATERIAL_WAVING_PLANTS:
|
case TILE_MATERIAL_WAVING_PLANTS:
|
||||||
case TILE_MATERIAL_WAVING_LIQUID_BASIC:
|
case TILE_MATERIAL_WAVING_LIQUID_BASIC:
|
||||||
material.MaterialTypeParam = 0.5;
|
irr_mat_type = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
irr_mat_param = 0.5f;
|
||||||
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:
|
|
||||||
break;
|
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;
|
material.BackfaceCulling = (material_flags & MATERIAL_FLAG_BACKFACE_CULLING) != 0;
|
||||||
if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) {
|
if (!(material_flags & MATERIAL_FLAG_TILEABLE_HORIZONTAL)) {
|
||||||
material.TextureLayers[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include "EMaterialTypes.h"
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
#include <ITexture.h>
|
#include <ITexture.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -39,6 +40,11 @@ enum MaterialType{
|
|||||||
TILE_MATERIAL_PLAIN_ALPHA
|
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
|
// Material flags
|
||||||
// Should backface culling be enabled?
|
// Should backface culling be enabled?
|
||||||
#define MATERIAL_FLAG_BACKFACE_CULLING 0x01
|
#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 "wieldmesh.h"
|
||||||
|
#include "EMaterialTypes.h"
|
||||||
|
#include "SMaterial.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "shader.h"
|
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "itemdef.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 "mapblock_mesh.h"
|
||||||
#include "client/meshgen/collector.h"
|
#include "client/meshgen/collector.h"
|
||||||
#include "client/tile.h"
|
#include "client/tile.h"
|
||||||
#include "log.h"
|
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <IMeshManipulator.h>
|
#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 MIN_EXTRUSION_MESH_RESOLUTION 16
|
||||||
#define MAX_EXTRUSION_MESH_RESOLUTION 512
|
#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)
|
static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y)
|
||||||
{
|
{
|
||||||
const f32 r = 0.5;
|
const f32 r = 0.5;
|
||||||
@ -193,10 +243,55 @@ class ExtrusionMeshCache: public IReferenceCounted
|
|||||||
|
|
||||||
static ExtrusionMeshCache *g_extrusion_mesh_cache = nullptr;
|
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):
|
WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting):
|
||||||
scene::ISceneNode(mgr->getRootSceneNode(), mgr, id),
|
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_lighting(lighting)
|
||||||
{
|
{
|
||||||
m_enable_shaders = g_settings->getBool("enable_shaders");
|
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::IMesh *cubemesh = g_extrusion_mesh_cache->createCube();
|
||||||
scene::SMesh *copy = cloneMesh(cubemesh);
|
scene::SMesh *copy = cloneMesh(cubemesh);
|
||||||
cubemesh->drop();
|
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);
|
changeToMesh(copy);
|
||||||
copy->drop();
|
copy->drop();
|
||||||
m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR);
|
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].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
|
||||||
material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
|
material.TextureLayers[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
|
||||||
material.MaterialType = m_material_type;
|
material.MaterialType = m_material_type;
|
||||||
material.MaterialTypeParam = 0.5f;
|
material.MaterialTypeParam = m_material_type_param;
|
||||||
|
material.ZWriteEnable = video::EZW_ON;
|
||||||
material.BackfaceCulling = true;
|
material.BackfaceCulling = true;
|
||||||
// Enable bi/trilinear filtering only for high resolution textures
|
// Enable bi/trilinear filtering only for high resolution textures
|
||||||
bool bilinear_filter = dim.Width > 32 && m_bilinear_filter;
|
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();
|
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
buf->Material.setTexture(0, p.layer.texture);
|
buf->Material.setTexture(0, p.layer.texture);
|
||||||
p.layer.applyMaterialOptions(buf->Material);
|
|
||||||
mesh->addMeshBuffer(buf);
|
mesh->addMeshBuffer(buf);
|
||||||
buf->append(&p.vertices[0], p.vertices.size(),
|
buf->append(&p.vertices[0], p.vertices.size(),
|
||||||
&p.indices[0], p.indices.size());
|
&p.indices[0], p.indices.size());
|
||||||
buf->drop();
|
buf->drop();
|
||||||
colors->push_back(
|
colors->emplace_back(p.layer.has_color, p.layer.color);
|
||||||
ItemPartColor(p.layer.has_color, p.layer.color));
|
|
||||||
}
|
}
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
@ -365,7 +469,6 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
|||||||
{
|
{
|
||||||
ITextureSource *tsrc = client->getTextureSource();
|
ITextureSource *tsrc = client->getTextureSource();
|
||||||
IItemDefManager *idef = client->getItemDefManager();
|
IItemDefManager *idef = client->getItemDefManager();
|
||||||
IShaderSource *shdrsrc = client->getShaderSource();
|
|
||||||
const NodeDefManager *ndef = client->getNodeDefManager();
|
const NodeDefManager *ndef = client->getNodeDefManager();
|
||||||
const ItemDefinition &def = item.getDefinition(idef);
|
const ItemDefinition &def = item.getDefinition(idef);
|
||||||
const ContentFeatures &f = ndef->get(def.name);
|
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;
|
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) {
|
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;
|
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) {
|
for (u32 i = 0; i < material_count; ++i) {
|
||||||
video::SMaterial &material = m_meshnode->getMaterial(i);
|
video::SMaterial &material = m_meshnode->getMaterial(i);
|
||||||
material.MaterialType = m_material_type;
|
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.BackfaceCulling = cull_backface;
|
||||||
material.forEachTexture([this] (auto &tex) {
|
material.forEachTexture([this] (auto &tex) {
|
||||||
setMaterialFilters(tex, m_bilinear_filter, m_trilinear_filter,
|
setMaterialFilters(tex, m_bilinear_filter, m_trilinear_filter,
|
||||||
@ -624,8 +736,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
|||||||
} else
|
} else
|
||||||
scaleMesh(mesh, v3f(1.2, 1.2, 1.2));
|
scaleMesh(mesh, v3f(1.2, 1.2, 1.2));
|
||||||
// add overlays
|
// add overlays
|
||||||
postProcessNodeMesh(mesh, f, false, false, nullptr,
|
postProcessNodeMesh(mesh, f, &result->buffer_colors);
|
||||||
&result->buffer_colors, true);
|
|
||||||
if (f.drawtype == NDT_ALLFACES)
|
if (f.drawtype == NDT_ALLFACES)
|
||||||
scaleMesh(mesh, v3f(f.visual_scale));
|
scaleMesh(mesh, v3f(f.visual_scale));
|
||||||
break;
|
break;
|
||||||
@ -664,14 +775,17 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
|||||||
for (u32 i = 0; i < mesh->getMeshBufferCount(); ++i) {
|
for (u32 i = 0; i < mesh->getMeshBufferCount(); ++i) {
|
||||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
||||||
video::SMaterial &material = buf->getMaterial();
|
video::SMaterial &material = buf->getMaterial();
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
// Note: This overwrites material types / type params
|
||||||
material.MaterialTypeParam = 0.5f;
|
// 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) {
|
material.forEachTexture([] (auto &tex) {
|
||||||
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
|
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
|
||||||
tex.MagFilter = video::ETMAGF_NEAREST;
|
tex.MagFilter = video::ETMAGF_NEAREST;
|
||||||
});
|
});
|
||||||
material.BackfaceCulling = cull_backface;
|
material.BackfaceCulling = cull_backface;
|
||||||
material.Lighting = false;
|
material.Lighting = false; // no lighting in the inventory
|
||||||
}
|
}
|
||||||
|
|
||||||
rotateMeshXZby(mesh, -45);
|
rotateMeshXZby(mesh, -45);
|
||||||
@ -685,109 +799,3 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
|||||||
}
|
}
|
||||||
result->mesh = mesh;
|
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
|
// Child scene node with the current wield mesh
|
||||||
scene::IMeshSceneNode *m_meshnode = nullptr;
|
scene::IMeshSceneNode *m_meshnode = nullptr;
|
||||||
video::E_MATERIAL_TYPE m_material_type;
|
video::E_MATERIAL_TYPE m_material_type;
|
||||||
|
f32 m_material_type_param = 0.0f;
|
||||||
|
|
||||||
// True if SMaterial::Lighting should be enabled.
|
// True if SMaterial::Lighting should be enabled.
|
||||||
bool m_lighting;
|
bool m_lighting;
|
||||||
@ -146,17 +147,3 @@ class WieldMeshSceneNode : public scene::ISceneNode
|
|||||||
};
|
};
|
||||||
|
|
||||||
void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result);
|
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;
|
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].Index = index;
|
||||||
ButtonSprites[(u32)state].Color = color;
|
ButtonSprites[(u32)state].Color = color;
|
||||||
ButtonSprites[(u32)state].Loop = loop;
|
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
|
//! 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;
|
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.
|
//! called if an event happened.
|
||||||
bool GUIButton::OnEvent(const SEvent& event)
|
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)
|
void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center)
|
||||||
{
|
{
|
||||||
u32 stateIdx = (u32)state;
|
u32 stateIdx = (u32)state;
|
||||||
|
s32 spriteIdx = ButtonSprites[stateIdx].Index;
|
||||||
|
if (spriteIdx == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
if (ButtonSprites[stateIdx].Index != -1)
|
u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber;
|
||||||
{
|
core::rect<s32> srcRect = SpriteBank->getPositions()[rectIdx];
|
||||||
if ( ButtonSprites[stateIdx].Scale )
|
|
||||||
{
|
IGUISkin *skin = Environment->getSkin();
|
||||||
const video::SColor colors[] = {ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color};
|
s32 scale = std::max(std::floor(skin->getScale()), 1.0f);
|
||||||
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect.UpperLeftCorner,
|
core::rect<s32> rect(center, srcRect.getSize() * scale);
|
||||||
&AbsoluteClippingRect, colors[0], // FIXME: remove [0]
|
rect -= rect.getSize() / 2;
|
||||||
porting::getTimeMs()-startTime, ButtonSprites[stateIdx].Loop);
|
|
||||||
}
|
const video::SColor colors[] = {
|
||||||
else
|
ButtonSprites[stateIdx].Color,
|
||||||
{
|
ButtonSprites[stateIdx].Color,
|
||||||
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
|
ButtonSprites[stateIdx].Color,
|
||||||
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, porting::getTimeMs(),
|
ButtonSprites[stateIdx].Color,
|
||||||
ButtonSprites[stateIdx].Loop, true);
|
};
|
||||||
}
|
SpriteBank->draw2DSprite(spriteIdx, rect, &AbsoluteClippingRect, colors,
|
||||||
}
|
porting::getTimeMs() - startTime, ButtonSprites[stateIdx].Loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const
|
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,
|
virtual void setSprite(gui::EGUI_BUTTON_STATE state, s32 index,
|
||||||
video::SColor color=video::SColor(255,255,255,255),
|
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
|
//! 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;
|
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
|
//! Returns if the sprite in the given state does loop
|
||||||
virtual bool getSpriteLoop(gui::EGUI_BUTTON_STATE state) const override;
|
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
|
//! 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,
|
//! can be in two states: Normal or Pressed. With a click on the button,
|
||||||
//! the user can change the state of 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
|
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;
|
s32 Index = -1;
|
||||||
video::SColor Color;
|
video::SColor Color;
|
||||||
bool Loop = false;
|
bool Loop = false;
|
||||||
bool Scale = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ButtonSprite ButtonSprites[gui::EGBS_COUNT];
|
ButtonSprite ButtonSprites[gui::EGBS_COUNT];
|
||||||
|
@ -27,6 +27,12 @@ namespace gui
|
|||||||
//! destructor
|
//! destructor
|
||||||
virtual ~GUISkin();
|
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
|
//! returns default color
|
||||||
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const;
|
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const;
|
||||||
|
|
||||||
@ -292,6 +298,7 @@ namespace gui
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
float Scale = 1.0f;
|
||||||
video::SColor Colors[EGDC_COUNT];
|
video::SColor Colors[EGDC_COUNT];
|
||||||
s32 Sizes[EGDS_COUNT];
|
s32 Sizes[EGDS_COUNT];
|
||||||
u32 Icons[EGDI_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;
|
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,
|
void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc,
|
||||||
scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings)
|
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];
|
tdef_spec[j] = tiledef_special[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_liquid = false;
|
updateAlpha(tsettings.translucent_liquids);
|
||||||
|
MaterialType material_type = getMaterialType();
|
||||||
MaterialType material_type = alpha == ALPHAMODE_OPAQUE ?
|
|
||||||
TILE_MATERIAL_OPAQUE : (alpha == ALPHAMODE_CLIP ? TILE_MATERIAL_BASIC :
|
|
||||||
TILE_MATERIAL_ALPHA);
|
|
||||||
|
|
||||||
switch (drawtype) {
|
switch (drawtype) {
|
||||||
default:
|
default:
|
||||||
@ -825,16 +896,10 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||||||
solidness = 0;
|
solidness = 0;
|
||||||
break;
|
break;
|
||||||
case NDT_LIQUID:
|
case NDT_LIQUID:
|
||||||
if (!tsettings.translucent_liquids)
|
|
||||||
alpha = ALPHAMODE_OPAQUE;
|
|
||||||
solidness = 1;
|
solidness = 1;
|
||||||
is_liquid = true;
|
|
||||||
break;
|
break;
|
||||||
case NDT_FLOWINGLIQUID:
|
case NDT_FLOWINGLIQUID:
|
||||||
solidness = 0;
|
solidness = 0;
|
||||||
if (!tsettings.translucent_liquids)
|
|
||||||
alpha = ALPHAMODE_OPAQUE;
|
|
||||||
is_liquid = true;
|
|
||||||
break;
|
break;
|
||||||
case NDT_GLASSLIKE:
|
case NDT_GLASSLIKE:
|
||||||
solidness = 0;
|
solidness = 0;
|
||||||
@ -879,13 +944,9 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||||||
for (TileDef &td : tdef)
|
for (TileDef &td : tdef)
|
||||||
td.name += std::string("^[noalpha");
|
td.name += std::string("^[noalpha");
|
||||||
}
|
}
|
||||||
if (waving >= 1)
|
|
||||||
material_type = TILE_MATERIAL_WAVING_LEAVES;
|
|
||||||
break;
|
break;
|
||||||
case NDT_PLANTLIKE:
|
case NDT_PLANTLIKE:
|
||||||
solidness = 0;
|
solidness = 0;
|
||||||
if (waving >= 1)
|
|
||||||
material_type = TILE_MATERIAL_WAVING_PLANTS;
|
|
||||||
break;
|
break;
|
||||||
case NDT_FIRELIKE:
|
case NDT_FIRELIKE:
|
||||||
solidness = 0;
|
solidness = 0;
|
||||||
@ -893,15 +954,6 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||||||
case NDT_MESH:
|
case NDT_MESH:
|
||||||
case NDT_NODEBOX:
|
case NDT_NODEBOX:
|
||||||
solidness = 0;
|
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;
|
break;
|
||||||
case NDT_TORCHLIKE:
|
case NDT_TORCHLIKE:
|
||||||
case NDT_SIGNLIKE:
|
case NDT_SIGNLIKE:
|
||||||
@ -914,17 +966,6 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||||||
break;
|
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);
|
u32 tile_shader = shdsrc->getShader("nodes_shader", material_type, drawtype);
|
||||||
|
|
||||||
MaterialType overlay_material = material_type;
|
MaterialType overlay_material = material_type;
|
||||||
@ -1082,6 +1123,7 @@ void NodeDefManager::clear()
|
|||||||
f.name = "air";
|
f.name = "air";
|
||||||
f.drawtype = NDT_AIRLIKE;
|
f.drawtype = NDT_AIRLIKE;
|
||||||
f.param_type = CPT_LIGHT;
|
f.param_type = CPT_LIGHT;
|
||||||
|
f.alpha = ALPHAMODE_CLIP;
|
||||||
f.light_propagates = true;
|
f.light_propagates = true;
|
||||||
f.sunlight_propagates = true;
|
f.sunlight_propagates = true;
|
||||||
f.walkable = false;
|
f.walkable = false;
|
||||||
|
@ -531,6 +531,8 @@ struct ContentFeatures
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
|
void updateAlpha(bool translucent_liquids);
|
||||||
|
MaterialType getMaterialType() const;
|
||||||
void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc,
|
void updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc,
|
||||||
scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings);
|
scene::IMeshManipulator *meshmanip, Client *client, const TextureSettings &tsettings);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user