1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-08-06 17:41:04 +00:00

Merge remote-tracking branch 'upstream/master' into Visuals-Vol-2

This commit is contained in:
Gefüllte Taubenbrust 2024-09-25 20:53:09 +02:00
commit 71e648a776
647 changed files with 60434 additions and 37195 deletions

View file

@ -648,6 +648,9 @@ if(BUILD_CLIENT)
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
target_link_libraries(${PROJECT_NAME} Catch2::Catch2)
endif()
if(BUILD_WITH_TRACY)
target_link_libraries(${PROJECT_NAME} Tracy::TracyClient)
endif()
if(PRECOMPILE_HEADERS)
target_precompile_headers(${PROJECT_NAME} PRIVATE ${PRECOMPILED_HEADERS_LIST})
@ -715,6 +718,9 @@ if(BUILD_SERVER)
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
target_link_libraries(${PROJECT_NAME}server Catch2::Catch2)
endif()
if(BUILD_WITH_TRACY)
target_link_libraries(${PROJECT_NAME}server Tracy::TracyClient)
endif()
if(PRECOMPILE_HEADERS)
target_precompile_headers(${PROJECT_NAME}server PRIVATE ${PRECOMPILED_HEADERS_LIST})
@ -781,7 +787,7 @@ endif()
if(MSVC)
# Visual Studio
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _WIN32_WINNT=0x0601 /D WIN32_LEAN_AND_MEAN")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D _WIN32_WINNT=0x0601 /D WIN32_LEAN_AND_MEAN /D _CRT_SECURE_NO_WARNINGS")
# EHa enables SEH exceptions (used for catching segfaults)
set(CMAKE_CXX_FLAGS_RELEASE "/EHa /Ox /MD /GS- /Zi /fp:fast /D NDEBUG /D _HAS_ITERATOR_DEBUGGING=0")
if(CMAKE_SIZEOF_VOID_P EQUAL 4)

View file

