From 21f1bec72433748e220d19e97a846df83340518e Mon Sep 17 00:00:00 2001 From: RealBadAngel Date: Sun, 26 Jan 2014 21:31:59 +0100 Subject: [PATCH] New HUD element - waypoint. --- doc/lua_api.txt | 8 +++++++- src/client.cpp | 9 +++++++++ src/client.h | 2 ++ src/game.cpp | 10 +++++++++- src/hud.cpp | 35 ++++++++++++++++++++++++++++++--- src/hud.h | 13 ++++++++---- src/script/lua_api/l_object.cpp | 13 ++++++++++++ src/server.cpp | 4 ++++ 8 files changed, 85 insertions(+), 9 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 736f6ca4f..9d97dd6fa 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -507,7 +507,13 @@ Note: Future revisions to the HUD API may be incompatible; the HUD API is still - number: Number of items in the inventory to be displayed. - item: Position of item that is selected. - direction - +- waypoint + Displays distance to selected world position. + - name: The name of the waypoint. + - text: Distance suffix. Can be blank. + - number: An integer containing the RGB value of the color used to draw the text. + - world_pos: World position of the waypoint. + Representations of simple things -------------------------------- Position/vector: diff --git a/src/client.cpp b/src/client.cpp index b2709b6f0..6c4d9eea8 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1941,6 +1941,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) u32 dir = readU32(is); v2f align = readV2F1000(is); v2f offset = readV2F1000(is); + v3f world_pos; + try{ + world_pos = readV3F1000(is); + }catch(SerializationError &e) {}; ClientEvent event; event.type = CE_HUDADD; @@ -1955,6 +1959,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) event.hudadd.dir = dir; event.hudadd.align = new v2f(align); event.hudadd.offset = new v2f(offset); + event.hudadd.world_pos = new v3f(world_pos); m_client_event_queue.push_back(event); } else if(command == TOCLIENT_HUDRM) @@ -1973,6 +1978,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) { std::string sdata; v2f v2fdata; + v3f v3fdata; u32 intdata = 0; std::string datastring((char *)&data[2], datasize - 2); @@ -1986,6 +1992,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) v2fdata = readV2F1000(is); else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT) sdata = deSerializeString(is); + else if (stat == HUD_STAT_WORLD_POS) + v3fdata = readV3F1000(is); else intdata = readU32(is); @@ -1994,6 +2002,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) event.hudchange.id = id; event.hudchange.stat = (HudElementStat)stat; event.hudchange.v2fdata = new v2f(v2fdata); + event.hudchange.v3fdata = new v3f(v3fdata); event.hudchange.sdata = new std::string(sdata); event.hudchange.data = intdata; m_client_event_queue.push_back(event); diff --git a/src/client.h b/src/client.h index 7f13c8149..9a788dfca 100644 --- a/src/client.h +++ b/src/client.h @@ -204,6 +204,7 @@ struct ClientEvent u32 dir; v2f *align; v2f *offset; + v3f *world_pos; } hudadd; struct{ u32 id; @@ -214,6 +215,7 @@ struct ClientEvent v2f *v2fdata; std::string *sdata; u32 data; + v3f *v3fdata; } hudchange; }; }; diff --git a/src/game.cpp b/src/game.cpp index 16fd42f16..407672ac2 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1486,7 +1486,7 @@ void the_game( /* HUD object */ - Hud hud(driver, guienv, font, text_height, + Hud hud(driver, smgr, guienv, font, text_height, gamedef, player, &local_inventory); bool use_weather = g_settings->getBool("weather"); @@ -2376,6 +2376,7 @@ void the_game( delete event.hudadd.text; delete event.hudadd.align; delete event.hudadd.offset; + delete event.hudadd.world_pos; continue; } @@ -2390,6 +2391,7 @@ void the_game( e->dir = event.hudadd.dir; e->align = *event.hudadd.align; e->offset = *event.hudadd.offset; + e->world_pos = *event.hudadd.world_pos; if (id == nhudelem) player->hud.push_back(e); @@ -2402,6 +2404,7 @@ void the_game( delete event.hudadd.text; delete event.hudadd.align; delete event.hudadd.offset; + delete event.hudadd.world_pos; } else if (event.type == CE_HUDRM) { @@ -2415,6 +2418,7 @@ void the_game( { u32 id = event.hudchange.id; if (id >= player->hud.size() || !player->hud[id]) { + delete event.hudchange.v3fdata; delete event.hudchange.v2fdata; delete event.hudchange.sdata; continue; @@ -2449,8 +2453,12 @@ void the_game( case HUD_STAT_OFFSET: e->offset = *event.hudchange.v2fdata; break; + case HUD_STAT_WORLD_POS: + e->world_pos = *event.hudchange.v3fdata; + break; } + delete event.hudchange.v3fdata; delete event.hudchange.v2fdata; delete event.hudchange.sdata; } diff --git a/src/hud.cpp b/src/hud.cpp index 183f94e49..80112a6ec 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -29,14 +29,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "inventory.h" #include "tile.h" #include "localplayer.h" +#include "camera.h" #include -Hud::Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv, - gui::IGUIFont *font, u32 text_height, IGameDef *gamedef, +Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr, + gui::IGUIEnvironment* guienv, gui::IGUIFont *font, + u32 text_height, IGameDef *gamedef, LocalPlayer *player, Inventory *inventory) { this->driver = driver; + this->smgr = smgr; this->guienv = guienv; this->font = font; this->text_height = text_height; @@ -268,6 +271,33 @@ void Hud::drawLuaElements() { InventoryList *inv = inventory->getList(e->text); drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir); break; } + case HUD_ELEM_WAYPOINT: { + v3f p_pos = player->getPosition() / BS; + v3f w_pos = e->world_pos * BS; + float distance = floor(10 * p_pos.getDistanceFrom(e->world_pos)) / 10; + scene::ICameraSceneNode* camera = smgr->getActiveCamera(); + core::matrix4 trans = camera->getProjectionMatrix(); + trans *= camera->getViewMatrix(); + f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f }; + trans.multiplyWith1x4Matrix(transformed_pos); + if (transformed_pos[3] < 0) + break; + f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f : + core::reciprocal(transformed_pos[3]); + pos.X = screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5); + pos.Y = screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5); + video::SColor color(255, (e->number >> 16) & 0xFF, + (e->number >> 8) & 0xFF, + (e->number >> 0) & 0xFF); + core::rect size(0, 0, 200, 2 * text_height); + std::wstring text = narrow_to_wide(e->name); + font->draw(text.c_str(), size + pos, color); + std::ostringstream os; + os<text; + text = narrow_to_wide(os.str()); + pos.Y += text_height; + font->draw(text.c_str(), size + pos, color); + break; } default: infostream << "Hud::drawLuaElements: ignoring drawform " << e->type << " of hud element ID " << i << " due to unrecognized type" << std::endl; @@ -477,4 +507,3 @@ void drawItemStack(video::IVideoDriver *driver, font->draw(text.c_str(), rect2, color, false, false, clip); } } - diff --git a/src/hud.h b/src/hud.h index c69867a23..1a24d0945 100644 --- a/src/hud.h +++ b/src/hud.h @@ -49,7 +49,8 @@ enum HudElementType { HUD_ELEM_IMAGE = 0, HUD_ELEM_TEXT = 1, HUD_ELEM_STATBAR = 2, - HUD_ELEM_INVENTORY = 3 + HUD_ELEM_INVENTORY = 3, + HUD_ELEM_WAYPOINT = 4, }; enum HudElementStat { @@ -61,7 +62,8 @@ enum HudElementStat { HUD_STAT_ITEM, HUD_STAT_DIR, HUD_STAT_ALIGN, - HUD_STAT_OFFSET + HUD_STAT_OFFSET, + HUD_STAT_WORLD_POS }; struct HudElement { @@ -75,6 +77,7 @@ struct HudElement { u32 dir; v2f align; v2f offset; + v3f world_pos; }; #ifndef SERVER @@ -93,6 +96,7 @@ struct ItemStack; class Hud { public: video::IVideoDriver *driver; + scene::ISceneManager* smgr; gui::IGUIEnvironment *guienv; gui::IGUIFont *font; u32 text_height; @@ -113,8 +117,9 @@ public: std::string hotbar_selected_image; bool use_hotbar_selected_image; - Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv, - gui::IGUIFont *font, u32 text_height, IGameDef *gamedef, + Hud(video::IVideoDriver *driver,scene::ISceneManager* smgr, + gui::IGUIEnvironment* guienv, gui::IGUIFont *font, + u32 text_height, IGameDef *gamedef, LocalPlayer *player, Inventory *inventory); void drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount, diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 6d4ce54fc..6c6415a09 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -38,6 +38,7 @@ struct EnumString es_HudElementType[] = {HUD_ELEM_TEXT, "text"}, {HUD_ELEM_STATBAR, "statbar"}, {HUD_ELEM_INVENTORY, "inventory"}, + {HUD_ELEM_WAYPOINT, "waypoint"}, {0, NULL}, }; @@ -53,6 +54,7 @@ struct EnumString es_HudElementStat[] = {HUD_STAT_DIR, "direction"}, {HUD_STAT_ALIGN, "alignment"}, {HUD_STAT_OFFSET, "offset"}, + {HUD_STAT_WORLD_POS, "world_pos"}, {0, NULL}, }; @@ -862,6 +864,10 @@ int ObjectRef::l_hud_add(lua_State *L) elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); lua_pop(L, 1); + lua_getfield(L, 2, "world_pos"); + elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f(); + lua_pop(L, 1); + u32 id = getServer(L)->hudAdd(player, elem); if (id == (u32)-1) { delete elem; @@ -953,6 +959,10 @@ int ObjectRef::l_hud_change(lua_State *L) e->offset = read_v2f(L, 4); value = &e->offset; break; + case HUD_STAT_WORLD_POS: + e->world_pos = read_v3f(L, 4); + value = &e->world_pos; + break; } getServer(L)->hudChange(player, id, stat, value); @@ -1003,6 +1013,9 @@ int ObjectRef::l_hud_get(lua_State *L) lua_pushnumber(L, e->dir); lua_setfield(L, -2, "dir"); + push_v3f(L, e->world_pos); + lua_setfield(L, -2, "world_pos"); + return 1; } diff --git a/src/server.cpp b/src/server.cpp index 0ada4d818..9fb0455eb 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3724,6 +3724,7 @@ void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form) writeU32(os, form->dir); writeV2F1000(os, form->align); writeV2F1000(os, form->offset); + writeV3F1000(os, form->world_pos); // Make data buffer std::string s = os.str(); @@ -3767,6 +3768,9 @@ void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value case HUD_STAT_TEXT: os << serializeString(*(std::string *)value); break; + case HUD_STAT_WORLD_POS: + writeV3F1000(os, *(v3f *)value); + break; case HUD_STAT_NUMBER: case HUD_STAT_ITEM: case HUD_STAT_DIR: