From 4f9f0b1c2dcf2d0c9e01175c59fb1a9dc5f3a95f Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Fri, 23 Feb 2024 13:19:32 -0500 Subject: [PATCH] Partial refactoring of radar into WIDGET --- src/display.cpp | 94 ++---------------------- src/display.h | 2 - src/hci.cpp | 22 ++++-- src/hci.h | 2 + src/init.cpp | 2 + src/loop.cpp | 6 -- src/radar.cpp | 192 ++++++++++++++++++++++++++++++++++++++++++++++++ src/radar.h | 7 +- 8 files changed, 224 insertions(+), 103 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index 94392b09f20..3fd3a3451fe 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -131,13 +131,11 @@ static float scrollSpeedLeftRight; //use two directions and add them because its static float scrollStepLeftRight; static float scrollSpeedUpDown; static float scrollStepUpDown; -static bool mouseOverRadar = false; static bool mouseOverConsole = false; static bool ignoreOrder = false; static bool ignoreRMBC = true; static DROID *psSelectedVtol; static DROID *psDominantSelected; -static bool bRadarDragging = false; static bool cameraAccel = true; bool rotActive = false; @@ -273,11 +271,6 @@ static void shakeUpdate() } } -bool isMouseOverRadar() -{ - return mouseOverRadar; -} - bool getCameraAccel() { return cameraAccel; @@ -335,73 +328,6 @@ void setDrawShadows(bool val) pie_setShadows(val); } -void ProcessRadarInput() -{ - int PosX, PosY; - int x = mouseX(); - int y = mouseY(); - UDWORD temp1, temp2; - - /* Only allow jump-to-area-of-map if radar is on-screen */ - mouseOverRadar = false; - if (radarVisible()) - { - if (CoordInRadar(x, y)) - { - mouseOverRadar = true; - - if (mousePressed(MOUSE_ORDER)) - { - x = mousePressPos_DEPRECATED(MOUSE_ORDER).x; - y = mousePressPos_DEPRECATED(MOUSE_ORDER).y; - - /* If we're tracking a droid, then cancel that */ - CalcRadarPosition(x, y, &PosX, &PosY); - if (mouseOverRadar && selectedPlayer < MAX_PLAYERS) - { - // MARKER - // Send all droids to that location - orderSelectedLoc(selectedPlayer, (PosX * TILE_UNITS) + TILE_UNITS / 2, - (PosY * TILE_UNITS) + TILE_UNITS / 2, ctrlShiftDown()); // ctrlShiftDown() = ctrl clicked a destination, add an order - - } - CheckScrollLimits(); - audio_PlayTrack(ID_SOUND_MESSAGEEND); - } - - - if (mouseDrag(MOUSE_SELECT, &temp1, &temp2) && !rotActive) - { - CalcRadarPosition(x, y, &PosX, &PosY); - setViewPos(PosX, PosY, true); - bRadarDragging = true; - if (ctrlShiftDown()) - { - playerPos.r.y = 0; - } - } - else if (mousePressed(MOUSE_SELECT)) - { - x = mousePressPos_DEPRECATED(MOUSE_SELECT).x; - y = mousePressPos_DEPRECATED(MOUSE_SELECT).y; - - CalcRadarPosition(x, y, &PosX, &PosY); - - if (war_GetRadarJump()) - { - /* Go instantly */ - setViewPos(PosX, PosY, true); - } - else - { - /* Pan to it */ - requestRadarTrack(PosX * TILE_UNITS, PosY * TILE_UNITS); - } - } - } - } -} - // reset the input state void resetInput() { @@ -493,7 +419,7 @@ void processInput() static bool OverRadarAndNotDragging() { - return mouseOverRadar && dragBox3D.status != DRAG_DRAGGING && wallDrag.status != DRAG_DRAGGING; + return isMouseOverRadar() && dragBox3D.status != DRAG_DRAGGING && wallDrag.status != DRAG_DRAGGING; } static void CheckFinishedDrag(SELECTION_TYPE selection) @@ -629,7 +555,7 @@ static void HandleDrag() { UDWORD dragX = 0, dragY = 0; - if (mouseDrag(MOUSE_LMB, &dragX, &dragY) && !mouseOverRadar && !mouseDown(MOUSE_RMB)) + if (mouseDrag(MOUSE_LMB, &dragX, &dragY) && !isMouseOverRadar() && !mouseDown(MOUSE_RMB)) { dragBox3D.x1 = dragX; dragBox3D.x2 = mouseX(); @@ -707,7 +633,6 @@ void processMouseClickInput() dragBox3D.status = DRAG_INACTIVE; // Pretty sure we wan't set walldrag status here aswell. wallDrag.status = DRAG_INACTIVE; - bRadarDragging = false; if (bRightClickOrders) { dealWithLMB(); @@ -723,30 +648,24 @@ void processMouseClickInput() } } - if (!mouseDrag(MOUSE_SELECT, (UDWORD *)&rotX, (UDWORD *)&rotY) && bRadarDragging) - { - bRadarDragging = false; - } - /* Right mouse click kills a building placement */ if (!rotActive && mouseReleased(MOUSE_RMB) && (buildState == BUILD3D_POS || buildState == BUILD3D_VALID)) { /* Stop the placement */ kill3DBuilding(); - bRadarDragging = false; } if (mouseReleased(MOUSE_RMB)) { cancelDeliveryRepos(); } - if (mouseDrag(MOUSE_ROTATE, (UDWORD *)&rotX, (UDWORD *)&rotY) && !rotActive && !bRadarDragging && !getRadarTrackingStatus()) + if (mouseDrag(MOUSE_ROTATE, (UDWORD *)&rotX, (UDWORD *)&rotY) && !rotActive && !isRadarDragging() && !getRadarTrackingStatus()) { rotationVerticalTracker->startTracking((UWORD)playerPos.r.x); rotationHorizontalTracker->startTracking((UWORD)playerPos.r.y); // negative values caused problems with float conversion rotActive = true; } - if (mouseDrag(MOUSE_PAN, (UDWORD *)&panMouseX, (UDWORD *)&panMouseY) && !rotActive && !panActive && !bRadarDragging && !getRadarTrackingStatus()) + if (mouseDrag(MOUSE_PAN, (UDWORD *)&panMouseX, (UDWORD *)&panMouseY) && !rotActive && !panActive && !isRadarDragging() && !getRadarTrackingStatus()) { panXTracker->startTracking(playerPos.p.x); panZTracker->startTracking(playerPos.p.z); @@ -1253,7 +1172,6 @@ void displayWorld() pos.y = playerPos.r.y; pos.z = playerPos.r.z; camInformOfRotation(&pos); - bRadarDragging = false; } draw3DScene(); @@ -2014,7 +1932,7 @@ void dealWithLMB() STRUCTURE *psStructure; /* Don't process if in game options are on screen */ - if (mouseOverRadar || + if (isMouseOverRadar() || InGameOpUp == true || widgGetFromID(psWScreen, INTINGAMEOP)) { return; @@ -2182,7 +2100,7 @@ static void dealWithRMB() DROID *psDroid; STRUCTURE *psStructure; - if (mouseOverRadar || InGameOpUp == true || widgGetFromID(psWScreen, INTINGAMEOP)) + if (isMouseOverRadar() || InGameOpUp == true || widgGetFromID(psWScreen, INTINGAMEOP)) { return; } diff --git a/src/display.h b/src/display.h index 717796a63dc..ada98591388 100644 --- a/src/display.h +++ b/src/display.h @@ -54,8 +54,6 @@ void clearSelection(); // deal with selecting a droid void dealWithDroidSelect(DROID *psDroid, bool bDragBox); -bool isMouseOverRadar(); - void setInvertMouseStatus(bool val); bool getInvertMouseStatus(); diff --git a/src/hci.cpp b/src/hci.cpp index a01dd98085f..a02eb91dfb9 100644 --- a/src/hci.cpp +++ b/src/hci.cpp @@ -1020,6 +1020,13 @@ void intRefreshGroupsUI() IntGroupsRefreshPending = true; } +bool intAddRadarWidget() +{ + auto radarWidget = getRadarWidget(); + ASSERT_OR_RETURN(false, radarWidget != nullptr, "Failed to get radar widget?"); + psWScreen->psForm->attach(radarWidget, WIDGET::ChildZPos::Back); + return true; +} // see if a delivery point is selected static FLAG_POSITION *intFindSelectedDelivPoint() @@ -1942,18 +1949,21 @@ void intDisplayWidgets() } } + bool desiredRadarVisibility = false; if (!gameUpdatePaused()) { - if (radarVisible()) - { - gfx_api::context::get().debugStringMarker("Draw 3D scene - radar"); - drawRadar(); - } - + desiredRadarVisibility = radarVisible(); + /* Ensure that any text messages are displayed at bottom of screen */ displayConsoleMessages(); } + auto radarWidget = getRadarWidget(); + if (radarWidget && (desiredRadarVisibility != radarWidget->visible())) + { + (desiredRadarVisibility) ? radarWidget->show() : radarWidget->hide(); + } + widgDisplayScreen(psWScreen); if (bLoadSaveUp) diff --git a/src/hci.h b/src/hci.h index c2ce0c9f49c..32ddb202717 100644 --- a/src/hci.h +++ b/src/hci.h @@ -268,6 +268,8 @@ extern iIMDShape *pNewDesignIMD; /* Initialise the in game interface */ bool intInitialise(); +bool intAddRadarWidget(); + // Check of coordinate is in the build menu bool CoordInBuild(int x, int y); diff --git a/src/init.cpp b/src/init.cpp index 92e188e62d0..58eb9016073 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1879,6 +1879,8 @@ bool stageThreeInitialise() challengeActive = true; } + // add radar to interface screen, and resize + intAddRadarWidget(); resizeRadar(); setAllPauseStates(false); diff --git a/src/loop.cpp b/src/loop.cpp index eb34098cc89..da0ac6e0de9 100644 --- a/src/loop.cpp +++ b/src/loop.cpp @@ -308,12 +308,6 @@ static GAMECODE renderLoop() { if (!gameUpdatePaused()) { - if (dragBox3D.status != DRAG_DRAGGING - && wallDrag.status != DRAG_DRAGGING - && intRetVal != INT_INTERCEPT) - { - ProcessRadarInput(); - } processInput(); //no key clicks or in Intelligence Screen diff --git a/src/radar.cpp b/src/radar.cpp index 373c1d6a335..9017c181216 100644 --- a/src/radar.cpp +++ b/src/radar.cpp @@ -30,6 +30,8 @@ #include "lib/ivis_opengl/piestate.h" #include "lib/ivis_opengl/piefunc.h" #include "lib/ivis_opengl/bitimage.h" +#include "lib/sound/audio.h" +#include "lib/sound/audio_id.h" #include "lib/gamelib/gtime.h" #include "advvis.h" #include "objects.h" @@ -50,6 +52,7 @@ #include "intdisplay.h" #include "texture.h" #include "warzoneconfig.h" +#include "order.h" #ifndef GLM_ENABLE_EXPERIMENTAL #define GLM_ENABLE_EXPERIMENTAL #endif @@ -71,6 +74,30 @@ static iV_Image radarBitmap; static UDWORD *radarOverlayBuffer = nullptr; static Vector3i playerpos = {0, 0, 0}; +class RadarWidget : public WIDGET { +public: + RadarWidget(); + + void run(W_CONTEXT *) override; + void display(int xOffset, int yOffset) override; + bool hitTest(int x, int y) override; + void clicked(W_CONTEXT *, WIDGET_KEY = WKEY_PRIMARY) override; + void released(W_CONTEXT *, WIDGET_KEY = WKEY_PRIMARY) override; + void highlight(W_CONTEXT *) override; + void highlightLost() override; + +public: + bool hasHighlight() const { return m_hasHighlight; } + bool isRadarDragging() const { return m_handlingDrag; } + +private: + std::array, 3> clickPosition; + bool m_hasHighlight = false; + bool m_handlingDrag = false; +}; + +static std::shared_ptr pRadarWidget; + PIELIGHT clanColours[] = { // see frontend2.png for team color order. @@ -191,6 +218,14 @@ static void radarSize(int ZoomLevel) radarCenterY = pie_GetVideoBufferHeight() - BASE_GAP * 4 - static_cast(radarHeight) / 2; } debug(LOG_WZ, "radar=(%u,%u) tex=(%zu,%zu) size=(%zu,%zu)", radarCenterX, radarCenterY, radarTexWidth, radarTexHeight, radarWidth, radarHeight); + + if (pRadarWidget) + { + auto radarDiag = static_cast(ceil(sqrt(double((radarWidth + 1) * (radarWidth + 1)) + double((radarHeight + 1) * (radarHeight + 1))))); + int radarX0 = radarCenterX - (radarDiag / 2); + int radarY0 = radarCenterY - (radarDiag / 2); + pRadarWidget->setGeometry(radarX0, radarY0, radarDiag, radarDiag); + } } void radarInitVars() @@ -210,6 +245,7 @@ bool InitRadar() colRadarAlly = WZCOL_YELLOW; colRadarEnemy = WZCOL_RED; colRadarMe = WZCOL_WHITE; + pRadarWidget = std::make_shared(); return true; } @@ -248,6 +284,8 @@ bool ShutdownRadar() free(radarOverlayBuffer); radarOverlayBuffer = nullptr; frameSkip = 0; + psWScreen->psForm->detach(pRadarWidget); + pRadarWidget.reset(); return true; } @@ -777,3 +815,157 @@ void radarColour(UDWORD tileNumber, uint8_t r, uint8_t g, uint8_t b) tileColours[tileNumber].byte.b = b; tileColours[tileNumber].byte.a = 255; } + + +// MARK: - RadarWidget + +std::shared_ptr getRadarWidget() +{ + return pRadarWidget; +} + +RadarWidget::RadarWidget() +: WIDGET() +{ } + +#define WKEY_ORDER (getRightClickOrders()?WKEY_SECONDARY:WKEY_PRIMARY) +#define WKEY_SELECT (getRightClickOrders()?WKEY_PRIMARY:WKEY_SECONDARY) +#define MOUSE_SELECT (getRightClickOrders()?MOUSE_LMB:MOUSE_RMB) + +void RadarWidget::run(W_CONTEXT *) +{ + int PosX, PosY; + UDWORD temp1, temp2; + + if (m_hasHighlight) + { + // process drag events + if (mouseDrag(MOUSE_SELECT, &temp1, &temp2)) + { + if (!getRotActive()) + { + int x = mouseX(); + int y = mouseY(); + CalcRadarPosition(x, y, &PosX, &PosY); + setViewPos(PosX, PosY, true); + m_handlingDrag = true; + if (ctrlShiftDown()) + { + playerPos.r.y = 0; + } + } + } + else + { + m_handlingDrag = false; + } + } + else + { + if (m_handlingDrag && !mouseDrag(MOUSE_SELECT, &temp1, &temp2)) + { + m_handlingDrag = false; + } + } +} + +void RadarWidget::display(int xOffset, int yOffset) +{ + if (!radarVisible()) { return; } + + gfx_api::context::get().debugStringMarker("Draw 3D scene - radar"); + drawRadar(); +} + +bool RadarWidget::hitTest(int x, int y) +{ + // NOTE: CoordInRadar expects x, y in *screen* coordinates - this is _currently_ the case as a byproduct of how the radar widget is added to the UI screen + return WIDGET::hitTest(x, y) && CoordInRadar(x, y); +} + +void RadarWidget::clicked(W_CONTEXT *context, WIDGET_KEY key) +{ + int x = context->xOffset + context->mx; + int y = context->yOffset + context->my; + + clickPosition[key] = Vector2i(x, y); +} + +void RadarWidget::highlight(W_CONTEXT *) +{ + m_hasHighlight = true; +} + +void RadarWidget::highlightLost() +{ + m_hasHighlight = false; + for (auto& keyClickPos : clickPosition) + { + keyClickPos.reset(); + } +} + +void RadarWidget::released(W_CONTEXT *context, WIDGET_KEY key) +{ + int PosX, PosY; + int x = context->xOffset + context->mx; + int y = context->yOffset + context->my; + + if (key == WKEY_ORDER) + { + if (clickPosition[WKEY_ORDER].has_value()) + { + x = clickPosition[WKEY_ORDER].value().x; + y = clickPosition[WKEY_ORDER].value().y; + + /* If we're tracking a droid, then cancel that */ + CalcRadarPosition(x, y, &PosX, &PosY); + if (selectedPlayer < MAX_PLAYERS) + { + // MARKER + // Send all droids to that location + orderSelectedLoc(selectedPlayer, (PosX * TILE_UNITS) + TILE_UNITS / 2, + (PosY * TILE_UNITS) + TILE_UNITS / 2, ctrlShiftDown()); // ctrlShiftDown() = ctrl clicked a destination, add an order + + } + CheckScrollLimits(); + audio_PlayTrack(ID_SOUND_MESSAGEEND); + } + } + + if (key == WKEY_SELECT && !m_handlingDrag) + { + if (clickPosition[WKEY_SELECT].has_value()) + { + x = clickPosition[WKEY_SELECT].value().x; + y = clickPosition[WKEY_SELECT].value().y; + + CalcRadarPosition(x, y, &PosX, &PosY); + + if (war_GetRadarJump()) + { + /* Go instantly */ + setViewPos(PosX, PosY, true); + } + else + { + /* Pan to it */ + requestRadarTrack(PosX * TILE_UNITS, PosY * TILE_UNITS); + } + } + } + + clickPosition[key].reset(); +} + +bool isMouseOverRadar() +{ + if (!pRadarWidget) { return false; } + return pRadarWidget->hasHighlight(); +} + +bool isRadarDragging() +{ + if (!pRadarWidget) { return false; } + return pRadarWidget->isRadarDragging(); +} diff --git a/src/radar.h b/src/radar.h index 49d9e21c23b..dd8de93dc4a 100644 --- a/src/radar.h +++ b/src/radar.h @@ -28,6 +28,8 @@ #ifndef __INCLUDED_SRC_RADAR_H__ #define __INCLUDED_SRC_RADAR_H__ +#include "lib/widget/widget.h" + void radarColour(UDWORD tileNumber, uint8_t r, uint8_t g, uint8_t b); ///< Set radar colour for given terrain type. #define MAX_RADARZOOM (64) @@ -42,7 +44,6 @@ void drawRadar(); ///< Draw the minimap on the screen. void CalcRadarPosition(int mX, int mY, int *PosX, int *PosY); ///< Given a position within the radar, returns a world coordinate. void SetRadarZoom(uint8_t ZoomLevel); ///< Set current zoom level. 1.0 is 1:1 resolution. uint8_t GetRadarZoom(); ///< Get current zoom level. -bool CoordInRadar(int x, int y); ///< Is screen coordinate inside minimap? /** Different mini-map draw modes. */ enum RADAR_DRAW_MODE @@ -62,6 +63,10 @@ extern bool radarRotationArrow; void radarInitVars(); ///< Recalculate minimap variables. For initialization code only. +std::shared_ptr getRadarWidget(); +bool isMouseOverRadar(); +bool isRadarDragging(); + extern PIELIGHT clanColours[]; /** @} */