1 /* 2 * This file is part of Dune Legacy. 3 * 4 * Dune Legacy is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * Dune Legacy is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with Dune Legacy. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef RADARVIEWBASE_H 19 #define RADARVIEWBASE_H 20 21 #include <GUI/Widget.h> 22 23 #include <DataTypes.h> 24 25 #include <SDL.h> 26 #include <functional> 27 28 29 #define NUM_STATIC_FRAMES 21 30 #define NUM_STATIC_FRAME_TIME 5 31 32 #define RADARVIEW_BORDERTHICKNESS 2 33 #define RADARWIDTH 128 34 #define RADARHEIGHT 128 35 36 37 /// This class manages the mini map at the top right corner of the screen 38 class RadarViewBase : public Widget 39 { 40 public: 41 /** 42 Constructor 43 */ RadarViewBase()44 RadarViewBase() : Widget(), bRadarInteraction(false) { 45 resize(RADARWIDTH + (2 * RADARVIEW_BORDERTHICKNESS), RADARHEIGHT + (2 * RADARVIEW_BORDERTHICKNESS)); 46 } 47 48 /** 49 Destructor 50 */ ~RadarViewBase()51 virtual ~RadarViewBase() { 52 53 } 54 55 /** 56 Get the map size in x direction 57 \return map width 58 */ 59 virtual int getMapSizeX() const = 0; 60 61 /** 62 Get the map size in y direction 63 \return map height 64 */ 65 virtual int getMapSizeY() const = 0; 66 67 68 /** 69 Draws the radar to screen. This method is called before drawOverlay(). 70 \param Position Position to draw the radar to 71 */ draw(Point position)72 virtual inline void draw(Point position) { ; }; 73 74 75 /** 76 This method checks if position is inside the radar view 77 \param mouseX the x-coordinate to check (relative to the top left corner of the radar) 78 \param mouseY the y-coordinate to check (relative to the top left corner of the radar) 79 \return true, if inside the radar view; false otherwise 80 */ isOnRadar(int mouseX,int mouseY)81 bool isOnRadar(int mouseX, int mouseY) const { 82 int scale = 1; 83 int offsetX = 0; 84 int offsetY = 0; 85 86 calculateScaleAndOffsets(getMapSizeX(), getMapSizeY(), scale, offsetX, offsetY); 87 88 int offsetFromRightX = 128 - getMapSizeX()*scale - offsetX; 89 int offsetFromBottomY = 128 - getMapSizeY()*scale - offsetY; 90 91 return ((mouseX >= offsetX + RADARVIEW_BORDERTHICKNESS) 92 && (mouseX < RADARWIDTH - offsetFromRightX + RADARVIEW_BORDERTHICKNESS) 93 && (mouseY >= offsetY + RADARVIEW_BORDERTHICKNESS) 94 && (mouseY < RADARHEIGHT - offsetFromBottomY + RADARVIEW_BORDERTHICKNESS) ); 95 } 96 97 /** 98 This method returns the corresponding world coordinates for a point on the radar 99 \param mouseX the position on the radar screen (relative to the top left corner of the radar) 100 \param mouseY the position on the radar screen (relative to the top left corner of the radar) 101 \return the world coordinates 102 */ getWorldCoords(int mouseX,int mouseY)103 Coord getWorldCoords(int mouseX, int mouseY) const { 104 Coord positionOnRadar(mouseX - RADARVIEW_BORDERTHICKNESS, mouseY - RADARVIEW_BORDERTHICKNESS); 105 106 int scale = 1; 107 int offsetX = 0; 108 int offsetY = 0; 109 110 calculateScaleAndOffsets(getMapSizeX(), getMapSizeY(), scale, offsetX, offsetY); 111 112 return Coord( ((positionOnRadar.x - offsetX) * getMapSizeX() * TILESIZE) / (getMapSizeX() * scale), 113 ((positionOnRadar.y - offsetY) * getMapSizeY() * TILESIZE) / (getMapSizeY() * scale)); 114 } 115 116 117 /** 118 This method calculates the scale and the offsets that are neccessary to show a minimap centered inside a 128x128 rectangle. 119 \param MapSizeX The width of the map in tiles 120 \param MapSizeY The height of the map in tiles 121 \param scale The scale factor is saved here 122 \param offsetX The offset in x direction is saved here 123 \param offsetY The offset in y direction is saved here 124 */ calculateScaleAndOffsets(int MapSizeX,int MapSizeY,int & scale,int & offsetX,int & offsetY)125 static void calculateScaleAndOffsets(int MapSizeX, int MapSizeY, int& scale, int& offsetX, int& offsetY) { 126 scale = 1; 127 offsetX = 0; 128 offsetY = 0; 129 130 if(MapSizeX <= 32 && MapSizeY <= 32) { 131 scale*=2; 132 } 133 134 if(MapSizeX <= 64 && MapSizeY <= 64) { 135 scale*=2; 136 } 137 138 if(MapSizeX <= 21 && MapSizeY <= 21) { 139 scale++; 140 } 141 142 offsetX = (128 - (MapSizeX*scale))/2; 143 offsetY = (128 - (MapSizeY*scale))/2; 144 } 145 146 147 /** 148 Returns the minimum size of this widget. The widget should not 149 resized to a size smaller than this. If the widget is not resizeable 150 in a direction this method returns the size in that direction. 151 \return the minimum size of this widget 152 */ getMinimumSize()153 virtual Point getMinimumSize() const { return Point(RADARWIDTH + (2 * RADARVIEW_BORDERTHICKNESS),RADARHEIGHT + (2 * RADARVIEW_BORDERTHICKNESS)); }; 154 155 156 /** 157 Handles a mouse movement. 158 \param x x-coordinate (relative to the left top corner of the widget) 159 \param y y-coordinate (relative to the left top corner of the widget) 160 \param insideOverlay true, if (x,y) is inside an overlay and this widget may be behind it, false otherwise 161 */ handleMouseMovement(Sint32 x,Sint32 y,bool insideOverlay)162 virtual void handleMouseMovement(Sint32 x, Sint32 y, bool insideOverlay) { 163 if(bRadarInteraction && isOnRadar(x,y)) { 164 if(pOnRadarClick) { 165 bRadarInteraction = pOnRadarClick(getWorldCoords(x,y), false, true); 166 } 167 } 168 } 169 170 171 /** 172 Handles a left mouse click. 173 \param x x-coordinate (relative to the left top corner of the widget) 174 \param y y-coordinate (relative to the left top corner of the widget) 175 \param pressed true = mouse button pressed, false = mouse button released 176 \return true = click was processed by the widget, false = click was not processed by the widget 177 */ handleMouseLeft(Sint32 x,Sint32 y,bool pressed)178 virtual bool handleMouseLeft(Sint32 x, Sint32 y, bool pressed) { 179 if(pressed) { 180 if(isOnRadar(x,y)) { 181 if(pOnRadarClick) { 182 bRadarInteraction = pOnRadarClick(getWorldCoords(x,y), false, false); 183 } 184 return true; 185 } 186 return false; 187 } else { 188 bRadarInteraction = false; 189 return false; 190 } 191 } 192 193 194 /** 195 Handles a right mouse click. 196 \param x x-coordinate (relative to the left top corner of the widget) 197 \param y y-coordinate (relative to the left top corner of the widget) 198 \param pressed true = mouse button pressed, false = mouse button released 199 \return true = click was processed by the widget, false = click was not processed by the widget 200 */ handleMouseRight(Sint32 x,Sint32 y,bool pressed)201 virtual bool handleMouseRight(Sint32 x, Sint32 y, bool pressed) { 202 if(pressed) { 203 if(isOnRadar(x,y)) { 204 if(pOnRadarClick) { 205 bRadarInteraction = pOnRadarClick(getWorldCoords(x,y), true, false); 206 } 207 return true; 208 } 209 return false; 210 } else { 211 bRadarInteraction = false; 212 return false; 213 } 214 } 215 216 217 /** 218 Sets the function that should be called when the radar view is clicked. 219 \param pOnRadarClick A function to be called on click 220 */ setOnRadarClick(std::function<bool (Coord,bool,bool)> pOnRadarClick)221 inline void setOnRadarClick(std::function<bool (Coord,bool,bool)> pOnRadarClick) { 222 this->pOnRadarClick = pOnRadarClick; 223 } 224 225 protected: 226 std::function<bool (Coord,bool,bool)> pOnRadarClick; ///< this function is called when the user clicks on the radar (1st parameter is world coordinate; 2nd parameter is whether the right mouse button was pressed; 3rd parameter is whether the mouse was moved while being pressed, e.g. dragging; return value shall be true if dragging should start or continue) 227 228 bool bRadarInteraction; ///< currently dragging on the radar? (e.g. moving the view rectangle on the radar) 229 }; 230 231 #endif // RADARVIEWBASE_H 232