From a1eabb98efb7fbe640b3e9af645f87c70d24fde5 Mon Sep 17 00:00:00 2001 From: Pedro Cruz Date: Fri, 7 Jun 2024 18:56:49 -0300 Subject: [PATCH] feat: lights out of ingame box (#77) Enables lights out of ingame box and adjusted menu bar to show lights out of ingame view section. Resolves #71 --- data/menubar.xml | 6 ++--- source/light_drawer.cpp | 40 +++++++++++++++++++++---------- source/light_drawer.h | 4 ++-- source/main_menubar.cpp | 53 +++++++++++++++++++++-------------------- source/map_drawer.cpp | 34 +++++++++++--------------- source/map_drawer.h | 2 +- 6 files changed, 73 insertions(+), 66 deletions(-) diff --git a/data/menubar.xml b/data/menubar.xml index 63c4d397..9dfc37b0 100644 --- a/data/menubar.xml +++ b/data/menubar.xml @@ -128,10 +128,8 @@ - - - - + + diff --git a/source/light_drawer.cpp b/source/light_drawer.cpp index 06451b2d..ad4c2cb3 100644 --- a/source/light_drawer.cpp +++ b/source/light_drawer.cpp @@ -32,16 +32,21 @@ LightDrawer::~LightDrawer() { lights.clear(); } -void LightDrawer::draw(int map_x, int map_y, int scroll_x, int scroll_y) { - constexpr int half_tile_size = rme::TileSize / 2; +void LightDrawer::draw(int map_x, int map_y, int end_x, int end_y, int scroll_x, int scroll_y) { + if (texture == 0) { + createGLTexture(); + } + + int w = end_x - map_x; + int h = end_y - map_y; - for (int x = 0; x < rme::ClientMapWidth; ++x) { - for (int y = 0; y < rme::ClientMapHeight; ++y) { + buffer.resize(static_cast(w * h * rme::PixelFormatRGBA)); + + for (int x = 0; x < w; ++x) { + for (int y = 0; y < h; ++y) { int mx = (map_x + x); int my = (map_y + y); - int px = (mx * rme::TileSize + half_tile_size); - int py = (my * rme::TileSize + half_tile_size); - int index = (y * rme::ClientMapWidth + x); + int index = (y * w + x); int color_index = index * rme::PixelFormatRGBA; buffer[color_index] = global_color.Red(); @@ -67,18 +72,19 @@ void LightDrawer::draw(int map_x, int map_y, int scroll_x, int scroll_y) { const int draw_x = map_x * rme::TileSize - scroll_x; const int draw_y = map_y * rme::TileSize - scroll_y; - constexpr int draw_width = rme::ClientMapWidth * rme::TileSize; - constexpr int draw_height = rme::ClientMapHeight * rme::TileSize; + int draw_width = w * rme::TileSize; + int draw_height = h * rme::TileSize; glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0x812F); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 0x812F); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rme::ClientMapWidth, rme::ClientMapHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data()); - + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data()); glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); + glColor4ub(255, 255, 255, 255); // reset color glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2f(0.f, 0.f); @@ -99,7 +105,12 @@ void LightDrawer::setGlobalLightColor(uint8_t color) { global_color = colorFromEightBit(color); } -void LightDrawer::addLight(int map_x, int map_y, const SpriteLight &light) { +void LightDrawer::addLight(int map_x, int map_y, int map_z, const SpriteLight &light) { + if (map_z <= rme::MapGroundLayer) { + map_x -= (rme::MapGroundLayer - map_z); + map_y -= (rme::MapGroundLayer - map_z); + } + if (map_x <= 0 || map_x >= rme::MapMaxWidth || map_y <= 0 || map_y >= rme::MapMaxHeight) { return; } @@ -123,8 +134,11 @@ void LightDrawer::clear() noexcept { void LightDrawer::createGLTexture() { glGenTextures(1, &texture); + ASSERT(texture == 0); } void LightDrawer::unloadGLTexture() { - glDeleteTextures(1, &texture); + if (texture != 0) { + glDeleteTextures(1, &texture); + } } diff --git a/source/light_drawer.h b/source/light_drawer.h index 778f8b79..683ec3d7 100644 --- a/source/light_drawer.h +++ b/source/light_drawer.h @@ -33,10 +33,10 @@ class LightDrawer { LightDrawer(); virtual ~LightDrawer(); - void draw(int map_x, int map_y, int scroll_x, int scroll_y); + void draw(int map_x, int map_y, int end_x, int end_y, int scroll_x, int scroll_y); void setGlobalLightColor(uint8_t color); - void addLight(int map_x, int map_y, const SpriteLight &light); + void addLight(int map_x, int map_y, int map_z, const SpriteLight &light); void clear() noexcept; private: diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index 92c90c61..42a33828 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -576,7 +576,7 @@ bool MainMenuBar::Load(const FileName &path, wxArrayString &warnings, wxString & } #ifdef __LINUX__ - const int count = 43; + const int count = 46; wxAcceleratorEntry entries[count]; // Edit entries[0].Set(wxACCEL_CTRL, (int)'Z', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::UNDO)); @@ -601,33 +601,34 @@ bool MainMenuBar::Load(const FileName &path, wxArrayString &warnings, wxString & entries[17].Set(wxACCEL_NORMAL, (int)'Q', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::GHOST_ITEMS)); entries[18].Set(wxACCEL_CTRL, (int)'L', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::GHOST_HIGHER_FLOORS)); entries[19].Set(wxACCEL_SHIFT, (int)'I', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_INGAME_BOX)); - entries[20].Set(wxACCEL_SHIFT, (int)'G', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_GRID)); - entries[21].Set(wxACCEL_NORMAL, (int)'V', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::HIGHLIGHT_ITEMS)); - entries[22].Set(wxACCEL_NORMAL, (int)'F', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_MONSTERS)); - entries[23].Set(wxACCEL_NORMAL, (int)'S', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_SPAWNS_MONSTER)); - entries[24].Set(wxACCEL_NORMAL, (int)'X', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_NPCS)); - entries[25].Set(wxACCEL_NORMAL, (int)'U', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_SPAWNS_NPC)); - entries[26].Set(wxACCEL_NORMAL, (int)'E', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_SPECIAL)); - entries[27].Set(wxACCEL_SHIFT, (int)'E', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_AS_MINIMAP)); - entries[28].Set(wxACCEL_CTRL, (int)'E', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_ONLY_COLORS)); - entries[29].Set(wxACCEL_CTRL, (int)'M', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_ONLY_MODIFIED)); - entries[30].Set(wxACCEL_CTRL, (int)'H', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_HOUSES)); - entries[31].Set(wxACCEL_NORMAL, (int)'O', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_PATHING)); - entries[32].Set(wxACCEL_NORMAL, (int)'Y', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_TOOLTIPS)); - entries[33].Set(wxACCEL_NORMAL, (int)'L', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_PREVIEW)); - entries[34].Set(wxACCEL_NORMAL, (int)'K', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_WALL_HOOKS)); + entries[20].Set(wxACCEL_SHIFT, (int)'L', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_LIGHTS)); + entries[21].Set(wxACCEL_SHIFT, (int)'G', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_GRID)); + entries[22].Set(wxACCEL_NORMAL, (int)'V', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::HIGHLIGHT_ITEMS)); + entries[23].Set(wxACCEL_NORMAL, (int)'F', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_MONSTERS)); + entries[24].Set(wxACCEL_NORMAL, (int)'S', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_SPAWNS_MONSTER)); + entries[25].Set(wxACCEL_NORMAL, (int)'X', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_NPCS)); + entries[26].Set(wxACCEL_NORMAL, (int)'U', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_SPAWNS_NPC)); + entries[27].Set(wxACCEL_NORMAL, (int)'E', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_SPECIAL)); + entries[28].Set(wxACCEL_SHIFT, (int)'E', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_AS_MINIMAP)); + entries[29].Set(wxACCEL_CTRL, (int)'E', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_ONLY_COLORS)); + entries[30].Set(wxACCEL_CTRL, (int)'M', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_ONLY_MODIFIED)); + entries[31].Set(wxACCEL_CTRL, (int)'H', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_HOUSES)); + entries[32].Set(wxACCEL_NORMAL, (int)'O', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_PATHING)); + entries[33].Set(wxACCEL_NORMAL, (int)'Y', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_TOOLTIPS)); + entries[34].Set(wxACCEL_NORMAL, (int)'L', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_PREVIEW)); + entries[35].Set(wxACCEL_NORMAL, (int)'K', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SHOW_WALL_HOOKS)); // Window - entries[33].Set(wxACCEL_NORMAL, (int)'M', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::WIN_MINIMAP)); - entries[34].Set(wxACCEL_NORMAL, (int)'T', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_TERRAIN)); - entries[35].Set(wxACCEL_NORMAL, (int)'D', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_DOODAD)); - entries[36].Set(wxACCEL_NORMAL, (int)'I', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_ITEM)); - entries[37].Set(wxACCEL_NORMAL, (int)'H', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_HOUSE)); - entries[38].Set(wxACCEL_NORMAL, (int)'C', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_MONSTER)); - entries[39].Set(wxACCEL_NORMAL, (int)'N', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_NPC)); - entries[40].Set(wxACCEL_NORMAL, (int)'W', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_WAYPOINT)); - entries[41].Set(wxACCEL_NORMAL, (int)'Z', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_ZONES)); - entries[42].Set(wxACCEL_NORMAL, (int)'R', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_RAW)); + entries[36].Set(wxACCEL_NORMAL, (int)'M', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::WIN_MINIMAP)); + entries[37].Set(wxACCEL_NORMAL, (int)'T', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_TERRAIN)); + entries[38].Set(wxACCEL_NORMAL, (int)'D', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_DOODAD)); + entries[39].Set(wxACCEL_NORMAL, (int)'I', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_ITEM)); + entries[40].Set(wxACCEL_NORMAL, (int)'H', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_HOUSE)); + entries[41].Set(wxACCEL_NORMAL, (int)'C', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_MONSTER)); + entries[42].Set(wxACCEL_NORMAL, (int)'N', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_NPC)); + entries[43].Set(wxACCEL_NORMAL, (int)'W', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_WAYPOINT)); + entries[44].Set(wxACCEL_NORMAL, (int)'Z', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_ZONES)); + entries[45].Set(wxACCEL_NORMAL, (int)'R', static_cast(MAIN_FRAME_MENU) + static_cast(MenuBar::SELECT_RAW)); wxAcceleratorTable accelerator(count, entries); frame->SetAcceleratorTable(accelerator); diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index ad9f5eaf..e48c337d 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -128,10 +128,6 @@ bool DrawingOptions::isTooltips() const noexcept { return show_tooltips && !isOnlyColors(); } -bool DrawingOptions::isDrawLight() const noexcept { - return show_ingame_box && show_lights; -} - MapDrawer::MapDrawer(MapCanvas* canvas) : canvas(canvas), editor(canvas->editor) { light_drawer = std::make_shared(); @@ -216,6 +212,9 @@ void MapDrawer::Release() { void MapDrawer::Draw() { DrawBackground(); DrawMap(); + if (options.show_lights) { + light_drawer->draw(start_x, start_y, end_x, end_y, view_scroll_x, view_scroll_y); + } DrawDraggingShadow(); DrawHigherFloors(); if (options.dragging) { @@ -283,10 +282,6 @@ void MapDrawer::DrawMap() { int center_x = start_x + int(screensize_x * zoom / 64); int center_y = start_y + int(screensize_y * zoom / 64); int offset_y = 2; - int box_start_map_x = center_x - view_scroll_x; - int box_start_map_y = center_y - view_scroll_x + offset_y; - int box_end_map_x = center_x + rme::ClientMapWidth; - int box_end_map_y = center_y + rme::ClientMapHeight + offset_y; bool live_client = editor.IsLiveClient(); @@ -336,11 +331,9 @@ void MapDrawer::DrawMap() { for (int map_y = 0; map_y < 4; ++map_y) { TileLocation* location = nd->getTile(map_x, map_y, map_z); DrawTile(location); - if (location && options.isDrawLight()) { - auto &position = location->getPosition(); - if (position.x >= box_start_map_x && position.x <= box_end_map_x && position.y >= box_start_map_y && position.y <= box_end_map_y) { - AddLight(location); - } + // draw light, but only if not zoomed too far + if (location && options.show_lights && zoom <= 10) { + AddLight(location); } } } @@ -509,10 +502,6 @@ void MapDrawer::DrawIngameBox() { int box_end_x = box_end_map_x * rme::TileSize - view_scroll_x; int box_end_y = box_end_map_y * rme::TileSize - view_scroll_y; - if (options.isDrawLight()) { - light_drawer->draw(box_start_map_x, box_start_map_y, view_scroll_x, view_scroll_y); - } - static wxColor side_color(0, 0, 0, 200); glDisable(GL_TEXTURE_2D); @@ -1913,6 +1902,11 @@ void MapDrawer::DrawTooltips() { #endif } +void MapDrawer::DrawLight() const { + // draw in-game light + light_drawer->draw(start_x, start_y, end_x, end_y, view_scroll_x, view_scroll_y); +} + void MapDrawer::MakeTooltip(int screenx, int screeny, const std::string &text, uint8_t r, uint8_t g, uint8_t b) { if (text.empty()) { return; @@ -1924,7 +1918,7 @@ void MapDrawer::MakeTooltip(int screenx, int screeny, const std::string &text, u } void MapDrawer::AddLight(TileLocation* location) { - if (!options.isDrawLight() || !location) { + if (!options.show_lights || !location) { return; } @@ -1937,7 +1931,7 @@ void MapDrawer::AddLight(TileLocation* location) { if (tile->ground) { if (tile->ground->hasLight()) { - light_drawer->addLight(position.x, position.y, tile->ground->getLight()); + light_drawer->addLight(position.x, position.y, position.z, tile->ground->getLight()); } } @@ -1945,7 +1939,7 @@ void MapDrawer::AddLight(TileLocation* location) { if (!hidden && !tile->items.empty()) { for (auto item : tile->items) { if (item->hasLight()) { - light_drawer->addLight(position.x, position.y, item->getLight()); + light_drawer->addLight(position.x, position.y, position.z, item->getLight()); } } } diff --git a/source/map_drawer.h b/source/map_drawer.h index aaa5d5ee..9951f1c7 100644 --- a/source/map_drawer.h +++ b/source/map_drawer.h @@ -54,7 +54,6 @@ struct DrawingOptions { bool isOnlyColors() const noexcept; bool isTileIndicators() const noexcept; bool isTooltips() const noexcept; - bool isDrawLight() const noexcept; bool transparent_floors; bool transparent_items; @@ -162,6 +161,7 @@ class MapDrawer { void DrawTileIndicators(TileLocation* location); void DrawIndicator(int x, int y, int indicator, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255, uint8_t a = 255); void DrawPositionIndicator(int z); + void DrawLight() const; void WriteTooltip(const Item* item, std::ostringstream &stream); void WriteTooltip(const Waypoint* item, std::ostringstream &stream); void MakeTooltip(int screenx, int screeny, const std::string &text, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255);