From 67c147cb789e0df41a7f9b52cc7e76138175966b Mon Sep 17 00:00:00 2001 From: Morgan Christiansson Date: Tue, 16 Jun 2026 16:36:40 +0200 Subject: [PATCH 1/6] Wrap brush for large screens --- CMap.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/CMap.cpp b/CMap.cpp index dd63715..ed8aa4c 100644 --- a/CMap.cpp +++ b/CMap.cpp @@ -995,26 +995,17 @@ void CMap::storeVerticesFromMouse(Position mousePos, Uint8 /*MouseState*/) // get X // following out commented lines are the correct ones, but for tolerance (to prevent to early jumps of the cursor) - // we subtract "triangleWidth/2" Xeven = (MouseX + displayRect.left) / triangleWidth; + // we subtract "triangleWidth/2" Xeven = (mousePos.x + displayRect.left) / triangleWidth; Xeven = (mousePos.x + displayRect.left - triangleWidth / 2) / triangleWidth; - if(Xeven < 0) - Xeven += (map->width); - else if(Xeven > map->width - 1) - Xeven -= (map->width - 1); + Xeven = ((Xeven % map->width) + map->width) % map->width; // Add rows are already shifted by triangleWidth / 2 Xodd = (mousePos.x + displayRect.left) / triangleWidth; // Xodd = (mousePos.x + displayRect.left) / triangleWidth; - if(Xodd < 0) - Xodd += (map->width - 1); - else if(Xodd > map->width - 1) - Xodd -= (map->width); + Xodd = ((Xodd % (map->width - 1)) + (map->width - 1)) % (map->width - 1); MousePosY = mousePos.y + displayRect.top; // correct mouse position Y if displayRect is outside map edges - if(MousePosY < 0) - MousePosY += map->height_pixel; - else if(MousePosY > map->height_pixel) - MousePosY = mousePos.y - (map->height_pixel - displayRect.top); + MousePosY = ((MousePosY % map->height_pixel) + map->height_pixel) % map->height_pixel; // get Y for(int j = 0; j < map->height; j++) From 7b7184370363f80414f2a202e80ea9db855ae085 Mon Sep 17 00:00:00 2001 From: Morgan Christiansson Date: Tue, 16 Jun 2026 16:41:02 +0200 Subject: [PATCH 2/6] Black area for small maps&large screens --- CMap.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CMap.cpp b/CMap.cpp index ed8aa4c..1065105 100644 --- a/CMap.cpp +++ b/CMap.cpp @@ -1079,9 +1079,8 @@ void CMap::render() else Surf_Map = makeRGBSurface(displayRect.getSize().x, displayRect.getSize().y); } - // else - // clear the surface before drawing new (in normal case not needed) - // SDL_FillRect( Surf_Map, nullptr, SDL_MapRGB(Surf_Map->format,0,0,0) ); + // Clear the surface before drawing so areas not covered by triangles stay black + SDL_FillRect(Surf_Map.get(), nullptr, SDL_MapRGBA(Surf_Map->format, 0, 0, 0, 0)); // touch vertex data if user modifies it if(modify) From 511324bcdee91805e02a5cb1c89d02855af00bda Mon Sep 17 00:00:00 2001 From: Morgan Christiansson Date: Tue, 16 Jun 2026 16:48:53 +0200 Subject: [PATCH 3/6] Fix mouse panning --- CGame_Event.cpp | 18 +++++++++--------- CMap.cpp | 7 +++---- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/CGame_Event.cpp b/CGame_Event.cpp index ed9570c..18df732 100644 --- a/CGame_Event.cpp +++ b/CGame_Event.cpp @@ -142,17 +142,17 @@ void CGame::EventHandling(SDL_Event* Event) case SDL_MOUSEMOTION: { - // setup mouse cursor data - if(MapObj && MapObj->isActive()) - { - if((Event->motion.state & SDL_BUTTON(SDL_BUTTON_RIGHT)) == 0) - { - Cursor.pos = Position(Event->motion.x, Event->motion.y); - } - } else + // Avoid duplicate events especially when warping the mouse back during panning { - Cursor.pos = Position(Event->motion.x, Event->motion.y); + static Position lastMousePos = Position::Invalid(); + const Position newPos(Event->motion.x, Event->motion.y); + if(newPos == lastMousePos) + break; + lastMousePos = newPos; } + + // setup mouse cursor data + Cursor.pos = Position(Event->motion.x, Event->motion.y); /* //NOTE: we will now deliver the data to menus, windows, map etc., sometimes we have to break the switch and stop diff --git a/CMap.cpp b/CMap.cpp index 1065105..5103f7c 100644 --- a/CMap.cpp +++ b/CMap.cpp @@ -493,7 +493,7 @@ void CMap::moveMap(Position offset) void CMap::setMouseData(const SDL_MouseMotionEvent& motion) { // following code important for blitting the right field of the map - // Are we scrolling? + // Are we scrolling? (right mouse button held) if(startScrollPos) { assert(motion.state & SDL_BUTTON(3)); @@ -504,10 +504,9 @@ void CMap::setMouseData(const SDL_MouseMotionEvent& motion) offset.y = 0; moveMap(offset); - // this whole "warping-thing" is to prevent cursor-moving WITHIN the window while user moves over the map - SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); + // Warp mouse back to start position so we can keep scrolling + // Duplicate motion events generated by this warp are filtered in CGame::EventHandling SDL_WarpMouseInWindow(nullptr, startScrollPos->x, startScrollPos->y); - SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE); } storeVerticesFromMouse(Position(motion.x, motion.y), motion.state); From 05fcd188a3bb19f311c1c2a416c808a361f0a31f Mon Sep 17 00:00:00 2001 From: Morgan Christiansson Date: Tue, 16 Jun 2026 17:01:25 +0200 Subject: [PATCH 4/6] Zoom with mouse wheel --- CGame_Event.cpp | 109 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 37 deletions(-) diff --git a/CGame_Event.cpp b/CGame_Event.cpp index 18df732..a231a4f 100644 --- a/CGame_Event.cpp +++ b/CGame_Event.cpp @@ -11,6 +11,41 @@ #include "callbacks.h" #include "globals.h" +namespace { +bool tryZoom(Position deltaTriangle, int deltaInc, CMap* mapObj) +{ + if(!mapObj || !mapObj->getMap()) + return false; + const int newInc = triangleIncrease + deltaInc; + if(newInc < 1 || newInc > 10) + return false; + + callback::PleaseWait(INITIALIZING_CALL); + triangleWidth += deltaTriangle.x; + triangleHeight += deltaTriangle.y; + triangleIncrease += deltaInc; + bobMAP* myMap = mapObj->getMap(); + myMap->updateVertexCoords(); + CSurface::get_nodeVectors(*myMap); + callback::PleaseWait(WINDOW_QUIT_MESSAGE); + return true; +} + +void resetZoom(CMap* mapObj) +{ + if(!mapObj || !mapObj->getMap()) + return; + callback::PleaseWait(INITIALIZING_CALL); + triangleHeight = TRIANGLE_HEIGHT_DEFAULT; + triangleWidth = TRIANGLE_WIDTH_DEFAULT; + triangleIncrease = TRIANGLE_INCREASE_DEFAULT; + bobMAP* myMap = mapObj->getMap(); + myMap->updateVertexCoords(); + CSurface::get_nodeVectors(*myMap); + callback::PleaseWait(WINDOW_QUIT_MESSAGE); +} +} // namespace + void CGame::EventHandling(SDL_Event* Event) { switch(Event->type) @@ -84,45 +119,11 @@ void CGame::EventHandling(SDL_Event* Event) #endif // F5 - F7 is ZOOM, F5 = zoom in, F6 = normal view, F7 = zoom out case SDLK_F5: - if(triangleIncrease < ZOOM_INCREASE_MAX && MapObj->getMap()) - { - callback::PleaseWait(INITIALIZING_CALL); - triangleHeight += ZOOM_STEP_HEIGHT; - triangleWidth += ZOOM_STEP_WIDTH; - triangleIncrease += ZOOM_STEP_INCREASE; - bobMAP* myMap = MapObj->getMap(); - myMap->updateVertexCoords(); - CSurface::get_nodeVectors(*myMap); - callback::PleaseWait(WINDOW_QUIT_MESSAGE); - } + tryZoom(Position(ZOOM_STEP_WIDTH, ZOOM_STEP_HEIGHT), ZOOM_STEP_INCREASE, MapObj.get()); break; - case SDLK_F6: - { - if(MapObj->getMap()) - { - callback::PleaseWait(INITIALIZING_CALL); - triangleHeight = TRIANGLE_HEIGHT_DEFAULT; - triangleWidth = TRIANGLE_WIDTH_DEFAULT; - triangleIncrease = TRIANGLE_INCREASE_DEFAULT; - bobMAP* myMap = MapObj->getMap(); - myMap->updateVertexCoords(); - CSurface::get_nodeVectors(*myMap); - callback::PleaseWait(WINDOW_QUIT_MESSAGE); - } - } - break; + case SDLK_F6: resetZoom(MapObj.get()); break; case SDLK_F7: - if(triangleIncrease > ZOOM_INCREASE_MIN && MapObj->getMap()) - { - callback::PleaseWait(INITIALIZING_CALL); - triangleHeight -= ZOOM_STEP_HEIGHT; - triangleWidth -= ZOOM_STEP_WIDTH; - triangleIncrease -= ZOOM_STEP_INCREASE; - bobMAP* myMap = MapObj->getMap(); - myMap->updateVertexCoords(); - CSurface::get_nodeVectors(*myMap); - callback::PleaseWait(WINDOW_QUIT_MESSAGE); - } + tryZoom(Position(-ZOOM_STEP_WIDTH, -ZOOM_STEP_HEIGHT), -ZOOM_STEP_INCREASE, MapObj.get()); break; default: break; @@ -384,6 +385,40 @@ void CGame::EventHandling(SDL_Event* Event) break; } + case SDL_MOUSEWHEEL: + { + if(!MapObj) + break; + + int y = Event->wheel.y; + if(Event->wheel.direction == SDL_MOUSEWHEEL_FLIPPED) + y = -y; + if(y == 0) + break; + + const Position deltaTri = (y > 0) ? Position(11, 5) : Position(-11, -5); + const int deltaInc = (y > 0) ? 1 : -1; + + // Save values before zoom for cursor-centered adjustment + const PointF oldTriSize(triangleWidth, triangleHeight); + const PointF mousePos(Cursor.pos); + + if(!tryZoom(deltaTri, deltaInc, MapObj.get())) + break; + + // Keep the map point under the cursor stable after zoom + DisplayRectangle dr = MapObj->getDisplayRect(); + const PointF ratio(triangleWidth / oldTriSize.x, triangleHeight / oldTriSize.y); + const auto size = dr.getSize(); + const PointF newOrigin = (PointF(dr.getOrigin()) + mousePos) * ratio - mousePos; + dr.left = static_cast(newOrigin.x); + dr.top = static_cast(newOrigin.y); + dr.right = dr.left + size.x; + dr.bottom = dr.top + size.y; + MapObj->setDisplayRect(dr); + break; + } + case SDL_WINDOWEVENT: { if(Event->window.event == SDL_WINDOWEVENT_RESIZED) From 74d768d7418e35a037f66c2b294ad1515e22431f Mon Sep 17 00:00:00 2001 From: Morgan Christiansson Date: Tue, 16 Jun 2026 18:10:07 +0200 Subject: [PATCH 5/6] Fix segfault when panning map --- callbacks.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/callbacks.cpp b/callbacks.cpp index 7c69194..8d96293 100644 --- a/callbacks.cpp +++ b/callbacks.cpp @@ -2819,7 +2819,6 @@ void callback::MinimapMenu(int Param) { static CWindow* WNDMinimap = nullptr; static CMap* MapObj = nullptr; - static SDL_Surface* WndSurface = nullptr; static int scaleNum = 1; // only in case INITIALIZING_CALL needed to create the window int width; @@ -2855,13 +2854,15 @@ void callback::MinimapMenu(int Param) std::make_unique(MinimapMenu, WINDOWQUIT, WindowPos::Center, Extent(width + 12, height + 30), "Overview", WINDOW_NOTHING, WINDOW_CLOSE | WINDOW_MOVE)); global::s2->RegisterCallback(MinimapMenu); - WndSurface = WNDMinimap->getSurface(); } break; case CALL_FROM_GAMELOOP: - if(MapObj && WndSurface) - MapObj->drawMinimap(WndSurface); + if(MapObj && WNDMinimap) + { + if(SDL_Surface* surf = WNDMinimap->getSurface()) + MapObj->drawMinimap(surf); + } break; case WINDOW_CLICKED_CALL: @@ -2893,7 +2894,6 @@ void callback::MinimapMenu(int Param) WNDMinimap = nullptr; } MapObj = nullptr; - WndSurface = nullptr; global::s2->UnregisterCallback(MinimapMenu); break; From 20cd336f4835060582af87f6bcb35ba503ddc970 Mon Sep 17 00:00:00 2001 From: Morgan Christiansson Date: Tue, 30 Jun 2026 14:15:32 +0200 Subject: [PATCH 6/6] fixup! Zoom with mouse wheel --- CGame_Event.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CGame_Event.cpp b/CGame_Event.cpp index a231a4f..24e77d6 100644 --- a/CGame_Event.cpp +++ b/CGame_Event.cpp @@ -36,8 +36,8 @@ void resetZoom(CMap* mapObj) if(!mapObj || !mapObj->getMap()) return; callback::PleaseWait(INITIALIZING_CALL); - triangleHeight = TRIANGLE_HEIGHT_DEFAULT; triangleWidth = TRIANGLE_WIDTH_DEFAULT; + triangleHeight = TRIANGLE_HEIGHT_DEFAULT; triangleIncrease = TRIANGLE_INCREASE_DEFAULT; bobMAP* myMap = mapObj->getMap(); myMap->updateVertexCoords();