@ -96,6 +96,9 @@ struct BoneOverride
{
core::quaternion previous;
core::quaternion next;
// Redundantly store the euler angles serverside
// so that we can return them in the appropriate getters
v3f next_radians;
bool absolute = false;
f32 interp_timer = 0;
} rotation;
@ -152,17 +155,19 @@ typedef std::unordered_map<std::string, BoneOverride> BoneOverrideMap;
class ActiveObject
{
public:
ActiveObject(u16 id):
typedef u16 object_t;
ActiveObject(object_t id):
m_id(id)
{
}
u16 getId() const
object_t getId() const
{
return m_id;
}
void setId(u16 id)
void setId(object_t id)
{
m_id = id;
}
@ -193,14 +198,22 @@ public:
virtual bool collideWithObjects() const = 0;
virtual void setAttachment(int parent_id, const std::string &bone, v3f position,
virtual void setAttachment(object_t parent_id, const std::string &bone, v3f position,
v3f rotation, bool force_visible) {}
virtual void getAttachment(int *parent_id, std::string *bone, v3f *position,
virtual void getAttachment(object_t *parent_id, std::string *bone, v3f *position,
v3f *rotation, bool *force_visible) const {}
// Detach all children
virtual void clearChildAttachments() {}
virtual void clearParentAttachment() {}
virtual void addAttachmentChild(int child_id) {}
virtual void removeAttachmentChild(int child_id) {}
// Detach from parent
virtual void clearParentAttachment()
{
setAttachment(0, "", v3f(), v3f(), false);
}
// To be be called from setAttachment() and descendants, but not manually!
virtual void addAttachmentChild(object_t child_id) {}
virtual void removeAttachmentChild(object_t child_id) {}
protected:
u16 m_id; // 0 is invalid, "no id"
object_t m_id; // 0 is invalid, "no id"
};

View file

@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "script/scripting_client.h"
#include "gettext.h"
#include <SViewFrustum.h>
#include <IVideoDriver.h>
#define CAMERA_OFFSET_STEP 200
#define WIELDMESH_OFFSET_X 55.0f
@ -62,7 +63,7 @@ Camera::Camera(MapDrawControl &draw_control, Client *client, RenderingEngine *re
// all other 3D scene nodes and before the GUI.
m_wieldmgr = smgr->createNewSceneManager();
m_wieldmgr->addCameraSceneNode();
m_wieldnode = new WieldMeshSceneNode(m_wieldmgr, -1, false);
m_wieldnode = new WieldMeshSceneNode(m_wieldmgr, -1);
m_wieldnode->setItem(ItemStack(), m_client);
m_wieldnode->drop(); // m_wieldmgr grabbed it

View file

@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes.h"
#include "inventory.h"
#include "util/numeric.h"
#include "client/localplayer.h"

View file

@ -52,6 +52,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "profiler.h"
#include "shader.h"
#include "gettext.h"
#include "clientdynamicinfo.h"
#include "clientmap.h"
#include "clientmedia.h"
#include "version.h"
@ -119,7 +120,7 @@ Client::Client(
m_rendering_engine(rendering_engine),
m_mesh_update_manager(std::make_unique<MeshUpdateManager>(this)),
m_env(
new ClientMap(this, rendering_engine, control, 666),
make_irr<ClientMap>(this, rendering_engine, control, 666),
tsrc, this
),
m_particle_manager(std::make_unique<ParticleManager>(&m_env)),
@ -392,15 +393,12 @@ void Client::connect(const Address &address, const std::string &address_name,
}
m_address_name = address_name;
m_con.reset(new con::Connection(PROTOCOL_ID, 512, CONNECTION_TIMEOUT,
address.isIPv6(), this));
m_con.reset(con::createMTP(CONNECTION_TIMEOUT, address.isIPv6(), this));
infostream << "Connecting to server at ";
address.print(infostream);
infostream << std::endl;
// Since we use TryReceive() a timeout here would be ineffective anyway
m_con->SetTimeoutMs(0);
m_con->Connect(address);
initLocalMapSaving(address, m_address_name, is_local_server);
@ -439,20 +437,16 @@ void Client::step(float dtime)
}
}
// UGLY hack to fix 2 second startup delay caused by non existent
// server client startup synchronization in local server or singleplayer mode
static bool initial_step = true;
if (initial_step) {
initial_step = false;
}
else if(m_state == LC_Created) {
// The issue that made this workaround necessary was fixed in August 2024, but
// it's not like we can remove this code - ever.
if (m_state == LC_Created) {
float &counter = m_connection_reinit_timer;
counter -= dtime;
if(counter <= 0.0) {
counter = 2.0;
if (counter <= 0) {
counter = 1.5f;
LocalPlayer *myplayer = m_env.getLocalPlayer();
FATAL_ERROR_IF(myplayer == NULL, "Local player not found in environment.");
FATAL_ERROR_IF(!myplayer, "Local player not found in environment");
sendInit(myplayer->getName());
}
@ -833,7 +827,7 @@ bool Client::loadMedia(const std::string &data, const std::string &filename,
}
const char *model_ext[] = {
".x", ".b3d", ".obj",
".x", ".b3d", ".obj", ".gltf",
NULL
};
name = removeStringEnd(filename, model_ext);
@ -866,13 +860,13 @@ bool Client::loadMedia(const std::string &data, const std::string &filename,
}
// Virtual methods from con::PeerHandler
void Client::peerAdded(con::Peer *peer)
void Client::peerAdded(con::IPeer *peer)
{
infostream << "Client::peerAdded(): peer->id="
<< peer->id << std::endl;
}
void Client::deletingPeer(con::Peer *peer, bool timeout)
void Client::deletingPeer(con::IPeer *peer, bool timeout)
{
infostream << "Client::deletingPeer(): "
"Server Peer is getting deleted "
@ -1147,10 +1141,7 @@ void Client::sendInit(const std::string &playerName)
{
NetworkPacket pkt(TOSERVER_INIT, 1 + 2 + 2 + (1 + playerName.size()));
// we don't support network compression yet
u16 supp_comp_modes = NETPROTO_COMPRESSION_NONE;
pkt << (u8) SER_FMT_VER_HIGHEST_READ << (u16) supp_comp_modes;
pkt << (u8) SER_FMT_VER_HIGHEST_READ << (u16) 0;
pkt << (u16) CLIENT_PROTOCOL_VERSION_MIN << (u16) CLIENT_PROTOCOL_VERSION_MAX;
pkt << playerName;
@ -1368,9 +1359,9 @@ void Client::sendDamage(u16 damage)
Send(&pkt);
}
void Client::sendRespawn()
void Client::sendRespawnLegacy()
{
NetworkPacket pkt(TOSERVER_RESPAWN, 0);
NetworkPacket pkt(TOSERVER_RESPAWN_LEGACY, 0);
Send(&pkt);
}
@ -1594,7 +1585,7 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
{
// Check if we are working with local player inventory
LocalPlayer *player = m_env.getLocalPlayer();
if (!player || strcmp(player->getName(), loc.name.c_str()) != 0)
if (!player || player->getName() != loc.name)
return NULL;
return &player->inventory;
}

View file

@ -20,22 +20,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "clientenvironment.h"
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes.h"
#include <ostream>
#include <map>
#include <memory>
#include <set>
#include <vector>
#include <unordered_set>
#include "clientobject.h"
#include "gamedef.h"
#include "inventorymanager.h"
#include "client/hud.h"
#include "tileanimation.h"
#include "network/address.h"
#include "network/networkprotocol.h" // multiple enums
#include "network/peerhandler.h"
#include "gameparams.h"
#include "clientdynamicinfo.h"
#include "script/common/c_types.h" // LuaError
#include "util/numeric.h"
#include "clouds.h"
@ -45,34 +43,35 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f
struct ClientEvent;
struct MeshMakeData;
struct ChatMessage;
class MapBlockMesh;
class RenderingEngine;
class IWritableTextureSource;
class IWritableShaderSource;
class IWritableItemDefManager;
class ISoundManager;
class NodeDefManager;
//class IWritableCraftDefManager;
class Camera;
class ClientMediaDownloader;
class SingleMediaDownloader;
struct MapDrawControl;
class ISoundManager;
class IWritableItemDefManager;
class IWritableShaderSource;
class IWritableTextureSource;
class MapBlockMesh;
class MapDatabase;
class MeshUpdateManager;
class Minimap;
class ModChannelMgr;
class MtEventManager;
struct PointedThing;
struct MapNode;
class MapDatabase;
class Minimap;
struct MinimapMapblock;
class MeshUpdateManager;
class ParticleManager;
class Camera;
struct PlayerControl;
class NetworkPacket;
class NodeDefManager;
class ParticleManager;
class RenderingEngine;
class SingleMediaDownloader;
struct ChatMessage;
struct ClientDynamicInfo;
struct ClientEvent;
struct MapDrawControl;
struct MapNode;
struct MeshMakeData;
struct MinimapMapblock;
struct PlayerControl;
struct PointedThing;
namespace con {
class Connection;
class IConnection;
}
using sound_handle_t = int;
@ -196,7 +195,7 @@ public:
void handleCommand_Breath(NetworkPacket* pkt);
void handleCommand_MovePlayer(NetworkPacket* pkt);
void handleCommand_MovePlayerRel(NetworkPacket* pkt);
void handleCommand_DeathScreen(NetworkPacket* pkt);
void handleCommand_DeathScreenLegacy(NetworkPacket* pkt);
void handleCommand_AnnounceMedia(NetworkPacket* pkt);
void handleCommand_Media(NetworkPacket* pkt);
void handleCommand_NodeDef(NetworkPacket* pkt);
@ -251,7 +250,7 @@ public:
void sendChangePassword(const std::string &oldpassword,
const std::string &newpassword);
void sendDamage(u16 damage);
void sendRespawn();
void sendRespawnLegacy();
void sendReady();
void sendHaveMedia(const std::vector<u32> &tokens);
void sendUpdateClientInfo(const ClientDynamicInfo &info);
@ -456,8 +455,8 @@ private:
void loadMods();
// Virtual methods from con::PeerHandler
void peerAdded(con::Peer *peer) override;
void deletingPeer(con::Peer *peer, bool timeout) override;
void peerAdded(con::IPeer *peer) override;
void deletingPeer(con::IPeer *peer, bool timeout) override;
void initLocalMapSaving(const Address &address,
const std::string &hostname,
@ -497,7 +496,7 @@ private:
std::unique_ptr<MeshUpdateManager> m_mesh_update_manager;
ClientEnvironment m_env;
std::unique_ptr<ParticleManager> m_particle_manager;
std::unique_ptr<con::Connection> m_con;
std::unique_ptr<con::IConnection> m_con;
std::string m_address_name;
ELoginRegister m_allow_login_or_register = ELoginRegister::Any;
Camera *m_camera = nullptr;

View file

@ -43,10 +43,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
ClientEnvironment
*/
ClientEnvironment::ClientEnvironment(ClientMap *map,
ClientEnvironment::ClientEnvironment(irr_ptr<ClientMap> map,
ITextureSource *texturesource, Client *client):
Environment(client),
m_map(map),
m_map(std::move(map)),
m_texturesource(texturesource),
m_client(client)
{
@ -60,18 +60,17 @@ ClientEnvironment::~ClientEnvironment()
delete simple_object;
}
// Drop/delete map
m_map->drop();
m_map.reset();
delete m_local_player;
}
Map & ClientEnvironment::getMap()
Map &ClientEnvironment::getMap()
{
return *m_map;
}
ClientMap & ClientEnvironment::getClientMap()
ClientMap &ClientEnvironment::getClientMap()
{
return *m_map;
}
@ -368,7 +367,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
void ClientEnvironment::removeActiveObject(u16 id)
{
// Get current attachment childs to detach them visually
std::unordered_set<int> attachment_childs;
std::unordered_set<ClientActiveObject::object_t> attachment_childs;
if (auto *obj = getActiveObject(id))
attachment_childs = obj->getAttachmentChildIds();

View file

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "environment.h"
#include "util/numeric.h" // IntervalLimiter
#include "activeobjectmgr.h" // client::ActiveObjectMgr
#include "irr_ptr.h"
#include <set>
#ifdef SERVER
@ -66,7 +67,7 @@ typedef std::unordered_map<u16, ClientActiveObject*> ClientActiveObjectMap;
class ClientEnvironment : public Environment
{
public:
ClientEnvironment(ClientMap *map, ITextureSource *texturesource, Client *client);
ClientEnvironment(irr_ptr<ClientMap> map, ITextureSource *texturesource, Client *client);
~ClientEnvironment();
Map & getMap();
@ -151,7 +152,7 @@ public:
u64 getFrameTimeDelta() const { return m_frame_dtime; }
private:
ClientMap *m_map;
irr_ptr<ClientMap> m_map;
LocalPlayer *m_local_player = nullptr;
ITextureSource *m_texturesource;
Client *m_client;

View file

@ -20,7 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include <string>
#include "irrlichttypes_bloated.h"
#include "irrlichttypes.h"
#include "client/hud.h" // HudElementStat
struct ParticleParameters;
struct ParticleSpawnerParameters;
@ -34,7 +35,7 @@ enum ClientEventType : u8
CE_NONE,
CE_PLAYER_DAMAGE,
CE_PLAYER_FORCE_MOVE,
CE_DEATHSCREEN,
CE_DEATHSCREEN_LEGACY,
CE_SHOW_FORMSPEC,
CE_SHOW_LOCAL_FORMSPEC,
CE_SPAWN_PARTICLE,
@ -95,13 +96,6 @@ struct ClientEvent
f32 yaw;
} player_force_move;
struct
{
bool set_camera_point_target;
f32 camera_point_target_x;
f32 camera_point_target_y;
f32 camera_point_target_z;
} deathscreen;
struct
{
std::string *formspec;
std::string *formname;
@ -136,6 +130,7 @@ struct ClientEvent
f32 density;
u32 color_bright;
u32 color_ambient;
u32 color_shadow;
f32 height;
f32 thickness;
f32 speed_x;

View file

@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "gui/mainmenumanager.h"
#include "clouds.h"
#include "gui/touchscreengui.h"
#include "gui/touchcontrols.h"
#include "server.h"
#include "filesys.h"
#include "gui/guiMainMenu.h"
@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "player.h"
#include "chat.h"
#include "gettext.h"
#include "inputhandler.h"
#include "profiler.h"
#include "gui/guiEngine.h"
#include "fontengine.h"
@ -34,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "version.h"
#include "renderingengine.h"
#include "network/networkexceptions.h"
#include "util/tracy_wrapper.h"
#include <IGUISpriteBank.h>
#include <ICameraSceneNode.h>
#include <unordered_map>
@ -69,6 +71,7 @@ static void dump_start_data(const GameStartData &data)
ClientLauncher::~ClientLauncher()
{
delete input;
g_settings->deregisterChangedCallback("dpi_change_notifier", setting_changed_callback, this);
g_settings->deregisterChangedCallback("gui_scaling", setting_changed_callback, this);
delete g_fontengine;
@ -129,6 +132,7 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
guienv = m_rendering_engine->get_gui_env();
config_guienv();
g_settings->registerChangedCallback("dpi_change_notifier", setting_changed_callback, this);
g_settings->registerChangedCallback("gui_scaling", setting_changed_callback, this);
g_fontengine = new FontEngine(guienv);
@ -136,8 +140,10 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
// Create the menu clouds
// This is only global so it can be used by RenderingEngine::draw_load_screen().
assert(!g_menucloudsmgr && !g_menuclouds);
std::unique_ptr<IWritableShaderSource> ssrc(createShaderSource());
ssrc->addShaderConstantSetterFactory(new FogShaderConstantSetterFactory());
g_menucloudsmgr = m_rendering_engine->get_scene_manager()->createNewSceneManager();
g_menuclouds = new Clouds(g_menucloudsmgr, nullptr, -1, rand());
g_menuclouds = new Clouds(g_menucloudsmgr, ssrc.get(), -1, rand());
g_menuclouds->setHeight(100.0f);
g_menuclouds->update(v3f(0, 0, 0), video::SColor(255, 240, 240, 255));
scene::ICameraSceneNode* camera;
@ -228,9 +234,9 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
m_rendering_engine->get_scene_manager()->clear();
if (g_touchscreengui) {
delete g_touchscreengui;
g_touchscreengui = NULL;
if (g_touchcontrols) {
delete g_touchcontrols;
g_touchcontrols = NULL;
}
/* Save the settings when leaving the game.
@ -350,6 +356,7 @@ void ClientLauncher::config_guienv()
float density = rangelim(g_settings->getFloat("gui_scaling"), 0.5f, 20) *
RenderingEngine::getDisplayDensity();
skin->setScale(density);
skin->setSize(gui::EGDS_CHECK_BOX_WIDTH, (s32)(17.0f * density));
skin->setSize(gui::EGDS_SCROLLBAR_SIZE, (s32)(21.0f * density));
skin->setSize(gui::EGDS_WINDOW_BUTTON_WIDTH, (s32)(15.0f * density));
@ -540,15 +547,19 @@ void ClientLauncher::main_menu(MainMenuData *menudata)
video::IVideoDriver *driver = m_rendering_engine->get_video_driver();
infostream << "Waiting for other menus" << std::endl;
auto framemarker = FrameMarker("ClientLauncher::main_menu()-wait-frame").started();
while (m_rendering_engine->run() && !*kill) {
if (!isMenuActive())
break;
driver->beginScene(true, true, video::SColor(255, 128, 128, 128));
m_rendering_engine->get_gui_env()->drawAll();
driver->endScene();
framemarker.end();
// On some computers framerate doesn't seem to be automatically limited
sleep_ms(25);
framemarker.start();
}
framemarker.end();
infostream << "Waited for other menus" << std::endl;
auto *cur_control = m_rendering_engine->get_raw_device()->getCursorControl();

View file

@ -19,11 +19,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include "client/inputhandler.h"
#include "gameparams.h"
#include <string>
class RenderingEngine;
class Settings;
class MyEventReceiver;
class InputHandler;
struct GameStartData;
struct MainMenuData;
class ClientLauncher
{

View file

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/mesh.h"
#include "mapblock_mesh.h"
#include <IMaterialRenderer.h>
#include <IVideoDriver.h>
#include <matrix4.h>
#include "mapsector.h"
#include "mapblock.h"
@ -30,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include "camera.h" // CameraModes
#include "util/basic_macros.h"
#include "util/tracy_wrapper.h"
#include "client/renderingengine.h"
#include <queue>
@ -73,11 +75,23 @@ namespace {
};
}
/*
ClientMap
*/
static void on_settings_changed(const std::string &name, void *data)
{
static_cast<ClientMap*>(data)->onSettingChanged(name);
static_cast<ClientMap*>(data)->onSettingChanged(name, false);
}
// ClientMap
static const std::string ClientMap_settings[] = {
"trilinear_filter",
"bilinear_filter",
"anisotropic_filter",
"transparency_sorting_distance",
"occlusion_culler",
"enable_raytraced_culling",
};
ClientMap::ClientMap(
Client *client,
@ -102,37 +116,32 @@ ClientMap::ClientMap(
m_box = aabb3f(-BS*1000000,-BS*1000000,-BS*1000000,
BS*1000000,BS*1000000,BS*1000000);
/* TODO: Add a callback function so these can be updated when a setting
* changes. At this point in time it doesn't matter (e.g. /set
* is documented to change server settings only)
*
* TODO: Local caching of settings is not optimal and should at some stage
* be updated to use a global settings object for getting thse values
* (as opposed to the this local caching). This can be addressed in
* a later release.
*/
m_cache_trilinear_filter = g_settings->getBool("trilinear_filter");
m_cache_bilinear_filter = g_settings->getBool("bilinear_filter");
m_cache_anistropic_filter = g_settings->getBool("anisotropic_filter");
m_cache_transparency_sorting_distance = g_settings->getU16("transparency_sorting_distance");
m_loops_occlusion_culler = g_settings->get("occlusion_culler") == "loops";
g_settings->registerChangedCallback("occlusion_culler", on_settings_changed, this);
m_enable_raytraced_culling = g_settings->getBool("enable_raytraced_culling");
g_settings->registerChangedCallback("enable_raytraced_culling", on_settings_changed, this);
for (const auto &name : ClientMap_settings)
g_settings->registerChangedCallback(name, on_settings_changed, this);
// load all settings at once
onSettingChanged("", true);
}
void ClientMap::onSettingChanged(const std::string &name)
void ClientMap::onSettingChanged(std::string_view name, bool all)
{
if (name == "occlusion_culler")
if (all || name == "trilinear_filter")
m_cache_trilinear_filter = g_settings->getBool("trilinear_filter");
if (all || name == "bilinear_filter")
m_cache_bilinear_filter = g_settings->getBool("bilinear_filter");
if (all || name == "anisotropic_filter")
m_cache_anistropic_filter = g_settings->getBool("anisotropic_filter");
if (all || name == "transparency_sorting_distance")
m_cache_transparency_sorting_distance = g_settings->getU16("transparency_sorting_distance");
if (all || name == "occlusion_culler")
m_loops_occlusion_culler = g_settings->get("occlusion_culler") == "loops";
if (name == "enable_raytraced_culling")
if (all || name == "enable_raytraced_culling")
m_enable_raytraced_culling = g_settings->getBool("enable_raytraced_culling");
}
ClientMap::~ClientMap()
{
g_settings->deregisterChangedCallback("occlusion_culler", on_settings_changed, this);
g_settings->deregisterChangedCallback("enable_raytraced_culling", on_settings_changed, this);
for (const auto &name : ClientMap_settings)
g_settings->deregisterChangedCallback(name, on_settings_changed, this);
}
void ClientMap::updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset, video::SColor light_color)
@ -185,6 +194,13 @@ void ClientMap::OnRegisterSceneNode()
// we have other way to find it
}
void ClientMap::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
renderMap(driver, SceneManager->getSceneNodeRenderPass());
}
void ClientMap::getBlocksInViewRange(v3s16 cam_pos_nodes,
v3s16 *p_blocks_min, v3s16 *p_blocks_max, float range)
{
@ -699,6 +715,8 @@ void ClientMap::touchMapBlocks()
void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
{
ZoneScoped;
bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
std::string prefix;
@ -767,15 +785,12 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
if (is_frustum_culled(mesh_sphere_center, mesh_sphere_radius))
continue;
v3f block_pos_r = intToFloat(block->getPosRelative() + MAP_BLOCKSIZE / 2, BS);
float d = camera_position.getDistanceFrom(block_pos_r);
d = MYMAX(0,d - BLOCK_MAX_RADIUS);
// Mesh animation
if (pass == scene::ESNRP_SOLID) {
// Pretty random but this should work somewhat nicely
bool faraway = d >= BS * 50;
// 50 nodes is pretty arbitrary but it should work somewhat nicely
float distance_sq = camera_position.getDistanceFromSQ(mesh_sphere_center);
bool faraway = distance_sq >= std::pow(BS * 50 + mesh_sphere_radius, 2.0f);
if (block_mesh->isAnimationForced() || !faraway ||
mesh_animate_count < (m_control.range_all ? 200 : 50)) {
@ -844,10 +859,8 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
drawcall_count += draw_order.size();
for (auto &descriptor : draw_order) {
scene::IMeshBuffer *buf = descriptor.getBuffer();
if (!descriptor.m_reuse_material) {
auto &material = buf->getMaterial();
auto &material = descriptor.getMaterial();
// Apply filter settings
material.forEachTexture([this] (auto &tex) {
@ -879,8 +892,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
m.setTranslation(block_wpos - offset);
driver->setTransform(video::ETS_WORLD, m);
descriptor.draw(driver);
vertex_count += buf->getIndexCount();
vertex_count += descriptor.draw(driver);
}
g_profiler->avg(prefix + "draw meshes [ms]", draw.stop(true));
@ -1197,13 +1209,22 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
// Render all mesh buffers in order
drawcall_count += draw_order.size();
for (auto &descriptor : draw_order) {
scene::IMeshBuffer *buf = descriptor.getBuffer();
bool translucent_foliage = g_settings->getBool("enable_translucent_foliage");
video::E_MATERIAL_TYPE leaves_material = video::EMT_SOLID;
// For translucent leaves, we want to use backface culling instead of frontface.
if (translucent_foliage) {
// this is the material leaves would use, compare to nodedef.cpp
auto* shdsrc = m_client->getShaderSource();
const u32 leaves_shader = shdsrc->getShader("nodes_shader", TILE_MATERIAL_WAVING_LEAVES, NDT_ALLFACES);
leaves_material = shdsrc->getShaderInfo(leaves_shader).material;
}
for (auto &descriptor : draw_order) {
if (!descriptor.m_reuse_material) {
// override some material properties
video::SMaterial local_material = buf->getMaterial();
local_material.MaterialType = material.MaterialType;
video::SMaterial local_material = descriptor.getMaterial();
// do not override culling if the original material renders both back
// and front faces in solid mode (e.g. plantlike)
// Transparent plants would still render shadows only from one side,
@ -1212,8 +1233,12 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
local_material.BackfaceCulling = material.BackfaceCulling;
local_material.FrontfaceCulling = material.FrontfaceCulling;
}
if (local_material.MaterialType == leaves_material && translucent_foliage) {
local_material.BackfaceCulling = true;
local_material.FrontfaceCulling = false;
}
local_material.MaterialType = material.MaterialType;
local_material.BlendOperation = material.BlendOperation;
local_material.Lighting = false;
driver->setMaterial(local_material);
++material_swaps;
}
@ -1222,8 +1247,7 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
m.setTranslation(block_wpos - offset);
driver->setTransform(video::ETS_WORLD, m);
descriptor.draw(driver);
vertex_count += buf->getIndexCount();
vertex_count += descriptor.draw(driver);
}
// restore the driver material state
@ -1305,27 +1329,35 @@ void ClientMap::updateTransparentMeshBuffers()
ScopeProfiler sp(g_profiler, "CM::updateTransparentMeshBuffers", SPT_AVG);
u32 sorted_blocks = 0;
u32 unsorted_blocks = 0;
f32 sorting_distance_sq = std::pow(m_cache_transparency_sorting_distance * BS, 2.0f);
bool transparency_sorting_enabled = m_cache_transparency_sorting_distance > 0;
f32 sorting_distance = m_cache_transparency_sorting_distance * BS;
// Update the order of transparent mesh buffers in each mesh
for (auto it = m_drawlist.begin(); it != m_drawlist.end(); it++) {
MapBlock* block = it->second;
if (!block->mesh)
MapBlock *block = it->second;
MapBlockMesh *blockmesh = block->mesh;
if (!blockmesh)
continue;
if (m_needs_update_transparent_meshes ||
block->mesh->getTransparentBuffers().size() == 0) {
blockmesh->getTransparentBuffers().size() == 0) {
bool do_sort_block = transparency_sorting_enabled;
v3s16 block_pos = block->getPos();
v3f block_pos_f = intToFloat(block_pos * MAP_BLOCKSIZE + MAP_BLOCKSIZE / 2, BS);
f32 distance = m_camera_position.getDistanceFromSQ(block_pos_f);
if (distance <= sorting_distance_sq) {
block->mesh->updateTransparentBuffers(m_camera_position, block_pos);
++sorted_blocks;
if (do_sort_block) {
v3f mesh_sphere_center = intToFloat(block->getPosRelative(), BS)
+ blockmesh->getBoundingSphereCenter();
f32 mesh_sphere_radius = blockmesh->getBoundingRadius();
f32 distance_sq = m_camera_position.getDistanceFromSQ(mesh_sphere_center);
if (distance_sq > std::pow(sorting_distance + mesh_sphere_radius, 2.0f))
do_sort_block = false;
}
else {
block->mesh->consolidateTransparentBuffers();
if (do_sort_block) {
blockmesh->updateTransparentBuffers(m_camera_position, block->getPos());
++sorted_blocks;
} else {
blockmesh->consolidateTransparentBuffers();
++unsorted_blocks;
}
}
@ -1336,19 +1368,19 @@ void ClientMap::updateTransparentMeshBuffers()
m_needs_update_transparent_meshes = false;
}
scene::IMeshBuffer* ClientMap::DrawDescriptor::getBuffer()
video::SMaterial &ClientMap::DrawDescriptor::getMaterial()
{
return m_use_partial_buffer ? m_partial_buffer->getBuffer() : m_buffer;
return (m_use_partial_buffer ? m_partial_buffer->getBuffer() : m_buffer)->getMaterial();
}
void ClientMap::DrawDescriptor::draw(video::IVideoDriver* driver)
u32 ClientMap::DrawDescriptor::draw(video::IVideoDriver* driver)
{
if (m_use_partial_buffer) {
m_partial_buffer->beforeDraw();
driver->drawMeshBuffer(m_partial_buffer->getBuffer());
m_partial_buffer->afterDraw();
m_partial_buffer->draw(driver);
return m_partial_buffer->getBuffer()->getVertexCount();
} else {
driver->drawMeshBuffer(m_buffer);
return m_buffer->getVertexCount();
}
}

View file

@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes_bloated.h"
#include "map.h"
#include "camera.h"
#include <set>
@ -41,6 +41,16 @@ class Client;
class ITextureSource;
class PartialMeshBuffer;
namespace irr::scene
{
class IMeshBuffer;
}
namespace irr::video
{
class IVideoDriver;
}
/*
ClientMap
@ -75,12 +85,7 @@ public:
virtual void OnRegisterSceneNode() override;
virtual void render() override
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
renderMap(driver, SceneManager->getSceneNodeRenderPass());
}
virtual void render() override;
virtual const aabb3f &getBoundingBox() const override
{
@ -112,7 +117,7 @@ public:
f32 getWantedRange() const { return m_control.wanted_range; }
f32 getCameraFov() const { return m_camera_fov; }
void onSettingChanged(const std::string &name);
void onSettingChanged(std::string_view name, bool all);
protected:
// use drop() instead
@ -162,8 +167,9 @@ private:
m_pos(pos), m_partial_buffer(buffer), m_reuse_material(false), m_use_partial_buffer(true)
{}
scene::IMeshBuffer* getBuffer();
void draw(video::IVideoDriver* driver);
video::SMaterial &getMaterial();
/// @return index count
u32 draw(video::IVideoDriver* driver);
};
Client *m_client;

View file

@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes_bloated.h"
#include "activeobject.h"
#include <memory>
#include <unordered_map>
@ -34,6 +34,13 @@ class LocalPlayer;
struct ItemStack;
class WieldMeshSceneNode;
namespace irr::scene
{
class IAnimatedMeshSceneNode;
class ISceneNode;
class ISceneManager;
}
class ClientActiveObject : public ActiveObject
{
public:
@ -57,8 +64,8 @@ public:
virtual bool isLocalPlayer() const { return false; }
virtual ClientActiveObject *getParent() const { return nullptr; };
virtual const std::unordered_set<int> &getAttachmentChildIds() const
{ static std::unordered_set<int> rv; return rv; }
virtual const std::unordered_set<object_t> &getAttachmentChildIds() const
{ static std::unordered_set<object_t> rv; return rv; }
virtual void updateAttachments() {};
virtual bool doShowSelectionBox() { return true; }

View file

@ -28,10 +28,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include <cmath>
// Menu clouds are created later
class Clouds;
Clouds *g_menuclouds = NULL;
scene::ISceneManager *g_menucloudsmgr = NULL;
scene::ISceneManager *g_menucloudsmgr = nullptr;
Clouds *g_menuclouds = nullptr;
// Constant for now
static constexpr const float cloud_size = BS * 64.0f;
@ -48,11 +47,9 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc,
scene::ISceneNode(g_settings->getBool("enable_volumetric_clouds") ? nullptr : mgr->getRootSceneNode(), mgr, id),
m_seed(seed)
{
assert(ssrc);
m_enable_shaders = g_settings->getBool("enable_shaders");
// menu clouds use shader-less clouds for simplicity (ssrc == NULL)
m_enable_shaders = m_enable_shaders && ssrc;
m_material.Lighting = false;
m_material.BackfaceCulling = true;
m_material.FogEnable = true;
m_material.AntiAliasing = video::EAAM_SIMPLE;
@ -68,6 +65,8 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc,
readSettings();
g_settings->registerChangedCallback("enable_3d_clouds",
&cloud_3d_setting_changed, this);
g_settings->registerChangedCallback("soft_clouds",
&cloud_3d_setting_changed, this);
updateBox();
@ -79,6 +78,8 @@ Clouds::~Clouds()
{
g_settings->deregisterChangedCallback("enable_3d_clouds",
&cloud_3d_setting_changed, this);
g_settings->deregisterChangedCallback("soft_clouds",
&cloud_3d_setting_changed, this);
}
void Clouds::OnRegisterSceneNode()
@ -134,7 +135,7 @@ void Clouds::updateMesh()
m_last_noise_center = center_of_drawing_in_noise_i;
m_mesh_valid = true;
const u32 num_faces_to_draw = m_enable_3d ? 6 : 1;
const u32 num_faces_to_draw = is3D() ? 6 : 1;
// Colors with primitive shading
@ -143,18 +144,21 @@ void Clouds::updateMesh()
video::SColorf c_side_2_f(m_color);
video::SColorf c_bottom_f(m_color);
if (m_enable_shaders) {
// shader mixes the base color, set via EmissiveColor
// shader mixes the base color, set via ColorParam
c_top_f = c_side_1_f = c_side_2_f = c_bottom_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);
}
c_side_1_f.r *= 0.95f;
c_side_1_f.g *= 0.95f;
c_side_1_f.b *= 0.95f;
c_side_2_f.r *= 0.90f;
c_side_2_f.g *= 0.90f;
c_side_2_f.b *= 0.90f;
c_bottom_f.r *= 0.80f;
c_bottom_f.g *= 0.80f;
c_bottom_f.b *= 0.80f;
video::SColorf shadow = m_params.color_shadow;
c_side_1_f.r *= shadow.r * 0.25f + 0.75f;
c_side_1_f.g *= shadow.g * 0.25f + 0.75f;
c_side_1_f.b *= shadow.b * 0.25f + 0.75f;
c_side_2_f.r *= shadow.r * 0.5f + 0.5f;
c_side_2_f.g *= shadow.g * 0.5f + 0.5f;
c_side_2_f.b *= shadow.b * 0.5f + 0.5f;
c_bottom_f.r *= shadow.r;
c_bottom_f.g *= shadow.g;
c_bottom_f.b *= shadow.b;
video::SColor c_top = c_top_f.toSColor();
video::SColor c_side_1 = c_side_1_f.toSColor();
video::SColor c_side_2 = c_side_2_f.toSColor();
@ -179,21 +183,23 @@ void Clouds::updateMesh()
auto *mb = m_meshbuffer.get();
auto &vertices = mb->Vertices->Data;
auto &indices = mb->Indices->Data;
{
const u32 vertex_count = num_faces_to_draw * 16 * m_cloud_radius_i * m_cloud_radius_i;
const u32 quad_count = vertex_count / 4;
const u32 index_count = quad_count * 6;
// reserve memory
mb->Vertices.reallocate(vertex_count);
mb->Indices.reallocate(index_count);
vertices.reserve(vertex_count);
indices.reserve(index_count);
}
#define GETINDEX(x, z, radius) (((z)+(radius))*(radius)*2 + (x)+(radius))
#define INAREA(x, z, radius) \
((x) >= -(radius) && (x) < (radius) && (z) >= -(radius) && (z) < (radius))
mb->Vertices.set_used(0);
vertices.clear();
for (s16 zi0= -m_cloud_radius_i; zi0 < m_cloud_radius_i; zi0++)
for (s16 xi0= -m_cloud_radius_i; xi0 < m_cloud_radius_i; xi0++)
{
@ -221,16 +227,17 @@ void Clouds::updateMesh()
const f32 rx = cloud_size / 2.0f;
// if clouds are flat, the top layer should be at the given height
const f32 ry = m_enable_3d ? m_params.thickness * BS : 0.0f;
const f32 ry = is3D() ? m_params.thickness * BS : 0.0f;
const f32 rz = cloud_size / 2;
for(u32 i = 0; i < num_faces_to_draw; i++)
bool soft_clouds_enabled = g_settings->getBool("soft_clouds");
for (u32 i = 0; i < num_faces_to_draw; i++)
{
switch(i)
switch (i)
{
case 0: // top
for (video::S3DVertex &vertex : v) {
vertex.Normal.set(0,1,0);
for (video::S3DVertex& vertex : v) {
vertex.Normal.set(0, 1, 0);
}
v[0].Pos.set(-rx, ry,-rz);
v[1].Pos.set(-rx, ry, rz);
@ -240,12 +247,20 @@ void Clouds::updateMesh()
case 1: // back
if (INAREA(xi, zi - 1, m_cloud_radius_i)) {
u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i);
if(m_grid[j])
if (grid[j])
continue;
}
for (video::S3DVertex &vertex : v) {
vertex.Color = c_side_1;
vertex.Normal.set(0,0,-1);
if (soft_clouds_enabled) {
for (video::S3DVertex& vertex : v) {
vertex.Normal.set(0, 0, -1);
}
v[2].Color = c_bottom;
v[3].Color = c_bottom;
} else {
for (video::S3DVertex& vertex : v) {
vertex.Color = c_side_1;
vertex.Normal.set(0, 0, -1);
}
}
v[0].Pos.set(-rx, ry,-rz);
v[1].Pos.set( rx, ry,-rz);
@ -254,28 +269,45 @@ void Clouds::updateMesh()
break;
case 2: //right
if (INAREA(xi + 1, zi, m_cloud_radius_i)) {
u32 j = GETINDEX(xi+1, zi, m_cloud_radius_i);
if(m_grid[j])
u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i);
if (grid[j])
continue;
}
for (video::S3DVertex &vertex : v) {
vertex.Color = c_side_2;
vertex.Normal.set(1,0,0);
if (soft_clouds_enabled) {
for (video::S3DVertex& vertex : v) {
vertex.Normal.set(1, 0, 0);
}
v[2].Color = c_bottom;
v[3].Color = c_bottom;
}
v[0].Pos.set( rx, ry,-rz);
v[1].Pos.set( rx, ry, rz);
v[2].Pos.set( rx, 0, rz);
v[3].Pos.set( rx, 0,-rz);
else {
for (video::S3DVertex& vertex : v) {
vertex.Color = c_side_2;
vertex.Normal.set(1, 0, 0);
}
}
v[0].Pos.set(rx, ry,-rz);
v[1].Pos.set(rx, ry, rz);
v[2].Pos.set(rx, 0, rz);
v[3].Pos.set(rx, 0,-rz);
break;
case 3: // front
if (INAREA(xi, zi + 1, m_cloud_radius_i)) {
u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i);
if(m_grid[j])
if (grid[j])
continue;
}
for (video::S3DVertex &vertex : v) {
vertex.Color = c_side_1;
vertex.Normal.set(0,0,-1);
if (soft_clouds_enabled) {
for (video::S3DVertex& vertex : v) {
vertex.Normal.set(0, 0, -1);
}
v[2].Color = c_bottom;
v[3].Color = c_bottom;
} else {
for (video::S3DVertex& vertex : v) {
vertex.Color = c_side_1;
vertex.Normal.set(0, 0, -1);
}
}
v[0].Pos.set( rx, ry, rz);
v[1].Pos.set(-rx, ry, rz);
@ -283,14 +315,22 @@ void Clouds::updateMesh()
v[3].Pos.set( rx, 0, rz);
break;
case 4: // left
if (INAREA(xi-1, zi, m_cloud_radius_i)) {
u32 j = GETINDEX(xi-1, zi, m_cloud_radius_i);
if(m_grid[j])
if (INAREA(xi - 1, zi, m_cloud_radius_i)) {
u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i);
if (grid[j])
continue;
}
for (video::S3DVertex &vertex : v) {
vertex.Color = c_side_2;
vertex.Normal.set(-1,0,0);
if (soft_clouds_enabled) {
for (video::S3DVertex& vertex : v) {
vertex.Normal.set(-1, 0, 0);
}
v[2].Color = c_bottom;
v[3].Color = c_bottom;
} else {
for (video::S3DVertex& vertex : v) {
vertex.Color = c_side_2;
vertex.Normal.set(-1, 0, 0);
}
}
v[0].Pos.set(-rx, ry, rz);
v[1].Pos.set(-rx, ry,-rz);
@ -298,9 +338,9 @@ void Clouds::updateMesh()
v[3].Pos.set(-rx, 0, rz);
break;
case 5: // bottom
for (video::S3DVertex &vertex : v) {
for (video::S3DVertex& vertex : v) {
vertex.Color = c_bottom;
vertex.Normal.set(0,-1,0);
vertex.Normal.set(0, -1, 0);
}
v[0].Pos.set( rx, 0, rz);
v[1].Pos.set(-rx, 0, rz);
@ -313,7 +353,7 @@ void Clouds::updateMesh()
for (video::S3DVertex &vertex : v) {
vertex.Pos += pos;
mb->Vertices.push_back(vertex);
vertices.push_back(vertex);
}
}
}
@ -323,18 +363,18 @@ void Clouds::updateMesh()
const u32 index_count = quad_count * 6;
// rewrite index array as needed
if (mb->getIndexCount() > index_count) {
mb->Indices.set_used(index_count);
indices.resize(index_count);
mb->setDirty(scene::EBT_INDEX);
} else if (mb->getIndexCount() < index_count) {
const u32 start = mb->getIndexCount() / 6;
assert(start * 6 == mb->getIndexCount());
for (u32 k = start; k < quad_count; k++) {
mb->Indices.push_back(4 * k + 0);
mb->Indices.push_back(4 * k + 1);
mb->Indices.push_back(4 * k + 2);
mb->Indices.push_back(4 * k + 2);
mb->Indices.push_back(4 * k + 3);
mb->Indices.push_back(4 * k + 0);
indices.push_back(4 * k + 0);
indices.push_back(4 * k + 1);
indices.push_back(4 * k + 2);
indices.push_back(4 * k + 2);
indices.push_back(4 * k + 3);
indices.push_back(4 * k + 0);
}
mb->setDirty(scene::EBT_INDEX);
}
@ -364,9 +404,9 @@ void Clouds::render()
updateAbsolutePosition();
}
m_material.BackfaceCulling = m_enable_3d;
m_material.BackfaceCulling = is3D();
if (m_enable_shaders)
m_material.EmissiveColor = m_color.toSColor();
m_material.ColorParam = m_color.toSColor();
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
driver->setMaterial(m_material);
@ -441,7 +481,7 @@ void Clouds::update(const v3f &camera_p, const video::SColorf &color_diffuse)
// is the camera inside the cloud mesh?
m_camera_pos = camera_p;
m_camera_inside_cloud = false; // default
if (m_enable_3d) {
if (is3D()) {
float camera_height = camera_p.Y - BS * m_camera_offset.Y;
if (camera_height >= m_box.MinEdge.Y &&
camera_height <= m_box.MaxEdge.Y) {

View file

@ -19,20 +19,28 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_bloated.h"
#include "constants.h"
#include "irr_ptr.h"
#include "irrlichttypes_extrabloated.h"
#include "skyparams.h"
#include <iostream>
#include <ISceneNode.h>
#include <SMaterial.h>
#include <SMeshBuffer.h>
class IShaderSource;
// Menu clouds
class Clouds;
extern Clouds *g_menuclouds;
namespace irr::scene
{
class ISceneManager;
}
// Scene manager used for menu clouds
// Menu clouds
// The mainmenu and the loading screen use the same Clouds object so that the
// clouds don't jump when switching between the two.
class Clouds;
extern scene::ISceneManager *g_menucloudsmgr;
extern Clouds *g_menuclouds;
class Clouds : public scene::ISceneNode
{
@ -107,6 +115,14 @@ public:
m_params.color_ambient = color_ambient;
}
void setColorShadow(video::SColor color_shadow)
{
if (m_params.color_shadow == color_shadow)
return;
m_params.color_shadow = color_shadow;
invalidateMesh();
}
void setHeight(float height)
{
if (m_params.height == height)
@ -157,8 +173,8 @@ private:
{
float height_bs = m_params.height * BS;
float thickness_bs = m_params.thickness * BS;
m_box = aabb3f(-BS * 1000000.0f, height_bs - BS * m_camera_offset.Y, -BS * 1000000.0f,
BS * 1000000.0f, height_bs + thickness_bs - BS * m_camera_offset.Y, BS * 1000000.0f);
m_box = aabb3f(-BS * 1000000.0f, height_bs, -BS * 1000000.0f,
BS * 1000000.0f, height_bs + thickness_bs, BS * 1000000.0f);
}
void updateMesh();
@ -169,7 +185,10 @@ private:
bool gridFilled(int x, int y) const;
video::ITexture *m_density_texture = nullptr;
// Are the clouds 3D?
inline bool is3D() const {
return m_enable_3d && m_params.thickness >= 0.01f;
}
video::SMaterial m_material;
irr_ptr<scene::SMeshBuffer> m_meshbuffer;

View file

@ -186,6 +186,12 @@ static bool logOnce(const std::ostringstream &from, std::ostream &log_to)
return true;
}
static void setColorParam(scene::ISceneNode *node, video::SColor color)
{
for (u32 i = 0; i < node->getMaterialCount(); ++i)
node->getMaterial(i).ColorParam = color;
}
/*
TestCAO
*/
@ -255,7 +261,6 @@ void TestCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
u16 indices[] = {0,1,2,2,3,0};
buf->append(vertices, 4, indices, 6);
// Set material
buf->getMaterial().Lighting = false;
buf->getMaterial().BackfaceCulling = false;
buf->getMaterial().TextureLayers[0].Texture = tsrc->getTextureForMesh("rat.png");
buf->getMaterial().TextureLayers[0].MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
@ -385,7 +390,7 @@ void GenericCAO::processInitData(const std::string &data)
if (m_is_player) {
// Check if it's the current player
LocalPlayer *player = m_env->getLocalPlayer();
if (player && strcmp(player->getName(), m_name.c_str()) == 0) {
if (player && player->getName() == m_name) {
m_is_local_player = true;
m_is_visible = false;
player->setCAO(this);
@ -465,7 +470,7 @@ scene::IAnimatedMeshSceneNode *GenericCAO::getAnimatedMeshSceneNode() const
void GenericCAO::setChildrenVisible(bool toset)
{
for (u16 cao_id : m_attachment_child_ids) {
for (object_t cao_id : m_attachment_child_ids) {
GenericCAO *obj = m_env->getGenericCAO(cao_id);
if (obj) {
// Check if the entity is forced to appear in first person.
@ -474,10 +479,10 @@ void GenericCAO::setChildrenVisible(bool toset)
}
}
void GenericCAO::setAttachment(int parent_id, const std::string &bone,
void GenericCAO::setAttachment(object_t parent_id, const std::string &bone,
v3f position, v3f rotation, bool force_visible)
{
int old_parent = m_attachment_parent_id;
const auto old_parent = m_attachment_parent_id;
m_attachment_parent_id = parent_id;
m_attachment_bone = bone;
m_attachment_position = position;
@ -509,7 +514,7 @@ void GenericCAO::setAttachment(int parent_id, const std::string &bone,
}
}
void GenericCAO::getAttachment(int *parent_id, std::string *bone, v3f *position,
void GenericCAO::getAttachment(object_t *parent_id, std::string *bone, v3f *position,
v3f *rotation, bool *force_visible) const
{
*parent_id = m_attachment_parent_id;
@ -523,29 +528,21 @@ void GenericCAO::clearChildAttachments()
{
// Cannot use for-loop here: setAttachment() modifies 'm_attachment_child_ids'!
while (!m_attachment_child_ids.empty()) {
int child_id = *m_attachment_child_ids.begin();
const auto child_id = *m_attachment_child_ids.begin();
if (ClientActiveObject *child = m_env->getActiveObject(child_id))
child->setAttachment(0, "", v3f(), v3f(), false);
removeAttachmentChild(child_id);
if (auto *child = m_env->getActiveObject(child_id))
child->clearParentAttachment();
else
removeAttachmentChild(child_id);
}
}
void GenericCAO::clearParentAttachment()
{
if (m_attachment_parent_id)
setAttachment(0, "", m_attachment_position, m_attachment_rotation, false);
else
setAttachment(0, "", v3f(), v3f(), false);
}
void GenericCAO::addAttachmentChild(int child_id)
void GenericCAO::addAttachmentChild(object_t child_id)
{
m_attachment_child_ids.insert(child_id);
}
void GenericCAO::removeAttachmentChild(int child_id)
void GenericCAO::removeAttachmentChild(object_t child_id)
{
m_attachment_child_ids.erase(child_id);
}
@ -650,12 +647,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
auto setMaterial = [this] (video::SMaterial &mat) {
mat.MaterialType = m_material_type;
mat.Lighting = false;
mat.FogEnable = true;
if (m_enable_shaders) {
mat.GouraudShading = false;
mat.NormalizeNormals = true;
}
mat.forEachTexture([] (auto &tex) {
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
tex.MagFilter = video::ETMAGF_NEAREST;
@ -712,7 +704,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
// Set material
setMaterial(buf->getMaterial());
if (m_enable_shaders) {
buf->getMaterial().EmissiveColor = c;
buf->getMaterial().ColorParam = c;
}
// Add to mesh
@ -738,7 +730,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
// Set material
setMaterial(buf->getMaterial());
if (m_enable_shaders) {
buf->getMaterial().EmissiveColor = c;
buf->getMaterial().ColorParam = c;
}
// Add to mesh
@ -782,8 +774,6 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
// set vertex colors to ensure alpha is set
setMeshColor(m_animated_meshnode->getMesh(), video::SColor(0xFFFFFFFF));
setAnimatedMeshColor(m_animated_meshnode, video::SColor(0xFFFFFFFF));
setSceneNodeMaterials(m_animated_meshnode);
m_animated_meshnode->forEachMaterial([this] (auto &mat) {
@ -818,15 +808,21 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
}
/* Set VBO hint */
// - if shaders are disabled we modify the mesh often
// - sprites are also modified often
// - the wieldmesh sets its own hint
// - bone transformations do not need to modify the vertex data
// wieldmesh sets its own hint, no need to handle it
if (m_enable_shaders && (m_meshnode || m_animated_meshnode)) {
if (m_meshnode)
// sprite uses vertex animation
if (m_meshnode && m_prop.visual != "upright_sprite")
m_meshnode->getMesh()->setHardwareMappingHint(scene::EHM_STATIC);
if (m_animated_meshnode)
m_animated_meshnode->getMesh()->setHardwareMappingHint(scene::EHM_STATIC);
if (m_animated_meshnode) {
auto *mesh = m_animated_meshnode->getMesh();
// skinning happens on the CPU
if (m_animated_meshnode->getJointCount() > 0)
mesh->setHardwareMappingHint(scene::EHM_STREAM, scene::EBT_VERTEX);
else
mesh->setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX);
mesh->setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_INDEX);
}
}
/* don't update while punch texture modifier is active */
@ -852,14 +848,19 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr)
if (m_animated_meshnode) {
u32 mat_count = m_animated_meshnode->getMaterialCount();
assert(mat_count == m_animated_meshnode->getMesh()->getMeshBufferCount());
u32 max_tex_idx = 0;
for (u32 i = 0; i < mat_count; ++i) {
max_tex_idx = std::max(max_tex_idx,
m_animated_meshnode->getMesh()->getTextureSlot(i));
}
if (mat_count == 0 || m_prop.textures.empty()) {
// nothing
} else if (mat_count > m_prop.textures.size()) {
} else if (max_tex_idx >= m_prop.textures.size()) {
std::ostringstream oss;
oss << "GenericCAO::addToScene(): Model "
<< m_prop.mesh << " loaded with " << mat_count
<< " mesh buffers but only " << m_prop.textures.size()
<< " texture(s) specified, this is deprecated.";
<< m_prop.mesh << " is missing " << (max_tex_idx + 1 - m_prop.textures.size())
<< " more texture(s), this is deprecated.";
logOnce(oss, warningstream);
video::ITexture *last = m_animated_meshnode->getMaterial(0).TextureLayers[0].Texture;
@ -926,26 +927,15 @@ void GenericCAO::setNodeLight(const video::SColor &light_color)
}
if (m_enable_shaders) {
if (m_prop.visual == "upright_sprite") {
if (!m_meshnode)
return;
for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i)
m_meshnode->getMaterial(i).EmissiveColor = light_color;
} else {
scene::ISceneNode *node = getSceneNode();
if (!node)
return;
for (u32 i = 0; i < node->getMaterialCount(); ++i) {
video::SMaterial &material = node->getMaterial(i);
material.EmissiveColor = light_color;
}
}
auto *node = getSceneNode();
if (!node)
return;
setColorParam(node, light_color);
} else {
if (m_meshnode) {
setMeshColor(m_meshnode->getMesh(), light_color);
} else if (m_animated_meshnode) {
setAnimatedMeshColor(m_animated_meshnode, light_color);
setMeshColor(m_animated_meshnode->getMesh(), light_color);
} else if (m_spritenode) {
m_spritenode->setColor(light_color);
}
@ -1267,6 +1257,16 @@ void GenericCAO::step(float dtime, ClientEnvironment *env)
}
}
static void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count)
{
assert(buf->getVertexType() == video::EVT_STANDARD);
assert(buf->getVertexCount() == count);
auto *vertices = static_cast<video::S3DVertex *>(buf->getVertices());
for (u32 i = 0; i < count; i++)
vertices[i].TCoords = uv[i];
buf->setDirty(scene::EBT_VERTEX);
}
void GenericCAO::updateTexturePos()
{
if(m_spritenode)
@ -1360,15 +1360,6 @@ void GenericCAO::updateTextures(std::string mod)
material.MaterialTypeParam = m_material_type_param;
material.setTexture(0, tsrc->getTextureForMesh(texturestring));
// This allows setting per-material colors. However, until a real lighting
// system is added, the code below will have no effect. Once MineTest
// has directional lighting, it should work automatically.
if (!m_prop.colors.empty()) {
material.AmbientColor = m_prop.colors[0];
material.DiffuseColor = m_prop.colors[0];
material.SpecularColor = m_prop.colors[0];
}
material.forEachTexture([=] (auto &tex) {
setMaterialFilters(tex, use_bilinear_filter, use_trilinear_filter,
use_anisotropic_filter);
@ -1378,9 +1369,11 @@ void GenericCAO::updateTextures(std::string mod)
else if (m_animated_meshnode) {
if (m_prop.visual == "mesh") {
for (u32 i = 0; i < m_prop.textures.size() &&
i < m_animated_meshnode->getMaterialCount(); ++i) {
std::string texturestring = m_prop.textures[i];
for (u32 i = 0; i < m_animated_meshnode->getMaterialCount(); ++i) {
const auto texture_idx = m_animated_meshnode->getMesh()->getTextureSlot(i);
if (texture_idx >= m_prop.textures.size())
continue;
std::string texturestring = m_prop.textures[texture_idx];
if (texturestring.empty())
continue; // Empty texture string means don't modify that material
texturestring += mod;
@ -1395,7 +1388,6 @@ void GenericCAO::updateTextures(std::string mod)
material.MaterialType = m_material_type;
material.MaterialTypeParam = m_material_type_param;
material.TextureLayers[0].Texture = texture;
material.Lighting = true;
material.BackfaceCulling = m_prop.backface_culling;
// don't filter low-res textures, makes them look blurry
@ -1410,17 +1402,6 @@ void GenericCAO::updateTextures(std::string mod)
use_anisotropic_filter);
});
}
for (u32 i = 0; i < m_prop.colors.size() &&
i < m_animated_meshnode->getMaterialCount(); ++i)
{
video::SMaterial &material = m_animated_meshnode->getMaterial(i);
// This allows setting per-material colors. However, until a real lighting
// system is added, the code below will have no effect. Once MineTest
// has directional lighting, it should work automatically.
material.AmbientColor = m_prop.colors[i];
material.DiffuseColor = m_prop.colors[i];
material.SpecularColor = m_prop.colors[i];
}
}
}
@ -1438,20 +1419,9 @@ void GenericCAO::updateTextures(std::string mod)
video::SMaterial &material = m_meshnode->getMaterial(i);
material.MaterialType = m_material_type;
material.MaterialTypeParam = m_material_type_param;
material.Lighting = false;
material.setTexture(0, tsrc->getTextureForMesh(texturestring));
material.getTextureMatrix(0).makeIdentity();
// This allows setting per-material colors. However, until a real lighting
// system is added, the code below will have no effect. Once MineTest
// has directional lighting, it should work automatically.
if(m_prop.colors.size() > i)
{
material.AmbientColor = m_prop.colors[i];
material.DiffuseColor = m_prop.colors[i];
material.SpecularColor = m_prop.colors[i];
}
material.forEachTexture([=] (auto &tex) {
setMaterialFilters(tex, use_bilinear_filter, use_trilinear_filter,
use_anisotropic_filter);
@ -1468,15 +1438,6 @@ void GenericCAO::updateTextures(std::string mod)
auto &material = m_meshnode->getMaterial(0);
material.setTexture(0, tsrc->getTextureForMesh(tname));
// This allows setting per-material colors. However, until a real lighting
// system is added, the code below will have no effect. Once MineTest
// has directional lighting, it should work automatically.
if(!m_prop.colors.empty()) {
material.AmbientColor = m_prop.colors[0];
material.DiffuseColor = m_prop.colors[0];
material.SpecularColor = m_prop.colors[0];
}
material.forEachTexture([=] (auto &tex) {
setMaterialFilters(tex, use_bilinear_filter, use_trilinear_filter,
use_anisotropic_filter);
@ -1493,19 +1454,6 @@ void GenericCAO::updateTextures(std::string mod)
auto &material = m_meshnode->getMaterial(1);
material.setTexture(0, tsrc->getTextureForMesh(tname));
// This allows setting per-material colors. However, until a real lighting
// system is added, the code below will have no effect. Once MineTest
// has directional lighting, it should work automatically.
if (m_prop.colors.size() >= 2) {
material.AmbientColor = m_prop.colors[1];
material.DiffuseColor = m_prop.colors[1];
material.SpecularColor = m_prop.colors[1];
} else if (!m_prop.colors.empty()) {
material.AmbientColor = m_prop.colors[0];
material.DiffuseColor = m_prop.colors[0];
material.SpecularColor = m_prop.colors[0];
}
material.forEachTexture([=] (auto &tex) {
setMaterialFilters(tex, use_bilinear_filter, use_trilinear_filter,
use_anisotropic_filter);
@ -1526,9 +1474,8 @@ void GenericCAO::updateAnimation()
if (!m_animated_meshnode)
return;
if (m_animated_meshnode->getStartFrame() != m_animation_range.X ||
m_animated_meshnode->getEndFrame() != m_animation_range.Y)
m_animated_meshnode->setFrameLoop(m_animation_range.X, m_animation_range.Y);
// Note: This sets the current frame as well, (re)starting the animation.
m_animated_meshnode->setFrameLoop(m_animation_range.X, m_animation_range.Y);
if (m_animated_meshnode->getAnimationSpeed() != m_animation_speed)
m_animated_meshnode->setAnimationSpeed(m_animation_speed);
m_animated_meshnode->setTransitionTime(m_animation_blend);

View file

@ -106,8 +106,8 @@ private:
// stores position and rotation for each bone name
BoneOverrideMap m_bone_override;
int m_attachment_parent_id = 0;
std::unordered_set<int> m_attachment_child_ids;
object_t m_attachment_parent_id = 0;
std::unordered_set<object_t> m_attachment_child_ids;
std::string m_attachment_bone = "";
v3f m_attachment_position;
v3f m_attachment_rotation;
@ -226,16 +226,15 @@ public:
}
void setChildrenVisible(bool toset);
void setAttachment(int parent_id, const std::string &bone, v3f position,
void setAttachment(object_t parent_id, const std::string &bone, v3f position,
v3f rotation, bool force_visible) override;
void getAttachment(int *parent_id, std::string *bone, v3f *position,
void getAttachment(object_t *parent_id, std::string *bone, v3f *position,
v3f *rotation, bool *force_visible) const override;
void clearChildAttachments() override;
void clearParentAttachment() override;
void addAttachmentChild(int child_id) override;
void removeAttachmentChild(int child_id) override;
void addAttachmentChild(object_t child_id) override;
void removeAttachmentChild(object_t child_id) override;
ClientActiveObject *getParent() const override;
const std::unordered_set<int> &getAttachmentChildIds() const override
const std::unordered_set<object_t> &getAttachmentChildIds() const override
{ return m_attachment_child_ids; }
void updateAttachments() override;

View file

@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_cso.h"
#include <IBillboardSceneNode.h>
#include <ISceneManager.h>
#include "client/texturesource.h"
#include "clientenvironment.h"
#include "client.h"
@ -39,7 +40,6 @@ public:
video::ITexture *tex = env->getGameDef()->tsrc()->getTextureForMesh("smoke_puff.png");
m_spritenode->forEachMaterial([tex] (auto &mat) {
mat.TextureLayers[0].Texture = tex;
mat.Lighting = false;
mat.TextureLayers[0].MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
mat.TextureLayers[0].MagFilter = video::ETMAGF_NEAREST;
mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;

View file

@ -19,8 +19,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes_bloated.h"
#include "clientsimpleobject.h"
namespace irr::scene
{
class ISceneManager;
}
ClientSimpleObject* createSmokePuff(scene::ISceneManager *smgr,
ClientEnvironment *env, v3f pos, v2f size);

View file

@ -19,8 +19,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <cmath>
#include "content_mapblock.h"
#include "util/basic_macros.h"
#include "util/numeric.h"
#include "util/directiontables.h"
#include "util/tracy_wrapper.h"
#include "mapblock_mesh.h"
#include "settings.h"
#include "nodedef.h"
@ -81,7 +83,8 @@ MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector
meshmanip(mm),
blockpos_nodes(data->m_blockpos * MAP_BLOCKSIZE),
enable_mesh_cache(g_settings->getBool("enable_mesh_cache") &&
!data->m_smooth_lighting) // Mesh cache is not supported with smooth lighting
!data->m_smooth_lighting), // Mesh cache is not supported with smooth lighting
smooth_liquids(g_settings->getBool("enable_water_reflections"))
{
}
@ -463,6 +466,8 @@ void MapblockMeshGenerator::drawSolidNode()
if (data->m_smooth_lighting) {
LightPair lights[6][4];
for (int face = 0; face < 6; ++face) {
if (mask & (1 << face))
continue;
for (int k = 0; k < 4; k++) {
v3s16 corner = light_dirs[light_indices[face][k]];
lights[face][k] = LightPair(getSmoothLightSolid(
@ -713,7 +718,7 @@ void MapblockMeshGenerator::drawLiquidSides()
if (data->m_smooth_lighting)
cur_node.color = blendLightColor(pos);
pos += cur_node.origin;
vertices[j] = video::S3DVertex(pos.X, pos.Y, pos.Z, 0, 0, 0, cur_node.color, vertex.u, v);
vertices[j] = video::S3DVertex(pos.X, pos.Y, pos.Z, face.dir.X, face.dir.Y, face.dir.Z, cur_node.color, vertex.u, v);
};
collector->append(cur_liquid.tile, vertices, 4, quad_indices, 6);
}
@ -736,6 +741,19 @@ void MapblockMeshGenerator::drawLiquidTop()
for (int i = 0; i < 4; i++) {
int u = corner_resolve[i][0];
int w = corner_resolve[i][1];
if (smooth_liquids) {
int x = vertices[i].Pos.X > 0;
int z = vertices[i].Pos.Z > 0;
f32 dx = 0.5f * (cur_liquid.neighbors[z][x].level - cur_liquid.neighbors[z][x + 1].level +
cur_liquid.neighbors[z + 1][x].level - cur_liquid.neighbors[z + 1][x + 1].level);
f32 dz = 0.5f * (cur_liquid.neighbors[z][x].level - cur_liquid.neighbors[z + 1][x].level +
cur_liquid.neighbors[z][x + 1].level - cur_liquid.neighbors[z + 1][x + 1].level);
vertices[i].Normal = v3f(dx, 1., dz).normalize();
}
vertices[i].Pos.Y += cur_liquid.corner_levels[w][u] * BS;
if (data->m_smooth_lighting)
vertices[i].Color = blendLightColor(vertices[i].Pos);
@ -775,6 +793,10 @@ void MapblockMeshGenerator::drawLiquidTop()
vertex.TCoords += tcoord_center;
vertex.TCoords += tcoord_translate;
if (!smooth_liquids) {
vertex.Normal = v3f(dx, 1., dz).normalize();
}
}
std::swap(vertices[0].TCoords, vertices[2].TCoords);
@ -1674,7 +1696,9 @@ void MapblockMeshGenerator::drawMeshNode()
int mesh_buffer_count = mesh->getMeshBufferCount();
for (int j = 0; j < mesh_buffer_count; j++) {
useTile(j);
// Only up to 6 tiles are supported
const auto tile = mesh->getTextureSlot(j);
useTile(MYMIN(tile, 5));
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices();
int vertex_count = buf->getVertexCount();
@ -1745,6 +1769,8 @@ void MapblockMeshGenerator::drawNode()
void MapblockMeshGenerator::generate()
{
ZoneScoped;
for (cur_node.p.Z = 0; cur_node.p.Z < data->side_length; cur_node.p.Z++)
for (cur_node.p.Y = 0; cur_node.p.Y < data->side_length; cur_node.p.Y++)
for (cur_node.p.X = 0; cur_node.p.X < data->side_length; cur_node.p.X++) {

View file

@ -134,6 +134,7 @@ private:
f32 corner_levels[2][2];
};
LiquidData cur_liquid;
bool smooth_liquids = false;
void prepareLiquidNodeDrawing();
void getLiquidNeighborhood();

View file

@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filecache.h"
#include "network/networkprotocol.h"
#include "log.h"
#include "filesys.h"
#include <string>

View file

@ -59,7 +59,7 @@ FontEngine::FontEngine(gui::IGUIEnvironment* env) :
"mono_font_path", "mono_font_path_bold", "mono_font_path_italic",
"mono_font_path_bold_italic",
"fallback_font_path",
"screen_dpi", "gui_scaling",
"dpi_change_notifier", "gui_scaling",
};
for (auto name : settings)

View file

@ -40,7 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content/subgames.h"
#include "client/event_manager.h"
#include "fontengine.h"
#include "gui/touchscreengui.h"
#include "gui/touchcontrols.h"
#include "itemdef.h"
#include "log.h"
#include "filesys.h"
@ -79,6 +79,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "hud.h"
#include "clientdynamicinfo.h"
#include <IAnimatedMeshSceneNode.h>
#include "util/tracy_wrapper.h"
#if USE_SOUND
#include "client/sound/sound_openal.h"
@ -185,7 +186,7 @@ struct LocalFormspecHandler : public TextDest
assert(m_client != nullptr);
if (fields.find("quit") != fields.end())
m_client->sendRespawn();
m_client->sendRespawnLegacy();
return;
}
@ -535,6 +536,10 @@ public:
float camera_far = m_client->getCamera()->getCameraNode()->getFarValue();
m_camera_far_pixel.set(&camera_far, services);
v3f camera_position = m_client->getCamera()->getPosition();
m_camera_position_pixel.set(camera_position, services);
m_camera_position_pixel.set(camera_position, services);
SamplerLayer_t tex_id;
tex_id = 0;
m_texture0.set(&tex_id, services);
@ -659,7 +664,8 @@ public:
m_client(client)
{}
void setSky(Sky *sky) {
void setSky(Sky *sky)
{
m_sky = sky;
for (GameGlobalShaderConstantSetter *ggscs : created_nosky) {
ggscs->setSky(m_sky);
@ -894,7 +900,7 @@ private:
bool disable_camera_update = false;
};
void showDeathFormspec();
void showDeathFormspecLegacy();
void showPauseMenu();
void pauseAnimation();
@ -904,7 +910,7 @@ private:
void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_DeathscreenLegacy(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HandleParticleEvent(ClientEvent *event,
@ -954,11 +960,11 @@ private:
QuicktuneShortcutter *quicktune = nullptr;
std::unique_ptr<GameUI> m_game_ui;
GUIChatConsole *gui_chat_console = nullptr; // Free using ->Drop()
irr_ptr<GUIChatConsole> gui_chat_console;
MapDrawControl *draw_control = nullptr;
Camera *camera = nullptr;
Clouds *clouds = nullptr; // Free using ->Drop()
Sky *sky = nullptr; // Free using ->Drop()
irr_ptr<Clouds> clouds;
irr_ptr<Sky> sky;
Hud *hud = nullptr;
Minimap *mapper = nullptr;
@ -1205,6 +1211,8 @@ bool Game::startup(bool *kill,
void Game::run()
{
ZoneScoped;
ProfilerGraph graph;
RunStats stats = {};
CameraOrientation cam_view_target = {};
@ -1232,15 +1240,21 @@ void Game::run()
const bool initial_window_maximized = !g_settings->getBool("fullscreen") &&
g_settings->getBool("window_maximized");
auto framemarker = FrameMarker("Game::run()-frame").started();
while (m_rendering_engine->run()
&& !(*kill || g_gamecallback->shutdown_requested
|| (server && server->isShutdownRequested()))) {
framemarker.end();
// Calculate dtime =
// m_rendering_engine->run() from this iteration
// + Sleep time until the wanted FPS are reached
draw_times.limit(device, &dtime, g_menumgr.pausesGame());
framemarker.start();
const auto current_dynamic_info = ClientDynamicInfo::getCurrent();
if (!current_dynamic_info.equal(client_display_info)) {
client_display_info = current_dynamic_info;
@ -1297,6 +1311,8 @@ void Game::run()
}
}
framemarker.end();
RenderingEngine::autosaveScreensizeAndCo(initial_screen_size, initial_window_maximized);
}
@ -1310,21 +1326,18 @@ void Game::shutdown()
// Clear text when exiting.
m_game_ui->clearText();
if (g_touchscreengui)
g_touchscreengui->hide();
if (g_touchcontrols)
g_touchcontrols->hide();
// only if the shutdown progress bar isn't shown yet
if (m_shutdown_progress == 0.0f)
showOverlayMessage(N_("Shutting down..."), 0, 0);
if (clouds)
clouds->drop();
clouds.reset();
if (gui_chat_console)
gui_chat_console->drop();
gui_chat_console.reset();
if (sky)
sky->drop();
sky.reset();
/* cleanup menus */
while (g_menumgr.menuCount() > 0) {
@ -1511,7 +1524,7 @@ void Game::copyServerClientCache()
{
// It would be possible to let the client directly read the media files
// from where the server knows they are. But aside from being more complicated
// it would also *not* fill the media cache and cause slower joining of
// it would also *not* fill the media cache and cause slower joining of
// remote servers.
// (Imagine that you launch a game once locally and then connect to a server.)
@ -1575,20 +1588,16 @@ bool Game::createClient(const GameStartData &start_data)
client->getScript()->on_camera_ready(camera);
client->setCamera(camera);
if (g_touchscreengui) {
g_touchscreengui->setUseCrosshair(!isTouchCrosshairDisabled());
}
/* Clouds
*/
if (m_cache_enable_clouds)
clouds = new Clouds(smgr, shader_src, -1, rand());
clouds = make_irr<Clouds>(smgr, shader_src, -1, rand());
client->setClouds(clouds);
/* Skybox
*/
sky = new Sky(-1, m_rendering_engine, texture_src, shader_src);
scsf->setSky(sky);
sky = make_irr<Sky>(-1, m_rendering_engine, texture_src, shader_src);
scsf->setSky(sky.get());
/* Pre-calculated values
*/
@ -1641,11 +1650,13 @@ bool Game::initGui()
chat_backend->applySettings();
// Chat backend and console
gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(),
gui_chat_console = make_irr<GUIChatConsole>(guienv, guienv->getRootGUIElement(),
-1, chat_backend, client, &g_menumgr);
if (g_settings->getBool("enable_touch"))
g_touchscreengui = new TouchScreenGUI(device, texture_src);
if (g_settings->getBool("touch_controls")) {
g_touchcontrols = new TouchControls(device, texture_src);
g_touchcontrols->setUseCrosshair(!isTouchCrosshairDisabled());
}
return true;
}
@ -1739,9 +1750,13 @@ bool Game::connectToServer(const GameStartData &start_data,
fps_control.reset();
auto framemarker = FrameMarker("Game::connectToServer()-frame").started();
while (m_rendering_engine->run()) {
framemarker.end();
fps_control.limit(device, &dtime);
framemarker.start();
// Update client and server
step(dtime);
@ -1787,6 +1802,7 @@ bool Game::connectToServer(const GameStartData &start_data,
// Update status
showOverlayMessage(N_("Connecting to server..."), dtime, 20);
}
framemarker.end();
} catch (con::PeerNotFoundException &e) {
warningstream << "This should not happen. Please report a bug." << std::endl;
return false;
@ -1804,9 +1820,11 @@ bool Game::getServerContent(bool *aborted)
fps_control.reset();
auto framemarker = FrameMarker("Game::getServerContent()-frame").started();
while (m_rendering_engine->run()) {
framemarker.end();
fps_control.limit(device, &dtime);
framemarker.start();
// Update client and server
step(dtime);
@ -1872,6 +1890,7 @@ bool Game::getServerContent(bool *aborted)
texture_src, dtime, progress);
}
}
framemarker.end();
*aborted = true;
infostream << "Connect aborted [device]" << std::endl;
@ -1922,26 +1941,26 @@ inline bool Game::handleCallbacks()
}
if (g_gamecallback->changepassword_requested) {
(new GUIPasswordChange(guienv, guiroot, -1,
&g_menumgr, client, texture_src))->drop();
(void)make_irr<GUIPasswordChange>(guienv, guiroot, -1,
&g_menumgr, client, texture_src);
g_gamecallback->changepassword_requested = false;
}
if (g_gamecallback->changevolume_requested) {
(new GUIVolumeChange(guienv, guiroot, -1,
&g_menumgr, texture_src))->drop();
(void)make_irr<GUIVolumeChange>(guienv, guiroot, -1,
&g_menumgr, texture_src);
g_gamecallback->changevolume_requested = false;
}
if (g_gamecallback->keyconfig_requested) {
(new GUIKeyChangeMenu(guienv, guiroot, -1,
&g_menumgr, texture_src))->drop();
(void)make_irr<GUIKeyChangeMenu>(guienv, guiroot, -1,
&g_menumgr, texture_src);
g_gamecallback->keyconfig_requested = false;
}
if (!g_gamecallback->show_open_url_dialog.empty()) {
(new GUIOpenURLMenu(guienv, guiroot, -1,
&g_menumgr, texture_src, g_gamecallback->show_open_url_dialog))->drop();
(void)make_irr<GUIOpenURLMenu>(guienv, guiroot, -1,
&g_menumgr, texture_src, g_gamecallback->show_open_url_dialog);
g_gamecallback->show_open_url_dialog.clear();
}
@ -1980,6 +1999,10 @@ void Game::updateDebugState()
if (!has_debug) {
draw_control->show_wireframe = false;
m_flags.disable_camera_update = false;
auto formspec = m_game_ui->getFormspecGUI();
if (formspec) {
formspec->setDebugView(false);
}
}
// noclip
@ -2015,6 +2038,14 @@ void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times,
g_profiler->graphAdd("Sleep [us]", draw_times.sleep_time);
g_profiler->graphSet("FPS", 1.0f / dtime);
auto stats2 = driver->getFrameStats();
g_profiler->avg("Irr: drawcalls", stats2.Drawcalls);
if (stats2.Drawcalls > 0)
g_profiler->avg("Irr: primitives per drawcall",
stats2.PrimitivesDrawn / float(stats2.Drawcalls));
g_profiler->avg("Irr: buffers uploaded", stats2.HWBuffersUploaded);
g_profiler->avg("Irr: buffers uploaded (bytes)", stats2.HWBuffersUploadedSize);
}
void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
@ -2075,7 +2106,7 @@ void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
void Game::processUserInput(f32 dtime)
{
// Reset input if window not active or some menu is active
if (!device->isWindowActive() || isMenuActive() || guienv->hasFocus(gui_chat_console)) {
if (!device->isWindowActive() || isMenuActive() || guienv->hasFocus(gui_chat_console.get())) {
if (m_game_focused) {
m_game_focused = false;
infostream << "Game lost focus" << std::endl;
@ -2084,21 +2115,21 @@ void Game::processUserInput(f32 dtime)
input->clear();
}
if (g_touchscreengui)
g_touchscreengui->hide();
if (g_touchcontrols)
g_touchcontrols->hide();
} else {
if (g_touchscreengui) {
/* on touchscreengui step may generate own input events which ain't
if (g_touchcontrols) {
/* on touchcontrols step may generate own input events which ain't
* what we want in case we just did clear them */
g_touchscreengui->show();
g_touchscreengui->step(dtime);
g_touchcontrols->show();
g_touchcontrols->step(dtime);
}
m_game_focused = true;
}
if (!guienv->hasFocus(gui_chat_console) && gui_chat_console->isOpen()) {
if (!guienv->hasFocus(gui_chat_console.get()) && gui_chat_console->isOpen()) {
gui_chat_console->closeConsoleAtOnce();
}
@ -2250,12 +2281,14 @@ void Game::processItemSelection(u16 *new_playeritem)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
*new_playeritem = player->getWieldIndex();
u16 max_item = player->getMaxHotbarItemcount();
if (max_item == 0)
return;
max_item -= 1;
/* Item selection using mouse wheel
*/
*new_playeritem = player->getWieldIndex();
u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1,
player->hud_hotbar_itemcount - 1);
s32 wheel = input->getMouseWheel();
if (!m_enable_hotbar_mouse_wheel)
wheel = 0;
@ -2285,8 +2318,8 @@ void Game::processItemSelection(u16 *new_playeritem)
}
}
if (g_touchscreengui) {
std::optional<u16> selection = g_touchscreengui->getHotbarSelection();
if (g_touchcontrols) {
std::optional<u16> selection = g_touchcontrols->getHotbarSelection();
if (selection)
*new_playeritem = *selection;
}
@ -2691,7 +2724,7 @@ void Game::updateCameraDirection(CameraOrientation *cam, float dtime)
this results in duplicated input. To avoid that, we don't enable relative
mouse mode if we're in touchscreen mode. */
if (cur_control)
cur_control->setRelativeMode(!g_touchscreengui && !isMenuActive());
cur_control->setRelativeMode(!g_touchcontrols && !isMenuActive());
if ((device->isWindowActive() && device->isWindowFocused()
&& !isMenuActive()) || input->isRandom()) {
@ -2734,9 +2767,9 @@ f32 Game::getSensitivityScaleFactor() const
void Game::updateCameraOrientation(CameraOrientation *cam, float dtime)
{
if (g_touchscreengui) {
cam->camera_yaw += g_touchscreengui->getYawChange();
cam->camera_pitch += g_touchscreengui->getPitchChange();
if (g_touchcontrols) {
cam->camera_yaw += g_touchcontrols->getYawChange();
cam->camera_pitch += g_touchcontrols->getPitchChange();
} else {
v2s32 center(driver->getScreenSize().Width / 2, driver->getScreenSize().Height / 2);
v2s32 dist = input->getMousePos() - center;
@ -2801,7 +2834,7 @@ void Game::updatePlayerControl(const CameraOrientation &cam)
* touch then its meaning is inverted (i.e. holding aux1 means walk and
* not fast)
*/
if (g_touchscreengui && m_touch_simulate_aux1) {
if (g_touchcontrols && m_touch_simulate_aux1) {
control.aux1 = control.aux1 ^ true;
}
@ -2827,6 +2860,8 @@ void Game::updatePauseState()
inline void Game::step(f32 dtime)
{
ZoneScoped;
if (server) {
float fps_max = (!device->isWindowFocused() || g_menumgr.pausesGame()) ?
g_settings->getFloat("fps_max_unfocused") :
@ -2883,7 +2918,7 @@ const ClientEventHandler Game::clientEventHandler[CLIENTEVENT_MAX] = {
{&Game::handleClientEvent_None},
{&Game::handleClientEvent_PlayerDamage},
{&Game::handleClientEvent_PlayerForceMove},
{&Game::handleClientEvent_Deathscreen},
{&Game::handleClientEvent_DeathscreenLegacy},
{&Game::handleClientEvent_ShowFormSpec},
{&Game::handleClientEvent_ShowLocalFormSpec},
{&Game::handleClientEvent_HandleParticleEvent},
@ -2939,20 +2974,9 @@ void Game::handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientati
cam->camera_pitch = event->player_force_move.pitch;
}
void Game::handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam)
void Game::handleClientEvent_DeathscreenLegacy(ClientEvent *event, CameraOrientation *cam)
{
// If client scripting is enabled, deathscreen is handled by CSM code in
// builtin/client/init.lua
if (client->modsLoaded())
client->getScript()->on_death();
else
showDeathFormspec();
/* Handle visualization */
LocalPlayer *player = client->getEnv().getLocalPlayer();
runData.damage_flash = 0;
player->hurt_tilt_timer = 0;
player->hurt_tilt_strength = 0;
showDeathFormspecLegacy();
}
void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam)
@ -3219,6 +3243,7 @@ void Game::handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *
clouds->setDensity(event->cloud_params.density);
clouds->setColorBright(video::SColor(event->cloud_params.color_bright));
clouds->setColorAmbient(video::SColor(event->cloud_params.color_ambient));
clouds->setColorShadow(video::SColor(event->cloud_params.color_shadow));
clouds->setHeight(event->cloud_params.height);
clouds->setThickness(event->cloud_params.thickness);
clouds->setSpeed(v2f(event->cloud_params.speed_x, event->cloud_params.speed_y));
@ -3290,8 +3315,8 @@ void Game::updateCamera(f32 dtime)
camera->toggleCameraMode();
if (g_touchscreengui)
g_touchscreengui->setUseCrosshair(!isTouchCrosshairDisabled());
if (g_touchcontrols)
g_touchcontrols->setUseCrosshair(!isTouchCrosshairDisabled());
// Make the player visible depending on camera mode.
playercao->updateMeshCulling();
@ -3392,8 +3417,8 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
}
shootline.end = shootline.start + camera_direction * BS * d;
if (g_touchscreengui && isTouchCrosshairDisabled()) {
shootline = g_touchscreengui->getShootline();
if (g_touchcontrols && isTouchCrosshairDisabled()) {
shootline = g_touchcontrols->getShootline();
// Scale shootline to the acual distance the player can reach
shootline.end = shootline.start +
shootline.getVector().normalize() * BS * d;
@ -3410,9 +3435,13 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
if (pointed != runData.pointed_old)
infostream << "Pointing at " << pointed.dump() << std::endl;
if (g_touchscreengui) {
auto mode = selected_def.touch_interaction.getMode(pointed.type);
g_touchscreengui->applyContextControls(mode);
if (g_touchcontrols) {
auto mode = selected_def.touch_interaction.getMode(selected_def, pointed.type);
g_touchcontrols->applyContextControls(mode);
// applyContextControls may change dig/place input.
// Update again so that TOSERVER_INTERACT packets have the correct controls set.
player->control.dig = isKeyDown(KeyType::DIG);
player->control.place = isKeyDown(KeyType::PLACE);
}
// Note that updating the selection mesh every frame is not particularly efficient,
@ -4049,8 +4078,12 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
runData.nodig_delay_timer =
runData.dig_time_complete / (float)crack_animation_length;
// Don't add a corresponding delay to very time consuming nodes.
runData.nodig_delay_timer = std::min(runData.nodig_delay_timer, 0.3f);
// We don't want a corresponding delay to very time consuming nodes
// and nodes without digging time (e.g. torches) get a fixed delay.
if (runData.nodig_delay_timer > 0.3f)
runData.nodig_delay_timer = 0.3f;
else if (runData.dig_instantly)
runData.nodig_delay_timer = 0.15f;
// Ensure that the delay between breaking nodes
// (dig_time_complete + nodig_delay_timer) is at least the
@ -4098,6 +4131,7 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
const CameraOrientation &cam)
{
ZoneScoped;
TimeTaker tt_update("Game::updateFrame()");
LocalPlayer *player = client->getEnv().getLocalPlayer();
@ -4242,7 +4276,8 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
updateShadows();
}
m_game_ui->update(*stats, client, draw_control, cam, runData.pointed_old, gui_chat_console, dtime);
m_game_ui->update(*stats, client, draw_control, cam, runData.pointed_old,
gui_chat_console.get(), dtime);
/*
make sure menu is on top
@ -4340,7 +4375,9 @@ void Game::updateShadows()
float timeoftheday = getWickedTimeOfDay(in_timeofday);
bool is_day = timeoftheday > 0.25 && timeoftheday < 0.75;
bool is_shadow_visible = is_day ? sky->getSunVisible() : sky->getMoonVisible();
shadow->setShadowIntensity(is_shadow_visible ? client->getEnv().getLocalPlayer()->getLighting().shadow_intensity : 0.0f);
const auto &lighting = client->getEnv().getLocalPlayer()->getLighting();
shadow->setShadowIntensity(is_shadow_visible ? lighting.shadow_intensity : 0.0f);
shadow->setShadowTint(lighting.shadow_tint);
timeoftheday = std::fmod(timeoftheday + 0.75f, 0.5f) + 0.25f;
const float offset_constant = 10000.0f;
@ -4357,6 +4394,8 @@ void Game::updateShadows()
void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
{
ZoneScoped;
const video::SColor fog_color = this->sky->getFogColor();
const video::SColor sky_color = this->sky->getSkyColor();
@ -4399,7 +4438,7 @@ void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
(this->camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT));
if (g_touchscreengui && isTouchCrosshairDisabled())
if (g_touchcontrols && isTouchCrosshairDisabled())
draw_crosshair = false;
this->m_rendering_engine->draw_scene(sky_color, this->m_game_ui->m_flags.show_hud,
@ -4454,8 +4493,8 @@ void Game::readSettings()
m_cache_enable_fog = g_settings->getBool("enable_fog");
m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity", 0.001f, 10.0f);
m_cache_joystick_frustum_sensitivity = std::max(g_settings->getFloat("joystick_frustum_sensitivity"), 0.001f);
m_repeat_place_time = g_settings->getFloat("repeat_place_time", 0.15f, 2.0f);
m_repeat_dig_time = g_settings->getFloat("repeat_dig_time", 0.15f, 2.0f);
m_repeat_place_time = g_settings->getFloat("repeat_place_time", 0.16f, 2.0f);
m_repeat_dig_time = g_settings->getFloat("repeat_dig_time", 0.0f, 2.0f);
m_cache_enable_noclip = g_settings->getBool("noclip");
m_cache_enable_free_move = g_settings->getBool("free_move");
@ -4482,7 +4521,7 @@ void Game::readSettings()
****************************************************************************/
/****************************************************************************/
void Game::showDeathFormspec()
void Game::showDeathFormspecLegacy()
{
static std::string formspec_str =
std::string("formspec_version[1]") +
@ -4510,7 +4549,7 @@ void Game::showPauseMenu()
{
std::string control_text;
if (g_touchscreengui) {
if (g_touchcontrols) {
control_text = strgettext("Controls:\n"
"No menu open:\n"
"- slide finger: look around\n"

View file

@ -23,10 +23,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <gettext.h>
#include "gui/mainmenumanager.h"
#include "gui/guiChatConsole.h"
#include "gui/guiFormSpecMenu.h"
#include "gui/touchcontrols.h"
#include "util/enriched_string.h"
#include "util/pointedthing.h"
#include "client.h"
#include "clientmap.h"
#include "fontengine.h"
#include "hud.h" // HUD_FLAG_*
#include "nodedef.h"
#include "profiler.h"
#include "renderingengine.h"
@ -188,16 +192,27 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_
}
}
setStaticText(m_guitext_status, m_statustext.c_str());
m_guitext_status->setVisible(!m_statustext.empty());
IGUIStaticText *guitext_status;
bool overriden = g_touchcontrols && g_touchcontrols->isStatusTextOverriden();
if (overriden) {
guitext_status = g_touchcontrols->getStatusText();
m_guitext_status->setVisible(false);
} else {
guitext_status = m_guitext_status;
if (g_touchcontrols)
g_touchcontrols->getStatusText()->setVisible(false);
}
setStaticText(guitext_status, m_statustext.c_str());
guitext_status->setVisible(!m_statustext.empty());
if (!m_statustext.empty()) {
s32 status_width = m_guitext_status->getTextWidth();
s32 status_height = m_guitext_status->getTextHeight();
s32 status_y = screensize.Y - 150;
s32 status_width = guitext_status->getTextWidth();
s32 status_height = guitext_status->getTextHeight();
s32 status_y = screensize.Y - (overriden ? 15 : 150);
s32 status_x = (screensize.X - status_width) / 2;
m_guitext_status->setRelativePosition(core::rect<s32>(status_x ,
guitext_status->setRelativePosition(core::rect<s32>(status_x ,
status_y - status_height, status_x + status_width, status_y));
// Fade out
@ -205,8 +220,8 @@ void GameUI::update(const RunStats &stats, Client *client, MapDrawControl *draw_
final_color.setAlpha(0);
video::SColor fade_color = m_statustext_initial_color.getInterpolated_quadratic(
m_statustext_initial_color, final_color, m_statustext_time / statustext_time_max);
m_guitext_status->setOverrideColor(fade_color);
m_guitext_status->enableOverrideColor(true);
guitext_status->setOverrideColor(fade_color);
guitext_status->enableOverrideColor(true);
}
// Hide chat when disabled by server or when console is visible

View file

@ -22,15 +22,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h"
#include <IGUIEnvironment.h>
#include "gui/guiFormSpecMenu.h"
#include "util/enriched_string.h"
#include "util/pointedthing.h"
#include "game.h"
using namespace irr;
class Client;
class EnrichedString;
class GUIChatConsole;
class GUIFormSpecMenu;
struct MapDrawControl;
struct PointedThing;
/*
* This object intend to contain the core UI elements

View file

@ -23,6 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h"
#include <cstdio>
#include "client/renderingengine.h"
#include <IImage.h>
#include <ITexture.h>
#include <IVideoDriver.h>
/* Maintain a static cache to store the images that correspond to textures
* in a format that's manipulable by code. Some platforms exhibit issues

View file

@ -18,7 +18,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes.h"
#include <path.h>
#include <rect.h>
#include <SColor.h>
namespace irr::video
{
class IImage;
class ITexture;
class IVideoDriver;
}
/* Manually insert an image into the cache, useful to avoid texture-to-image
* conversion whenever we can intercept it.

View file

@ -39,7 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "wieldmesh.h"
#include "client/renderingengine.h"
#include "client/minimap.h"
#include "gui/touchscreengui.h"
#include "gui/touchcontrols.h"
#include "util/enriched_string.h"
#include "irrlicht_changes/CGUITTFont.h"
@ -60,6 +60,7 @@ Hud::Hud(Client *client, LocalPlayer *player,
this->inventory = inventory;
readScalingSetting();
g_settings->registerChangedCallback("dpi_change_notifier", setting_changed_callback, this);
g_settings->registerChangedCallback("hud_scaling", setting_changed_callback, this);
for (auto &hbar_color : hbar_colors)
@ -96,7 +97,8 @@ Hud::Hud(Client *client, LocalPlayer *player,
m_mode = HIGHLIGHT_BOX;
}
m_selection_material.Lighting = false;
// Initialize m_selection_material
if (g_settings->getBool("enable_shaders")) {
IShaderSource *shdrsrc = client->getShaderSource();
@ -117,28 +119,42 @@ Hud::Hud(Client *client, LocalPlayer *player,
m_selection_material.MaterialType = video::EMT_SOLID;
}
// Initialize m_block_bounds_material
if (g_settings->getBool("enable_shaders")) {
IShaderSource *shdrsrc = client->getShaderSource();
auto shader_id = shdrsrc->getShader("default_shader", TILE_MATERIAL_ALPHA);
m_block_bounds_material.MaterialType = shdrsrc->getShaderInfo(shader_id).material;
} else {
m_block_bounds_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
}
m_block_bounds_material.Thickness =
rangelim(g_settings->getS16("selectionbox_width"), 1, 5);
// Prepare mesh for compass drawing
m_rotation_mesh_buffer.Vertices.set_used(4);
m_rotation_mesh_buffer.Indices.set_used(6);
m_rotation_mesh_buffer.reset(new scene::SMeshBuffer());
auto *b = m_rotation_mesh_buffer.get();
auto &vertices = b->Vertices->Data;
auto &indices = b->Indices->Data;
vertices.resize(4);
indices.resize(6);
video::SColor white(255, 255, 255, 255);
v3f normal(0.f, 0.f, 1.f);
m_rotation_mesh_buffer.Vertices[0] = video::S3DVertex(v3f(-1.f, -1.f, 0.f), normal, white, v2f(0.f, 1.f));
m_rotation_mesh_buffer.Vertices[1] = video::S3DVertex(v3f(-1.f, 1.f, 0.f), normal, white, v2f(0.f, 0.f));
m_rotation_mesh_buffer.Vertices[2] = video::S3DVertex(v3f( 1.f, 1.f, 0.f), normal, white, v2f(1.f, 0.f));
m_rotation_mesh_buffer.Vertices[3] = video::S3DVertex(v3f( 1.f, -1.f, 0.f), normal, white, v2f(1.f, 1.f));
vertices[0] = video::S3DVertex(v3f(-1.f, -1.f, 0.f), normal, white, v2f(0.f, 1.f));
vertices[1] = video::S3DVertex(v3f(-1.f, 1.f, 0.f), normal, white, v2f(0.f, 0.f));
vertices[2] = video::S3DVertex(v3f( 1.f, 1.f, 0.f), normal, white, v2f(1.f, 0.f));
vertices[3] = video::S3DVertex(v3f( 1.f, -1.f, 0.f), normal, white, v2f(1.f, 1.f));
m_rotation_mesh_buffer.Indices[0] = 0;
m_rotation_mesh_buffer.Indices[1] = 1;
m_rotation_mesh_buffer.Indices[2] = 2;
m_rotation_mesh_buffer.Indices[3] = 2;
m_rotation_mesh_buffer.Indices[4] = 3;
m_rotation_mesh_buffer.Indices[5] = 0;
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 2;
indices[4] = 3;
indices[5] = 0;
m_rotation_mesh_buffer.getMaterial().Lighting = false;
m_rotation_mesh_buffer.getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
m_rotation_mesh_buffer.setHardwareMappingHint(scene::EHM_STATIC);
b->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
b->setHardwareMappingHint(scene::EHM_STATIC);
}
void Hud::readScalingSetting()
@ -153,6 +169,7 @@ void Hud::readScalingSetting()
Hud::~Hud()
{
g_settings->deregisterChangedCallback("dpi_change_notifier", setting_changed_callback, this);
g_settings->deregisterChangedCallback("hud_scaling", setting_changed_callback, this);
if (m_selection_mesh)
@ -238,7 +255,7 @@ void Hud::drawItem(const ItemStack &item, const core::rect<s32>& rect,
// NOTE: selectitem = 0 -> no selected; selectitem is 1-based
// mainlist can be NULL, but draw the frame anyway.
void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
void Hud::drawItems(v2s32 screen_pos, v2s32 screen_offset, s32 itemcount, v2f alignment,
s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction,
bool is_hotbar)
{
@ -251,9 +268,11 @@ void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
width = tmp;
}
// Position of upper left corner of bar
v2s32 pos = screen_offset * m_scale_factor;
pos += upperleftpos;
// Position: screen_pos + screen_offset + alignment
v2s32 pos(screen_offset.X * m_scale_factor, screen_offset.Y * m_scale_factor);
pos += screen_pos;
pos.X += (alignment.X - 1.0f) * (width * 0.5f);
pos.Y += (alignment.Y - 1.0f) * (height * 0.5f);
// Store hotbar_image in member variable, used by drawItem()
if (hotbar_image != player->hotbar_image) {
@ -305,8 +324,8 @@ void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
drawItem(mainlist->getItem(i), item_rect, (i + 1) == selectitem);
if (is_hotbar && g_touchscreengui)
g_touchscreengui->registerHotbarRect(i, item_rect);
if (is_hotbar && g_touchcontrols)
g_touchcontrols->registerHotbarRect(i, item_rect);
}
}
@ -351,13 +370,20 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
std::vector<HudElement*> elems;
elems.reserve(player->maxHudId());
// Add builtin minimap if the server doesn't send it.
// Add builtin elements if the server doesn't send them.
// Declared here such that they have the same lifetime as the elems vector
HudElement minimap;
HudElement hotbar;
if (client->getProtoVersion() < 44 && (player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE)) {
minimap = {HUD_ELEM_MINIMAP, v2f(1, 0), "", v2f(), "", 0 , 0, 0, v2f(-1, 1),
v2f(-10, 10), v3f(), v2s32(256, 256), 0, "", 0};
elems.push_back(&minimap);
}
if (client->getProtoVersion() < 46 && player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
hotbar = {HUD_ELEM_HOTBAR, v2f(0.5, 1), "", v2f(), "", 0 , 0, 0, v2f(0, -1),
v2f(0, -4), v3f(), v2s32(), 0, "", 0};
elems.push_back(&hotbar);
}
for (size_t i = 0; i != player->maxHudId(); i++) {
HudElement *e = player->getHud(i);
@ -432,7 +458,7 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
InventoryList *inv = inventory->getList(e->text);
if (!inv)
warningstream << "HUD: Unknown inventory list. name=" << e->text << std::endl;
drawItems(pos, v2s32(e->offset.X, e->offset.Y), e->number, 0,
drawItems(pos, v2s32(e->offset.X, e->offset.Y), e->number, e->align, 0,
inv, e->item, e->dir, false);
break; }
case HUD_ELEM_WAYPOINT: {
@ -542,14 +568,21 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
}
break; }
case HUD_ELEM_MINIMAP: {
if (e->size.X <= 0 || e->size.Y <= 0)
break;
if (!client->getMinimap())
break;
// Draw a minimap of size "size"
v2s32 dstsize(e->size.X * m_scale_factor,
e->size.Y * m_scale_factor);
// (no percent size as minimap would likely be anamorphosed)
// Only one percentage is supported to avoid distortion.
if (e->size.X < 0)
dstsize.X = dstsize.Y = m_screensize.X * (e->size.X * -0.01);
else if (e->size.Y < 0)
dstsize.X = dstsize.Y = m_screensize.Y * (e->size.Y * -0.01);
if (dstsize.X <= 0 || dstsize.Y <= 0)
return;
v2s32 offset((e->align.X - 1.0) * dstsize.X / 2,
(e->align.Y - 1.0) * dstsize.Y / 2);
core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y);
@ -557,6 +590,9 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
e->offset.Y * m_scale_factor);
client->getMinimap()->drawMinimap(rect);
break; }
case HUD_ELEM_HOTBAR: {
drawHotbar(pos, e->offset, e->dir, e->align);
break; }
default:
infostream << "Hud::drawLuaElements: ignoring drawform " << e->type
<< " due to unrecognized type" << std::endl;
@ -620,10 +656,10 @@ void Hud::drawCompassRotate(HudElement *e, video::ITexture *texture,
driver->setTransform(video::ETS_VIEW, core::matrix4());
driver->setTransform(video::ETS_WORLD, Matrix);
video::SMaterial &material = m_rotation_mesh_buffer.getMaterial();
auto &material = m_rotation_mesh_buffer->getMaterial();
material.TextureLayers[0].Texture = texture;
driver->setMaterial(material);
driver->drawMeshBuffer(&m_rotation_mesh_buffer);
driver->drawMeshBuffer(m_rotation_mesh_buffer.get());
driver->setTransform(video::ETS_WORLD, core::matrix4());
driver->setTransform(video::ETS_VIEW, oldViewMat);
@ -766,12 +802,10 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir,
}
}
}
void Hud::drawHotbar(u16 playeritem)
void Hud::drawHotbar(const v2s32 &pos, const v2f &offset, u16 dir, const v2f &align)
{
if (g_touchscreengui)
g_touchscreengui->resetHotbarRects();
if (g_touchcontrols)
g_touchcontrols->resetHotbarRects();
InventoryList *mainlist = inventory->getList("main");
if (mainlist == NULL) {
@ -779,30 +813,30 @@ void Hud::drawHotbar(u16 playeritem)
return;
}
u16 playeritem = player->getWieldIndex();
v2s32 screen_offset(offset.X, offset.Y);
v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y);
s32 hotbar_itemcount = player->hud_hotbar_itemcount;
s32 hotbar_itemcount = player->getMaxHotbarItemcount();
s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2);
v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3);
const v2u32 &window_size = RenderingEngine::getWindowSize();
if ((float) width / (float) window_size.X <=
g_settings->getFloat("hud_hotbar_max_width")) {
if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
drawItems(pos, v2s32(0, 0), hotbar_itemcount, 0, mainlist, playeritem + 1, 0, true);
}
drawItems(pos, screen_offset, hotbar_itemcount, align, 0,
mainlist, playeritem + 1, dir, true);
} else {
pos.X += width/4;
v2s32 firstpos = pos;
firstpos.X += width/4;
v2s32 secondpos = pos;
pos = pos - v2s32(0, m_hotbar_imagesize + m_padding);
v2s32 secondpos = firstpos;
firstpos = firstpos - v2s32(0, m_hotbar_imagesize + m_padding);
if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
drawItems(pos, v2s32(0, 0), hotbar_itemcount / 2, 0,
mainlist, playeritem + 1, 0, true);
drawItems(secondpos, v2s32(0, 0), hotbar_itemcount,
hotbar_itemcount / 2, mainlist, playeritem + 1, 0, true);
}
drawItems(firstpos, screen_offset, hotbar_itemcount / 2, align, 0,
mainlist, playeritem + 1, dir, true);
drawItems(secondpos, screen_offset, hotbar_itemcount, align,
hotbar_itemcount / 2, mainlist, playeritem + 1, dir, true);
}
}
@ -931,33 +965,57 @@ void Hud::drawBlockBounds()
}
video::SMaterial old_material = driver->getMaterial2D();
driver->setMaterial(m_selection_material);
driver->setMaterial(m_block_bounds_material);
u16 mesh_chunk_size = std::max<u16>(1, g_settings->getU16("client_mesh_chunk"));
v3s16 pos = player->getStandingNodePos();
v3s16 blockPos(
v3s16 block_pos(
floorf((float) pos.X / MAP_BLOCKSIZE),
floorf((float) pos.Y / MAP_BLOCKSIZE),
floorf((float) pos.Z / MAP_BLOCKSIZE)
);
v3f offset = intToFloat(client->getCamera()->getOffset(), BS);
v3f cam_offset = intToFloat(client->getCamera()->getOffset(), BS);
s8 radius = m_block_bounds_mode == BLOCK_BOUNDS_NEAR ? 2 : 0;
v3f half_node = v3f(BS, BS, BS) / 2.0f;
v3f base_corner = intToFloat(block_pos * MAP_BLOCKSIZE, BS) - cam_offset - half_node;
v3f halfNode = v3f(BS, BS, BS) / 2.0f;
s16 radius = m_block_bounds_mode == BLOCK_BOUNDS_NEAR ?
rangelim(g_settings->getU16("show_block_bounds_radius_near"), 0, 1000) : 0;
for (s8 x = -radius; x <= radius; x++)
for (s8 y = -radius; y <= radius; y++)
for (s8 z = -radius; z <= radius; z++) {
v3s16 blockOffset(x, y, z);
for (s16 x = -radius; x <= radius + 1; x++)
for (s16 y = -radius; y <= radius + 1; y++) {
// Red for mesh chunk edges, yellow for other block edges.
auto choose_color = [&](s16 x_base, s16 y_base) {
// See also MeshGrid::isMeshPos().
// If the block is mesh pos, it means it's at the (-,-,-) corner of
// the mesh. And we're drawing a (-,-) edge of this block. Hence,
// it is an edge of the mesh grid.
return (x + x_base) % mesh_chunk_size == 0
&& (y + y_base) % mesh_chunk_size == 0 ?
video::SColor(255, 255, 0, 0) :
video::SColor(255, 255, 255, 0);
};
aabb3f box(
intToFloat((blockPos + blockOffset) * MAP_BLOCKSIZE, BS) - offset - halfNode,
intToFloat(((blockPos + blockOffset) * MAP_BLOCKSIZE) + (MAP_BLOCKSIZE - 1), BS) - offset + halfNode
v3f pmin = v3f(x, y, -radius) * MAP_BLOCKSIZE * BS;
v3f pmax = v3f(x, y, 1 + radius) * MAP_BLOCKSIZE * BS;
driver->draw3DLine(
base_corner + v3f(pmin.X, pmin.Y, pmin.Z),
base_corner + v3f(pmax.X, pmax.Y, pmax.Z),
choose_color(block_pos.X, block_pos.Y)
);
driver->draw3DLine(
base_corner + v3f(pmin.X, pmin.Z, pmin.Y),
base_corner + v3f(pmax.X, pmax.Z, pmax.Y),
choose_color(block_pos.X, block_pos.Z)
);
driver->draw3DLine(
base_corner + v3f(pmin.Z, pmin.X, pmin.Y),
base_corner + v3f(pmax.Z, pmax.X, pmax.Y),
choose_color(block_pos.Y, block_pos.Z)
);
driver->draw3DBox(box, video::SColor(255, 255, 0, 0));
}
driver->setMaterial(old_material);
@ -1144,7 +1202,6 @@ void drawItemStack(
video::SMaterial &material = buf->getMaterial();
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
material.Lighting = false;
driver->setMaterial(material);
driver->drawMeshBuffer(buf);
}

View file

@ -22,6 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <vector>
#include <IGUIFont.h>
#include <SMaterial.h>
#include <SMeshBuffer.h>
#include "irr_ptr.h"
#include "irr_aabb3d.h"
#include "../hud.h"
@ -32,6 +35,17 @@ class InventoryList;
class LocalPlayer;
struct ItemStack;
namespace irr::scene
{
class IMesh;
}
namespace irr::video
{
class ITexture;
class IVideoDriver;
}
class Hud
{
public:
@ -63,7 +77,7 @@ public:
void disableBlockBounds();
void drawBlockBounds();
void drawHotbar(u16 playeritem);
void drawHotbar(const v2s32 &pos, const v2f &offset, u16 direction, const v2f &align);
void resizeHotbar();
void drawCrosshair();
void drawSelectionMesh();
@ -99,7 +113,7 @@ private:
const std::string &texture, const std::string& bgtexture,
s32 count, s32 maxcount, v2s32 offset, v2s32 size = v2s32());
void drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
void drawItems(v2s32 screen_pos, v2s32 screen_offset, s32 itemcount, v2f alignment,
s32 inv_offset, InventoryList *mainlist, u16 selectitem,
u16 direction, bool is_hotbar);
@ -137,8 +151,9 @@ private:
v3f m_selected_face_normal;
video::SMaterial m_selection_material;
video::SMaterial m_block_bounds_material;
scene::SMeshBuffer m_rotation_mesh_buffer;
irr_ptr<scene::SMeshBuffer> m_rotation_mesh_buffer;
enum
{

View file

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <cassert>
#include <vector>
#include <algorithm>
#include <IVideoDriver.h>
// Simple 2D bitmap class with just the functionality needed here
class Bitmap {

View file

@ -18,7 +18,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes.h"
#include <rect.h>
namespace irr::video
{
class IVideoDriver;
class IImage;
}
/* Fill in RGB values for transparent pixels, to correct for odd colors
* appearing at borders when blending. This is because many PNG optimizers

View file

@ -371,14 +371,12 @@ void blitBaseImage(video::IImage* &src, video::IImage* &dst)
namespace {
/** Calculate the color of a single pixel drawn on top of another pixel without
* gamma correction
/** Calculate the result of the overlay texture modifier (`^`) for a single
* pixel
*
* The color mixing is a little more complicated than just
* video::SColor::getInterpolated because getInterpolated does not handle alpha
* correctly.
* For example, a pixel with alpha=64 drawn atop a pixel with alpha=128 should
* yield a pixel with alpha=160, while getInterpolated would yield alpha=96.
* This is not alpha blending if both src and dst are semi-transparent. The
* reason this is that an old implementation did it wrong, and fixing it would
* break backwards compatibility (see #14847).
*
* \tparam overlay If enabled, only modify dst_col if it is fully opaque
* \param src_col Color of the top pixel
@ -420,12 +418,11 @@ void blit_pixel(video::SColor src_col, video::SColor &dst_col)
return;
}
// A semi-transparent pixel is on top of a
// semi-transparent pixel -> general alpha compositing
u16 a_new_255 = src_a * 255 + (255 - src_a) * dst_a;
dst.r = (dst.r * (255 - src_a) * dst_a + src.r * src_a * 255) / a_new_255;
dst.g = (dst.g * (255 - src_a) * dst_a + src.g * src_a * 255) / a_new_255;
dst.b = (dst.b * (255 - src_a) * dst_a + src.b * src_a * 255) / a_new_255;
dst_a = (a_new_255 + 127) / 255;
// semi-transparent pixel -> weird overlaying
dst.r = (dst.r * (255 - src_a) + src.r * src_a) / 255;
dst.g = (dst.g * (255 - src_a) + src.g * src_a) / 255;
dst.b = (dst.b * (255 - src_a) + src.b * src_a) / 255;
dst_a = dst_a + (255 - dst_a) * src_a * src_a / (255 * 255);
dst_col.set(dst_a, dst.r, dst.g, dst.b);
}
@ -1911,7 +1908,8 @@ video::IImage* ImageSource::generateImage(std::string_view name,
video::IImage *tmp = generateImage(name2, source_image_names);
if (!tmp) {
errorstream << "generateImage(): "
"Failed to generate \"" << name2 << "\""
"Failed to generate \"" << name2 << "\"\n"
"part of texture \"" << name << "\""
<< std::endl;
return NULL;
}
@ -1926,7 +1924,8 @@ video::IImage* ImageSource::generateImage(std::string_view name,
} else if (!generateImagePart(last_part_of_name, baseimg, source_image_names)) {
// Generate image according to part of name
errorstream << "generateImage(): "
"Failed to generate \"" << last_part_of_name << "\""
"Failed to generate \"" << last_part_of_name << "\"\n"
"part of texture \"" << name << "\""
<< std::endl;
}

View file

@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h"
#include "inputhandler.h"
#include "gui/mainmenumanager.h"
#include "gui/touchscreengui.h"
#include "gui/touchcontrols.h"
#include "hud.h"
void KeyCache::populate_nonchanging()
@ -94,7 +94,6 @@ void KeyCache::populate()
handler->listenForKey(k);
}
handler->listenForKey(EscapeKey);
handler->listenForKey(CancelKey);
}
}
@ -114,13 +113,28 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
return true;
}
if (event.EventType == EET_APPLICATION_EVENT &&
event.ApplicationEvent.EventType == EAET_DPI_CHANGED) {
// This is a fake setting so that we can use (de)registerChangedCallback
// not only to listen for gui/hud_scaling changes, but also for DPI changes.
g_settings->setU16("dpi_change_notifier",
g_settings->getU16("dpi_change_notifier") + 1);
return true;
}
// This is separate from other keyboard handling so that it also works in menus.
if (event.EventType == EET_KEY_INPUT_EVENT) {
const KeyPress keyCode(event.KeyInput);
if (keyCode == getKeySetting("keymap_fullscreen")) {
if (event.KeyInput.PressedDown && !fullscreen_is_down) {
bool fullscreen = RenderingEngine::get_raw_device()->isFullscreen();
g_settings->setBool("fullscreen", !fullscreen);
IrrlichtDevice *device = RenderingEngine::get_raw_device();
bool new_fullscreen = !device->isFullscreen();
// Only update the setting if toggling succeeds - it always fails
// if Minetest was built without SDL.
if (device->setFullscreen(new_fullscreen)) {
g_settings->setBool("fullscreen", new_fullscreen);
}
}
fullscreen_is_down = event.KeyInput.PressedDown;
return true;
@ -129,8 +143,8 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
// Let the menu handle events, if one is active.
if (isMenuActive()) {
if (g_touchscreengui)
g_touchscreengui->setVisible(false);
if (g_touchcontrols)
g_touchcontrols->setVisible(false);
return g_menumgr.preprocessEvent(event);
}
@ -154,9 +168,9 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
return true;
}
} else if (g_touchscreengui && event.EventType == irr::EET_TOUCH_INPUT_EVENT) {
// In case of touchscreengui, we have to handle different events
g_touchscreengui->translateEvent(event);
} else if (g_touchcontrols && event.EventType == irr::EET_TOUCH_INPUT_EVENT) {
// In case of touchcontrols, we have to handle different events
g_touchcontrols->translateEvent(event);
return true;
} else if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) {
// joystick may be nullptr if game is launched with '--random-input' parameter
@ -223,8 +237,8 @@ float RealInputHandler::getMovementSpeed()
return 0.0f;
return 1.0f; // If there is a keyboard event, assume maximum speed
}
if (g_touchscreengui && g_touchscreengui->getMovementSpeed())
return g_touchscreengui->getMovementSpeed();
if (g_touchcontrols && g_touchcontrols->getMovementSpeed())
return g_touchcontrols->getMovementSpeed();
return joystick.getMovementSpeed();
}
@ -246,8 +260,8 @@ float RealInputHandler::getMovementDirection()
return std::atan2(x, z);
// `getMovementDirection() == 0` means forward, so we cannot use
// `getMovementDirection()` as a condition.
else if (g_touchscreengui && g_touchscreengui->getMovementSpeed())
return g_touchscreengui->getMovementDirection();
else if (g_touchcontrols && g_touchcontrols->getMovementSpeed())
return g_touchcontrols->getMovementDirection();
return joystick.getMovementDirection();
}

View file

@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes.h"
#include "joystick_controller.h"
#include <list>
#include "keycode.h"
@ -269,11 +269,12 @@ public:
JoystickController joystick;
KeyCache keycache;
};
/*
Separated input handler
Separated input handler implementations
*/
class RealInputHandler : public InputHandler
class RealInputHandler final : public InputHandler
{
public:
RealInputHandler(MyEventReceiver *receiver) : m_receiver(receiver)
@ -309,7 +310,7 @@ public:
virtual bool cancelPressed()
{
return wasKeyDown(KeyType::ESC) || m_receiver->WasKeyDown(CancelKey);
return wasKeyDown(KeyType::ESC);
}
virtual void clearWasKeyPressed()
@ -372,7 +373,7 @@ private:
v2s32 m_mousepos;
};
class RandomInputHandler : public InputHandler
class RandomInputHandler final : public InputHandler
{
public:
RandomInputHandler() = default;

View file

@ -155,6 +155,11 @@ public:
float getMovementDirection();
float getMovementSpeed();
u8 getJoystickId() const
{
return m_joystick_id;
}
f32 doubling_dtime;
private:

View file

@ -348,7 +348,6 @@ const char *KeyPress::name() const
}
const KeyPress EscapeKey("KEY_ESCAPE");
const KeyPress CancelKey("KEY_CANCEL");
const KeyPress LMBKey("KEY_LBUTTON");
const KeyPress MMBKey("KEY_MBUTTON");

View file

@ -66,7 +66,6 @@ protected:
// Global defines for convenience
extern const KeyPress EscapeKey;
extern const KeyPress CancelKey;
extern const KeyPress LMBKey;
extern const KeyPress MMBKey; // Middle Mouse Button

View file

@ -75,7 +75,7 @@ void PlayerSettings::settingsChangedCallback(const std::string &name, void *data
LocalPlayer
*/
LocalPlayer::LocalPlayer(Client *client, const char *name):
LocalPlayer::LocalPlayer(Client *client, const std::string &name):
Player(name, client->idef()),
m_client(client)
{
@ -360,7 +360,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
collisionMoveResult result = collisionMoveSimple(env, m_client,
pos_max_d, m_collisionbox, player_stepheight, dtime,
&position, &m_speed, accel_f);
&position, &m_speed, accel_f, m_cao);
bool could_sneak = control.sneak && !free_move && !in_liquid &&
!is_climbing && physics_override.sneak;
@ -444,7 +444,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
v3f check_pos = position;
check_pos.Y += y_diff * dtime * 22.0f + BS * 0.01f;
if (y_diff < BS * 0.6f || (physics_override.sneak_glitch
&& !collision_check_intersection(env, m_client, m_collisionbox, check_pos))) {
&& !collision_check_intersection(env, m_client, m_collisionbox, check_pos, m_cao))) {
// Smoothen the movement (based on 'position.Y = bmax.Y')
position.Y = std::min(check_pos.Y, bmax.Y);
m_speed.Y = 0.0f;
@ -990,7 +990,7 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
collisionMoveResult result = collisionMoveSimple(env, m_client,
pos_max_d, m_collisionbox, player_stepheight, dtime,
&position, &m_speed, accel_f);
&position, &m_speed, accel_f, m_cao);
// Position was slightly changed; update standing node pos
if (touching_ground)
@ -1254,7 +1254,7 @@ void LocalPlayer::handleAutojump(f32 dtime, Environment *env,
// try at peak of jump, zero step height
collisionMoveResult jump_result = collisionMoveSimple(env, m_client, pos_max_d,
m_collisionbox, 0.0f, dtime, &jump_pos, &jump_speed, v3f(0.0f));
m_collisionbox, 0.0f, dtime, &jump_pos, &jump_speed, v3f(0.0f), m_cao);
// see if we can get a little bit farther horizontally if we had
// jumped

View file

@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h"
#include "settings.h"
#include "lighting.h"
#include <string>
class Client;
class Environment;
@ -63,7 +64,8 @@ private:
class LocalPlayer : public Player
{
public:
LocalPlayer(Client *client, const char *name);
LocalPlayer(Client *client, const std::string &name);
virtual ~LocalPlayer();
// Initialize hp to 0, so that no hearts will be shown if server

View file

@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "minimap.h"
#include "content_mapblock.h"
#include "util/directiontables.h"
#include "util/tracy_wrapper.h"
#include "client/meshgen/collector.h"
#include "client/renderingengine.h"
#include <array>
@ -592,17 +593,11 @@ void MapBlockBspTree::traverse(s32 node, v3f viewpoint, std::vector<s32> &output
PartialMeshBuffer
*/
void PartialMeshBuffer::beforeDraw() const
void PartialMeshBuffer::draw(video::IVideoDriver *driver) const
{
// Patch the indexes in the mesh buffer before draw
m_buffer->Indices = std::move(m_vertex_indexes);
m_buffer->setDirty(scene::EBT_INDEX);
}
void PartialMeshBuffer::afterDraw() const
{
// Take the data back
m_vertex_indexes = m_buffer->Indices.steal();
const auto pType = m_buffer->getPrimitiveType();
driver->drawBuffers(m_buffer->getVertexBuffer(), m_indices.get(),
m_indices->getPrimitiveCount(pType), pType);
}
/*
@ -617,8 +612,10 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
m_last_crack(-1),
m_last_daynight_ratio((u32) -1)
{
ZoneScoped;
for (auto &m : m_mesh)
m = new scene::SMesh();
m = make_irr<scene::SMesh>();
m_enable_shaders = data->m_use_shaders;
auto mesh_grid = client->getMeshGrid();
@ -666,7 +663,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
m_bounding_radius = std::sqrt(collector.m_bounding_radius_sq);
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
scene::SMesh *mesh = (scene::SMesh *)m_mesh[layer];
scene::SMesh *mesh = static_cast<scene::SMesh *>(m_mesh[layer].get());
for(u32 i = 0; i < collector.prebuffers[layer].size(); i++)
{
@ -739,7 +736,6 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
// Create material
video::SMaterial material;
material.Lighting = false;
material.BackfaceCulling = true;
material.FogEnable = true;
material.setTexture(0, p.layer.texture);
@ -752,9 +748,6 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
material.MaterialType = m_shdrsrc->getShaderInfo(
p.layer.shader_id).material;
p.layer.applyMaterialOptionsWithShaders(material);
if (p.layer.normal_texture)
material.setTexture(1, p.layer.normal_texture);
material.setTexture(2, p.layer.flags_texture);
} else {
p.layer.applyMaterialOptions(material);
}
@ -783,12 +776,11 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
}
if (mesh) {
// Use VBO for mesh (this just would set this for ever buffer)
// Use VBO for mesh (this just would set this for every buffer)
mesh->setHardwareMappingHint(scene::EHM_STATIC);
}
}
//std::cout<<"added "<<fastfaces.getSize()<<" faces."<<std::endl;
m_bsp_tree.buildTree(&m_transparent_triangles, data->side_length);
// Check if animation is required for this mesh
@ -801,10 +793,10 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
MapBlockMesh::~MapBlockMesh()
{
size_t sz = 0;
for (scene::IMesh *m : m_mesh) {
for (auto &&m : m_mesh) {
for (u32 i = 0; i < m->getMeshBufferCount(); i++)
sz += m->getMeshBuffer(i)->getSize();
m->drop();
m.reset();
}
for (MinimapMapblock *block : m_minimap_mapblocks)
delete block;
@ -865,11 +857,6 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
const FrameSpec &frame = (*tile.frames)[frameno];
buf->getMaterial().setTexture(0, frame.texture);
if (m_enable_shaders) {
if (frame.normal_texture)
buf->getMaterial().setTexture(1, frame.normal_texture);
buf->getMaterial().setTexture(2, frame.flags_texture);
}
}
// Day-night transition
@ -878,7 +865,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
get_sunlight_color(&day_color, daynight_ratio);
for (auto &daynight_diff : m_daynight_diffs) {
auto *mesh = m_mesh[daynight_diff.first.first];
auto *mesh = m_mesh[daynight_diff.first.first].get();
mesh->setDirty(scene::EBT_VERTEX); // force reload to VBO
scene::IMeshBuffer *buf = mesh->
getMeshBuffer(daynight_diff.first.second);
@ -906,6 +893,7 @@ void MapBlockMesh::updateTransparentBuffers(v3f camera_pos, v3s16 block_pos)
m_bsp_tree.traverse(rel_camera_pos, triangle_refs);
// arrange index sequences into partial buffers
m_transparent_buffers_consolidated = false;
m_transparent_buffers.clear();
scene::SMeshBuffer *current_buffer = nullptr;
@ -930,6 +918,8 @@ void MapBlockMesh::updateTransparentBuffers(v3f camera_pos, v3s16 block_pos)
void MapBlockMesh::consolidateTransparentBuffers()
{
if (m_transparent_buffers_consolidated)
return;
m_transparent_buffers.clear();
scene::SMeshBuffer *current_buffer = nullptr;
@ -952,6 +942,8 @@ void MapBlockMesh::consolidateTransparentBuffers()
if (!current_strain.empty()) {
this->m_transparent_buffers.emplace_back(current_buffer, std::move(current_strain));
}
m_transparent_buffers_consolidated = true;
}
video::SColor encode_light(u16 light, u8 emissive_light)

View file

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include "irr_ptr.h"
#include "util/numeric.h"
#include "client/tile.h"
#include "voxel.h"
@ -144,26 +145,24 @@ private:
*
* Attach alternate `Indices` to an existing mesh buffer, to make it possible to use different
* indices with the same vertex buffer.
*
* Irrlicht does not currently support this: `CMeshBuffer` ties together a single vertex buffer
* and a single index buffer. There's no way to share these between mesh buffers.
*
*/
class PartialMeshBuffer
{
public:
PartialMeshBuffer(scene::SMeshBuffer *buffer, std::vector<u16> &&vertex_indexes) :
m_buffer(buffer), m_vertex_indexes(std::move(vertex_indexes))
{}
PartialMeshBuffer(scene::SMeshBuffer *buffer, std::vector<u16> &&vertex_indices) :
m_buffer(buffer), m_indices(make_irr<scene::SIndexBuffer>())
{
m_indices->Data = std::move(vertex_indices);
m_indices->setHardwareMappingHint(scene::EHM_STATIC);
}
scene::IMeshBuffer *getBuffer() const { return m_buffer; }
const std::vector<u16> &getVertexIndexes() const { return m_vertex_indexes; }
auto *getBuffer() const { return m_buffer; }
void draw(video::IVideoDriver *driver) const;
void beforeDraw() const;
void afterDraw() const;
private:
scene::SMeshBuffer *m_buffer;
mutable std::vector<u16> m_vertex_indexes;
irr_ptr<scene::SIndexBuffer> m_indices;
};
/*
@ -194,12 +193,12 @@ public:
scene::IMesh *getMesh()
{
return m_mesh[0];
return m_mesh[0].get();
}
scene::IMesh *getMesh(u8 layer)
{
return m_mesh[layer];
return m_mesh[layer].get();
}
std::vector<MinimapMapblock*> moveMinimapMapblocks()
@ -243,7 +242,7 @@ private:
TileLayer tile;
};
scene::IMesh *m_mesh[MAX_TILE_LAYERS];
irr_ptr<scene::IMesh> m_mesh[MAX_TILE_LAYERS];
std::vector<MinimapMapblock*> m_minimap_mapblocks;
ITextureSource *m_tsrc;
IShaderSource *m_shdrsrc;
@ -282,6 +281,8 @@ private:
MapBlockBspTree m_bsp_tree;
// Ordered list of references to parts of transparent buffers to draw
std::vector<PartialMeshBuffer> m_transparent_buffers;
// Is m_transparent_buffers currently in consolidated form?
bool m_transparent_buffers_consolidated = false;
};
/*!

View file

@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "mesh.h"
#include "S3DVertex.h"
#include "debug.h"
#include "log.h"
#include <cmath>
@ -33,7 +34,7 @@ inline static void applyShadeFactor(video::SColor& color, float factor)
color.setBlue(core::clamp(core::round32(color.getBlue()*factor), 0, 255));
}
void applyFacesShading(video::SColor &color, const v3f &normal)
void applyFacesShading(video::SColor &color, const v3f normal)
{
/*
Some drawtypes have normals set to (0, 0, 0), this must result in
@ -98,7 +99,6 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale)
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
buf->append(vertices + 4 * i, 4, indices, 6);
// Set default material
buf->getMaterial().Lighting = false;
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
buf->getMaterial().forEachTexture([] (auto &tex) {
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
@ -132,6 +132,7 @@ void scaleMesh(scene::IMesh *mesh, v3f scale)
for (u32 i = 0; i < vertex_count; i++)
((video::S3DVertex *)(vertices + i * stride))->Pos *= scale;
buf->setDirty(scene::EBT_VERTEX);
buf->recalculateBoundingBox();
// calculate total bounding box
@ -160,6 +161,7 @@ void translateMesh(scene::IMesh *mesh, v3f vec)
for (u32 i = 0; i < vertex_count; i++)
((video::S3DVertex *)(vertices + i * stride))->Pos += vec;
buf->setDirty(scene::EBT_VERTEX);
buf->recalculateBoundingBox();
// calculate total bounding box
@ -171,23 +173,17 @@ void translateMesh(scene::IMesh *mesh, v3f vec)
mesh->setBoundingBox(bbox);
}
void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor &color)
void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor color)
{
const u32 stride = getVertexPitchFromType(buf->getVertexType());
u32 vertex_count = buf->getVertexCount();
u8 *vertices = (u8 *) buf->getVertices();
for (u32 i = 0; i < vertex_count; i++)
((video::S3DVertex *) (vertices + i * stride))->Color = color;
buf->setDirty(scene::EBT_VERTEX);
}
void setAnimatedMeshColor(scene::IAnimatedMeshSceneNode *node, const video::SColor &color)
{
for (u32 i = 0; i < node->getMaterialCount(); ++i) {
node->getMaterial(i).EmissiveColor = color;
}
}
void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
void setMeshColor(scene::IMesh *mesh, const video::SColor color)
{
if (mesh == NULL)
return;
@ -197,15 +193,6 @@ void setMeshColor(scene::IMesh *mesh, const video::SColor &color)
setMeshBufferColor(mesh->getMeshBuffer(j), color);
}
void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count)
{
const u32 stride = getVertexPitchFromType(buf->getVertexType());
assert(buf->getVertexCount() >= count);
u8 *vertices = (u8 *) buf->getVertices();
for (u32 i = 0; i < count; i++)
((video::S3DVertex*) (vertices + i * stride))->TCoords = uv[i];
}
template <typename F>
static void applyToMesh(scene::IMesh *mesh, const F &fn)
{
@ -217,6 +204,7 @@ static void applyToMesh(scene::IMesh *mesh, const F &fn)
char *vertices = reinterpret_cast<char *>(buf->getVertices());
for (u32 i = 0; i < vertex_count; i++)
fn(reinterpret_cast<video::S3DVertex *>(vertices + i * stride));
buf->setDirty(scene::EBT_VERTEX);
}
}
@ -233,6 +221,7 @@ void colorizeMeshBuffer(scene::IMeshBuffer *buf, const video::SColor *buffercolo
// Apply shading
applyFacesShading(*vc, vertex->Normal);
}
buf->setDirty(scene::EBT_VERTEX);
}
void setMeshColorByNormalXYZ(scene::IMesh *mesh,
@ -397,8 +386,8 @@ scene::SMesh* cloneMesh(scene::IMesh *src_mesh)
scene::IMeshBuffer *temp_buf = cloneMeshBuffer(
src_mesh->getMeshBuffer(j));
dst_mesh->addMeshBuffer(temp_buf);
dst_mesh->setTextureSlot(j, src_mesh->getTextureSlot(j));
temp_buf->drop();
}
return dst_mesh;
}
@ -411,7 +400,6 @@ scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes,
for (u16 j = 0; j < 6; j++)
{
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
buf->getMaterial().Lighting = false;
buf->getMaterial().forEachTexture([] (auto &tex) {
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
tex.MagFilter = video::ETMAGF_NEAREST;

View file

@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
* Applies shading to a color based on the surface's
* normal vector.
*/
void applyFacesShading(video::SColor &color, const v3f &normal);
void applyFacesShading(video::SColor &color, const v3f normal);
/*
Create a new cube mesh.
@ -52,24 +52,12 @@ void translateMesh(scene::IMesh *mesh, v3f vec);
/*!
* Sets a constant color for all vertices in the mesh buffer.
*/
void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor &color);
void setMeshBufferColor(scene::IMeshBuffer *buf, const video::SColor color);
/*
Set a constant color for all vertices in the mesh
*/
void setMeshColor(scene::IMesh *mesh, const video::SColor &color);
/*
Sets texture coords for vertices in the mesh buffer.
`uv[]` must have `count` elements
*/
void setMeshBufferTextureCoords(scene::IMeshBuffer *buf, const v2f *uv, u32 count);
/*
Set a constant color for an animated mesh
*/
void setAnimatedMeshColor(scene::IAnimatedMeshSceneNode *node, const video::SColor &color);
void setMeshColor(scene::IMesh *mesh, const video::SColor color);
/*!
* Overwrites the color of a mesh buffer.
@ -139,5 +127,5 @@ bool checkMeshNormals(scene::IMesh *mesh);
Set the MinFilter, MagFilter and AnisotropicFilter properties of a texture
layer according to the three relevant boolean values found in the Minetest
settings.
*/
*/
void setMaterialFilters(video::SMaterialLayer &tex, bool bilinear, bool trilinear, bool anisotropic);

View file

@ -24,18 +24,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapblock.h"
#include "map.h"
#include "util/directiontables.h"
#include "porting.h"
static class BlockPlaceholder {
public:
MapNode data[MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE];
// Data placeholder used for copying from non-existent blocks
static struct BlockPlaceholder {
MapNode data[MapBlock::nodecount];
BlockPlaceholder()
{
for (std::size_t i = 0; i < MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE; i++)
for (std::size_t i = 0; i < MapBlock::nodecount; i++)
data[i] = MapNode(CONTENT_IGNORE);
}
} block_placeholder;
/*
QueuedMeshUpdate
*/
@ -225,12 +227,13 @@ void MeshUpdateWorkerThread::doUpdate()
while ((q = m_queue_in->pop())) {
if (m_generation_interval)
sleep_ms(m_generation_interval);
porting::TriggerMemoryTrim();
ScopeProfiler sp(g_profiler, "Client: Mesh making (sum)");
MapBlockMesh *mesh_new = new MapBlockMesh(m_client, q->data, *m_camera_offset);
MeshUpdateResult r;
r.p = q->p;
r.mesh = mesh_new;

View file

@ -201,7 +201,7 @@ Minimap::Minimap(Client *client)
addMode(MINIMAP_TYPE_RADAR, 128);
// Initialize minimap data
data = new MinimapData;
data = std::make_unique<MinimapData>();
data->map_invalidated = true;
data->minimap_shape_round = g_settings->getBool("minimap_shape_round");
@ -209,11 +209,11 @@ Minimap::Minimap(Client *client)
setModeIndex(0);
// Create mesh buffer for minimap
m_meshbuffer = getMinimapMeshBuffer();
m_meshbuffer = createMinimapMeshBuffer();
// Initialize and start thread
m_minimap_update_thread = new MinimapUpdateThread();
m_minimap_update_thread->data = data;
m_minimap_update_thread = std::make_unique<MinimapUpdateThread>();
m_minimap_update_thread->data = data.get();
m_minimap_update_thread->start();
}
@ -222,7 +222,7 @@ Minimap::~Minimap()
m_minimap_update_thread->stop();
m_minimap_update_thread->wait();
m_meshbuffer->drop();
m_meshbuffer.reset();
if (data->minimap_mask_round)
data->minimap_mask_round->drop();
@ -232,12 +232,10 @@ Minimap::~Minimap()
driver->removeTexture(data->texture);
driver->removeTexture(data->heightmap_texture);
for (MinimapMarker *m : m_markers)
delete m;
m_markers.clear();
delete data;
delete m_minimap_update_thread;
data.reset();
m_minimap_update_thread.reset();
}
void Minimap::addBlock(v3s16 pos, MinimapMapblock *data)
@ -552,24 +550,26 @@ v3f Minimap::getYawVec()
return v3f(1.0, 0.0, 1.0);
}
scene::SMeshBuffer *Minimap::getMinimapMeshBuffer()
irr_ptr<scene::SMeshBuffer> Minimap::createMinimapMeshBuffer()
{
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
buf->Vertices.set_used(4);
buf->Indices.set_used(6);
auto buf = make_irr<scene::SMeshBuffer>();
auto &vertices = buf->Vertices->Data;
auto &indices = buf->Indices->Data;
vertices.resize(4);
indices.resize(6);
static const video::SColor c(255, 255, 255, 255);
buf->Vertices[0] = video::S3DVertex(-1, -1, 0, 0, 0, 1, c, 0, 1);
buf->Vertices[1] = video::S3DVertex(-1, 1, 0, 0, 0, 1, c, 0, 0);
buf->Vertices[2] = video::S3DVertex( 1, 1, 0, 0, 0, 1, c, 1, 0);
buf->Vertices[3] = video::S3DVertex( 1, -1, 0, 0, 0, 1, c, 1, 1);
vertices[0] = video::S3DVertex(-1, -1, 0, 0, 0, 1, c, 0, 1);
vertices[1] = video::S3DVertex(-1, 1, 0, 0, 0, 1, c, 0, 0);
vertices[2] = video::S3DVertex( 1, 1, 0, 0, 0, 1, c, 1, 0);
vertices[3] = video::S3DVertex( 1, -1, 0, 0, 0, 1, c, 1, 1);
buf->Indices[0] = 0;
buf->Indices[1] = 1;
buf->Indices[2] = 2;
buf->Indices[3] = 2;
buf->Indices[4] = 3;
buf->Indices[5] = 0;
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 2;
indices[4] = 3;
indices[5] = 0;
buf->setHardwareMappingHint(scene::EHM_STATIC);
return buf;
@ -610,7 +610,6 @@ void Minimap::drawMinimap(core::rect<s32> rect)
tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST;
tex.MagFilter = video::ETMAGF_NEAREST;
});
material.Lighting = false;
material.TextureLayers[0].Texture = minimap_texture;
material.TextureLayers[1].Texture = data->heightmap_texture;
@ -627,7 +626,7 @@ void Minimap::drawMinimap(core::rect<s32> rect)
// Draw minimap
driver->setTransform(video::ETS_WORLD, matrix);
driver->setMaterial(material);
driver->drawMeshBuffer(m_meshbuffer);
driver->drawMeshBuffer(m_meshbuffer.get());
// Draw overlay
video::ITexture *minimap_overlay = data->minimap_shape_round ?
@ -635,7 +634,7 @@ void Minimap::drawMinimap(core::rect<s32> rect)
material.TextureLayers[0].Texture = minimap_overlay;
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
driver->setMaterial(material);
driver->drawMeshBuffer(m_meshbuffer);
driver->drawMeshBuffer(m_meshbuffer.get());
// Draw player marker on minimap
if (data->minimap_shape_round) {
@ -647,8 +646,7 @@ void Minimap::drawMinimap(core::rect<s32> rect)
material.TextureLayers[0].Texture = data->player_marker;
driver->setTransform(video::ETS_WORLD, matrix);
driver->setMaterial(material);
driver->drawMeshBuffer(m_meshbuffer);
driver->drawMeshBuffer(m_meshbuffer);
driver->drawMeshBuffer(m_meshbuffer.get());
// Reset transformations
driver->setTransform(video::ETS_VIEW, oldViewMat);
@ -686,17 +684,17 @@ void Minimap::drawMinimap(core::rect<s32> rect)
}
}
MinimapMarker* Minimap::addMarker(scene::ISceneNode *parent_node)
MinimapMarker *Minimap::addMarker(scene::ISceneNode *parent_node)
{
MinimapMarker *m = new MinimapMarker(parent_node);
m_markers.push_back(m);
return m;
auto m = std::make_unique<MinimapMarker>(parent_node);
auto ret = m.get();
m_markers.push_back(std::move(m));
return ret;
}
void Minimap::removeMarker(MinimapMarker **m)
{
m_markers.remove(*m);
delete *m;
m_markers.remove_if([ptr = *m](const auto &up) { return up.get() == ptr; });
*m = nullptr;
}
@ -710,7 +708,7 @@ void Minimap::updateActiveMarkers()
data->mode.scan_height / 2,
data->mode.map_size / 2);
for (MinimapMarker *marker : m_markers) {
for (auto &&marker : m_markers) {
v3s16 pos = floatToInt(marker->parent_node->getAbsolutePosition() +
cam_offset, BS) - pos_offset;
if (pos.X < 0 || pos.X > data->mode.map_size ||

View file

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "../hud.h"
#include "irrlichttypes_extrabloated.h"
#include "irr_ptr.h"
#include "util/thread.h"
#include "voxel.h"
#include <map>
@ -148,7 +149,7 @@ public:
void blitMinimapPixelsToImageSurface(video::IImage *map_image,
video::IImage *heightmap_image);
scene::SMeshBuffer *getMinimapMeshBuffer();
irr_ptr<scene::SMeshBuffer> createMinimapMeshBuffer();
MinimapMarker* addMarker(scene::ISceneNode *parent_node);
void removeMarker(MinimapMarker **marker);
@ -158,20 +159,20 @@ public:
video::IVideoDriver *driver;
Client* client;
MinimapData *data;
std::unique_ptr<MinimapData> data;
private:
ITextureSource *m_tsrc;
IShaderSource *m_shdrsrc;
const NodeDefManager *m_ndef;
MinimapUpdateThread *m_minimap_update_thread = nullptr;
scene::SMeshBuffer *m_meshbuffer;
std::unique_ptr<MinimapUpdateThread> m_minimap_update_thread;
irr_ptr<scene::SMeshBuffer> m_meshbuffer;
bool m_enable_shaders;
std::vector<MinimapModeDef> m_modes;
size_t m_current_mode_index;
u16 m_surface_mode_scan_height;
f32 m_angle;
std::mutex m_mutex;
std::list<MinimapMarker*> m_markers;
std::list<std::unique_ptr<MinimapMarker>> m_markers;
std::list<v2f> m_active_markers;
};

View file

@ -989,7 +989,6 @@ video::SMaterial ParticleManager::getMaterialForParticle(const ClientParticleTex
video::SMaterial material;
// Texture
material.Lighting = false;
material.BackfaceCulling = false;
material.FogEnable = true;
material.forEachTexture([] (auto &tex) {

View file

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "anaglyph.h"
#include "client/camera.h"
#include <IrrlichtDevice.h>
/// SetColorMaskStep step

View file

@ -21,6 +21,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
namespace irr
{
class IrrlichtDevice;
}
class ShadowRenderer;
class Camera;
class Client;

View file

@ -19,6 +19,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include <IrrlichtDevice.h> // used in all render/*.cpp
#include <IVideoDriver.h> // used in all render/*.cpp
#include <vector>
#include <memory>
@ -31,6 +33,11 @@ class Client;
class Hud;
class ShadowRenderer;
namespace irr::video
{
class IRenderTarget;
}
struct PipelineContext
{
PipelineContext(IrrlichtDevice *_device, Client *_client, Hud *_hud, ShadowRenderer *_shadow_renderer, video::SColor _color, v2u32 _target_size)

View file

@ -61,7 +61,6 @@ void DrawHUD::run(PipelineContext &context)
if (context.draw_crosshair)
context.hud->drawCrosshair();
context.hud->drawHotbar(context.client->getEnv().getLocalPlayer()->getWieldIndex());
context.hud->drawLuaElements(context.client->getCamera()->getOffset());
context.client->getCamera()->drawNametags();
}

View file

@ -36,7 +36,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "inputhandler.h"
#include "gettext.h"
#include "filesys.h"
#include "../gui/guiSkin.h"
#include "irrlicht_changes/static_text.h"
#include "irr_ptr.h"
@ -126,27 +125,6 @@ IShaderConstantSetter *FogShaderConstantSetterFactory::create()
/* Other helpers */
static gui::GUISkin *createSkin(gui::IGUIEnvironment *environment,
gui::EGUI_SKIN_TYPE type, video::IVideoDriver *driver)
{
gui::GUISkin *skin = new gui::GUISkin(type, driver);
gui::IGUIFont *builtinfont = environment->getBuiltInFont();
gui::IGUIFontBitmap *bitfont = nullptr;
if (builtinfont && builtinfont->getType() == gui::EGFT_BITMAP)
bitfont = (gui::IGUIFontBitmap*)builtinfont;
gui::IGUISpriteBank *bank = 0;
skin->setFont(builtinfont);
if (bitfont)
bank = bitfont->getSpriteBank();
skin->setSpriteBank(bank);
return skin;
}
static std::optional<video::E_DRIVER_TYPE> chooseVideoDriver()
{
auto &&configured_name = g_settings->get("video_driver");
@ -250,11 +228,6 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
s_singleton = this;
auto skin = createSkin(m_device->getGUIEnvironment(),
gui::EGST_WINDOWS_METALLIC, driver);
m_device->getGUIEnvironment()->setSkin(skin);
skin->drop();
g_settings->registerChangedCallback("fullscreen", settingChangedCallback, this);
g_settings->registerChangedCallback("window_maximized", settingChangedCallback, this);
}
@ -418,7 +391,6 @@ std::vector<video::E_DRIVER_TYPE> RenderingEngine::getSupportedVideoDrivers()
video::EDT_OPENGL,
video::EDT_OPENGL3,
video::EDT_OGLES2,
video::EDT_OGLES1,
video::EDT_NULL,
};
std::vector<video::E_DRIVER_TYPE> drivers;
@ -454,7 +426,6 @@ const VideoDriverInfo &RenderingEngine::getVideoDriverInfo(irr::video::E_DRIVER_
{(int)video::EDT_NULL, {"null", "NULL Driver"}},
{(int)video::EDT_OPENGL, {"opengl", "OpenGL"}},
{(int)video::EDT_OPENGL3, {"opengl3", "OpenGL 3+"}},
{(int)video::EDT_OGLES1, {"ogles1", "OpenGL ES1"}},
{(int)video::EDT_OGLES2, {"ogles2", "OpenGL ES2"}},
};
return driver_info_map.at((int)type);
@ -462,18 +433,14 @@ const VideoDriverInfo &RenderingEngine::getVideoDriverInfo(irr::video::E_DRIVER_
float RenderingEngine::getDisplayDensity()
{
float user_factor = g_settings->getFloat("display_density_factor", 0.5f, 5.0f);
#ifndef __ANDROID__
static float cached_display_density = [&] {
float dpi = get_raw_device()->getDisplayDensity();
// fall back to manually specified dpi
if (dpi == 0.0f)
dpi = g_settings->getFloat("screen_dpi");
return dpi / 96.0f;
}();
return std::max(cached_display_density * g_settings->getFloat("display_density_factor"), 0.5f);
float dpi = get_raw_device()->getDisplayDensity();
if (dpi == 0.0f)
dpi = 96.0f;
return std::max(dpi / 96.0f * user_factor, 0.5f);
#else // __ANDROID__
return porting::getDisplayDensity();
return porting::getDisplayDensity() * user_factor;
#endif // __ANDROID__
}
@ -489,11 +456,14 @@ void RenderingEngine::autosaveScreensizeAndCo(
// we do not want to save the thing. This allows users to also manually change
// the settings.
// Don't save the fullscreen size, we want the windowed size.
bool fullscreen = RenderingEngine::get_raw_device()->isFullscreen();
// Screen size
const irr::core::dimension2d<u32> current_screen_size =
RenderingEngine::get_video_driver()->getScreenSize();
// Don't replace good value with (0, 0)
if (current_screen_size != irr::core::dimension2d<u32>(0, 0) &&
if (!fullscreen &&
current_screen_size != irr::core::dimension2d<u32>(0, 0) &&
current_screen_size != initial_screen_size) {
g_settings->setU16("screen_w", current_screen_size.Width);
g_settings->setU16("screen_h", current_screen_size.Height);

View file

@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/render/core.h"
// include the shadow mapper classes too
#include "client/shadows/dynamicshadowsrender.h"
#include <IVideoDriver.h>
#ifdef SERVER
#error Do not include in server builds

View file

@ -218,15 +218,15 @@ class MainShaderConstantSetter : public IShaderConstantSetter
CachedVertexShaderSetting<float, 16> m_texture{"mTexture"};
// commonly used way to pass material color to shader
video::SColor m_emissive_color;
CachedPixelShaderSetting<float, 4> m_emissive_color_setting{"emissiveColor"};
video::SColor m_material_color;
CachedPixelShaderSetting<float, 4> m_material_color_setting{"materialColor"};
public:
~MainShaderConstantSetter() = default;
virtual void onSetMaterial(const video::SMaterial& material) override
{
m_emissive_color = material.EmissiveColor;
m_material_color = material.ColorParam;
}
virtual void onSetConstants(video::IMaterialRendererServices *services) override
@ -249,13 +249,13 @@ public:
m_world_view_proj.set(worldViewProj, services);
if (driver->getDriverType() == video::EDT_OGLES2 || driver->getDriverType() == video::EDT_OPENGL3) {
core::matrix4 texture = driver->getTransform(video::ETS_TEXTURE_0);
auto &texture = driver->getTransform(video::ETS_TEXTURE_0);
m_world_view.set(worldView, services);
m_texture.set(texture, services);
}
video::SColorf emissive_color(m_emissive_color);
m_emissive_color_setting.set(emissive_color, services);
video::SColorf colorf(m_material_color);
m_material_color_setting.set(colorf, services);
}
};
@ -573,6 +573,7 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
} else {
shaders_header << "#version 100\n";
}
// cf. EVertexAttributes.h for the predefined ones
vertex_header = R"(
precision mediump float;
@ -582,7 +583,7 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
attribute highp vec4 inVertexPosition;
attribute lowp vec4 inVertexColor;
attribute mediump vec4 inTexCoord0;
attribute mediump vec2 inTexCoord0;
attribute mediump vec3 inVertexNormal;
attribute mediump vec4 inVertexTangent;
attribute mediump vec4 inVertexBinormal;
@ -691,6 +692,15 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
if (g_settings->getBool("enable_bumpmaps"))
shaders_header << "#define ENABLE_BUMPMAPS 1\n";
if (g_settings->getBool("enable_water_reflections"))
shaders_header << "#define ENABLE_WATER_REFLECTIONS 1\n";
if (g_settings->getBool("enable_translucent_foliage"))
shaders_header << "#define ENABLE_TRANSLUCENT_FOLIAGE 1\n";
if (g_settings->getBool("enable_node_specular"))
shaders_header << "#define ENABLE_NODE_SPECULAR 1\n";
s32 shadow_filter = g_settings->getS32("shadow_filters");
shaders_header << "#define SHADOW_FILTER " << shadow_filter << "\n";

View file

@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/clientenvironment.h"
#include "client/clientmap.h"
#include "client/camera.h"
#include <IVideoDriver.h>
using m4f = core::matrix4;

View file

@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "EShaderTypes.h"
#include "IGPUProgrammingServices.h"
#include "IMaterialRenderer.h"
#include <IVideoDriver.h>
ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) :
m_smgr(device->getSceneManager()), m_driver(device->getVideoDriver()),
@ -140,7 +141,7 @@ void ShadowRenderer::initialize()
}
createShaders();
m_texture_format = m_shadow_map_texture_32bit
? video::ECOLOR_FORMAT::ECF_R32F

View file

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string>
#include <vector>
#include <IrrlichtDevice.h>
#include "irrlichttypes_extrabloated.h"
#include "client/shadows/dynamicshadows.h"
@ -93,9 +94,11 @@ public:
bool is_active() const { return m_shadows_enabled && shadowMapTextureFinal != nullptr; }
void setTimeOfDay(float isDay) { m_time_day = isDay; };
void setShadowIntensity(float shadow_intensity);
void setShadowTint(video::SColor shadow_tint) { m_shadow_tint = shadow_tint; }
s32 getShadowSamples() const { return m_shadow_samples; }
float getShadowStrength() const { return m_shadows_enabled ? m_shadow_strength : 0.0f; }
video::SColor getShadowTint() const { return m_shadow_tint; }
float getTimeOfDay() const { return m_time_day; }
f32 getPerspectiveBiasXY() { return m_perspective_bias_xy; }
@ -130,6 +133,7 @@ private:
std::vector<NodeToApply> m_shadow_node_array;
float m_shadow_strength;
video::SColor m_shadow_tint{ 255, 0, 0, 0 };
float m_shadow_strength_gamma;
float m_shadow_map_max_distance;
float m_shadow_map_texture_size;

View file

@ -18,11 +18,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "shadowsScreenQuad.h"
#include <IVideoDriver.h>
shadowScreenQuad::shadowScreenQuad()
{
Material.Wireframe = false;
Material.Lighting = false;
video::SColor color(0x0);
Vertices[0] = video::S3DVertex(

View file

@ -40,6 +40,9 @@ void ShadowConstantSetter::onSetConstants(video::IMaterialRendererServices *serv
f32 ShadowStrength = shadow->getShadowStrength();
m_shadow_strength.set(&ShadowStrength, services);
video::SColor ShadowTint = shadow->getShadowTint();
m_shadow_tint.set(ShadowTint, services);
f32 timeOfDay = shadow->getTimeOfDay();
m_time_of_day.set(&timeOfDay, services);

View file

@ -31,6 +31,7 @@ class ShadowConstantSetter : public IShaderConstantSetter
CachedPixelShaderSetting<f32, 3> m_light_direction{"v_LightDirection"};
CachedPixelShaderSetting<f32> m_texture_res{"f_textureresolution"};
CachedPixelShaderSetting<f32> m_shadow_strength{"f_shadow_strength"};
CachedPixelShaderSetting<f32, 3> m_shadow_tint{ "shadow_tint" };
CachedPixelShaderSetting<f32> m_time_of_day{"f_timeofday"};
CachedPixelShaderSetting<f32> m_shadowfar{"f_shadowfar"};
CachedPixelShaderSetting<f32, 4> m_camera_pos{"CameraPos"};

View file

@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <ISceneManager.h>
#include <ICameraSceneNode.h>
#include <S3DVertex.h>
#include "client/mesh.h"
#include "client/tile.h"
#include "noise.h" // easeCurve
#include "profiler.h"
@ -38,7 +39,6 @@ using namespace irr::core;
static video::SMaterial baseMaterial()
{
video::SMaterial mat;
mat.Lighting = false;
mat.ZBuffer = video::ECFN_DISABLED;
mat.ZWriteEnable = video::EZW_OFF;
mat.AntiAliasing = 0;
@ -77,10 +77,9 @@ Sky::Sky(s32 id, RenderingEngine *rendering_engine, ITextureSource *tsrc, IShade
// Create materials
m_materials[0] = baseMaterial();
// FIXME: shouldn't this check m_enable_shaders?
m_materials[0].MaterialType = ssrc->getShaderInfo(ssrc->getShader("stars_shader", TILE_MATERIAL_ALPHA)).material;
m_materials[0].Lighting = true;
m_materials[0].ColorMaterial = video::ECM_NONE;
m_materials[0].MaterialType = m_enable_shaders ?
ssrc->getShaderInfo(ssrc->getShader("stars_shader", TILE_MATERIAL_ALPHA)).material :
video::EMT_TRANSPARENT_ALPHA_CHANNEL;
m_materials[1] = baseMaterial();
m_materials[1].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
@ -95,7 +94,6 @@ Sky::Sky(s32 id, RenderingEngine *rendering_engine, ITextureSource *tsrc, IShade
for (int i = 5; i < 11; i++) {
m_materials[i] = baseMaterial();
m_materials[i].Lighting = true;
m_materials[i].MaterialType = video::EMT_SOLID;
}
@ -169,7 +167,8 @@ void Sky::render()
video::SColor texel_color (255, texel->getRed(),
texel->getGreen(), texel->getBlue());
m_sun_tonemap->unlock();
m_materials[3].EmissiveColor = texel_color;
// Only accessed by our code later, not used by a shader
m_materials[3].ColorParam = texel_color;
}
if (m_moon_tonemap) {
@ -178,7 +177,8 @@ void Sky::render()
video::SColor texel_color (255, texel->getRed(),
texel->getGreen(), texel->getBlue());
m_moon_tonemap->unlock();
m_materials[4].EmissiveColor = texel_color;
// Only accessed by our code later, not used by a shader
m_materials[4].ColorParam = texel_color;
}
const f32 t = 1.0f;
@ -465,11 +465,11 @@ void Sky::update(float time_of_day, float time_brightness,
// which keeps previous behavior.
if (m_sun_tonemap && m_default_tint) {
pointcolor_sun_f.r = pointcolor_light *
(float)m_materials[3].EmissiveColor.getRed() / 255;
(float)m_materials[3].ColorParam.getRed() / 255;
pointcolor_sun_f.b = pointcolor_light *
(float)m_materials[3].EmissiveColor.getBlue() / 255;
(float)m_materials[3].ColorParam.getBlue() / 255;
pointcolor_sun_f.g = pointcolor_light *
(float)m_materials[3].EmissiveColor.getGreen() / 255;
(float)m_materials[3].ColorParam.getGreen() / 255;
} else if (!m_default_tint) {
pointcolor_sun_f = m_sky_params.fog_sun_tint;
} else {
@ -498,11 +498,11 @@ void Sky::update(float time_of_day, float time_brightness,
}
if (m_moon_tonemap && m_default_tint) {
pointcolor_moon_f.r = pointcolor_light *
(float)m_materials[4].EmissiveColor.getRed() / 255;
(float)m_materials[4].ColorParam.getRed() / 255;
pointcolor_moon_f.b = pointcolor_light *
(float)m_materials[4].EmissiveColor.getBlue() / 255;
(float)m_materials[4].ColorParam.getBlue() / 255;
pointcolor_moon_f.g = pointcolor_light *
(float)m_materials[4].EmissiveColor.getGreen() / 255;
(float)m_materials[4].ColorParam.getGreen() / 255;
}
video::SColor pointcolor_sun = pointcolor_sun_f.toSColor();
@ -603,11 +603,8 @@ void Sky::draw_sun(video::IVideoDriver *driver, const video::SColor &suncolor,
// Another magic number that contributes to the ratio 1.57 sun/moon size
// difference.
float d = (sunsize * 1.7) * m_sun_params.scale;
video::SColor c;
if (m_sun_tonemap)
c = video::SColor(0, 0, 0, 0);
else
c = video::SColor(255, 255, 255, 255);
video::SColor c = m_sun_tonemap ? m_materials[3].ColorParam :
video::SColor(255, 255, 255, 255);
draw_sky_body(vertices, -d, d, c);
place_sky_body(vertices, 90, wicked_time_of_day * 360 - 90);
driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
@ -660,11 +657,8 @@ void Sky::draw_moon(video::IVideoDriver *driver, const video::SColor &mooncolor,
// Another magic number that contributes to the ratio 1.57 sun/moon size
// difference.
float d = (moonsize * 1.9) * m_moon_params.scale;
video::SColor c;
if (m_moon_tonemap)
c = video::SColor(0, 0, 0, 0);
else
c = video::SColor(255, 255, 255, 255);
video::SColor c = m_sun_tonemap ? m_materials[4].ColorParam :
video::SColor(255, 255, 255, 255);
draw_sky_body(vertices, -d, d, c);
place_sky_body(vertices, -90, wicked_time_of_day * 360 - 90);
driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2);
@ -688,7 +682,10 @@ void Sky::draw_stars(video::IVideoDriver * driver, float wicked_time_of_day)
color.a *= alpha;
if (color.a <= 0.0f) // Stars are only drawn when not fully transparent
return;
m_materials[0].EmissiveColor = color.toSColor();
if (m_enable_shaders)
m_materials[0].ColorParam = color.toSColor();
else
setMeshBufferColor(m_stars.get(), color.toSColor());
auto sky_rotation = core::matrix4().setRotationAxisRadians(2.0f * M_PI * (wicked_time_of_day - 0.25f), v3f(0.0f, 0.0f, 1.0f));
auto world_matrix = driver->getTransform(video::ETS_WORLD);
@ -742,7 +739,6 @@ void Sky::setSunTexture(const std::string &sun_texture,
m_sun_params.tonemap = sun_tonemap;
m_sun_tonemap = tsrc->isKnownSourceImage(sun_tonemap) ?
tsrc->getTexture(sun_tonemap) : nullptr;
m_materials[3].Lighting = !!m_sun_tonemap;
if (m_sun_params.texture == sun_texture && !m_first_update)
return;
@ -762,7 +758,6 @@ void Sky::setSunTexture(const std::string &sun_texture,
m_materials[3].setTexture(0, m_sun_texture);
m_materials[3].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
disableTextureFiltering(m_materials[3]);
m_materials[3].Lighting = !!m_sun_tonemap;
}
}
@ -786,7 +781,6 @@ void Sky::setMoonTexture(const std::string &moon_texture,
m_moon_params.tonemap = moon_tonemap;
m_moon_tonemap = tsrc->isKnownSourceImage(moon_tonemap) ?
tsrc->getTexture(moon_tonemap) : nullptr;
m_materials[4].Lighting = !!m_moon_tonemap;
if (m_moon_params.texture == moon_texture && !m_first_update)
return;
@ -806,7 +800,6 @@ void Sky::setMoonTexture(const std::string &moon_texture,
m_materials[4].setTexture(0, m_moon_texture);
m_materials[4].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
disableTextureFiltering(m_materials[4]);
m_materials[4].Lighting = !!m_moon_tonemap;
}
}
@ -830,10 +823,11 @@ void Sky::updateStars()
warningstream << "Requested " << m_star_params.count << " stars but " << 0x4000 << " is the max\n";
m_star_params.count = 0x4000;
}
m_stars->Vertices.reallocate(4 * m_star_params.count);
m_stars->Indices.reallocate(6 * m_star_params.count);
auto &vertices = m_stars->Vertices->Data;
auto &indices = m_stars->Indices->Data;
vertices.reserve(4 * m_star_params.count);
indices.reserve(6 * m_star_params.count);
video::SColor fallback_color = m_star_params.starcolor; // used on GLES 2 “without shaders”
PcgRandom rgen(m_seed);
float d = (0.006 / 2) * m_star_params.scale;
for (u16 i = 0; i < m_star_params.count; i++) {
@ -852,20 +846,21 @@ void Sky::updateStars()
a.rotateVect(p1);
a.rotateVect(p2);
a.rotateVect(p3);
m_stars->Vertices.push_back(video::S3DVertex(p, {}, fallback_color, {}));
m_stars->Vertices.push_back(video::S3DVertex(p1, {}, fallback_color, {}));
m_stars->Vertices.push_back(video::S3DVertex(p2, {}, fallback_color, {}));
m_stars->Vertices.push_back(video::S3DVertex(p3, {}, fallback_color, {}));
vertices.push_back(video::S3DVertex(p, {}, {}, {}));
vertices.push_back(video::S3DVertex(p1, {}, {}, {}));
vertices.push_back(video::S3DVertex(p2, {}, {}, {}));
vertices.push_back(video::S3DVertex(p3, {}, {}, {}));
}
for (u16 i = 0; i < m_star_params.count; i++) {
m_stars->Indices.push_back(i * 4 + 0);
m_stars->Indices.push_back(i * 4 + 1);
m_stars->Indices.push_back(i * 4 + 2);
m_stars->Indices.push_back(i * 4 + 2);
m_stars->Indices.push_back(i * 4 + 3);
m_stars->Indices.push_back(i * 4 + 0);
indices.push_back(i * 4 + 0);
indices.push_back(i * 4 + 1);
indices.push_back(i * 4 + 2);
indices.push_back(i * 4 + 2);
indices.push_back(i * 4 + 3);
indices.push_back(i * 4 + 0);
}
m_stars->setHardwareMappingHint(scene::EHM_STATIC);
if (m_enable_shaders)
m_stars->setHardwareMappingHint(scene::EHM_STATIC);
}
void Sky::setSkyColors(const SkyColor &sky_color)

View file

@ -19,16 +19,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes_bloated.h"
#include <ISceneNode.h>
#include <SMeshBuffer.h>
#include <array>
#include "camera.h"
#include "camera.h" // CameraMode
#include "irr_ptr.h"
#include "shader.h"
#include "skyparams.h"
#define SKY_MATERIAL_COUNT 12
namespace irr::video
{
class IVideoDriver;
}
class IShaderSource;
class ITextureSource;
// Skybox, rendered with zbuffer turned off, before all other nodes.

View file

@ -26,9 +26,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "sound_singleton.h"
#include "util/numeric.h" // myrand()
#include "util/tracy_wrapper.h"
#include "filesys.h"
#include "porting.h"
#include <limits>
namespace sound {
void OpenALSoundManager::stepStreams(f32 dtime)
@ -347,6 +350,13 @@ void OpenALSoundManager::updateListener(const v3f &pos_, const v3f &vel_,
void OpenALSoundManager::setListenerGain(f32 gain)
{
#if defined(__APPLE__)
/* macOS OpenAL implementation ignore setting AL_GAIN to zero
* so we use smallest possible value
*/
if (gain == 0.0f)
gain = std::numeric_limits<f32>::min();
#endif
alListenerf(AL_GAIN, gain);
}
@ -492,6 +502,8 @@ void *OpenALSoundManager::run()
u64 t_step_start = porting::getTimeMs();
while (true) {
auto framemarker = FrameMarker("OpenALSoundManager::run()-frame").started();
auto get_time_since_last_step = [&] {
return (f32)(porting::getTimeMs() - t_step_start);
};

View file

@ -39,7 +39,7 @@ struct TextureInfo
};
// TextureSource
class TextureSource : public IWritableTextureSource
class TextureSource final : public IWritableTextureSource
{
public:
TextureSource();
@ -137,7 +137,6 @@ public:
video::ITexture* getNormalTexture(const std::string &name);
video::SColor getTextureAverageColor(const std::string &name);
video::ITexture *getShaderFlagsTexture(bool normamap_present);
private:
@ -541,25 +540,3 @@ video::SColor TextureSource::getTextureAverageColor(const std::string &name)
return c;
}
video::ITexture *TextureSource::getShaderFlagsTexture(bool normalmap_present)
{
std::string tname = "__shaderFlagsTexture";
tname += normalmap_present ? "1" : "0";
if (isKnownSourceImage(tname)) {
return getTexture(tname);
}
video::IVideoDriver *driver = RenderingEngine::get_video_driver();
video::IImage *flags_image = driver->createImage(
video::ECF_A8R8G8B8, core::dimension2d<u32>(1, 1));
sanity_check(flags_image);
video::SColor c(255, normalmap_present ? 255 : 0, 0, 0);
flags_image->setPixel(0, 0, c);
insertSourceImage(tname, flags_image);
flags_image->drop();
return getTexture(tname);
}

View file

@ -20,10 +20,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "irrlichttypes.h"
#include <ITexture.h>
#include <SColor.h>
#include <string>
#include <vector>
namespace irr::video
{
class IImage;
class ITexture;
}
typedef std::vector<video::SColor> Palette;
/*
@ -65,7 +71,6 @@ public:
virtual bool isKnownSourceImage(const std::string &name)=0;
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
virtual video::SColor getTextureAverageColor(const std::string &name)=0;
virtual video::ITexture *getShaderFlagsTexture(bool normalmap_present)=0;
};
class IWritableTextureSource : public ITextureSource
@ -87,7 +92,6 @@ public:
virtual void rebuildImagesAndTextures()=0;
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
virtual video::SColor getTextureAverageColor(const std::string &name)=0;
virtual video::ITexture *getShaderFlagsTexture(bool normalmap_present)=0;
};
IWritableTextureSource *createTextureSource();

View file

@ -62,8 +62,6 @@ struct FrameSpec
u32 texture_id = 0;
video::ITexture *texture = nullptr;
video::ITexture *normal_texture = nullptr;
video::ITexture *flags_texture = nullptr;
};
#define MAX_TILE_LAYERS 2
@ -114,8 +112,6 @@ struct TileLayer
// Ordered for size, please do not reorder
video::ITexture *texture = nullptr;
video::ITexture *normal_texture = nullptr;
video::ITexture *flags_texture = nullptr;
u32 shader_id = 0;

View file

@ -194,10 +194,9 @@ private:
static ExtrusionMeshCache *g_extrusion_mesh_cache = nullptr;
WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting):
WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id):
scene::ISceneNode(mgr->getRootSceneNode(), mgr, id),
m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF),
m_lighting(lighting)
m_material_type(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF)
{
m_enable_shaders = g_settings->getBool("enable_shaders");
m_anisotropic_filter = g_settings->getBool("anisotropic_filter");
@ -306,9 +305,6 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename,
});
// mipmaps cause "thin black line" artifacts
material.UseMipMaps = false;
if (m_enable_shaders) {
material.setTexture(2, tsrc->getShaderFlagsTexture(false));
}
}
}
@ -343,7 +339,6 @@ static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n,
if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) {
const FrameSpec &frame = (*p.layer.frames)[0];
p.layer.texture = frame.texture;
p.layer.normal_texture = frame.normal_texture;
}
for (video::S3DVertex &v : p.vertices) {
v.Color.setAlpha(255);
@ -394,8 +389,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
// overlay is white, if present
m_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
// initialize the color
if (!m_lighting)
setColor(video::SColor(0xFFFFFFFF));
setColor(video::SColor(0xFFFFFFFF));
return;
}
@ -472,8 +466,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
}
// initialize the color
if (!m_lighting)
setColor(video::SColor(0xFFFFFFFF));
setColor(video::SColor(0xFFFFFFFF));
return;
} else {
const std::string inventory_image = item.getInventoryImage(idef);
@ -489,8 +482,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
m_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
// initialize the color
if (!m_lighting)
setColor(video::SColor(0xFFFFFFFF));
setColor(video::SColor(0xFFFFFFFF));
return;
}
@ -500,7 +492,6 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
void WieldMeshSceneNode::setColor(video::SColor c)
{
assert(!m_lighting);
scene::IMesh *mesh = m_meshnode->getMesh();
if (!mesh)
return;
@ -539,7 +530,7 @@ void WieldMeshSceneNode::setNodeLightColor(video::SColor color)
if (m_enable_shaders) {
for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i) {
video::SMaterial &material = m_meshnode->getMaterial(i);
material.EmissiveColor = color;
material.ColorParam = color;
}
} else {
setColor(color);
@ -569,11 +560,6 @@ void WieldMeshSceneNode::changeToMesh(scene::IMesh *mesh)
mesh->setHardwareMappingHint(scene::EHM_DYNAMIC);
}
m_meshnode->forEachMaterial([this] (auto &mat) {
mat.Lighting = m_lighting;
// need to normalize normals when lighting is enabled (because of setScale())
mat.NormalizeNormals = m_lighting;
});
m_meshnode->setVisible(true);
}
@ -671,7 +657,6 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
tex.MagFilter = video::ETMAGF_NEAREST;
});
material.BackfaceCulling = cull_backface;
material.Lighting = false;
}
rotateMeshXZby(mesh, -45);
@ -724,7 +709,6 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc,
tex.MagFilter = video::ETMAGF_NEAREST;
});
material.BackfaceCulling = true;
material.Lighting = false;
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
material.MaterialTypeParam = 0.5f;
}
@ -772,16 +756,6 @@ void postProcessNodeMesh(scene::SMesh *mesh, const ContentFeatures &f,
} 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();

View file

@ -21,7 +21,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string>
#include <vector>
#include "irrlichttypes_extrabloated.h"
#include "irr_aabb3d.h"
#include "irr_v3d.h"
#include <EMaterialTypes.h>
#include <IMeshSceneNode.h>
#include <SColor.h>
namespace irr::scene
{
class ISceneManager;
class IMesh;
struct SMesh;
}
using namespace irr;
struct ItemStack;
class Client;
@ -91,7 +104,7 @@ struct ItemMesh
class WieldMeshSceneNode : public scene::ISceneNode
{
public:
WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id = -1, bool lighting = false);
WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id = -1);
virtual ~WieldMeshSceneNode();
void setCube(const ContentFeatures &f, v3f wield_scale);
@ -119,9 +132,6 @@ private:
scene::IMeshSceneNode *m_meshnode = nullptr;
video::E_MATERIAL_TYPE m_material_type;
// True if SMaterial::Lighting should be enabled.
bool m_lighting;
bool m_enable_shaders;
bool m_anisotropic_filter;
bool m_bilinear_filter;

View file

@ -23,7 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include "client/renderingengine.h"
#include "gui/touchscreengui.h"
#include "gui/guiFormSpecMenu.h"
#include "gui/touchcontrols.h"
ClientDynamicInfo ClientDynamicInfo::getCurrent()
{
@ -33,23 +34,26 @@ ClientDynamicInfo ClientDynamicInfo::getCurrent()
f32 hud_scaling = g_settings->getFloat("hud_scaling", 0.5f, 20.0f);
f32 real_gui_scaling = gui_scaling * density;
f32 real_hud_scaling = hud_scaling * density;
bool touch_controls = g_touchscreengui;
bool touch_controls = g_touchcontrols;
return {
screen_size, real_gui_scaling, real_hud_scaling,
ClientDynamicInfo::calculateMaxFSSize(screen_size, gui_scaling),
ClientDynamicInfo::calculateMaxFSSize(screen_size, density, gui_scaling),
touch_controls
};
}
v2f32 ClientDynamicInfo::calculateMaxFSSize(v2u32 render_target_size, f32 gui_scaling)
v2f32 ClientDynamicInfo::calculateMaxFSSize(v2u32 render_target_size, f32 density, f32 gui_scaling)
{
f32 factor = (g_settings->getBool("enable_touch") ? 10 : 15) / gui_scaling;
f32 ratio = (f32)render_target_size.X / (f32)render_target_size.Y;
if (ratio < 1)
return { factor, factor / ratio };
else
return { factor * ratio, factor };
// must stay in sync with GUIFormSpecMenu::calculateImgsize
const double screen_dpi = density * 96;
// assume padding[0,0] since max_formspec_size is used for fullscreen formspecs
double prefer_imgsize = GUIFormSpecMenu::getImgsize(render_target_size,
screen_dpi, gui_scaling);
return v2f32(render_target_size.X / prefer_imgsize,
render_target_size.Y / prefer_imgsize);
}
#endif

View file

@ -42,6 +42,6 @@ public:
static ClientDynamicInfo getCurrent();
private:
static v2f32 calculateMaxFSSize(v2u32 render_target_size, f32 gui_scaling);
static v2f32 calculateMaxFSSize(v2u32 render_target_size, f32 density, f32 gui_scaling);
#endif
};

View file

@ -40,3 +40,5 @@
#cmakedefine01 CURSES_HAVE_NCURSESW_CURSES_H
#cmakedefine01 BUILD_UNITTESTS
#cmakedefine01 BUILD_BENCHMARKS
#cmakedefine01 USE_SDL2
#cmakedefine01 BUILD_WITH_TRACY

View file

@ -273,7 +273,7 @@ static void add_object_boxes(Environment *env,
const v3f pos_f, const v3f speed_f, ActiveObject *self,
std::vector<NearbyCollisionInfo> &cinfo)
{
auto process_object = [&] (ActiveObject *object) {
auto process_object = [&cinfo] (ActiveObject *object) {
if (object && object->collideWithObjects()) {
aabb3f box;
if (object->getCollisionBox(&box))
@ -292,7 +292,7 @@ static void add_object_boxes(Environment *env,
c_env->getActiveObjects(pos_f, distance, clientobjects);
for (auto &clientobject : clientobjects) {
// Do collide with everything but itself and the parent CAO
// Do collide with everything but itself and children
if (!self || (self != clientobject.obj &&
self != clientobject.obj->getParent())) {
process_object(clientobject.obj);
@ -301,12 +301,12 @@ static void add_object_boxes(Environment *env,
// add collision with local player
LocalPlayer *lplayer = c_env->getLocalPlayer();
if (lplayer->getParent() == nullptr) {
auto *obj = (ClientActiveObject*) lplayer->getCAO();
if (!self || (self != obj && self != obj->getParent())) {
aabb3f lplayer_collisionbox = lplayer->getCollisionbox();
v3f lplayer_pos = lplayer->getPosition();
lplayer_collisionbox.MinEdge += lplayer_pos;
lplayer_collisionbox.MaxEdge += lplayer_pos;
auto *obj = (ActiveObject*) lplayer->getCAO();
cinfo.emplace_back(obj, 0, lplayer_collisionbox);
}
}
@ -315,7 +315,7 @@ static void add_object_boxes(Environment *env,
{
ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
if (s_env) {
// search for objects which are not us, or we are not its parent.
// search for objects which are not us and not our children.
// we directly process the object in this callback to avoid useless
// looping afterwards.
auto include_obj_cb = [self, &process_object] (ServerActiveObject *obj) {
@ -623,8 +623,10 @@ bool collision_check_intersection(Environment *env, IGameDef *gamedef,
Collision detection
*/
aabb3f checkbox = box_0;
checkbox.MinEdge += pos_f;
checkbox.MaxEdge += pos_f;
// aabbox3d::intersectsWithBox(box) returns true when the faces are touching perfectly.
// However, we do not want want a true-ish return value in that case. Add some tolerance.
checkbox.MinEdge += pos_f + (0.1f * BS);
checkbox.MaxEdge += pos_f - (0.1f * BS);
/*
Go through every node and object box

View file

@ -65,7 +65,8 @@ struct collisionMoveResult
std::vector<CollisionInfo> collisions;
};
// Moves using a single iteration; speed should not exceed pos_max_d/dtime
/// @brief Moves using a single iteration; speed should not exceed pos_max_d/dtime
/// @param self (optional) ActiveObject to ignore in the collision detection.
collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
f32 pos_max_d, const aabb3f &box_0,
f32 stepheight, f32 dtime,
@ -73,7 +74,11 @@ collisionMoveResult collisionMoveSimple(Environment *env,IGameDef *gamedef,
v3f accel_f, ActiveObject *self=NULL,
bool collide_with_objects=true);
// check if box is in collision on actual position
/// @brief A simpler version of "collisionMoveSimple" that only checks whether
/// a collision occurs at the given position.
/// @param self (optional) ActiveObject to ignore in the collision detection.
/// @returns `true` when `box_0` truly intersects with a node or object.
/// Touching faces are not counted as intersection.
bool collision_check_intersection(Environment *env, IGameDef *gamedef,
const aabb3f &box_0, const v3f &pos_f, ActiveObject *self = nullptr,
bool collide_with_objects = true);

View file

@ -48,8 +48,7 @@ void PlayerDatabaseFiles::deSerialize(RemotePlayer *p, std::istream &is,
p->m_dirty = true;
//args.getS32("version"); // Version field value not used
const std::string &name = args.get("name");
strlcpy(p->m_name, name.c_str(), PLAYERNAME_SIZE);
p->m_name = args.get("name");
if (sao) {
try {
@ -96,7 +95,7 @@ void PlayerDatabaseFiles::deSerialize(RemotePlayer *p, std::istream &is,
p->inventory.deSerialize(is);
} catch (SerializationError &e) {
errorstream << "Failed to deserialize player inventory. player_name="
<< name << " " << e.what() << std::endl;
<< p->getName() << " " << e.what() << std::endl;
}
if (!p->inventory.getList("craftpreview") && p->inventory.getList("craftresult")) {
@ -119,7 +118,7 @@ void PlayerDatabaseFiles::serialize(RemotePlayer *p, std::ostream &os)
// Utilize a Settings object for storing values
Settings args("PlayerArgsEnd");
args.setS32("version", 1);
args.set("name", p->m_name);
args.set("name", p->getName());
PlayerSAO *sao = p->getPlayerSAO();
// This should not happen
@ -171,7 +170,7 @@ void PlayerDatabaseFiles::savePlayer(RemotePlayer *player)
deSerialize(&testplayer, is, path, NULL);
is.close();
if (strcmp(testplayer.getName(), player->getName()) == 0) {
if (testplayer.getName() == player->getName()) {
path_found = true;
continue;
}

View file

@ -468,7 +468,7 @@ void PlayerDatabasePostgreSQL::savePlayer(RemotePlayer *player)
std::string hp = itos(sao->getHP());
std::string breath = itos(sao->getBreath());
const char *values[] = {
player->getName(),
player->getName().c_str(),
pitch.c_str(),
yaw.c_str(),
posx.c_str(), posy.c_str(), posz.c_str(),
@ -476,7 +476,7 @@ void PlayerDatabasePostgreSQL::savePlayer(RemotePlayer *player)
breath.c_str()
};
const char* rmvalues[] = { player->getName() };
const char* rmvalues[] = { player->getName().c_str() };
beginSave();
if (getPGVersion() < 90500) {
@ -501,7 +501,7 @@ void PlayerDatabasePostgreSQL::savePlayer(RemotePlayer *player)
inv_id = itos(i), lsize = itos(list->getSize());
const char* inv_values[] = {
player->getName(),
player->getName().c_str(),
inv_id.c_str(),
width.c_str(),
name.c_str(),
@ -516,7 +516,7 @@ void PlayerDatabasePostgreSQL::savePlayer(RemotePlayer *player)
std::string itemStr = oss.str(), slotId = itos(j);
const char* invitem_values[] = {
player->getName(),
player->getName().c_str(),
inv_id.c_str(),
slotId.c_str(),
itemStr.c_str()
@ -529,7 +529,7 @@ void PlayerDatabasePostgreSQL::savePlayer(RemotePlayer *player)
const StringMap &attrs = sao->getMeta().getStrings();
for (const auto &attr : attrs) {
const char *meta_values[] = {
player->getName(),
player->getName().c_str(),
attr.first.c_str(),
attr.second.c_str()
};
@ -545,7 +545,7 @@ bool PlayerDatabasePostgreSQL::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
sanity_check(sao);
verifyDatabase();
const char *values[] = { player->getName() };
const char *values[] = { player->getName().c_str() };
PGresult *results = execPrepared("load_player", 1, values, false, false);
// Player not found, return not found
@ -580,7 +580,7 @@ bool PlayerDatabasePostgreSQL::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
std::string invIdStr = itos(invId);
const char* values2[] = {
player->getName(),
player->getName().c_str(),
invIdStr.c_str()
};
PGresult *results2 = execPrepared("load_player_inventory_items", 2,

View file

@ -32,9 +32,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <hiredis.h>
#include <cassert>
#if VERSION_MAJOR > 5 || VERSION_MINOR > 9
#define DEPRECATION_PERIOD_OVER
#endif
/*
* Redis is not a good fit for Minetest and only still supported for legacy as
* well as advanced use case reasons, see:
* <https://github.com/minetest/minetest/issues/14822>
*
* Do NOT extend this backend with any new functionality.
*/
Database_Redis::Database_Redis(Settings &conf)
{
@ -70,13 +74,8 @@ Database_Redis::Database_Redis(Settings &conf)
freeReplyObject(reply);
}
warningstream << "/!\\ You are using the deprecated redis backend. "
#ifdef DEPRECATION_PERIOD_OVER
<< "This backend is only still supported for migrations. /!\\\n"
#else
<< "This backend will become read-only in the next release. /!\\\n"
#endif
<< "Please migrate to SQLite3 or PostgreSQL instead." << std::endl;
dstream << "Note: When storing data in Redis you need to ensure that eviction"
" is disabled, or you risk DATA LOSS." << std::endl;
}
Database_Redis::~Database_Redis()
@ -86,16 +85,12 @@ Database_Redis::~Database_Redis()
void Database_Redis::beginSave()
{
#ifdef DEPRECATION_PERIOD_OVER
throw DatabaseException("Redis backend is read-only, see deprecation notice.");
#else
redisReply *reply = static_cast<redisReply *>(redisCommand(ctx, "MULTI"));
if (!reply) {
throw DatabaseException(std::string(
"Redis command 'MULTI' failed: ") + ctx->errstr);
}
freeReplyObject(reply);
#endif
}
void Database_Redis::endSave()

View file

@ -76,13 +76,6 @@ static bool detect_touch()
return false;
}
return false;
#elif defined(_WIN32)
// 0x01 The device has an integrated touch digitizer
// 0x80 The device is ready to receive digitizer input.
if ((GetSystemMetrics(SM_DIGITIZER) & 0x81) == 0x81)
return true;
return false;
#else
// we don't know, return default
@ -104,7 +97,8 @@ void set_default_settings()
// Client
settings->setDefault("address", "");
settings->setDefault("enable_sound", "true");
settings->setDefault("enable_touch", bool_to_cstr(has_touch));
settings->setDefault("touch_controls", bool_to_cstr(has_touch));
settings->setDefault("touch_gui", bool_to_cstr(has_touch));
settings->setDefault("sound_volume", "0.8");
settings->setDefault("sound_volume_unfocused", "0.3");
settings->setDefault("mute_sound", "false");
@ -281,6 +275,7 @@ void set_default_settings()
settings->setDefault("view_bobbing_amount", "1.0");
settings->setDefault("fall_bobbing_amount", "0.03");
settings->setDefault("enable_3d_clouds", "true");
settings->setDefault("soft_clouds", "false");
settings->setDefault("cloud_radius", "12");
settings->setDefault("menu_clouds", "true");
settings->setDefault("translucent_liquids", "true");
@ -299,6 +294,7 @@ void set_default_settings()
settings->setDefault("gui_scaling", "1.0");
settings->setDefault("gui_scaling_filter", "false");
settings->setDefault("gui_scaling_filter_txr2img", "true");
settings->setDefault("smooth_scrolling", "true");
settings->setDefault("desynchronize_mapblock_texture_animation", "false");
settings->setDefault("hud_hotbar_max_width", "1.0");
settings->setDefault("enable_local_map_saving", "false");
@ -308,6 +304,7 @@ void set_default_settings()
settings->setDefault("enable_particles", "true");
settings->setDefault("arm_inertia", "true");
settings->setDefault("show_nametag_backgrounds", "true");
settings->setDefault("show_block_bounds_radius_near", "4");
settings->setDefault("transparency_sorting_distance", "16");
settings->setDefault("enable_minimap", "true");
@ -344,6 +341,9 @@ void set_default_settings()
settings->setDefault("enable_volumetric_lighting", "false");
settings->setDefault("enable_volumetric_clouds", "false");
settings->setDefault("enable_bumpmaps", "false");
settings->setDefault("enable_water_reflections", "false");
settings->setDefault("enable_translucent_foliage", "false");
settings->setDefault("enable_node_specular", "false");
// Effects Shadows
settings->setDefault("enable_dynamic_shadows", "false");
@ -364,7 +364,7 @@ void set_default_settings()
settings->setDefault("invert_hotbar_mouse_wheel", "false");
settings->setDefault("mouse_sensitivity", "0.2");
settings->setDefault("repeat_place_time", "0.25");
settings->setDefault("repeat_dig_time", "0.15");
settings->setDefault("repeat_dig_time", "0.0");
settings->setDefault("safe_dig_and_place", "false");
settings->setDefault("random_input", "false");
settings->setDefault("aux1_descends", "false");
@ -407,6 +407,7 @@ void set_default_settings()
// ContentDB
settings->setDefault("contentdb_url", "https://content.minetest.net");
settings->setDefault("contentdb_enable_updates_indicator", "true");
settings->setDefault("contentdb_max_concurrent_downloads", "3");
#ifdef __ANDROID__
@ -539,13 +540,14 @@ void set_default_settings()
settings->setDefault("server_address", "");
settings->setDefault("server_name", "");
settings->setDefault("server_description", "");
settings->setDefault("server_announce_send_players", "true");
settings->setDefault("enable_console", "false");
settings->setDefault("screen_dpi", "72");
settings->setDefault("display_density_factor", "1");
settings->setDefault("dpi_change_notifier", "0");
// Altered settings for macOS
#if defined(__MACH__) && defined(__APPLE__)
// Altered settings for CIrrDeviceOSX
#if !USE_SDL2 && defined(__MACH__) && defined(__APPLE__)
settings->setDefault("keymap_sneak", "KEY_SHIFT");
#endif

View file

@ -662,6 +662,8 @@ void *EmergeThread::run()
EmergeAction action;
MapBlock *block = nullptr;
porting::TriggerMemoryTrim();
if (!popBlockEmerge(&pos, &bedata)) {
m_queue_event.wait();
continue;
@ -690,7 +692,7 @@ void *EmergeThread::run()
"EmergeThread: Lua on_generated", SPT_AVG);
try {
m_script->on_generated(&bmdata);
m_script->on_generated(&bmdata, m_mapgen->blockseed);
} catch (const LuaError &e) {
m_server->setAsyncFatalError(e);
error = true;

View file

@ -50,6 +50,7 @@ class ModApiMapgen;
// Structure containing inputs/outputs for chunk generation
struct BlockMakeData {
MMVManip *vmanip = nullptr;
// Global map seed
u64 seed = 0;
v3s16 blockpos_min;
v3s16 blockpos_max;

View file

@ -697,32 +697,43 @@ bool MoveDir(const std::string &source, const std::string &target)
bool PathStartsWith(const std::string &path, const std::string &prefix)
{
if (prefix.empty())
return path.empty();
size_t pathsize = path.size();
size_t pathpos = 0;
size_t prefixsize = prefix.size();
size_t prefixpos = 0;
for(;;){
// Test if current characters at path and prefix are delimiter OR EOS
bool delim1 = pathpos == pathsize
|| IsDirDelimiter(path[pathpos]);
bool delim2 = prefixpos == prefixsize
|| IsDirDelimiter(prefix[prefixpos]);
// Return false if it's delimiter/EOS in one path but not in the other
if(delim1 != delim2)
return false;
if(delim1){
// Skip consequent delimiters in path, in prefix
while(pathpos < pathsize &&
IsDirDelimiter(path[pathpos]))
++pathpos;
while(prefixpos < prefixsize &&
IsDirDelimiter(prefix[prefixpos]))
++prefixpos;
// Return true if prefix has ended (at delimiter/EOS)
if(prefixpos == prefixsize)
return true;
// Return false if path has ended (at delimiter/EOS)
// while prefix did not.
if(pathpos == pathsize)
return false;
}
else{
// Skip pairwise-equal characters in path and prefix until
// delimiter/EOS in path or prefix.
// Return false if differing characters are met.
size_t len = 0;
do{
char pathchar = path[pathpos+len];
@ -954,13 +965,22 @@ bool extractZipFile(io::IFileSystem *fs, const char *filename, const std::string
const io::IFileList* files_in_zip = opened_zip->getFileList();
for (u32 i = 0; i < files_in_zip->getFileCount(); i++) {
std::string fullpath = destination + DIR_DELIM;
fullpath += files_in_zip->getFullFileName(i).c_str();
std::string fullpath_dir = fs::RemoveLastPathComponent(fullpath);
if (files_in_zip->isDirectory(i))
continue; // ignore, we create dirs as necessary
const auto &filename = files_in_zip->getFullFileName(i);
std::string fullpath = destination + DIR_DELIM;
fullpath += filename.c_str();
fullpath = fs::RemoveRelativePathComponents(fullpath);
if (!fs::PathStartsWith(fullpath, destination)) {
warningstream << "fs::extractZipFile(): refusing to extract file \""
<< filename.c_str() << "\"" << std::endl;
continue;
}
std::string fullpath_dir = fs::RemoveLastPathComponent(fullpath);
if (!fs::PathExists(fullpath_dir) && !fs::CreateAllDirs(fullpath_dir))
return false;

View file

@ -19,12 +19,11 @@ set(gui_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/guiScene.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiScrollBar.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiScrollContainer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiSkin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiTable.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiHyperText.cpp
${CMAKE_CURRENT_SOURCE_DIR}/guiVolumeChange.cpp
${CMAKE_CURRENT_SOURCE_DIR}/modalMenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/profilergraph.cpp
${CMAKE_CURRENT_SOURCE_DIR}/touchscreengui.cpp
${CMAKE_CURRENT_SOURCE_DIR}/touchcontrols.cpp
PARENT_SCOPE
)

View file

@ -17,16 +17,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "client/texturesource.h"
#include "client/fontengine.h"
#include "debug.h"
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes_bloated.h"
#include "util/string.h"
#include <algorithm>
#include <array>
#include <vector>
#pragma once
class StyleSpec
{

View file

@ -6,6 +6,7 @@
#include "util/string.h"
#include <string>
#include <vector>
#include <ITexture.h>
GUIAnimatedImage::GUIAnimatedImage(gui::IGUIEnvironment *env, gui::IGUIElement *parent,
s32 id, const core::rect<s32> &rectangle) :

View file

@ -19,6 +19,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "client/guiscalingfilter.h"
#include "log.h"
#include "client/texturesource.h"
#include <ITexture.h>
GUIBackgroundImage::GUIBackgroundImage(gui::IGUIEnvironment *env,
gui::IGUIElement *parent, s32 id, const core::rect<s32> &rectangle,

View file

@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "guiBox.h"
#include <IVideoDriver.h>
GUIBox::GUIBox(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id,
const core::rect<s32> &rectangle,

View file

@ -89,12 +89,11 @@ void GUIButton::setSpriteBank(IGUISpriteBank* sprites)
SpriteBank = sprites;
}
void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale)
void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
{
ButtonSprites[(u32)state].Index = index;
ButtonSprites[(u32)state].Color = color;
ButtonSprites[(u32)state].Loop = loop;
ButtonSprites[(u32)state].Scale = scale;
}
//! Get the sprite-index for the given state or -1 when no sprite is set
@ -115,12 +114,6 @@ bool GUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const
return ButtonSprites[(u32)state].Loop;
}
//! Returns if the sprite in the given state is scaled
bool GUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const
{
return ButtonSprites[(u32)state].Scale;
}
//! called if an event happened.
bool GUIButton::OnEvent(const SEvent& event)
{
@ -260,8 +253,8 @@ void GUIButton::draw()
setFromState();
}
GUISkin* skin = dynamic_cast<GUISkin*>(Environment->getSkin());
video::IVideoDriver* driver = Environment->getVideoDriver();
IGUISkin *skin = Environment->getSkin();
// END PATCH
if (DrawBorder)
@ -354,23 +347,26 @@ void GUIButton::draw()
void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center)
{
u32 stateIdx = (u32)state;
s32 spriteIdx = ButtonSprites[stateIdx].Index;
if (spriteIdx == -1)
return;
if (ButtonSprites[stateIdx].Index != -1)
{
if ( ButtonSprites[stateIdx].Scale )
{
const video::SColor colors[] = {ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color};
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect.UpperLeftCorner,
&AbsoluteClippingRect, colors[0], // FIXME: remove [0]
porting::getTimeMs()-startTime, ButtonSprites[stateIdx].Loop);
}
else
{
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, porting::getTimeMs(),
ButtonSprites[stateIdx].Loop, true);
}
}
u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber;
core::rect<s32> srcRect = SpriteBank->getPositions()[rectIdx];
IGUISkin *skin = Environment->getSkin();
s32 scale = std::max(std::floor(skin->getScale()), 1.0f);
core::rect<s32> rect(center, srcRect.getSize() * scale);
rect -= rect.getSize() / 2;
const video::SColor colors[] = {
ButtonSprites[stateIdx].Color,
ButtonSprites[stateIdx].Color,
ButtonSprites[stateIdx].Color,
ButtonSprites[stateIdx].Color,
};
SpriteBank->draw2DSprite(spriteIdx, rect, &AbsoluteClippingRect, colors,
porting::getTimeMs() - startTime, ButtonSprites[stateIdx].Loop);
}
EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const
@ -741,7 +737,7 @@ void GUIButton::setFromStyle(const StyleSpec& style)
Padding.UpperLeftCorner + BgMiddle.UpperLeftCorner,
Padding.LowerRightCorner + BgMiddle.LowerRightCorner);
GUISkin* skin = dynamic_cast<GUISkin*>(Environment->getSkin());
IGUISkin *skin = Environment->getSkin();
core::vector2d<s32> defaultPressOffset(
skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X),
skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y));

View file

@ -10,7 +10,6 @@
#include "IGUISpriteBank.h"
#include "ITexture.h"
#include "SColor.h"
#include "guiSkin.h"
#include "StyleSpec.h"
using namespace irr;
@ -92,7 +91,7 @@ public:
*/
virtual void setSprite(gui::EGUI_BUTTON_STATE state, s32 index,
video::SColor color=video::SColor(255,255,255,255),
bool loop=false, bool scale=false) override;
bool loop=false) override;
//! Get the sprite-index for the given state or -1 when no sprite is set
virtual s32 getSpriteIndex(gui::EGUI_BUTTON_STATE state) const override;
@ -103,9 +102,6 @@ public:
//! Returns if the sprite in the given state does loop
virtual bool getSpriteLoop(gui::EGUI_BUTTON_STATE state) const override;
//! Returns if the sprite in the given state is scaled
virtual bool getSpriteScale(gui::EGUI_BUTTON_STATE state) const override;
//! Sets if the button should behave like a push button. Which means it
//! can be in two states: Normal or Pressed. With a click on the button,
//! the user can change the state of the button.
@ -230,13 +226,12 @@ private:
{
bool operator==(const ButtonSprite &other) const
{
return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;
return Index == other.Index && Color == other.Color && Loop == other.Loop;
}
s32 Index = -1;
video::SColor Color;
bool Loop = false;
bool Scale = false;
};
ButtonSprite ButtonSprites[gui::EGBS_COUNT];

View file

@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <ICameraSceneNode.h>
#include <IGUIStaticText.h>
#include "client/imagefilters.h"
#include "util/tracy_wrapper.h"
#if USE_SOUND
#include "client/sound/sound_openal.h"
@ -141,10 +142,6 @@ GUIEngine::GUIEngine(JoystickController *joystick,
// create texture source
m_texture_source = std::make_unique<MenuTextureSource>(rendering_engine->get_video_driver());
// create shader source
// (currently only used by clouds)
m_shader_source.reset(createShaderSource());
// create soundmanager
#if USE_SOUND
if (g_settings->getBool("enable_sound") && g_sound_manager_singleton.get()) {
@ -295,10 +292,6 @@ void GUIEngine::run()
IrrlichtDevice *device = m_rendering_engine->get_raw_device();
video::IVideoDriver *driver = device->getVideoDriver();
// Always create clouds because they may or may not be
// needed based on the game selected
cloudInit();
unsigned int text_height = g_fontengine->getTextHeight();
// Reset fog color
@ -329,9 +322,12 @@ void GUIEngine::run()
fps_control.reset();
while (m_rendering_engine->run() && !m_startgame && !m_kill) {
auto framemarker = FrameMarker("GUIEngine::run()-frame").started();
while (m_rendering_engine->run() && !m_startgame && !m_kill) {
framemarker.end();
fps_control.limit(device, &dtime);
framemarker.start();
if (device->isWindowVisible()) {
// check if we need to update the "upper left corner"-text
@ -371,6 +367,7 @@ void GUIEngine::run()
m_menu->getAndroidUIInput();
#endif
}
framemarker.end();
m_script->beforeClose();
@ -390,8 +387,6 @@ GUIEngine::~GUIEngine()
m_irr_toplefttext->remove();
m_cloud.clouds.reset();
// delete textures
for (image_definition &texture : m_textures) {
if (texture.texture)
@ -399,26 +394,11 @@ GUIEngine::~GUIEngine()
}
}
/******************************************************************************/
void GUIEngine::cloudInit()
{
m_shader_source->addShaderConstantSetterFactory(
new FogShaderConstantSetterFactory());
m_cloud.clouds = make_irr<Clouds>(m_smgr, m_shader_source.get(), -1, rand());
m_cloud.clouds->setHeight(100.0f);
m_cloud.clouds->update(v3f(0, 0, 0), video::SColor(255,240,240,255));
m_cloud.camera = m_smgr->addCameraSceneNode(0,
v3f(0,0,0), v3f(0, 60, 100));
m_cloud.camera->setFarValue(10000);
}
/******************************************************************************/
void GUIEngine::drawClouds(float dtime)
{
m_cloud.clouds->step(dtime*3);
m_smgr->drawAll();
g_menuclouds->step(dtime * 3);
g_menucloudsmgr->drawAll();
}
/******************************************************************************/

View file

@ -203,8 +203,6 @@ private:
MainMenuData *m_data = nullptr;
/** texture source */
std::unique_ptr<ISimpleTextureSource> m_texture_source;
/** shader source */
std::unique_ptr<IWritableShaderSource> m_shader_source;
/** sound manager */
std::unique_ptr<ISoundManager> m_sound_manager;
@ -279,23 +277,11 @@ private:
/** and text that is in it */
EnrichedString m_toplefttext;
/** initialize cloud subsystem */
void cloudInit();
/** do preprocessing for cloud subsystem */
void drawClouds(float dtime);
/** internam data required for drawing clouds */
struct clouddata {
/** pointer to cloud class */
irr_ptr<Clouds> clouds;
/** camera required for drawing clouds */
scene::ICameraSceneNode *camera = nullptr;
};
/** is drawing of clouds enabled atm */
bool m_clouds_enabled = true;
/** data used to draw clouds */
clouddata m_cloud;
bool m_clouds_enabled = true;
static void fullscreenChangedCallback(const std::string &name, void *data);
};

View file

@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <IGUIImage.h>
#include <IAnimatedMeshSceneNode.h>
#include "client/renderingengine.h"
#include "client/joystick_controller.h"
#include "log.h"
#include "client/hud.h" // drawItemStack
#include "filesys.h"
@ -315,7 +316,7 @@ void GUIFormSpecMenu::parseSize(parserData* data, const std::string &element)
data->invsize.Y = MYMAX(0, stof(parts[1]));
lockSize(false);
if (!g_settings->getBool("enable_touch") && parts.size() == 3) {
if (!g_settings->getBool("touch_gui") && parts.size() == 3) {
if (parts[2] == "true") {
lockSize(true,v2u32(800,600));
}
@ -342,7 +343,7 @@ void GUIFormSpecMenu::parseContainer(parserData* data, const std::string &elemen
errorstream<< "Invalid container start element (" << parts.size() << "): '" << element << "'" << std::endl;
}
void GUIFormSpecMenu::parseContainerEnd(parserData* data)
void GUIFormSpecMenu::parseContainerEnd(parserData* data, const std::string &)
{
if (container_stack.empty()) {
errorstream<< "Invalid container end element, no matching container start element" << std::endl;
@ -419,7 +420,7 @@ void GUIFormSpecMenu::parseScrollContainer(parserData *data, const std::string &
pos_offset.Y = 0.0f;
}
void GUIFormSpecMenu::parseScrollContainerEnd(parserData *data)
void GUIFormSpecMenu::parseScrollContainerEnd(parserData *data, const std::string &)
{
if (data->current_parent == this || data->current_parent->getParent() == this ||
container_stack.empty()) {
@ -641,6 +642,11 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data, const std::string &element
m_fields.push_back(spec);
}
void GUIFormSpecMenu::parseRealCoordinates(parserData* data, const std::string &element)
{
data->real_coordinates = is_yes(element);
}
void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &element)
{
std::vector<std::string> parts;
@ -973,10 +979,9 @@ void GUIFormSpecMenu::parseItemImage(parserData* data, const std::string &elemen
m_fields.push_back(spec);
}
void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element,
const std::string &type)
void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element)
{
int expected_parts = (type == "button_url" || type == "button_url_exit") ? 5 : 4;
int expected_parts = (data->type == "button_url" || data->type == "button_url_exit") ? 5 : 4;
std::vector<std::string> parts;
if (!precheckElement("button", element, expected_parts, expected_parts, parts))
return;
@ -986,7 +991,7 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element,
std::string name = parts[2];
std::string label = parts[3];
std::string url;
if (type == "button_url" || type == "button_url_exit")
if (data->type == "button_url" || data->type == "button_url_exit")
url = parts[4];
MY_CHECKPOS("button",0);
@ -1022,15 +1027,15 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element,
258 + m_fields.size()
);
spec.ftype = f_Button;
if (type == "button_exit" || type == "button_url_exit")
if (data->type == "button_exit" || data->type == "button_url_exit")
spec.is_exit = true;
if (type == "button_url" || type == "button_url_exit")
if (data->type == "button_url" || data->type == "button_url_exit")
spec.url = url;
GUIButton *e = GUIButton::addButton(Environment, rect, m_tsrc,
data->current_parent, spec.fid, spec.flabel.c_str());
auto style = getStyleForElement(type, name, (type != "button") ? "button" : "");
auto style = getStyleForElement(data->type, name, (data->type != "button") ? "button" : "");
spec.sound = style[StyleSpec::STATE_DEFAULT].get(StyleSpec::Property::SOUND, "");
@ -1188,7 +1193,9 @@ void GUIFormSpecMenu::parseTable(parserData* data, const std::string &element)
std::vector<std::string> v_pos = split(parts[0],',');
std::vector<std::string> v_geom = split(parts[1],',');
std::string name = parts[2];
std::vector<std::string> items = split(parts[3],',');
std::vector<std::string> items;
if (!parts[3].empty())
items = split(parts[3],',');
std::string str_initial_selection;
if (parts.size() >= 5)
@ -1258,7 +1265,9 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element
std::vector<std::string> v_pos = split(parts[0],',');
std::vector<std::string> v_geom = split(parts[1],',');
std::string name = parts[2];
std::vector<std::string> items = split(parts[3],',');
std::vector<std::string> items;
if (!parts[3].empty())
items = split(parts[3],',');
std::string str_initial_selection;
std::string str_transparent = "false";
@ -1686,11 +1695,10 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector<std::string>&
m_fields.push_back(spec);
}
void GUIFormSpecMenu::parseField(parserData* data, const std::string &element,
const std::string &type)
void GUIFormSpecMenu::parseField(parserData* data, const std::string &element)
{
std::vector<std::string> parts;
if (!precheckElement(type, element, 3, 5, parts))
if (!precheckElement(data->type, element, 3, 5, parts))
return;
if (parts.size() == 3 || parts.size() == 4) {
@ -1699,7 +1707,7 @@ void GUIFormSpecMenu::parseField(parserData* data, const std::string &element,
}
// Else: >= 5 arguments in "parts"
parseTextArea(data, parts, type);
parseTextArea(data, parts, data->type);
}
void GUIFormSpecMenu::parseHyperText(parserData *data, const std::string &element)
@ -1922,8 +1930,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen
m_clickthrough_elements.push_back(e);
}
void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &element,
const std::string &type)
void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &element)
{
std::vector<std::string> parts;
if (!precheckElement("image_button", element, 5, 8, parts))
@ -1980,7 +1987,8 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem
258 + m_fields.size()
);
spec.ftype = f_Button;
if (type == "image_button_exit")
if (data->type == "image_button_exit")
spec.is_exit = true;
GUIButtonImage *e = GUIButtonImage::addButton(Environment, rect, m_tsrc,
@ -2580,14 +2588,21 @@ void GUIFormSpecMenu::parsePadding(parserData *data, const std::string &element)
<< "'" << std::endl;
}
bool GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element, bool style_type)
void GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element)
{
if (data->type != "style" && data->type != "style_type") {
errorstream << "Invalid style element type: '" << data->type << "'" << std::endl;
return;
}
bool style_type = (data->type == "style_type");
std::vector<std::string> parts = split(element, ';');
if (parts.size() < 2) {
errorstream << "Invalid style element (" << parts.size() << "): '" << element
<< "'" << std::endl;
return false;
return;
}
StyleSpec spec;
@ -2598,7 +2613,7 @@ bool GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element, b
if (equal_pos == std::string::npos) {
errorstream << "Invalid style element (Property missing value): '" << element
<< "'" << std::endl;
return false;
return;
}
std::string propname = trim(parts[i].substr(0, equal_pos));
@ -2713,10 +2728,10 @@ bool GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element, b
}
}
return true;
return;
}
void GUIFormSpecMenu::parseSetFocus(const std::string &element)
void GUIFormSpecMenu::parseSetFocus(parserData*, const std::string &element)
{
std::vector<std::string> parts;
if (!precheckElement("set_focus", element, 1, 2, parts))
@ -2793,8 +2808,13 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
auto meshnode = e->setMesh(mesh);
for (u32 i = 0; i < textures.size() && i < meshnode->getMaterialCount(); ++i)
e->setTexture(i, m_tsrc->getTexture(unescape_string(textures[i])));
for (u32 i = 0; i < meshnode->getMaterialCount(); ++i) {
const auto texture_idx = mesh->getTextureSlot(i);
if (texture_idx >= textures.size())
warningstream << "Invalid model element: Not enough textures" << std::endl;
else
e->setTexture(i, m_tsrc->getTexture(unescape_string(textures[texture_idx])));
}
if (vec_rot.size() >= 2)
e->setRotation(v2f(stof(vec_rot[0]), stof(vec_rot[1])));
@ -2842,6 +2862,55 @@ void GUIFormSpecMenu::removeAll()
scroll_container_it.second->drop();
}
const std::unordered_map<std::string, std::function<void(GUIFormSpecMenu*, GUIFormSpecMenu::parserData *data,
const std::string &description)>> GUIFormSpecMenu::element_parsers = {
{"container", &GUIFormSpecMenu::parseContainer},
{"container_end", &GUIFormSpecMenu::parseContainerEnd},
{"list", &GUIFormSpecMenu::parseList},
{"listring", &GUIFormSpecMenu::parseListRing},
{"checkbox", &GUIFormSpecMenu::parseCheckbox},
{"image", &GUIFormSpecMenu::parseImage},
{"animated_image", &GUIFormSpecMenu::parseAnimatedImage},
{"item_image", &GUIFormSpecMenu::parseItemImage},
{"button", &GUIFormSpecMenu::parseButton},
{"button_exit", &GUIFormSpecMenu::parseButton},
{"button_url", &GUIFormSpecMenu::parseButton},
{"button_url_exit", &GUIFormSpecMenu::parseButton},
{"background", &GUIFormSpecMenu::parseBackground},
{"background9", &GUIFormSpecMenu::parseBackground},
{"tableoptions", &GUIFormSpecMenu::parseTableOptions},
{"tablecolumns", &GUIFormSpecMenu::parseTableColumns},
{"table", &GUIFormSpecMenu::parseTable},
{"textlist", &GUIFormSpecMenu::parseTextList},
{"dropdown", &GUIFormSpecMenu::parseDropDown},
{"field_enter_after_edit", &GUIFormSpecMenu::parseFieldEnterAfterEdit},
{"field_close_on_enter", &GUIFormSpecMenu::parseFieldCloseOnEnter},
{"pwdfield", &GUIFormSpecMenu::parsePwdField},
{"field", &GUIFormSpecMenu::parseField},
{"textarea", &GUIFormSpecMenu::parseField},
{"hypertext", &GUIFormSpecMenu::parseHyperText},
{"label", &GUIFormSpecMenu::parseLabel},
{"vertlabel", &GUIFormSpecMenu::parseVertLabel},
{"item_image_button", &GUIFormSpecMenu::parseItemImageButton},
{"image_button", &GUIFormSpecMenu::parseImageButton},
{"image_button_exit", &GUIFormSpecMenu::parseImageButton},
{"tabheader", &GUIFormSpecMenu::parseTabHeader},
{"box", &GUIFormSpecMenu::parseBox},
{"bgcolor", &GUIFormSpecMenu::parseBackgroundColor},
{"listcolors", &GUIFormSpecMenu::parseListColors},
{"tooltip", &GUIFormSpecMenu::parseTooltip},
{"scrollbar", &GUIFormSpecMenu::parseScrollBar},
{"real_coordinates", &GUIFormSpecMenu::parseRealCoordinates},
{"style", &GUIFormSpecMenu::parseStyle},
{"style_type", &GUIFormSpecMenu::parseStyle},
{"scrollbaroptions", &GUIFormSpecMenu::parseScrollBarOptions},
{"scroll_container", &GUIFormSpecMenu::parseScrollContainer},
{"scroll_container_end", &GUIFormSpecMenu::parseScrollContainerEnd},
{"set_focus", &GUIFormSpecMenu::parseSetFocus},
{"model", &GUIFormSpecMenu::parseModel},
};
void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
{
//some prechecks
@ -2858,195 +2927,15 @@ void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
std::string type = trim(element.substr(0, pos));
std::string description = element.substr(pos+1);
if (type == "container") {
parseContainer(data, description);
// They remain here due to bool flags, for now
data->type = type;
auto it = element_parsers.find(type);
if (it != element_parsers.end()) {
it->second(this, data, description);
return;
}
if (type == "container_end") {
parseContainerEnd(data);
return;
}
if (type == "list") {
parseList(data, description);
return;
}
if (type == "listring") {
parseListRing(data, description);
return;
}
if (type == "checkbox") {
parseCheckbox(data, description);
return;
}
if (type == "image") {
parseImage(data, description);
return;
}
if (type == "animated_image") {
parseAnimatedImage(data, description);
return;
}
if (type == "item_image") {
parseItemImage(data, description);
return;
}
if (type == "button" || type == "button_exit" || type == "button_url" || type == "button_url_exit") {
parseButton(data, description, type);
return;
}
if (type == "background" || type == "background9") {
parseBackground(data, description);
return;
}
if (type == "tableoptions"){
parseTableOptions(data,description);
return;
}
if (type == "tablecolumns"){
parseTableColumns(data,description);
return;
}
if (type == "table"){
parseTable(data,description);
return;
}
if (type == "textlist"){
parseTextList(data,description);
return;
}
if (type == "dropdown"){
parseDropDown(data,description);
return;
}
if (type == "field_enter_after_edit") {
parseFieldEnterAfterEdit(data, description);
return;
}
if (type == "field_close_on_enter") {
parseFieldCloseOnEnter(data, description);
return;
}
if (type == "pwdfield") {
parsePwdField(data,description);
return;
}
if ((type == "field") || (type == "textarea")){
parseField(data,description,type);
return;
}
if (type == "hypertext") {
parseHyperText(data,description);
return;
}
if (type == "label") {
parseLabel(data,description);
return;
}
if (type == "vertlabel") {
parseVertLabel(data,description);
return;
}
if (type == "item_image_button") {
parseItemImageButton(data,description);
return;
}
if ((type == "image_button") || (type == "image_button_exit")) {
parseImageButton(data,description,type);
return;
}
if (type == "tabheader") {
parseTabHeader(data,description);
return;
}
if (type == "box") {
parseBox(data,description);
return;
}
if (type == "bgcolor") {
parseBackgroundColor(data,description);
return;
}
if (type == "listcolors") {
parseListColors(data,description);
return;
}
if (type == "tooltip") {
parseTooltip(data,description);
return;
}
if (type == "scrollbar") {
parseScrollBar(data, description);
return;
}
if (type == "real_coordinates") {
data->real_coordinates = is_yes(description);
return;
}
if (type == "style") {
parseStyle(data, description, false);
return;
}
if (type == "style_type") {
parseStyle(data, description, true);
return;
}
if (type == "scrollbaroptions") {
parseScrollBarOptions(data, description);
return;
}
if (type == "scroll_container") {
parseScrollContainer(data, description);
return;
}
if (type == "scroll_container_end") {
parseScrollContainerEnd(data);
return;
}
if (type == "set_focus") {
parseSetFocus(description);
return;
}
if (type == "model") {
parseModel(data, description);
return;
}
// Ignore others
infostream << "Unknown DrawSpec: type=" << type << ", data=\"" << description << "\""
@ -3244,58 +3133,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
offset = v2s32(0,0);
}
const double gui_scaling = g_settings->getFloat("gui_scaling", 0.5f, 42.0f);
const double screen_dpi = RenderingEngine::getDisplayDensity() * 96;
double use_imgsize;
if (m_lock) {
// In fixed-size mode, inventory image size
// is 0.53 inch multiplied by the gui_scaling
// config parameter. This magic size is chosen
// to make the main menu (15.5 inventory images
// wide, including border) just fit into the
// default window (800 pixels wide) at 96 DPI
// and default scaling (1.00).
use_imgsize = 0.5555 * screen_dpi * gui_scaling;
} else {
// Variables for the maximum imgsize that can fit in the screen.
double fitx_imgsize;
double fity_imgsize;
v2f padded_screensize(
mydata.screensize.X * (1.0f - mydata.padding.X * 2.0f),
mydata.screensize.Y * (1.0f - mydata.padding.Y * 2.0f)
);
if (mydata.real_coordinates) {
fitx_imgsize = padded_screensize.X / mydata.invsize.X;
fity_imgsize = padded_screensize.Y / mydata.invsize.Y;
} else {
// The maximum imgsize in the old coordinate system also needs to
// factor in padding and spacing along with 0.1 inventory slot spare
// and help text space, hence the magic numbers.
fitx_imgsize = padded_screensize.X /
((5.0 / 4.0) * (0.5 + mydata.invsize.X));
fity_imgsize = padded_screensize.Y /
((15.0 / 13.0) * (0.85 + mydata.invsize.Y));
}
s32 min_screen_dim = std::min(padded_screensize.X, padded_screensize.Y);
double prefer_imgsize;
if (g_settings->getBool("enable_touch")) {
// The preferred imgsize should be larger to accommodate the
// smaller screensize.
prefer_imgsize = min_screen_dim / 10 * gui_scaling;
} else {
// Desktop computers have more space, so try to fit 15 coordinates.
prefer_imgsize = min_screen_dim / 15 * gui_scaling;
}
// Try to use the preferred imgsize, but if that's bigger than the maximum
// size, use the maximum size.
use_imgsize = std::min(prefer_imgsize,
std::min(fitx_imgsize, fity_imgsize));
}
double use_imgsize = calculateImgsize(mydata);
// Everything else is scaled in proportion to the
// inventory image size. The inventory slot spacing
@ -4098,6 +3936,8 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
skin->setFont(m_font);
bool retval = hovered->OnEvent(event);
skin->setFont(old_font);
// This is expected to be set to BET_OTHER with mouse UP event
m_held_mouse_button = BET_OTHER;
return retval;
}
}
@ -4105,7 +3945,7 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
// Fix Esc/Return key being eaten by checkboxen and tables
if (event.EventType == EET_KEY_INPUT_EVENT) {
KeyPress kp(event.KeyInput);
if (kp == EscapeKey || kp == CancelKey
if (kp == EscapeKey
|| kp == getKeySetting("keymap_inventory")
|| event.KeyInput.Key==KEY_RETURN) {
gui::IGUIElement *focused = Environment->getFocus();
@ -4136,10 +3976,9 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
}
if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) {
/* TODO add a check like:
if (event.JoystickEvent != joystick_we_listen_for)
if (event.JoystickEvent.Joystick != m_joystick->getJoystickId())
return false;
*/
bool handled = m_joystick->handleEvent(event.JoystickEvent);
if (handled) {
if (m_joystick->wasKeyDown(KeyType::ESC)) {
@ -4173,7 +4012,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
if (event.EventType==EET_KEY_INPUT_EVENT) {
KeyPress kp(event.KeyInput);
if (event.KeyInput.PressedDown && (
(kp == EscapeKey) || (kp == CancelKey) ||
(kp == EscapeKey) ||
((m_client != NULL) && (kp == getKeySetting("keymap_inventory"))))) {
tryClose();
return true;
@ -4184,8 +4023,10 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
m_client->makeScreenshot();
}
if (event.KeyInput.PressedDown && kp == getKeySetting("keymap_toggle_debug"))
m_show_debug = !m_show_debug;
if (event.KeyInput.PressedDown && kp == getKeySetting("keymap_toggle_debug")) {
if (!m_client || m_client->checkPrivilege("debug"))
m_show_debug = !m_show_debug;
}
if (event.KeyInput.PressedDown &&
(event.KeyInput.Key==KEY_RETURN ||
@ -5179,3 +5020,68 @@ std::array<StyleSpec, StyleSpec::NUM_STATES> GUIFormSpecMenu::getStyleForElement
return ret;
}
double GUIFormSpecMenu::getFixedImgsize(double screen_dpi, double gui_scaling)
{
// In fixed-size mode, inventory image size
// is 0.53 inch multiplied by the gui_scaling
// config parameter. This magic size is chosen
// to make the main menu (15.5 inventory images
// wide, including border) just fit into the
// default window (800 pixels wide) at 96 DPI
// and default scaling (1.00).
return 0.5555 * screen_dpi * gui_scaling;
}
double GUIFormSpecMenu::getImgsize(v2u32 avail_screensize, double screen_dpi, double gui_scaling)
{
double fixed_imgsize = getFixedImgsize(screen_dpi, gui_scaling);
s32 min_screen_dim = std::min(avail_screensize.X, avail_screensize.Y);
double prefer_imgsize = min_screen_dim / 15 * gui_scaling;
// Use the available space more effectively on small windows/screens.
// This is especially important for mobile platforms.
prefer_imgsize = std::max(prefer_imgsize, fixed_imgsize);
return prefer_imgsize;
}
double GUIFormSpecMenu::calculateImgsize(const parserData &data)
{
// must stay in sync with ClientDynamicInfo::calculateMaxFSSize
const double screen_dpi = RenderingEngine::getDisplayDensity() * 96;
const double gui_scaling = g_settings->getFloat("gui_scaling", 0.5f, 42.0f);
// Fixed-size mode
if (m_lock)
return getFixedImgsize(screen_dpi, gui_scaling);
// Variables for the maximum imgsize that can fit in the screen.
double fitx_imgsize;
double fity_imgsize;
v2f padded_screensize(
data.screensize.X * (1.0f - data.padding.X * 2.0f),
data.screensize.Y * (1.0f - data.padding.Y * 2.0f)
);
if (data.real_coordinates) {
fitx_imgsize = padded_screensize.X / data.invsize.X;
fity_imgsize = padded_screensize.Y / data.invsize.Y;
} else {
// The maximum imgsize in the old coordinate system also needs to
// factor in padding and spacing along with 0.1 inventory slot spare
// and help text space, hence the magic numbers.
fitx_imgsize = padded_screensize.X /
((5.0 / 4.0) * (0.5 + data.invsize.X));
fity_imgsize = padded_screensize.Y /
((15.0 / 13.0) * (0.85 + data.invsize.Y));
}
double prefer_imgsize = getImgsize(v2u32(padded_screensize.X, padded_screensize.Y),
screen_dpi, gui_scaling);
// Try to use the preferred imgsize, but if that's bigger than the maximum
// size, use the maximum size.
return std::min(prefer_imgsize, std::min(fitx_imgsize, fity_imgsize));
}

View file

@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <stack>
#include <unordered_set>
#include "irrlichttypes_extrabloated.h"
#include "irrlichttypes_bloated.h"
#include "irr_ptr.h"
#include "inventory.h"
#include "inventorymanager.h"
@ -32,11 +32,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiInventoryList.h"
#include "guiScrollBar.h"
#include "guiTable.h"
#include "network/networkprotocol.h"
#include "client/joystick_controller.h"
#include "util/string.h"
#include "util/enriched_string.h"
#include "StyleSpec.h"
#include <ICursorControl.h> // gui::ECURSOR_ICON
#include <IGUIStaticText.h>
class InventoryManager;
@ -44,6 +43,7 @@ class ISimpleTextureSource;
class Client;
class GUIScrollContainer;
class ISoundManager;
class JoystickController;
enum FormspecFieldType {
f_Button,
@ -223,6 +223,11 @@ public:
m_allowclose = value;
}
void setDebugView(bool value)
{
m_show_debug = value;
}
void lockSize(bool lock,v2u32 basescreensize=v2u32(0,0))
{
m_lock = lock;
@ -291,6 +296,11 @@ public:
void getAndroidUIInput();
#endif
// Returns the fixed formspec coordinate size for the given parameters.
static double getFixedImgsize(double screen_dpi, double gui_scaling);
// Returns the preferred non-fixed formspec coordinate size for the given parameters.
static double getImgsize(v2u32 avail_screensize, double screen_dpi, double gui_scaling);
protected:
v2s32 getBasePos() const
{
@ -418,8 +428,11 @@ private:
// used to restore table selection/scroll/treeview state
std::unordered_map<std::string, GUITable::DynamicData> table_dyndata;
std::string type;
};
static const std::unordered_map<std::string, std::function<void(GUIFormSpecMenu*, GUIFormSpecMenu::parserData *data, const std::string &description)>> element_parsers;
struct fs_key_pending {
bool key_up;
bool key_down;
@ -437,17 +450,16 @@ private:
void parseSize(parserData* data, const std::string &element);
void parseContainer(parserData* data, const std::string &element);
void parseContainerEnd(parserData* data);
void parseContainerEnd(parserData* data, const std::string &element);
void parseScrollContainer(parserData *data, const std::string &element);
void parseScrollContainerEnd(parserData *data);
void parseScrollContainerEnd(parserData *data, const std::string &element);
void parseList(parserData* data, const std::string &element);
void parseListRing(parserData* data, const std::string &element);
void parseCheckbox(parserData* data, const std::string &element);
void parseImage(parserData* data, const std::string &element);
void parseAnimatedImage(parserData *data, const std::string &element);
void parseItemImage(parserData* data, const std::string &element);
void parseButton(parserData* data, const std::string &element,
const std::string &typ);
void parseButton(parserData* data, const std::string &element);
void parseBackground(parserData* data, const std::string &element);
void parseTableOptions(parserData* data, const std::string &element);
void parseTableColumns(parserData* data, const std::string &element);
@ -457,7 +469,7 @@ private:
void parseFieldEnterAfterEdit(parserData *data, const std::string &element);
void parseFieldCloseOnEnter(parserData *data, const std::string &element);
void parsePwdField(parserData* data, const std::string &element);
void parseField(parserData* data, const std::string &element, const std::string &type);
void parseField(parserData* data, const std::string &element);
void createTextField(parserData *data, FieldSpec &spec,
core::rect<s32> &rect, bool is_multiline);
void parseSimpleField(parserData* data,std::vector<std::string> &parts);
@ -466,8 +478,7 @@ private:
void parseHyperText(parserData *data, const std::string &element);
void parseLabel(parserData* data, const std::string &element);
void parseVertLabel(parserData* data, const std::string &element);
void parseImageButton(parserData* data, const std::string &element,
const std::string &type);
void parseImageButton(parserData* data, const std::string &element);
void parseItemImageButton(parserData* data, const std::string &element);
void parseTabHeader(parserData* data, const std::string &element);
void parseBox(parserData* data, const std::string &element);
@ -476,6 +487,7 @@ private:
void parseTooltip(parserData* data, const std::string &element);
bool parseVersionDirect(const std::string &data);
bool parseSizeDirect(parserData* data, const std::string &element);
void parseRealCoordinates(parserData* data, const std::string &element);
void parseScrollBar(parserData* data, const std::string &element);
void parseScrollBarOptions(parserData *data, const std::string &element);
bool parsePositionDirect(parserData *data, const std::string &element);
@ -484,8 +496,8 @@ private:
void parseAnchor(parserData *data, const std::string &element);
bool parsePaddingDirect(parserData *data, const std::string &element);
void parsePadding(parserData *data, const std::string &element);
bool parseStyle(parserData *data, const std::string &element, bool style_type);
void parseSetFocus(const std::string &element);
void parseStyle(parserData *data, const std::string &element);
void parseSetFocus(parserData *, const std::string &element);
void parseModel(parserData *data, const std::string &element);
bool parseMiddleRect(const std::string &value, core::rect<s32> *parsed_rect);
@ -507,6 +519,9 @@ private:
// used by getAbsoluteRect
s32 m_tabheader_upper_edge = 0;
// Determines the size (in pixels) of formspec coordinate units.
double calculateImgsize(const parserData &data);
};
class FormspecFormSource: public IFormSource

View file

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiHyperText.h"
#include "guiScrollBar.h"
#include "client/fontengine.h"
#include "client/hud.h" // drawItemStack
#include "IVideoDriver.h"
#include "client/client.h"
#include "client/renderingengine.h"

View file

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiFormSpecMenu.h"
#include "client/hud.h"
#include "client/client.h"
#include <IVideoDriver.h>
GUIInventoryList::GUIInventoryList(gui::IGUIEnvironment *env,
gui::IGUIElement *parent,

View file

@ -19,7 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiItemImage.h"
#include "client/client.h"
#include "client/hud.h" // drawItemStack
#include "inventory.h"
#include <IGUIFont.h>
GUIItemImage::GUIItemImage(gui::IGUIEnvironment *env, gui::IGUIElement *parent,
s32 id, const core::rect<s32> &rectangle, const std::string &item_name,

View file

@ -29,6 +29,7 @@
#include <IGUIButton.h>
#include <IGUIStaticText.h>
#include <IGUIFont.h>
#include <IVideoDriver.h>
#include "settings.h"
#include <algorithm>
@ -377,6 +378,7 @@ void GUIKeyChangeMenu::add_key(int id, std::wstring button_name, const std::stri
key_settings.push_back(k);
}
// compare with button_titles in touchcontrols.cpp
void GUIKeyChangeMenu::init_keys()
{
this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wstrgettext("Forward"), "keymap_forward");

View file

@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "guiEditBoxWithScrollbar.h"
#include <IGUIEditBox.h>
#include <IGUIFont.h>
#include <IVideoDriver.h>
#include "client/renderingengine.h"
#include "porting.h"
#include "gettext.h"
@ -160,9 +161,7 @@ void GUIOpenURLMenu::drawMenu()
bool GUIOpenURLMenu::OnEvent(const SEvent &event)
{
if (event.EventType == EET_KEY_INPUT_EVENT) {
if ((event.KeyInput.Key == KEY_ESCAPE ||
event.KeyInput.Key == KEY_CANCEL) &&
event.KeyInput.PressedDown) {
if (event.KeyInput.Key == KEY_ESCAPE && event.KeyInput.PressedDown) {
quitMenu();
return true;
}

View file

@ -24,6 +24,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <IGUIButton.h>
#include <IGUIStaticText.h>
#include <IGUIFont.h>
#include <IVideoDriver.h>
#include "porting.h"
#include "gettext.h"
@ -187,9 +188,7 @@ bool GUIPasswordChange::processInput()
bool GUIPasswordChange::OnEvent(const SEvent &event)
{
if (event.EventType == EET_KEY_INPUT_EVENT) {
if ((event.KeyInput.Key == KEY_ESCAPE ||
event.KeyInput.Key == KEY_CANCEL) &&
event.KeyInput.PressedDown) {
if (event.KeyInput.Key == KEY_ESCAPE && event.KeyInput.PressedDown) {
quitMenu();
return true;
}

View file

@ -18,6 +18,7 @@
*/
#include "guiPathSelectMenu.h"
#include "guiFormSpecMenu.h" //required because of TextDest only !!!
GUIFileSelectMenu::GUIFileSelectMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr,

Some files were not shown because too many files have changed in this diff Show more