diff --git a/src/camera.cpp b/src/camera.cpp index 94bbe9880386f9c16fc42d4ec85e371abc1d7aba..8aac32123b42042f06fd06ec9145b5e1d03fbd67 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/numeric.h" #include "util/mathconstants.h" #include "constants.h" +#include "fontengine.h" #define CAMERA_OFFSET_STEP 200 @@ -81,6 +82,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control, { //dstream<<FUNCTION_NAME<<std::endl; + m_driver = smgr->getVideoDriver(); // note: making the camera node a child of the player node // would lead to unexpected behaviour, so we don't do that. m_playernode = smgr->addEmptySceneNode(smgr->getRootSceneNode()); @@ -110,6 +112,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control, m_cache_wanted_fps = g_settings->getFloat("wanted_fps"); m_cache_fov = g_settings->getFloat("fov"); m_cache_view_bobbing = g_settings->getBool("view_bobbing"); + m_nametags.clear(); } Camera::~Camera() @@ -662,3 +665,49 @@ void Camera::drawWieldedTool(irr::core::matrix4* translation) } m_wieldmgr->drawAll(); } + +void Camera::drawNametags() +{ + core::matrix4 trans = m_cameranode->getProjectionMatrix(); + trans *= m_cameranode->getViewMatrix(); + + for (std::list<Nametag *>::const_iterator + i = m_nametags.begin(); + i != m_nametags.end(); ++i) { + Nametag *nametag = *i; + v3f pos = nametag->parent_node->getPosition() - + intToFloat(m_camera_offset, BS) + v3f(0.0, 1.1 * BS, 0.0); + f32 transformed_pos[4] = { pos.X, pos.Y, pos.Z, 1.0f }; + trans.multiplyWith1x4Matrix(transformed_pos); + if (transformed_pos[3] > 0) { + core::dimension2d<u32> textsize = + g_fontengine->getFont()->getDimension( + utf8_to_wide(nametag->nametag_text).c_str()); + f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f : + core::reciprocal(transformed_pos[3]); + v2u32 screensize = m_driver->getScreenSize(); + v2s32 screen_pos; + screen_pos.X = screensize.X * + (0.5 * transformed_pos[0] * zDiv + 0.5) - textsize.Width / 2; + screen_pos.Y = screensize.Y * + (0.5 - transformed_pos[1] * zDiv * 0.5) - textsize.Height / 2; + core::rect<s32> size(0, 0, textsize.Width, textsize.Height); + g_fontengine->getFont()->draw(utf8_to_wide(nametag->nametag_text).c_str(), + size + screen_pos, nametag->nametag_color); + } + } +} + +Nametag *Camera::addNametag(scene::ISceneNode *parent_node, + std::string nametag_text, video::SColor nametag_color) +{ + Nametag *nametag = new Nametag(parent_node, nametag_text, nametag_color); + m_nametags.push_back(nametag); + return nametag; +} + +void Camera::removeNametag(Nametag *nametag) +{ + m_nametags.remove(nametag); + delete nametag; +} diff --git a/src/camera.h b/src/camera.h index 006f4b3cebadf1a74f9e682d2e1ed74b9bd54198..2df7da2b83be5a196bdfab763f9294af43d884cb 100644 --- a/src/camera.h +++ b/src/camera.h @@ -26,6 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/tile.h" #include "util/numeric.h" #include <ICameraSceneNode.h> +#include <ISceneNode.h> +#include <list> #include "client.h" @@ -34,6 +36,20 @@ struct MapDrawControl; class IGameDef; class WieldMeshSceneNode; +struct Nametag { + Nametag(scene::ISceneNode *a_parent_node, + const std::string &a_nametag_text, + const video::SColor &a_nametag_color): + parent_node(a_parent_node), + nametag_text(a_nametag_text), + nametag_color(a_nametag_color) + { + } + scene::ISceneNode *parent_node; + std::string nametag_text; + video::SColor nametag_color; +}; + enum CameraMode {CAMERA_MODE_FIRST, CAMERA_MODE_THIRD, CAMERA_MODE_THIRD_FRONT}; /* @@ -84,7 +100,7 @@ class Camera { return m_camera_direction; } - + // Get the camera offset inline v3s16 getOffset() const { @@ -151,6 +167,13 @@ class Camera return m_camera_mode; } + Nametag *addNametag(scene::ISceneNode *parent_node, + std::string nametag_text, video::SColor nametag_color); + + void removeNametag(Nametag *nametag); + + void drawNametags(); + private: // Nodes scene::ISceneNode* m_playernode; @@ -162,8 +185,9 @@ class Camera // draw control MapDrawControl& m_draw_control; - + IGameDef *m_gamedef; + video::IVideoDriver *m_driver; // Absolute camera position v3f m_camera_position; @@ -214,6 +238,8 @@ class Camera f32 m_cache_wanted_fps; f32 m_cache_fov; bool m_cache_view_bobbing; + + std::list<Nametag *> m_nametags; }; #endif diff --git a/src/client.cpp b/src/client.cpp index ed5ff96fefad4f3c24fddda1931ff37712820a36..3fe67d64597dd110eb254e3228c318fa3db33edb 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -228,6 +228,7 @@ Client::Client( m_particle_manager(&m_env), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, ipv6, this), m_device(device), + m_camera(NULL), m_minimap_disabled_by_server(false), m_server_ser_ver(SER_FMT_VER_INVALID), m_proto_ver(0), diff --git a/src/client.h b/src/client.h index c16e9b77aee6f1d9fdab26607fa4d3455e88af6a..cdadb9d3ea42b1f2566f0a48fcb3524a1477345c 100644 --- a/src/client.h +++ b/src/client.h @@ -50,6 +50,7 @@ struct PointedThing; class Database; class Mapper; struct MinimapMapblock; +class Camera; struct QueuedMeshUpdate { @@ -507,6 +508,12 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef Mapper* getMapper () { return m_mapper; } + void setCamera(Camera* camera) + { m_camera = camera; } + + Camera* getCamera () + { return m_camera; } + bool isMinimapDisabledByServer() { return m_minimap_disabled_by_server; } @@ -589,6 +596,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef ParticleManager m_particle_manager; con::Connection m_con; IrrlichtDevice *m_device; + Camera *m_camera; Mapper *m_mapper; bool m_minimap_disabled_by_server; // Server serialization version diff --git a/src/content_cao.cpp b/src/content_cao.cpp index e7c7a0be5fbf8eace98a7f6760cf42ded7f8f201..d701e4f725d66c04d127ece4754024bf90d1315a 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -546,12 +546,14 @@ GenericCAO::GenericCAO(IGameDef *gamedef, ClientEnvironment *env): // m_smgr(NULL), m_irr(NULL), + m_camera(NULL), + m_gamedef(NULL), m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.), m_meshnode(NULL), m_animated_meshnode(NULL), m_wield_meshnode(NULL), m_spritenode(NULL), - m_textnode(NULL), + m_nametag(NULL), m_position(v3f(0,10*BS,0)), m_velocity(v3f(0,0,0)), m_acceleration(v3f(0,0,0)), @@ -580,8 +582,11 @@ GenericCAO::GenericCAO(IGameDef *gamedef, ClientEnvironment *env): m_last_light(255), m_is_visible(false) { - if(gamedef == NULL) + if (gamedef == NULL) { ClientActiveObject::registerType(getType(), create); + } else { + m_gamedef = gamedef; + } } bool GenericCAO::getCollisionBox(aabb3f *toset) @@ -667,8 +672,7 @@ void GenericCAO::initialize(const std::string &data) GenericCAO::~GenericCAO() { - if(m_is_player) - { + if (m_is_player) { m_env->removePlayerName(m_name.c_str()); } removeFromScene(true); @@ -695,14 +699,15 @@ v3f GenericCAO::getPosition() scene::ISceneNode* GenericCAO::getSceneNode() { - if (m_meshnode) + if (m_meshnode) { return m_meshnode; - if (m_animated_meshnode) + } else if (m_animated_meshnode) { return m_animated_meshnode; - if (m_wield_meshnode) + } else if (m_wield_meshnode) { return m_wield_meshnode; - if (m_spritenode) + } else if (m_spritenode) { return m_spritenode; + } return NULL; } @@ -775,56 +780,47 @@ void GenericCAO::removeFromScene(bool permanent) } } - if(m_meshnode) - { + if (m_meshnode) { m_meshnode->remove(); m_meshnode->drop(); m_meshnode = NULL; - } - if(m_animated_meshnode) - { + } else if (m_animated_meshnode) { m_animated_meshnode->remove(); m_animated_meshnode->drop(); m_animated_meshnode = NULL; - } - if(m_wield_meshnode) - { + } else if (m_wield_meshnode) { m_wield_meshnode->remove(); m_wield_meshnode->drop(); m_wield_meshnode = NULL; - } - if(m_spritenode) - { + } else if (m_spritenode) { m_spritenode->remove(); m_spritenode->drop(); m_spritenode = NULL; } - if (m_textnode) - { - m_textnode->remove(); - m_textnode->drop(); - m_textnode = NULL; + + if (m_nametag) { + m_gamedef->getCamera()->removeNametag(m_nametag); + m_nametag = NULL; } } -void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr) +void GenericCAO::addToScene(scene::ISceneManager *smgr, + ITextureSource *tsrc, IrrlichtDevice *irr) { m_smgr = smgr; m_irr = irr; - if (getSceneNode() != NULL) + if (getSceneNode() != NULL) { return; + } m_visuals_expired = false; - if(!m_prop.is_visible) + if (!m_prop.is_visible) { return; + } - //video::IVideoDriver* driver = smgr->getVideoDriver(); - - if(m_prop.visual == "sprite") - { + if (m_prop.visual == "sprite") { infostream<<"GenericCAO::addToScene(): single_sprite"<<std::endl; m_spritenode = smgr->addBillboardSceneNode( NULL, v2f(1, 1), v3f(0,0,0), -1); @@ -972,18 +968,9 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, scene::ISceneNode *node = getSceneNode(); if (node && m_prop.nametag != "" && !m_is_local_player) { - // Add a text node for showing the name - gui::IGUIEnvironment* gui = irr->getGUIEnvironment(); - std::wstring nametag_text = utf8_to_wide(m_prop.nametag); - m_textnode = smgr->addTextSceneNode(gui->getSkin()->getFont(), - nametag_text.c_str(), m_prop.nametag_color, node); - m_textnode->grab(); - m_textnode->setPosition(v3f(0, BS*1.1, 0)); - - // Enforce hiding nametag, - // because if freetype is enabled, a grey - // shadow can remain. - m_textnode->setVisible(m_prop.nametag_color.getAlpha() > 0); + // Add nametag + m_nametag = m_gamedef->getCamera()->addNametag(node, + m_prop.nametag, m_prop.nametag_color); } updateNodePos(); @@ -1785,12 +1772,8 @@ void GenericCAO::processMessage(const std::string &data) // Deprecated, for backwards compatibility only. readU8(is); // version m_prop.nametag_color = readARGB8(is); - if (m_textnode != NULL) { - m_textnode->setTextColor(m_prop.nametag_color); - - // Enforce hiding nametag, - // because if freetype is enabled, a grey shadow can remain. - m_textnode->setVisible(m_prop.nametag_color.getAlpha() > 0); + if (m_nametag != NULL) { + m_nametag->nametag_color = m_prop.nametag_color; } } } diff --git a/src/content_cao.h b/src/content_cao.h index f71dfeb1f36c16f6c813d08eb1be1ad23d539475..a166ff4943d34bad84bc9214ead733ea48e3d489 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -26,6 +26,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "object_properties.h" #include "itemgroup.h" +class Camera; +struct Nametag; + /* SmoothTranslator */ @@ -65,12 +68,14 @@ class GenericCAO : public ClientActiveObject // scene::ISceneManager *m_smgr; IrrlichtDevice *m_irr; + Camera* m_camera; + IGameDef *m_gamedef; aabb3f m_selection_box; scene::IMeshSceneNode *m_meshnode; scene::IAnimatedMeshSceneNode *m_animated_meshnode; WieldMeshSceneNode *m_wield_meshnode; scene::IBillboardSceneNode *m_spritenode; - scene::ITextSceneNode* m_textnode; + Nametag* m_nametag; v3f m_position; v3f m_velocity; v3f m_acceleration; diff --git a/src/drawscene.cpp b/src/drawscene.cpp index 32eafeb29422e2c087e49bb6206166ce7ab1a221..c6abda4ac135b28efb588396a144ae5471c32437 100644 --- a/src/drawscene.cpp +++ b/src/drawscene.cpp @@ -195,7 +195,7 @@ video::ITexture* draw_hud(video::IVideoDriver* driver, const v2u32& screensize, hud.drawCrosshair(); hud.drawHotbar(client.getPlayerItem()); hud.drawLuaElements(camera.getOffset()); - + camera.drawNametags(); guienv->drawAll(); } @@ -416,6 +416,7 @@ void draw_pageflip_3d_mode(Camera& camera, bool show_hud, camera.drawWieldedTool(&leftMove); hud.drawHotbar(client.getPlayerItem()); hud.drawLuaElements(camera.getOffset()); + camera.drawNametags(); } guienv->drawAll(); @@ -443,6 +444,7 @@ void draw_pageflip_3d_mode(Camera& camera, bool show_hud, camera.drawWieldedTool(&rightMove); hud.drawHotbar(client.getPlayerItem()); hud.drawLuaElements(camera.getOffset()); + camera.drawNametags(); } guienv->drawAll(); @@ -538,8 +540,11 @@ void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr, { if (draw_crosshair) hud.drawCrosshair(); + hud.drawHotbar(client.getPlayerItem()); hud.drawLuaElements(camera.getOffset()); + camera.drawNametags(); + if (show_minimap) mapper.drawMinimap(); } diff --git a/src/game.cpp b/src/game.cpp index 44b35ff5bf402e19c19abda6832be7a2f30abe1b..53db14fb3de5bc59a20ee3d6596775b8f19d0d3a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2087,6 +2087,7 @@ bool Game::createClient(const std::string &playername, camera = new Camera(smgr, *draw_control, gamedef); if (!camera || !camera->successfullyCreated(*error_message)) return false; + client->setCamera(camera); /* Clouds */ diff --git a/src/gamedef.h b/src/gamedef.h index a5f6b596822842397e53b5e77c5e49d3cd7a0a6d..7e3da4cacf8e29d7bbcdc1034f4cf3463136e5bd 100644 --- a/src/gamedef.h +++ b/src/gamedef.h @@ -32,6 +32,8 @@ class IShaderSource; class MtEventManager; class IRollbackManager; class EmergeManager; +class Camera; + namespace irr { namespace scene { class IAnimatedMesh; class ISceneManager; @@ -67,6 +69,10 @@ class IGameDef { return NULL; } virtual scene::ISceneManager* getSceneManager()=0; + virtual Camera* getCamera() + { return NULL; } + virtual void setCamera(Camera *camera) {} + // Only usable on the server, and NOT thread-safe. It is usable from the // environment thread. virtual IRollbackManager* getRollbackManager(){return NULL;}