diff --git a/.github/workflows/png_file_checks.yml b/.github/workflows/png_file_checks.yml
new file mode 100644
index 000000000..86cd93527
--- /dev/null
+++ b/.github/workflows/png_file_checks.yml
@@ -0,0 +1,26 @@
+name: png_file_checks
+
+# Check whether all png files are in a valid format
+on:
+ push:
+ paths:
+ - '**.png'
+ - '.github/workflows/**.yml'
+ pull_request:
+ paths:
+ - '**.png'
+ - '.github/workflows/**.yml'
+
+jobs:
+ png_optimized:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install deps
+ run: |
+ sudo apt-get update
+ sudo apt install -y optipng
+
+ - name: Check whether all png files are optimized
+ run: |
+ ./util/ci/check_png_optimized.sh
diff --git a/LICENSE.txt b/LICENSE.txt
index f7930f528..503dd62d2 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -14,6 +14,9 @@ https://www.apache.org/licenses/LICENSE-2.0.html
Textures by Zughy are under CC BY-SA 4.0
https://creativecommons.org/licenses/by-sa/4.0/
+Textures by cx384 are under CC BY-SA 4.0
+https://creativecommons.org/licenses/by-sa/4.0/
+
Media files by DS are under CC BY-SA 4.0
https://creativecommons.org/licenses/by-sa/4.0/
@@ -64,7 +67,13 @@ Zughy:
textures/base/pack/settings_info.png
textures/base/pack/settings_reset.png
textures/base/pack/server_url.png
+ textures/base/pack/server_url_unavailable.png
textures/base/pack/server_view_clients.png
+ textures/base/pack/server_view_clients_unavailable.png
+
+cx384:
+ textures/base/pack/server_view_mods.png
+ textures/base/pack/server_view_mods_unavailable.png
appgurueu:
textures/base/pack/server_incompatible.png
diff --git a/builtin/game/falling.lua b/builtin/game/falling.lua
index bb6ca1a64..6abd16c58 100644
--- a/builtin/game/falling.lua
+++ b/builtin/game/falling.lua
@@ -308,23 +308,26 @@ core.register_entity(":__builtin:falling_node", {
core.remove_node(bcp)
else
+ -- We are placing on top so check what's there
np.y = np.y + 1
- end
- -- Check what's here
- local n2 = core.get_node(np)
- local nd = core.registered_nodes[n2.name]
- -- If it's not air or liquid, remove node and replace it with
- -- it's drops
- if n2.name ~= "air" and (not nd or nd.liquidtype ~= "source") then
- if nd and nd.buildable_to == false then
+ local n2 = core.get_node(np)
+ local nd = core.registered_nodes[n2.name]
+ if not nd or nd.buildable_to then
+ core.remove_node(np)
+ else
+ -- 'walkable' is used to mean "falling nodes can't replace this"
+ -- here. Normally we would collide with the walkable node itself
+ -- and place our node on top (so `n2.name == "air"`), but we
+ -- re-check this in case we ended up inside a node.
+ if not nd.diggable or nd.walkable then
+ return false
+ end
nd.on_dig(np, n2, nil)
-- If it's still there, it might be protected
if core.get_node(np).name == n2.name then
return false
end
- else
- core.remove_node(np)
end
end
diff --git a/builtin/mainmenu/dlg_server_list_mods.lua b/builtin/mainmenu/dlg_server_list_mods.lua
new file mode 100644
index 000000000..ad44ac37f
--- /dev/null
+++ b/builtin/mainmenu/dlg_server_list_mods.lua
@@ -0,0 +1,105 @@
+-- Luanti
+-- Copyright (C) 2024 cx384
+-- SPDX-License-Identifier: LGPL-2.1-or-later
+
+local function get_formspec(dialogdata)
+ local TOUCH_GUI = core.settings:get_bool("touch_gui")
+ local server = dialogdata.server
+ local group_by_prefix = dialogdata.group_by_prefix
+ local expand_all = dialogdata.expand_all
+
+ -- A wrongly behaving server may send ill formed mod names
+ table.sort(server.mods)
+
+ local cells = {}
+ if group_by_prefix then
+ local function get_prefix(mod)
+ return mod:match("[^_]*")
+ end
+ local count = {}
+ for _, mod in ipairs(server.mods) do
+ local prefix = get_prefix(mod)
+ count[prefix] = (count[prefix] or 0) + 1
+ end
+ local last_prefix
+ local function add_row(depth, mod)
+ table.insert(cells, ("%d"):format(depth))
+ table.insert(cells, mod)
+ end
+ for i, mod in ipairs(server.mods) do
+ local prefix = get_prefix(mod)
+ if last_prefix == prefix then
+ add_row(1, mod)
+ elseif count[prefix] > 1 then
+ add_row(0, prefix)
+ add_row(1, mod)
+ else
+ add_row(0, mod)
+ end
+ last_prefix = prefix
+ end
+ else
+ cells = table.copy(server.mods)
+ end
+
+ for i, cell in ipairs(cells) do
+ cells[i] = core.formspec_escape(cell)
+ end
+ cells = table.concat(cells, ",")
+
+ local heading
+ if server.gameid then
+ heading = fgettext("The $1 server uses a game called $2 and the following mods:",
+ "" .. core.hypertext_escape(server.name) .. "",
+ "")
+ else
+ heading = fgettext("The $1 server uses the following mods:",
+ "" .. core.hypertext_escape(server.name) .. "")
+ end
+
+ local formspec = {
+ "formspec_version[8]",
+ "size[8,9.5]",
+ TOUCH_GUI and "padding[0.01,0.01]" or "",
+ "hypertext[0,0;8,1.5;;", heading, "]",
+ "tablecolumns[", group_by_prefix and
+ (expand_all and "indent;text" or "tree;text") or "text", "]",
+ "table[0.5,1.5;7,6.8;mods;", cells, "]",
+ "checkbox[0.5,8.7;group_by_prefix;", fgettext("Group by prefix"), ";",
+ group_by_prefix and "true" or "false", "]",
+ group_by_prefix and ("checkbox[0.5,9.15;expand_all;" .. fgettext("Expand all") .. ";" ..
+ (expand_all and "true" or "false") .. "]") or "",
+ "button[5.5,8.5;2,0.8;quit;OK]"
+ }
+ return table.concat(formspec, "")
+end
+
+local function buttonhandler(this, fields)
+ if fields.quit then
+ this:delete()
+ return true
+ end
+
+ if fields.group_by_prefix then
+ this.data.group_by_prefix = core.is_yes(fields.group_by_prefix)
+ return true
+ end
+
+ if fields.expand_all then
+ this.data.expand_all = core.is_yes(fields.expand_all)
+ return true
+ end
+
+ return false
+end
+
+function create_server_list_mods_dialog(server)
+ local retval = dialog_create("dlg_server_list_mods",
+ get_formspec,
+ buttonhandler,
+ nil)
+ retval.data.group_by_prefix = false
+ retval.data.expand_all = false
+ retval.data.server = server
+ return retval
+end
diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua
index 4e1c201cd..9eceb41a8 100644
--- a/builtin/mainmenu/init.lua
+++ b/builtin/mainmenu/init.lua
@@ -56,6 +56,7 @@ dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
dofile(menupath .. DIR_DELIM .. "dlg_version_info.lua")
dofile(menupath .. DIR_DELIM .. "dlg_reinstall_mtg.lua")
dofile(menupath .. DIR_DELIM .. "dlg_clients_list.lua")
+dofile(menupath .. DIR_DELIM .. "dlg_server_list_mods.lua")
local tabs = {
content = dofile(menupath .. DIR_DELIM .. "tab_content.lua"),
diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua
index 02c6a9c24..bd7f45342 100644
--- a/builtin/mainmenu/tab_online.lua
+++ b/builtin/mainmenu/tab_online.lua
@@ -161,6 +161,26 @@ local function get_formspec(tabview, name, tabdata)
core.formspec_escape(gamedata.serverdescription) .. "]"
end
+ -- Mods button
+ local mods = selected_server.mods
+ if mods and #mods > 0 then
+ local tooltip = ""
+ if selected_server.gameid then
+ tooltip = fgettext("Game: $1", selected_server.gameid) .. "\n"
+ end
+ tooltip = tooltip .. fgettext("Number of mods: $1", #mods)
+
+ retval = retval ..
+ "tooltip[btn_view_mods;" .. tooltip .. "]" ..
+ "style[btn_view_mods;padding=6]" ..
+ "image_button[4,1.3;0.5,0.5;" .. core.formspec_escape(defaulttexturedir ..
+ "server_view_mods.png") .. ";btn_view_mods;]"
+ else
+ retval = retval .. "image[4.1,1.4;0.3,0.3;" .. core.formspec_escape(defaulttexturedir ..
+ "server_view_mods_unavailable.png") .. "]"
+ end
+
+ -- Clients list button
local clients_list = selected_server.clients_list
local can_view_clients_list = clients_list and #clients_list > 0
if can_view_clients_list then
@@ -178,15 +198,23 @@ local function get_formspec(tabview, name, tabdata)
retval = retval .. "style[btn_view_clients;padding=6]"
retval = retval .. "image_button[4.5,1.3;0.5,0.5;" .. core.formspec_escape(defaulttexturedir ..
"server_view_clients.png") .. ";btn_view_clients;]"
+ else
+ retval = retval .. "image[4.6,1.4;0.3,0.3;" .. core.formspec_escape(defaulttexturedir ..
+ "server_view_clients_unavailable.png") .. "]"
end
+ -- URL button
if selected_server.url then
retval = retval .. "tooltip[btn_server_url;" .. fgettext("Open server website") .. "]"
retval = retval .. "style[btn_server_url;padding=6]"
- retval = retval .. "image_button[" .. (can_view_clients_list and "4" or "4.5") .. ",1.3;0.5,0.5;" ..
+ retval = retval .. "image_button[3.5,1.3;0.5,0.5;" ..
core.formspec_escape(defaulttexturedir .. "server_url.png") .. ";btn_server_url;]"
+ else
+ retval = retval .. "image[3.6,1.4;0.3,0.3;" .. core.formspec_escape(defaulttexturedir ..
+ "server_url_unavailable.png") .. "]"
end
+ -- Favorites toggle button
if is_selected_fav() then
retval = retval .. "tooltip[btn_delete_favorite;" .. fgettext("Remove favorite") .. "]"
retval = retval .. "style[btn_delete_favorite;padding=6]"
@@ -468,6 +496,14 @@ local function main_button_handler(tabview, fields, name, tabdata)
return true
end
+ if fields.btn_view_mods then
+ local dlg = create_server_list_mods_dialog(find_selected_server())
+ dlg:set_parent(tabview)
+ tabview:hide()
+ dlg:show()
+ return true
+ end
+
if fields.btn_mp_clear then
tabdata.search_for = ""
menudata.search_result = nil
diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt
index f13f7f69e..d8afc4b78 100644
--- a/builtin/settingtypes.txt
+++ b/builtin/settingtypes.txt
@@ -377,17 +377,12 @@ fog_start (Fog start) float 0.4 0.0 0.99
[**Clouds]
-# Clouds are a client-side effect.
-enable_clouds (Clouds) bool true
-
-# Use 3D cloud look instead of flat.
-#
-# Requires: enable_clouds
+# Allow clouds to look 3D instead of flat.
enable_3d_clouds (3D clouds) bool true
# Use smooth cloud shading.
#
-# Requires: enable_3d_clouds, enable_clouds
+# Requires: enable_3d_clouds
soft_clouds (Soft clouds) bool false
[**Filtering and Antialiasing]
@@ -472,9 +467,6 @@ smooth_lighting (Smooth lighting) bool true
# at the expense of minor visual glitches that do not impact game playability.
performance_tradeoffs (Tradeoffs for performance) bool false
-# Adds particles when digging a node.
-enable_particles (Digging particles) bool true
-
[**Waving Nodes]
@@ -667,8 +659,7 @@ sound_volume (Volume) float 0.8 0.0 1.0
# Volume multiplier when the window is unfocused.
sound_volume_unfocused (Volume when unfocused) float 0.3 0.0 1.0
-# Whether to mute sounds. You can unmute sounds at any time, unless the
-# sound system is disabled (enable_sound=false).
+# Whether to mute sounds. You can unmute sounds at any time.
# In-game, you can toggle the mute state with the mute key or by using the
# pause menu.
mute_sound (Mute sound) bool false
@@ -709,12 +700,6 @@ formspec_fullscreen_bg_color (Formspec Full-Screen Background Color) string (0,0
# to hardware (e.g. render-to-texture for nodes in inventory).
gui_scaling_filter (GUI scaling filter) bool false
-# When gui_scaling_filter_txr2img is true, copy those images
-# from hardware to software for scaling. When false, fall back
-# to the old scaling method, for video drivers that don't
-# properly support downloading textures back from hardware.
-gui_scaling_filter_txr2img (GUI scaling filter txr2img) bool true
-
# Delay showing tooltips, stated in milliseconds.
tooltip_show_delay (Tooltip delay) int 400 0 18446744073709551615
@@ -1869,10 +1854,7 @@ transparency_sorting_group_by_buffers (Transparency Sorting Group by Buffers) bo
# Radius of cloud area stated in number of 64 node cloud squares.
# Values larger than 26 will start to produce sharp cutoffs at cloud area corners.
-cloud_radius (Cloud radius) int 12 1 62
-
-# Whether node texture animations should be desynchronized per mapblock.
-desynchronize_mapblock_texture_animation (Desynchronize block animation) bool false
+cloud_radius (Cloud radius) int 12 8 62
# Delay between mesh updates on the client in ms. Increasing this will slow
# down the rate of mesh updates, thus reducing jitter on slower clients.
@@ -1942,7 +1924,7 @@ shadow_poisson_filter (Poisson filtering) bool true
# Minimum value: 1; maximum value: 16
#
# Requires: enable_dynamic_shadows, opengl
-shadow_update_frames (Map shadows update frames) int 8 1 16
+shadow_update_frames (Map shadows update frames) int 16 1 32
# Set to true to render debugging breakdown of the bloom effect.
# In debug mode, the screen is split into 4 quadrants:
@@ -2126,9 +2108,6 @@ max_block_send_distance (Max block send distance) int 12 1 65535
# Set this to -1 to disable the limit.
max_forceloaded_blocks (Maximum forceloaded blocks) int 16 -1
-# Interval of sending time of day to clients, stated in seconds.
-time_send_interval (Time send interval) float 5.0 0.001
-
# Interval of saving important changes in the world, stated in seconds.
server_map_save_interval (Map save interval) float 5.3 0.001
@@ -2137,7 +2116,7 @@ server_map_save_interval (Map save interval) float 5.3 0.001
server_unload_unused_data_timeout (Unload unused server data) int 29 0 4294967295
# Maximum number of statically stored objects in a block.
-max_objects_per_block (Maximum objects per block) int 256 1 65535
+max_objects_per_block (Maximum objects per block) int 256 256 65535
# Length of time between active block management cycles, stated in seconds.
active_block_mgmt_interval (Active block management interval) float 2.0 0.0
@@ -2356,12 +2335,6 @@ show_technical_names (Show technical names) bool false
# Controlled by a checkbox in the settings menu.
show_advanced (Show advanced settings) bool false
-# Enables the sound system.
-# If disabled, this completely disables all sounds everywhere and the in-game
-# sound controls will be non-functional.
-# Changing this setting requires a restart.
-enable_sound (Sound) bool true
-
# Key for moving the player forward.
keymap_forward (Forward key) key KEY_KEY_W
diff --git a/client/shaders/nodes_shader/opengl_fragment.glsl b/client/shaders/nodes_shader/opengl_fragment.glsl
index 9027c5fa1..8a10f34c4 100644
--- a/client/shaders/nodes_shader/opengl_fragment.glsl
+++ b/client/shaders/nodes_shader/opengl_fragment.glsl
@@ -53,7 +53,6 @@ centroid varying float nightRatio;
varying highp vec3 eyeVec;
varying float nightFactor;
-#ifdef ENABLE_DYNAMIC_SHADOWS
#if (MATERIAL_WAVING_LIQUID && defined(ENABLE_WATER_REFLECTIONS))
vec4 perm(vec4 x)
{
@@ -536,7 +535,7 @@ void main(void)
col.rgb += water_reflect_color * f_shadow_factor * brightness_factor;
#endif
-#if (defined(ENABLE_NODE_SPECULAR) && !MATERIAL_WAVING_LIQUID)
+#if (defined(ENABLE_NODE_SPECULAR) && !MATERIAL_WATER_REFLECTIONS)
// Apply specular to blocks.
if (dot(v_LightDirection, vNormal) < 0.0) {
// This intensity is a placeholder and should be replaced by proper specular maps.
diff --git a/doc/lua_api.md b/doc/lua_api.md
index a4e6c7c69..eceb11937 100644
--- a/doc/lua_api.md
+++ b/doc/lua_api.md
@@ -5044,7 +5044,7 @@ inside the VoxelManip.
can use `core.emerge_area` to make sure that the area you want to
read/write is already generated.
-* Other mods, or the core itself, could possibly modify the area of the map
+* Other mods, or the engine itself, could possibly modify the area of the map
currently loaded into a VoxelManip object. With the exception of Mapgen
VoxelManips (see above section), the internal buffers are not updated. For
this reason, it is strongly encouraged to complete the usage of a particular
@@ -5059,9 +5059,11 @@ inside the VoxelManip.
Methods
-------
-* `read_from_map(p1, p2)`: Loads a chunk of map into the VoxelManip object
+* `read_from_map(p1, p2)`: Loads a chunk of map into the VoxelManip object
containing the region formed by `p1` and `p2`.
* returns actual emerged `pmin`, actual emerged `pmax`
+ * Note that calling this multiple times will *add* to the area loaded in the
+ VoxelManip, and not reset it.
* `write_to_map([light])`: Writes the data loaded from the `VoxelManip` back to
the map.
* **important**: data must be set using `VoxelManip:set_data()` before
@@ -5120,8 +5122,8 @@ Methods
generated mapchunk above are propagated down into the mapchunk, defaults
to `true` if left out.
* `update_liquids()`: Update liquid flow
-* `was_modified()`: Returns `true` if the data in the voxel manipulator has been modified
- since it was last read from the map. This means you have to call `get_data` again.
+* `was_modified()`: Returns `true` if the data in the VoxelManip has been modified
+ since it was last read from the map. This means you have to call `get_data()` again.
This only applies to a `VoxelManip` object from `core.get_mapgen_object`,
where the engine will keep the map and the VM in sync automatically.
* Note: this doesn't do what you think it does and is subject to removal. Don't use it!
diff --git a/games/devtest/mods/testabms/textures/testabms_after_node.png b/games/devtest/mods/testabms/textures/testabms_after_node.png
index dab87594b..2a1efd53e 100644
Binary files a/games/devtest/mods/testabms/textures/testabms_after_node.png and b/games/devtest/mods/testabms/textures/testabms_after_node.png differ
diff --git a/games/devtest/mods/testabms/textures/testabms_wait_node.png b/games/devtest/mods/testabms/textures/testabms_wait_node.png
index a9bd9a36f..67ef96b6e 100644
Binary files a/games/devtest/mods/testabms/textures/testabms_wait_node.png and b/games/devtest/mods/testabms/textures/testabms_wait_node.png differ
diff --git a/games/devtest/mods/testnodes/textures/testnodes_attachedwr_bottom.png b/games/devtest/mods/testnodes/textures/testnodes_attachedwr_bottom.png
index 1a2e1e90e..9318c9454 100644
Binary files a/games/devtest/mods/testnodes/textures/testnodes_attachedwr_bottom.png and b/games/devtest/mods/testnodes/textures/testnodes_attachedwr_bottom.png differ
diff --git a/games/devtest/mods/testnodes/textures/testnodes_attachedwr_side.png b/games/devtest/mods/testnodes/textures/testnodes_attachedwr_side.png
index 382e2dafa..7701dc9e2 100644
Binary files a/games/devtest/mods/testnodes/textures/testnodes_attachedwr_side.png and b/games/devtest/mods/testnodes/textures/testnodes_attachedwr_side.png differ
diff --git a/games/devtest/mods/testnodes/textures/testnodes_attachedwr_top.png b/games/devtest/mods/testnodes/textures/testnodes_attachedwr_top.png
index 39ea67b8b..70976ca15 100644
Binary files a/games/devtest/mods/testnodes/textures/testnodes_attachedwr_top.png and b/games/devtest/mods/testnodes/textures/testnodes_attachedwr_top.png differ
diff --git a/games/devtest/mods/testnodes/textures/testnodes_sign3d.png b/games/devtest/mods/testnodes/textures/testnodes_sign3d.png
index e4ad9479f..d37a0de7e 100644
Binary files a/games/devtest/mods/testnodes/textures/testnodes_sign3d.png and b/games/devtest/mods/testnodes/textures/testnodes_sign3d.png differ
diff --git a/games/devtest/mods/testtools/textures/testtools_particle_clip.png b/games/devtest/mods/testtools/textures/testtools_particle_clip.png
index 5fb9ad09a..773e55e50 100644
Binary files a/games/devtest/mods/testtools/textures/testtools_particle_clip.png and b/games/devtest/mods/testtools/textures/testtools_particle_clip.png differ
diff --git a/games/devtest/mods/unittests/init.lua b/games/devtest/mods/unittests/init.lua
index 724334326..a971632c9 100644
--- a/games/devtest/mods/unittests/init.lua
+++ b/games/devtest/mods/unittests/init.lua
@@ -12,6 +12,7 @@ unittests.list = {}
-- player = false, -- Does test require a player?
-- map = false, -- Does test require map access?
-- async = false, -- Does the test run asynchronously? (read notes above!)
+-- random = false, -- Does the test use math.random directly or indirectly?
-- }
function unittests.register(name, func, opts)
local def = table.copy(opts or {})
@@ -47,8 +48,18 @@ local function await(invoke)
return coroutine.yield()
end
+local function printf(fmt, ...)
+ print(fmt:format(...))
+end
+
function unittests.run_one(idx, counters, out_callback, player, pos)
local def = unittests.list[idx]
+ local seed
+ if def.random then
+ seed = core.get_us_time()
+ math.randomseed(seed)
+ end
+
if not def.player then
player = nil
elseif player == nil then
@@ -70,8 +81,10 @@ function unittests.run_one(idx, counters, out_callback, player, pos)
if not status then
core.log("error", err)
end
- print(string.format("[%s] %s - %dms",
- status and "PASS" or "FAIL", def.name, ms_taken))
+ printf("[%s] %s - %dms", status and "PASS" or "FAIL", def.name, ms_taken)
+ if seed and not status then
+ printf("Random was seeded to %d", seed)
+ end
counters.time = counters.time + ms_taken
counters.total = counters.total + 1
if status then
@@ -160,11 +173,11 @@ function unittests.run_all()
-- Print stats
assert(#unittests.list == counters.total)
print(string.rep("+", 80))
- print(string.format("Devtest Unit Test Results: %s",
- counters.total == counters.passed and "PASSED" or "FAILED"))
- print(string.format(" %d / %d failed tests.",
- counters.total - counters.passed, counters.total))
- print(string.format(" Testing took %dms total.", counters.time))
+ local passed = counters.total == counters.passed
+ printf("Devtest Unit Test Results: %s", passed and "PASSED" or "FAILED")
+ printf(" %d / %d failed tests.",
+ counters.total - counters.passed, counters.total)
+ printf(" Testing took %dms total.", counters.time)
print(string.rep("+", 80))
unittests.on_finished(counters.total == counters.passed)
return counters.total == counters.passed
diff --git a/games/devtest/mods/unittests/raycast.lua b/games/devtest/mods/unittests/raycast.lua
index 08d6a1120..1dc196cc5 100644
--- a/games/devtest/mods/unittests/raycast.lua
+++ b/games/devtest/mods/unittests/raycast.lua
@@ -34,3 +34,70 @@ local function test_raycast_pointabilities(player, pos1)
end
unittests.register("test_raycast_pointabilities", test_raycast_pointabilities, {map=true})
+
+local function test_raycast_noskip(_, pos)
+ local function random_point_in_area(min, max)
+ local extents = max - min
+ local v = extents:multiply(vector.new(
+ math.random(),
+ math.random(),
+ math.random()
+ ))
+ return min + v
+ end
+
+ -- FIXME a variation of this unit test fails in an edge case.
+ -- This is because Luanti does not handle perfectly diagonal raycasts correctly:
+ -- Perfect diagonals collide with neither "outside" face and may thus "pierce" nodes.
+ -- Enable the following code to reproduce:
+ if 0 == 1 then
+ pos = vector.new(6, 32, -3)
+ math.randomseed(1596190898)
+ function random_point_in_area(min, max)
+ return min:combine(max, math.random)
+ end
+ end
+
+ local function cuboid_minmax(extent)
+ return pos:offset(-extent, -extent, -extent),
+ pos:offset(extent, extent, extent)
+ end
+
+ -- Carve out a 3x3x3 dirt cuboid in a larger air cuboid
+ local r = 8
+ local min, max = cuboid_minmax(r + 1)
+ local vm = core.get_voxel_manip(min, max)
+ local old_data = vm:get_data()
+ local data = vm:get_data()
+ local emin, emax = vm:get_emerged_area()
+ local va = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
+ for index in va:iterp(min, max) do
+ data[index] = core.CONTENT_AIR
+ end
+ for index in va:iterp(cuboid_minmax(1)) do
+ data[index] = core.get_content_id("basenodes:dirt")
+ end
+ vm:set_data(data)
+ vm:write_to_map()
+
+ -- Raycast many times from outside the cuboid
+ for _ = 1, 100 do
+ local ray_start
+ repeat
+ ray_start = random_point_in_area(cuboid_minmax(r))
+ until not ray_start:in_area(cuboid_minmax(1.501))
+ -- Pick a random position inside the dirt
+ local ray_end = random_point_in_area(cuboid_minmax(1.499))
+ -- The first pointed thing should have only air "in front" of it,
+ -- or a dirt node got falsely skipped.
+ local pt = core.raycast(ray_start, ray_end, false, false):next()
+ if pt then
+ assert(core.get_node(pt.above).name == "air")
+ end
+ end
+
+ vm:set_data(old_data)
+ vm:write_to_map()
+end
+
+unittests.register("test_raycast_noskip", test_raycast_noskip, {map = true, random = true})
diff --git a/irr/include/EDebugSceneTypes.h b/irr/include/EDebugSceneTypes.h
index 29ca8ad0e..2994eca6c 100644
--- a/irr/include/EDebugSceneTypes.h
+++ b/irr/include/EDebugSceneTypes.h
@@ -34,7 +34,7 @@ enum E_DEBUG_SCENE_TYPE
EDS_BBOX_ALL = EDS_BBOX | EDS_BBOX_BUFFERS,
//! Show all debug infos
- EDS_FULL = 0xffffffff
+ EDS_FULL = 0xffff
};
} // end namespace scene
diff --git a/irr/include/IGUIButton.h b/irr/include/IGUIButton.h
index 8870f8b1c..fdee609d9 100644
--- a/irr/include/IGUIButton.h
+++ b/irr/include/IGUIButton.h
@@ -5,6 +5,7 @@
#pragma once
#include "IGUIElement.h"
+#include "SColor.h"
namespace irr
{
diff --git a/irr/include/IGUIElement.h b/irr/include/IGUIElement.h
index 429bc06b3..cdd3d7487 100644
--- a/irr/include/IGUIElement.h
+++ b/irr/include/IGUIElement.h
@@ -10,7 +10,6 @@
#include "IEventReceiver.h"
#include "EGUIElementTypes.h"
#include "EGUIAlignment.h"
-#include "IGUIEnvironment.h"
#include
#include
#include
@@ -19,6 +18,8 @@ namespace irr
{
namespace gui
{
+class IGUIEnvironment;
+
//! Base class of all GUI elements.
class IGUIElement : virtual public IReferenceCounted, public IEventReceiver
{
diff --git a/irr/include/IGUIImage.h b/irr/include/IGUIImage.h
index 33453a3cd..cc3c66eb9 100644
--- a/irr/include/IGUIImage.h
+++ b/irr/include/IGUIImage.h
@@ -5,6 +5,7 @@
#pragma once
#include "IGUIElement.h"
+#include "SColor.h"
namespace irr
{
diff --git a/irr/include/ISceneManager.h b/irr/include/ISceneManager.h
index 25e1e5fe4..31604214f 100644
--- a/irr/include/ISceneManager.h
+++ b/irr/include/ISceneManager.h
@@ -387,6 +387,14 @@ public:
pass currently is active they can render the correct part of their geometry. */
virtual E_SCENE_NODE_RENDER_PASS getSceneNodeRenderPass() const = 0;
+ /**
+ * Sets debug data flags that will be set on every rendered scene node.
+ * Refer to `E_DEBUG_SCENE_TYPE`.
+ * @param setBits bit mask of types to enable
+ * @param unsetBits bit mask of types to disable
+ */
+ virtual void setGlobalDebugData(u16 setBits, u16 unsetBits) = 0;
+
//! Creates a new scene manager.
/** This can be used to easily draw and/or store two
independent scenes at the same time. The mesh cache will be
diff --git a/irr/include/ISceneNode.h b/irr/include/ISceneNode.h
index 0438d855f..897cfb350 100644
--- a/irr/include/ISceneNode.h
+++ b/irr/include/ISceneNode.h
@@ -403,14 +403,14 @@ public:
their geometry because it is their only reason for existence,
for example the OctreeSceneNode.
\param state The culling state to be used. Check E_CULLING_TYPE for possible values.*/
- void setAutomaticCulling(u32 state)
+ void setAutomaticCulling(u16 state)
{
AutomaticCullingState = state;
}
//! Gets the automatic culling state.
/** \return The automatic culling state. */
- u32 getAutomaticCulling() const
+ u16 getAutomaticCulling() const
{
return AutomaticCullingState;
}
@@ -419,7 +419,7 @@ public:
/** A bitwise OR of the types from @ref irr::scene::E_DEBUG_SCENE_TYPE.
Please note that not all scene nodes support all debug data types.
\param state The debug data visibility state to be used. */
- virtual void setDebugDataVisible(u32 state)
+ virtual void setDebugDataVisible(u16 state)
{
DebugDataVisible = state;
}
@@ -427,7 +427,7 @@ public:
//! Returns if debug data like bounding boxes are drawn.
/** \return A bitwise OR of the debug data values from
@ref irr::scene::E_DEBUG_SCENE_TYPE that are currently visible. */
- u32 isDebugDataVisible() const
+ u16 isDebugDataVisible() const
{
return DebugDataVisible;
}
@@ -581,10 +581,10 @@ protected:
s32 ID;
//! Automatic culling state
- u32 AutomaticCullingState;
+ u16 AutomaticCullingState;
//! Flag if debug data should be drawn, such as Bounding Boxes.
- u32 DebugDataVisible;
+ u16 DebugDataVisible;
//! Is the node visible?
bool IsVisible;
diff --git a/irr/include/SMaterial.h b/irr/include/SMaterial.h
index 867557154..3bbc6e946 100644
--- a/irr/include/SMaterial.h
+++ b/irr/include/SMaterial.h
@@ -20,7 +20,7 @@ class ITexture;
//! Flag for MaterialTypeParam (in combination with EMT_ONETEXTURE_BLEND) or for BlendFactor
//! BlendFunc = source * sourceFactor + dest * destFactor
-enum E_BLEND_FACTOR
+enum E_BLEND_FACTOR : u8
{
EBF_ZERO = 0, //!< src & dest (0, 0, 0, 0)
EBF_ONE, //!< src & dest (1, 1, 1, 1)
@@ -36,7 +36,7 @@ enum E_BLEND_FACTOR
};
//! Values defining the blend operation
-enum E_BLEND_OPERATION
+enum E_BLEND_OPERATION : u8
{
EBO_NONE = 0, //!< No blending happens
EBO_ADD, //!< Default blending adds the color values
@@ -51,7 +51,7 @@ enum E_BLEND_OPERATION
};
//! MaterialTypeParam: e.g. DirectX: D3DTOP_MODULATE, D3DTOP_MODULATE2X, D3DTOP_MODULATE4X
-enum E_MODULATE_FUNC
+enum E_MODULATE_FUNC : u8
{
EMFN_MODULATE_1X = 1,
EMFN_MODULATE_2X = 2,
@@ -59,7 +59,7 @@ enum E_MODULATE_FUNC
};
//! Comparison function, e.g. for depth buffer test
-enum E_COMPARISON_FUNC
+enum E_COMPARISON_FUNC : u8
{
//! Depth test disabled (disable also write to depth buffer)
ECFN_DISABLED = 0,
@@ -82,7 +82,7 @@ enum E_COMPARISON_FUNC
};
//! Enum values for enabling/disabling color planes for rendering
-enum E_COLOR_PLANE
+enum E_COLOR_PLANE : u8
{
//! No color enabled
ECP_NONE = 0,
@@ -103,7 +103,7 @@ enum E_COLOR_PLANE
//! Source of the alpha value to take
/** This is currently only supported in EMT_ONETEXTURE_BLEND. You can use an
or'ed combination of values. Alpha values are modulated (multiplied). */
-enum E_ALPHA_SOURCE
+enum E_ALPHA_SOURCE : u8
{
//! Use no alpha, somewhat redundant with other settings
EAS_NONE = 0,
@@ -181,7 +181,7 @@ Some drivers don't support a per-material setting of the anti-aliasing
modes. In those cases, FSAA/multisampling is defined by the device mode
chosen upon creation via irr::SIrrCreationParameters.
*/
-enum E_ANTI_ALIASING_MODE
+enum E_ANTI_ALIASING_MODE : u8
{
//! Use to turn off anti-aliasing for this material
EAAM_OFF = 0,
@@ -202,7 +202,7 @@ const c8 *const PolygonOffsetDirectionNames[] = {
};
//! For SMaterial.ZWriteEnable
-enum E_ZWRITE
+enum E_ZWRITE : u8
{
//! zwrite always disabled for this material
EZW_OFF = 0,
@@ -240,10 +240,10 @@ public:
//! Default constructor. Creates a solid material
SMaterial() :
MaterialType(EMT_SOLID), ColorParam(0, 0, 0, 0),
- MaterialTypeParam(0.0f), Thickness(1.0f), ZBuffer(ECFN_LESSEQUAL),
- AntiAliasing(EAAM_SIMPLE), ColorMask(ECP_ALL),
- BlendOperation(EBO_NONE), BlendFactor(0.0f), PolygonOffsetDepthBias(0.f),
- PolygonOffsetSlopeScale(0.f), Wireframe(false), PointCloud(false),
+ MaterialTypeParam(0.0f), Thickness(1.0f), BlendFactor(0.0f),
+ PolygonOffsetDepthBias(0.f), PolygonOffsetSlopeScale(0.f),
+ ZBuffer(ECFN_LESSEQUAL), AntiAliasing(EAAM_SIMPLE), ColorMask(ECP_ALL),
+ BlendOperation(EBO_NONE), Wireframe(false), PointCloud(false),
ZWriteEnable(EZW_AUTO),
BackfaceCulling(true), FrontfaceCulling(false), FogEnable(false),
UseMipMaps(true)
@@ -268,28 +268,6 @@ public:
//! Thickness of non-3dimensional elements such as lines and points.
f32 Thickness;
- //! Is the ZBuffer enabled? Default: ECFN_LESSEQUAL
- /** If you want to disable depth test for this material
- just set this parameter to ECFN_DISABLED.
- Values are from E_COMPARISON_FUNC. */
- u8 ZBuffer;
-
- //! Sets the antialiasing mode
- /** Values are chosen from E_ANTI_ALIASING_MODE. Default is
- EAAM_SIMPLE, i.e. simple multi-sample anti-aliasing. */
- u8 AntiAliasing;
-
- //! Defines the enabled color planes
- /** Values are defined as or'ed values of the E_COLOR_PLANE enum.
- Only enabled color planes will be rendered to the current render
- target. Typical use is to disable all colors when rendering only to
- depth or stencil buffer, or using Red and Green for Stereo rendering. */
- u8 ColorMask : 4;
-
- //! Store the blend operation of choice
- /** Values to be chosen from E_BLEND_OPERATION. */
- E_BLEND_OPERATION BlendOperation : 4;
-
//! Store the blend factors
/** textureBlendFunc/textureBlendFuncSeparate functions should be used to write
properly blending factors to this parameter.
@@ -304,11 +282,7 @@ public:
//! A constant z-buffer offset for a polygon/line/point
/** The range of the value is driver specific.
- On OpenGL you get units which are multiplied by the smallest value that is guaranteed to produce a resolvable offset.
- On D3D9 you can pass a range between -1 and 1. But you should likely divide it by the range of the depthbuffer.
- Like dividing by 65535.0 for a 16 bit depthbuffer. Thought it still might produce too large of a bias.
- Some article (https://aras-p.info/blog/2008/06/12/depth-bias-and-the-power-of-deceiving-yourself/)
- recommends multiplying by 2.0*4.8e-7 (and strangely on both 16 bit and 24 bit). */
+ On OpenGL you get units which are multiplied by the smallest value that is guaranteed to produce a resolvable offset. */
f32 PolygonOffsetDepthBias;
//! Variable Z-Buffer offset based on the slope of the polygon.
@@ -320,6 +294,25 @@ public:
and -1.f to pull them towards the camera. */
f32 PolygonOffsetSlopeScale;
+ //! Is the ZBuffer enabled? Default: ECFN_LESSEQUAL
+ /** If you want to disable depth test for this material
+ just set this parameter to ECFN_DISABLED. */
+ E_COMPARISON_FUNC ZBuffer : 4;
+
+ //! Sets the antialiasing mode
+ /** Default is EAAM_SIMPLE, i.e. simple multi-sample anti-aliasing. */
+ E_ANTI_ALIASING_MODE AntiAliasing : 4;
+
+ //! Defines the enabled color planes
+ /** Values are defined as or'ed values of the E_COLOR_PLANE enum.
+ Only enabled color planes will be rendered to the current render
+ target. Typical use is to disable all colors when rendering only to
+ depth or stencil buffer, or using Red and Green for Stereo rendering. */
+ E_COLOR_PLANE ColorMask : 4;
+
+ //! Store the blend operation of choice
+ E_BLEND_OPERATION BlendOperation : 4;
+
//! Draw as wireframe or filled triangles? Default: false
bool Wireframe : 1;
diff --git a/irr/include/SMaterialLayer.h b/irr/include/SMaterialLayer.h
index 419a8f1e9..4d43bd820 100644
--- a/irr/include/SMaterialLayer.h
+++ b/irr/include/SMaterialLayer.h
@@ -45,7 +45,7 @@ static const char *const aTextureClampNames[] = {
//! Texture minification filter.
/** Used when scaling textures down. See the documentation on OpenGL's
`GL_TEXTURE_MIN_FILTER` for more information. */
-enum E_TEXTURE_MIN_FILTER
+enum E_TEXTURE_MIN_FILTER : u8
{
//! Aka nearest-neighbor.
ETMINF_NEAREST_MIPMAP_NEAREST = 0,
@@ -61,7 +61,7 @@ enum E_TEXTURE_MIN_FILTER
/** Used when scaling textures up. See the documentation on OpenGL's
`GL_TEXTURE_MAG_FILTER` for more information.
Note that mipmaps are only used for minification, not for magnification. */
-enum E_TEXTURE_MAG_FILTER
+enum E_TEXTURE_MAG_FILTER : u8
{
//! Aka nearest-neighbor.
ETMAGF_NEAREST = 0,
diff --git a/irr/src/CAnimatedMeshSceneNode.cpp b/irr/src/CAnimatedMeshSceneNode.cpp
index 3871d52a3..6facfcd06 100644
--- a/irr/src/CAnimatedMeshSceneNode.cpp
+++ b/irr/src/CAnimatedMeshSceneNode.cpp
@@ -253,7 +253,7 @@ void CAnimatedMeshSceneNode::render()
// for debug purposes only:
if (DebugDataVisible && PassCount == 1) {
video::SMaterial debug_mat;
- debug_mat.AntiAliasing = 0;
+ debug_mat.AntiAliasing = video::EAAM_OFF;
driver->setMaterial(debug_mat);
// show normals
if (DebugDataVisible & scene::EDS_NORMALS) {
@@ -276,9 +276,6 @@ void CAnimatedMeshSceneNode::render()
debug_mat.ZBuffer = video::ECFN_DISABLED;
driver->setMaterial(debug_mat);
- if (DebugDataVisible & scene::EDS_BBOX)
- driver->draw3DBox(Box, video::SColor(255, 255, 255, 255));
-
// show bounding box
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) {
for (u32 g = 0; g < m->getMeshBufferCount(); ++g) {
@@ -290,6 +287,9 @@ void CAnimatedMeshSceneNode::render()
}
}
+ if (DebugDataVisible & scene::EDS_BBOX)
+ driver->draw3DBox(Box, video::SColor(255, 255, 255, 255));
+
// show skeleton
if (DebugDataVisible & scene::EDS_SKELETON) {
if (Mesh->getMeshType() == EAMT_SKINNED) {
diff --git a/irr/src/CFileSystem.h b/irr/src/CFileSystem.h
index 9400d85a3..d2a627e49 100644
--- a/irr/src/CFileSystem.h
+++ b/irr/src/CFileSystem.h
@@ -91,7 +91,7 @@ public:
private:
//! Currently used FileSystemType
- EFileSystemType FileSystemType;
+ EFileSystemType FileSystemType = FILESYSTEM_NATIVE;
//! WorkingDirectory for Native and Virtual filesystems
io::path WorkingDirectory[2];
//! currently attached ArchiveLoaders
diff --git a/irr/src/CGUIEnvironment.cpp b/irr/src/CGUIEnvironment.cpp
index b40896327..31e7038f4 100644
--- a/irr/src/CGUIEnvironment.cpp
+++ b/irr/src/CGUIEnvironment.cpp
@@ -948,7 +948,7 @@ IGUIElement *CGUIEnvironment::getNextElement(bool reverse, bool group)
// this element is not part of the tab cycle,
// but its parent might be...
IGUIElement *el = Focus;
- while (el && el->getParent() && startOrder == -1) {
+ while (el->getParent() && startOrder == -1) {
el = el->getParent();
startOrder = el->getTabOrder();
}
diff --git a/irr/src/CMeshSceneNode.cpp b/irr/src/CMeshSceneNode.cpp
index 2d9e400e9..89220cdc7 100644
--- a/irr/src/CMeshSceneNode.cpp
+++ b/irr/src/CMeshSceneNode.cpp
@@ -109,12 +109,10 @@ void CMeshSceneNode::render()
// for debug purposes only:
if (DebugDataVisible && PassCount == 1) {
video::SMaterial m;
- m.AntiAliasing = 0;
+ m.AntiAliasing = video::EAAM_OFF;
+ m.ZBuffer = video::ECFN_DISABLED;
driver->setMaterial(m);
- if (DebugDataVisible & scene::EDS_BBOX) {
- driver->draw3DBox(Box, video::SColor(255, 255, 255, 255));
- }
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) {
for (u32 g = 0; g < Mesh->getMeshBufferCount(); ++g) {
driver->draw3DBox(
@@ -123,6 +121,10 @@ void CMeshSceneNode::render()
}
}
+ if (DebugDataVisible & scene::EDS_BBOX) {
+ driver->draw3DBox(Box, video::SColor(255, 255, 255, 255));
+ }
+
if (DebugDataVisible & scene::EDS_NORMALS) {
// draw normals
const f32 debugNormalLength = 1.f;
diff --git a/irr/src/CNullDriver.cpp b/irr/src/CNullDriver.cpp
index 385e978b1..c87d5ae93 100644
--- a/irr/src/CNullDriver.cpp
+++ b/irr/src/CNullDriver.cpp
@@ -619,20 +619,17 @@ void CNullDriver::draw3DBox(const core::aabbox3d &box, SColor color)
core::vector3df edges[8];
box.getEdges(edges);
- // TODO: optimize into one big drawIndexPrimitive call.
+ video::S3DVertex v[8];
+ for (u32 i = 0; i < 8; i++) {
+ v[i].Pos = edges[i];
+ v[i].Color = color;
+ }
- draw3DLine(edges[5], edges[1], color);
- draw3DLine(edges[1], edges[3], color);
- draw3DLine(edges[3], edges[7], color);
- draw3DLine(edges[7], edges[5], color);
- draw3DLine(edges[0], edges[2], color);
- draw3DLine(edges[2], edges[6], color);
- draw3DLine(edges[6], edges[4], color);
- draw3DLine(edges[4], edges[0], color);
- draw3DLine(edges[1], edges[0], color);
- draw3DLine(edges[3], edges[2], color);
- draw3DLine(edges[7], edges[6], color);
- draw3DLine(edges[5], edges[4], color);
+ const static u16 box_indices[24] = {
+ 5, 1, 1, 3, 3, 7, 7, 5, 0, 2, 2, 6, 6, 4, 4, 0, 1, 0, 3, 2, 7, 6, 5, 4
+ };
+
+ drawVertexPrimitiveList(v, 8, box_indices, 12, EVT_STANDARD, scene::EPT_LINES);
}
//! draws an 2d image
@@ -1314,7 +1311,7 @@ void CNullDriver::runOcclusionQuery(scene::ISceneNode *node, bool visible)
OcclusionQueries[index].Run = 0;
if (!visible) {
SMaterial mat;
- mat.AntiAliasing = 0;
+ mat.AntiAliasing = video::EAAM_OFF;
mat.ColorMask = ECP_NONE;
mat.ZWriteEnable = EZW_OFF;
setMaterial(mat);
diff --git a/irr/src/COpenGLCoreTexture.h b/irr/src/COpenGLCoreTexture.h
index d8a813d5d..2254076a7 100644
--- a/irr/src/COpenGLCoreTexture.h
+++ b/irr/src/COpenGLCoreTexture.h
@@ -137,6 +137,9 @@ public:
Images.clear();
}
+ if (!name.empty())
+ Driver->irrGlObjectLabel(GL_TEXTURE, TextureName, name.c_str());
+
Driver->getCacheHandler()->getTextureCache().set(0, prevTexture);
TEST_GL_ERROR(Driver);
@@ -247,6 +250,9 @@ public:
break;
}
+ if (!name.empty())
+ Driver->irrGlObjectLabel(GL_TEXTURE, TextureName, name.c_str());
+
Driver->getCacheHandler()->getTextureCache().set(0, prevTexture);
if (TEST_GL_ERROR(Driver)) {
char msg[256];
diff --git a/irr/src/COpenGLDriver.cpp b/irr/src/COpenGLDriver.cpp
index 73eb22095..e9cd10b49 100644
--- a/irr/src/COpenGLDriver.cpp
+++ b/irr/src/COpenGLDriver.cpp
@@ -2462,66 +2462,6 @@ void COpenGLDriver::setFog(SColor c, E_FOG_TYPE fogType, f32 start,
glFogfv(GL_FOG_COLOR, data);
}
-//! Draws a 3d box.
-void COpenGLDriver::draw3DBox(const core::aabbox3d &box, SColor color)
-{
- core::vector3df edges[8];
- box.getEdges(edges);
-
- setRenderStates3DMode();
-
- video::S3DVertex v[24];
-
- for (u32 i = 0; i < 24; i++)
- v[i].Color = color;
-
- v[0].Pos = edges[5];
- v[1].Pos = edges[1];
- v[2].Pos = edges[1];
- v[3].Pos = edges[3];
- v[4].Pos = edges[3];
- v[5].Pos = edges[7];
- v[6].Pos = edges[7];
- v[7].Pos = edges[5];
- v[8].Pos = edges[0];
- v[9].Pos = edges[2];
- v[10].Pos = edges[2];
- v[11].Pos = edges[6];
- v[12].Pos = edges[6];
- v[13].Pos = edges[4];
- v[14].Pos = edges[4];
- v[15].Pos = edges[0];
- v[16].Pos = edges[1];
- v[17].Pos = edges[0];
- v[18].Pos = edges[3];
- v[19].Pos = edges[2];
- v[20].Pos = edges[7];
- v[21].Pos = edges[6];
- v[22].Pos = edges[5];
- v[23].Pos = edges[4];
-
- if (!FeatureAvailable[IRR_ARB_vertex_array_bgra] && !FeatureAvailable[IRR_EXT_vertex_array_bgra])
- getColorBuffer(v, 24, EVT_STANDARD);
-
- CacheHandler->setClientState(true, false, true, false);
-
- glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex), &(static_cast(v))[0].Pos);
-
-#ifdef GL_BGRA
- const GLint colorSize = (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra]) ? GL_BGRA : 4;
-#else
- const GLint colorSize = 4;
-#endif
- if (FeatureAvailable[IRR_ARB_vertex_array_bgra] || FeatureAvailable[IRR_EXT_vertex_array_bgra])
- glColorPointer(colorSize, GL_UNSIGNED_BYTE, sizeof(S3DVertex), &(static_cast(v))[0].Color);
- else {
- _IRR_DEBUG_BREAK_IF(ColorBuffer.size() == 0);
- glColorPointer(colorSize, GL_UNSIGNED_BYTE, 0, &ColorBuffer[0]);
- }
-
- glDrawArrays(GL_LINES, 0, 24);
-}
-
//! Draws a 3d line.
void COpenGLDriver::draw3DLine(const core::vector3df &start,
const core::vector3df &end, SColor color)
diff --git a/irr/src/COpenGLDriver.h b/irr/src/COpenGLDriver.h
index 0fdd15d16..1b5c0c6d3 100644
--- a/irr/src/COpenGLDriver.h
+++ b/irr/src/COpenGLDriver.h
@@ -170,9 +170,6 @@ public:
const core::position2d &end,
SColor color = SColor(255, 255, 255, 255)) override;
- //! Draws a 3d box
- void draw3DBox(const core::aabbox3d &box, SColor color = SColor(255, 255, 255, 255)) override;
-
//! Draws a 3d line.
virtual void draw3DLine(const core::vector3df &start,
const core::vector3df &end,
diff --git a/irr/src/COpenGLExtensionHandler.h b/irr/src/COpenGLExtensionHandler.h
index a1754a328..63c55f26c 100644
--- a/irr/src/COpenGLExtensionHandler.h
+++ b/irr/src/COpenGLExtensionHandler.h
@@ -1065,6 +1065,10 @@ public:
void irrGlCompressedTexSubImage2D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLenum format, GLsizei imageSize, const void *data);
+ inline void irrGlObjectLabel(GLenum identifier, GLuint name, const char *label)
+ {
+ // unimplemented
+ }
// shader programming
void extGlGenPrograms(GLsizei n, GLuint *programs);
diff --git a/irr/src/CSceneManager.cpp b/irr/src/CSceneManager.cpp
index d8a147b34..23e5335ce 100644
--- a/irr/src/CSceneManager.cpp
+++ b/irr/src/CSceneManager.cpp
@@ -490,13 +490,19 @@ void CSceneManager::drawAll()
// let all nodes register themselves
OnRegisterSceneNode();
+ const auto &render_node = [this] (ISceneNode *node) {
+ u32 flags = node->isDebugDataVisible();
+ node->setDebugDataVisible((flags & DebugDataMask) | DebugDataBits);
+ node->render();
+ };
+
// render camera scenes
{
CurrentRenderPass = ESNRP_CAMERA;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
for (auto *node : CameraList)
- node->render();
+ render_node(node);
CameraList.clear();
}
@@ -507,7 +513,7 @@ void CSceneManager::drawAll()
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
for (auto *node : SkyBoxList)
- node->render();
+ render_node(node);
SkyBoxList.clear();
}
@@ -520,7 +526,7 @@ void CSceneManager::drawAll()
std::sort(SolidNodeList.begin(), SolidNodeList.end());
for (auto &it : SolidNodeList)
- it.Node->render();
+ render_node(it.Node);
SolidNodeList.clear();
}
@@ -533,7 +539,7 @@ void CSceneManager::drawAll()
std::sort(TransparentNodeList.begin(), TransparentNodeList.end());
for (auto &it : TransparentNodeList)
- it.Node->render();
+ render_node(it.Node);
TransparentNodeList.clear();
}
@@ -546,7 +552,7 @@ void CSceneManager::drawAll()
std::sort(TransparentEffectNodeList.begin(), TransparentEffectNodeList.end());
for (auto &it : TransparentEffectNodeList)
- it.Node->render();
+ render_node(it.Node);
TransparentEffectNodeList.clear();
}
@@ -557,7 +563,7 @@ void CSceneManager::drawAll()
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
for (auto *node : GuiNodeList)
- node->render();
+ render_node(node);
GuiNodeList.clear();
}
diff --git a/irr/src/CSceneManager.h b/irr/src/CSceneManager.h
index 2a4fb7f7b..8f03a1fec 100644
--- a/irr/src/CSceneManager.h
+++ b/irr/src/CSceneManager.h
@@ -179,6 +179,11 @@ public:
//! Set current render time.
void setCurrentRenderPass(E_SCENE_NODE_RENDER_PASS nextPass) override { CurrentRenderPass = nextPass; }
+ void setGlobalDebugData(u16 setBits, u16 unsetBits) override {
+ DebugDataMask = ~unsetBits;
+ DebugDataBits = setBits;
+ }
+
//! returns if node is culled
bool isCulled(const ISceneNode *node) const override;
@@ -268,6 +273,9 @@ private:
//! Mesh cache
IMeshCache *MeshCache;
+ //! Global debug render state
+ u16 DebugDataMask = 0, DebugDataBits = 0;
+
E_SCENE_NODE_RENDER_PASS CurrentRenderPass;
};
diff --git a/irr/src/OpenGL/Driver.cpp b/irr/src/OpenGL/Driver.cpp
index c33b3c9d9..25c9a14f6 100644
--- a/irr/src/OpenGL/Driver.cpp
+++ b/irr/src/OpenGL/Driver.cpp
@@ -164,13 +164,6 @@ COpenGL3DriverBase::COpenGL3DriverBase(const SIrrlichtCreationParameters ¶ms
ExposedData = ContextManager->getContext();
ContextManager->activateContext(ExposedData, false);
GL.LoadAllProcedures(ContextManager);
- if (EnableErrorTest && GL.IsExtensionPresent("GL_KHR_debug")) {
- GL.Enable(GL_DEBUG_OUTPUT);
- GL.DebugMessageCallback(debugCb, this);
- } else if (EnableErrorTest) {
- os::Printer::log("GL debug extension not available");
- }
- initQuadsIndices();
TEST_GL_ERROR(this);
}
@@ -248,6 +241,20 @@ bool COpenGL3DriverBase::genericDriverInit(const core::dimension2d &screenS
initFeatures();
printTextureFormats();
+ if (EnableErrorTest) {
+ if (KHRDebugSupported) {
+ GL.Enable(GL_DEBUG_OUTPUT);
+ GL.DebugMessageCallback(debugCb, this);
+ } else {
+ os::Printer::log("GL debug extension not available");
+ }
+ } else {
+ // don't do debug things if they are not wanted (even if supported)
+ KHRDebugSupported = false;
+ }
+
+ initQuadsIndices();
+
// reset cache handler
delete CacheHandler;
CacheHandler = new COpenGL3CacheHandler(this);
@@ -1025,9 +1032,7 @@ void COpenGL3DriverBase::drawGeneric(const void *vertices, const void *indexList
GL.DrawElements(GL_TRIANGLE_FAN, primitiveCount + 2, indexSize, indexList);
break;
case scene::EPT_TRIANGLES:
- GL.DrawElements((LastMaterial.Wireframe) ? GL_LINES : (LastMaterial.PointCloud) ? GL_POINTS
- : GL_TRIANGLES,
- primitiveCount * 3, indexSize, indexList);
+ GL.DrawElements(GL_TRIANGLES, primitiveCount * 3, indexSize, indexList);
break;
default:
break;
@@ -1306,7 +1311,28 @@ void COpenGL3DriverBase::setBasicRenderStates(const SMaterial &material, const S
getGLBlend(srcAlphaFact), getGLBlend(dstAlphaFact));
}
- // TODO: Polygon Offset. Not sure if it was left out deliberately or if it won't work with this driver.
+ // fillmode
+ if (Version.Spec != OpenGLSpec::ES && // not supported in gles
+ (resetAllRenderStates ||
+ lastmaterial.Wireframe != material.Wireframe ||
+ lastmaterial.PointCloud != material.PointCloud)) {
+ GL.PolygonMode(GL_FRONT_AND_BACK,
+ material.Wireframe ? GL_LINE :
+ material.PointCloud ? GL_POINT :
+ GL_FILL);
+ }
+
+ // Polygon Offset
+ if (resetAllRenderStates ||
+ lastmaterial.PolygonOffsetDepthBias != material.PolygonOffsetDepthBias ||
+ lastmaterial.PolygonOffsetSlopeScale != material.PolygonOffsetSlopeScale) {
+ if (material.PolygonOffsetDepthBias || material.PolygonOffsetSlopeScale) {
+ GL.Enable(GL.POLYGON_OFFSET_FILL);
+ GL.PolygonOffset(material.PolygonOffsetSlopeScale, material.PolygonOffsetDepthBias);
+ } else {
+ GL.Disable(GL.POLYGON_OFFSET_FILL);
+ }
+ }
if (resetAllRenderStates || lastmaterial.Thickness != material.Thickness)
GL.LineWidth(core::clamp(static_cast(material.Thickness), DimAliasedLine[0], DimAliasedLine[1]));
@@ -1615,7 +1641,7 @@ s32 COpenGL3DriverBase::addHighLevelShaderMaterial(
s32 nr = -1;
COpenGL3MaterialRenderer *r = new COpenGL3MaterialRenderer(
this, nr, vertexShaderProgram,
- pixelShaderProgram,
+ pixelShaderProgram, shaderName,
callback, baseMaterial, userData);
r->drop();
diff --git a/irr/src/OpenGL/ExtensionHandler.h b/irr/src/OpenGL/ExtensionHandler.h
index 0e3a0af2d..209fd415b 100644
--- a/irr/src/OpenGL/ExtensionHandler.h
+++ b/irr/src/OpenGL/ExtensionHandler.h
@@ -161,10 +161,23 @@ public:
GL.BlendEquation(mode);
}
+ inline void irrGlObjectLabel(GLenum identifier, GLuint name, const char *label)
+ {
+ if (KHRDebugSupported) {
+ u32 len = strlen(label);
+ // Since our texture strings can get quite long we also truncate
+ // to a hardcoded limit of 82
+ len = std::min(len, std::min(MaxLabelLength, 82U));
+ GL.ObjectLabel(identifier, name, len, label);
+ }
+ }
+
bool LODBiasSupported = false;
bool AnisotropicFilterSupported = false;
bool BlendMinMaxSupported = false;
bool TextureMultisampleSupported = false;
+ bool KHRDebugSupported = false;
+ u32 MaxLabelLength = 0;
};
}
diff --git a/irr/src/OpenGL/MaterialRenderer.cpp b/irr/src/OpenGL/MaterialRenderer.cpp
index 7439dba61..269f28ae9 100644
--- a/irr/src/OpenGL/MaterialRenderer.cpp
+++ b/irr/src/OpenGL/MaterialRenderer.cpp
@@ -24,6 +24,7 @@ COpenGL3MaterialRenderer::COpenGL3MaterialRenderer(COpenGL3DriverBase *driver,
s32 &outMaterialTypeNr,
const c8 *vertexShaderProgram,
const c8 *pixelShaderProgram,
+ const c8 *debugName,
IShaderConstantSetCallBack *callback,
E_MATERIAL_TYPE baseMaterial,
s32 userData) :
@@ -45,7 +46,7 @@ COpenGL3MaterialRenderer::COpenGL3MaterialRenderer(COpenGL3DriverBase *driver,
if (CallBack)
CallBack->grab();
- init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram);
+ init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram, debugName);
}
COpenGL3MaterialRenderer::COpenGL3MaterialRenderer(COpenGL3DriverBase *driver,
@@ -98,6 +99,7 @@ GLuint COpenGL3MaterialRenderer::getProgram() const
void COpenGL3MaterialRenderer::init(s32 &outMaterialTypeNr,
const c8 *vertexShaderProgram,
const c8 *pixelShaderProgram,
+ const c8 *debugName,
bool addMaterial)
{
outMaterialTypeNr = -1;
@@ -121,6 +123,9 @@ void COpenGL3MaterialRenderer::init(s32 &outMaterialTypeNr,
if (!linkProgram())
return;
+ if (debugName)
+ Driver->irrGlObjectLabel(GL_PROGRAM, Program, debugName);
+
if (addMaterial)
outMaterialTypeNr = Driver->addMaterialRenderer(this);
}
diff --git a/irr/src/OpenGL/MaterialRenderer.h b/irr/src/OpenGL/MaterialRenderer.h
index fca71478a..0916f1ad5 100644
--- a/irr/src/OpenGL/MaterialRenderer.h
+++ b/irr/src/OpenGL/MaterialRenderer.h
@@ -28,6 +28,7 @@ public:
s32 &outMaterialTypeNr,
const c8 *vertexShaderProgram = 0,
const c8 *pixelShaderProgram = 0,
+ const c8 *debugName = nullptr,
IShaderConstantSetCallBack *callback = 0,
E_MATERIAL_TYPE baseMaterial = EMT_SOLID,
s32 userData = 0);
@@ -66,7 +67,9 @@ protected:
E_MATERIAL_TYPE baseMaterial = EMT_SOLID,
s32 userData = 0);
- void init(s32 &outMaterialTypeNr, const c8 *vertexShaderProgram, const c8 *pixelShaderProgram, bool addMaterial = true);
+ void init(s32 &outMaterialTypeNr, const c8 *vertexShaderProgram,
+ const c8 *pixelShaderProgram, const c8 *debugName = nullptr,
+ bool addMaterial = true);
bool createShader(GLenum shaderType, const char *shader);
bool linkProgram();
diff --git a/irr/src/OpenGL/Renderer2D.cpp b/irr/src/OpenGL/Renderer2D.cpp
index b7b8edf1b..ec53cc9f9 100644
--- a/irr/src/OpenGL/Renderer2D.cpp
+++ b/irr/src/OpenGL/Renderer2D.cpp
@@ -23,8 +23,8 @@ COpenGL3Renderer2D::COpenGL3Renderer2D(const c8 *vertexShaderProgram, const c8 *
WithTexture(withTexture)
{
int Temp = 0;
-
- init(Temp, vertexShaderProgram, pixelShaderProgram, false);
+ init(Temp, vertexShaderProgram, pixelShaderProgram,
+ withTexture ? "2DTexture" : "2DNoTexture", false);
COpenGL3CacheHandler *cacheHandler = Driver->getCacheHandler();
diff --git a/irr/src/OpenGL3/Driver.cpp b/irr/src/OpenGL3/Driver.cpp
index 767ce5992..7a62f4a12 100644
--- a/irr/src/OpenGL3/Driver.cpp
+++ b/irr/src/OpenGL3/Driver.cpp
@@ -72,6 +72,9 @@ void COpenGL3Driver::initFeatures()
LODBiasSupported = true;
BlendMinMaxSupported = true;
TextureMultisampleSupported = true;
+ KHRDebugSupported = isVersionAtLeast(4, 6) || queryExtension("GL_KHR_debug");
+ if (KHRDebugSupported)
+ MaxLabelLength = GetInteger(GL.MAX_LABEL_LENGTH);
// COGLESCoreExtensionHandler::Feature
static_assert(MATERIAL_MAX_TEXTURES <= 16, "Only up to 16 textures are guaranteed");
diff --git a/irr/src/OpenGLES2/Driver.cpp b/irr/src/OpenGLES2/Driver.cpp
index 25c4f485d..6b234842a 100644
--- a/irr/src/OpenGLES2/Driver.cpp
+++ b/irr/src/OpenGLES2/Driver.cpp
@@ -124,6 +124,9 @@ void COpenGLES2Driver::initFeatures()
AnisotropicFilterSupported = queryExtension("GL_EXT_texture_filter_anisotropic");
BlendMinMaxSupported = (Version.Major >= 3) || FeatureAvailable[IRR_GL_EXT_blend_minmax];
TextureMultisampleSupported = isVersionAtLeast(3, 1);
+ KHRDebugSupported = queryExtension("GL_KHR_debug");
+ if (KHRDebugSupported)
+ MaxLabelLength = GetInteger(GL.MAX_LABEL_LENGTH);
// COGLESCoreExtensionHandler::Feature
static_assert(MATERIAL_MAX_TEXTURES <= 8, "Only up to 8 textures are guaranteed");
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 692651049..88c0c5a45 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -417,7 +417,6 @@ set(independent_SRCS
hud.cpp
inventory.cpp
itemstackmetadata.cpp
- lighting.cpp
log.cpp
metadata.cpp
modchannels.cpp
diff --git a/src/activeobjectmgr.h b/src/activeobjectmgr.h
index 943147160..a9b007018 100644
--- a/src/activeobjectmgr.h
+++ b/src/activeobjectmgr.h
@@ -5,7 +5,6 @@
#pragma once
#include
-#include "debug.h"
#include "util/container.h"
#include "irrlichttypes.h"
#include "util/basic_macros.h"
diff --git a/src/chat.h b/src/chat.h
index d328732c3..97b391ccb 100644
--- a/src/chat.h
+++ b/src/chat.h
@@ -112,7 +112,8 @@ public:
void resize(u32 scrollback);
-protected:
+ // Get the current scroll position
+ s32 getScrollPosition() const { return m_scroll; }
s32 getTopScrollPos() const;
s32 getBottomScrollPos() const;
diff --git a/src/chat_interface.h b/src/chat_interface.h
index 1276c3a23..6ee1451db 100644
--- a/src/chat_interface.h
+++ b/src/chat_interface.h
@@ -4,10 +4,9 @@
#pragma once
-#include "util/container.h"
-#include
-#include
#include "irrlichttypes.h"
+#include "util/container.h" // MutexedQueue
+#include
enum ChatEventType {
CET_CHAT,
diff --git a/src/client/client.cpp b/src/client/client.cpp
index 222c1a2ac..b709f8cbf 100644
--- a/src/client/client.cpp
+++ b/src/client/client.cpp
@@ -37,6 +37,7 @@
#include "profiler.h"
#include "shader.h"
#include "gettext.h"
+#include "gettime.h"
#include "clientdynamicinfo.h"
#include "clientmap.h"
#include "clientmedia.h"
diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp
index b68edb790..725ff4323 100644
--- a/src/client/clientlauncher.cpp
+++ b/src/client/clientlauncher.cpp
@@ -91,8 +91,7 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
init_args(start_data, cmd_args);
#if USE_SOUND
- if (g_settings->getBool("enable_sound"))
- g_sound_manager_singleton = createSoundManagerSingleton();
+ g_sound_manager_singleton = createSoundManagerSingleton();
#endif
if (!init_engine())
diff --git a/src/client/clouds.cpp b/src/client/clouds.cpp
index 55e89410d..b65970f95 100644
--- a/src/client/clouds.cpp
+++ b/src/client/clouds.cpp
@@ -445,8 +445,8 @@ void Clouds::readSettings()
// chosen to avoid exactly that.
// refer to vertex_count in updateMesh()
m_enable_3d = g_settings->getBool("enable_3d_clouds");
- const u16 maximum = m_enable_3d ? 62 : 25;
- m_cloud_radius_i = rangelim(g_settings->getU16("cloud_radius"), 1, maximum);
+ const u16 maximum = !m_enable_3d ? 62 : 25;
+ m_cloud_radius_i = rangelim(g_settings->getU16("cloud_radius"), 8, maximum);
invalidateMesh();
}
diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp
index d90d4e8b0..5307047c4 100644
--- a/src/client/content_cao.cpp
+++ b/src/client/content_cao.cpp
@@ -656,25 +656,33 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
}
} else if (m_prop.visual == "upright_sprite") {
grabMatrixNode();
- scene::SMesh *mesh = new scene::SMesh();
- double dx = BS * m_prop.visual_size.X / 2;
- double dy = BS * m_prop.visual_size.Y / 2;
+ auto mesh = make_irr();
+ f32 dx = BS * m_prop.visual_size.X / 2;
+ f32 dy = BS * m_prop.visual_size.Y / 2;
video::SColor c(0xFFFFFFFF);
- { // Front
- scene::IMeshBuffer *buf = new scene::SMeshBuffer();
- video::S3DVertex vertices[4] = {
- video::S3DVertex(-dx, -dy, 0, 0,0,1, c, 1,1),
- video::S3DVertex( dx, -dy, 0, 0,0,1, c, 0,1),
- video::S3DVertex( dx, dy, 0, 0,0,1, c, 0,0),
- video::S3DVertex(-dx, dy, 0, 0,0,1, c, 1,0),
- };
- if (m_is_player) {
- // Move minimal Y position to 0 (feet position)
- for (video::S3DVertex &vertex : vertices)
- vertex.Pos.Y += dy;
+ video::S3DVertex vertices[4] = {
+ video::S3DVertex(-dx, -dy, 0, 0,0,1, c, 1,1),
+ video::S3DVertex( dx, -dy, 0, 0,0,1, c, 0,1),
+ video::S3DVertex( dx, dy, 0, 0,0,1, c, 0,0),
+ video::S3DVertex(-dx, dy, 0, 0,0,1, c, 1,0),
+ };
+ if (m_is_player) {
+ // Move minimal Y position to 0 (feet position)
+ for (auto &vertex : vertices)
+ vertex.Pos.Y += dy;
+ }
+ const u16 indices[] = {0,1,2,2,3,0};
+
+ for (int face : {0, 1}) {
+ auto buf = make_irr();
+ // Front (0) or Back (1)
+ if (face == 1) {
+ for (auto &v : vertices)
+ v.Normal *= -1;
+ for (int i : {0, 2})
+ std::swap(vertices[i].Pos, vertices[i+1].Pos);
}
- u16 indices[] = {0,1,2,2,3,0};
buf->append(vertices, 4, indices, 6);
// Set material
@@ -682,36 +690,12 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
buf->getMaterial().ColorParam = c;
// Add to mesh
- mesh->addMeshBuffer(buf);
- buf->drop();
+ mesh->addMeshBuffer(buf.get());
}
- { // Back
- scene::IMeshBuffer *buf = new scene::SMeshBuffer();
- video::S3DVertex vertices[4] = {
- video::S3DVertex( dx,-dy, 0, 0,0,-1, c, 1,1),
- video::S3DVertex(-dx,-dy, 0, 0,0,-1, c, 0,1),
- video::S3DVertex(-dx, dy, 0, 0,0,-1, c, 0,0),
- video::S3DVertex( dx, dy, 0, 0,0,-1, c, 1,0),
- };
- if (m_is_player) {
- // Move minimal Y position to 0 (feet position)
- for (video::S3DVertex &vertex : vertices)
- vertex.Pos.Y += dy;
- }
- u16 indices[] = {0,1,2,2,3,0};
- buf->append(vertices, 4, indices, 6);
- // Set material
- setMaterial(buf->getMaterial());
- buf->getMaterial().ColorParam = c;
-
- // Add to mesh
- mesh->addMeshBuffer(buf);
- buf->drop();
- }
- m_meshnode = m_smgr->addMeshSceneNode(mesh, m_matrixnode);
+ mesh->recalculateBoundingBox();
+ m_meshnode = m_smgr->addMeshSceneNode(mesh.get(), m_matrixnode);
m_meshnode->grab();
- mesh->drop();
} else if (m_prop.visual == "cube") {
grabMatrixNode();
scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS));
diff --git a/src/client/content_cao.h b/src/client/content_cao.h
index 1115b6819..a6b9beeab 100644
--- a/src/client/content_cao.h
+++ b/src/client/content_cao.h
@@ -4,15 +4,23 @@
#pragma once
-#include