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:
commit
71e648a776
647 changed files with 60434 additions and 37195 deletions
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -134,6 +134,7 @@ private:
|
|||
f32 corner_levels[2][2];
|
||||
};
|
||||
LiquidData cur_liquid;
|
||||
bool smooth_liquids = false;
|
||||
|
||||
void prepareLiquidNodeDrawing();
|
||||
void getLiquidNeighborhood();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -155,6 +155,11 @@ public:
|
|||
float getMovementDirection();
|
||||
float getMovementSpeed();
|
||||
|
||||
u8 getJoystickId() const
|
||||
{
|
||||
return m_joystick_id;
|
||||
}
|
||||
|
||||
f32 doubling_dtime;
|
||||
|
||||
private:
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -40,3 +40,5 @@
|
|||
#cmakedefine01 CURSES_HAVE_NCURSESW_CURSES_H
|
||||
#cmakedefine01 BUILD_UNITTESTS
|
||||
#cmakedefine01 BUILD_BENCHMARKS
|
||||
#cmakedefine01 USE_SDL2
|
||||
#cmakedefine01 BUILD_WITH_TRACY
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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) :
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue