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 #include <RadarView.h>
19 
20 #include <globals.h>
21 
22 #include <FileClasses/GFXManager.h>
23 
24 #include <Game.h>
25 #include <Map.h>
26 #include <House.h>
27 #include <ScreenBorder.h>
28 #include <Tile.h>
29 #include <SoundPlayer.h>
30 
31 #include <globals.h>
32 
33 #include <misc/draw_util.h>
34 
35 
RadarView()36 RadarView::RadarView()
37  : RadarViewBase(), currentRadarMode(RadarMode::RadarOff), animFrame(NUM_STATIC_FRAMES - 1), animCounter(NUM_STATIC_FRAME_TIME)
38 {
39     radarStaticAnimation = pGFXManager->getUIGraphic(UI_RadarAnimation);
40 
41     if((radarSurface = SDL_CreateRGBSurface(0, 128, 128, SCREEN_BPP, RMASK, GMASK, BMASK, AMASK)) == nullptr) {
42         THROW(std::runtime_error, "RadarView::RadarView(): Cannot create new surface!");
43     }
44     SDL_FillRect(radarSurface, nullptr, COLOR_BLACK);
45 
46     radarTexture = SDL_CreateTexture(renderer, SCREEN_FORMAT, SDL_TEXTUREACCESS_STREAMING, 128, 128);
47 }
48 
49 
~RadarView()50 RadarView::~RadarView()
51 {
52     SDL_FreeSurface(radarSurface);
53     SDL_DestroyTexture(radarTexture);
54 }
55 
getMapSizeX() const56 int RadarView::getMapSizeX() const {
57     return currentGameMap->getSizeX();
58 }
59 
getMapSizeY() const60 int RadarView::getMapSizeY() const {
61     return currentGameMap->getSizeY();
62 }
63 
64 
draw(Point position)65 void RadarView::draw(Point position)
66 {
67     SDL_Rect radarPosition = { position.x + RADARVIEW_BORDERTHICKNESS, position.y + RADARVIEW_BORDERTHICKNESS, RADARWIDTH, RADARHEIGHT};
68 
69     switch(currentRadarMode) {
70         case RadarMode::RadarOff:
71         case RadarMode::RadarOn: {
72             int mapSizeX = currentGameMap->getSizeX();
73             int mapSizeY = currentGameMap->getSizeY();
74 
75             int scale = 1;
76             int offsetX = 0;
77             int offsetY = 0;
78 
79             calculateScaleAndOffsets(mapSizeX, mapSizeY, scale, offsetX, offsetY);
80 
81             updateRadarSurface(mapSizeX, mapSizeY, scale, offsetX, offsetY);
82 
83             SDL_UpdateTexture(radarTexture, nullptr, radarSurface->pixels, radarSurface->pitch);
84 
85             SDL_Rect dest = calcDrawingRect(radarTexture, radarPosition.x, radarPosition.y);
86             SDL_RenderCopy(renderer, radarTexture, nullptr, &dest);
87 
88             SDL_Rect radarRect;
89             radarRect.x = (screenborder->getLeft() * mapSizeX*scale) / (mapSizeX*TILESIZE) + offsetX;
90             radarRect.y = (screenborder->getTop() * mapSizeY*scale) / (mapSizeY*TILESIZE) + offsetY;
91             radarRect.w = ((screenborder->getRight() - screenborder->getLeft()) * mapSizeX*scale) / (mapSizeX*TILESIZE);
92             radarRect.h = ((screenborder->getBottom() - screenborder->getTop()) * mapSizeY*scale) / (mapSizeY*TILESIZE);
93 
94             if(radarRect.x < offsetX) {
95                 radarRect.w -= radarRect.x;
96                 radarRect.x = offsetX;
97             }
98 
99             if(radarRect.y < offsetY) {
100                 radarRect.h -= radarRect.y;
101                 radarRect.y = offsetY;
102             }
103 
104             int offsetFromRightX = 128 - mapSizeX*scale - offsetX;
105             if(radarRect.x + radarRect.w > radarPosition.w - offsetFromRightX) {
106                 radarRect.w  = radarPosition.w - offsetFromRightX - radarRect.x - 1;
107             }
108 
109             int offsetFromBottomY = 128 - mapSizeY*scale - offsetY;
110             if(radarRect.y + radarRect.h > radarPosition.h - offsetFromBottomY) {
111                 radarRect.h = radarPosition.h - offsetFromBottomY - radarRect.y - 1;
112             }
113 
114             renderDrawRect( renderer,
115                             radarPosition.x + radarRect.x,
116                             radarPosition.y + radarRect.y,
117                             radarPosition.x + (radarRect.x + radarRect.w),
118                             radarPosition.y + (radarRect.y + radarRect.h),
119                             COLOR_WHITE);
120 
121         } break;
122 
123         case RadarMode::AnimationRadarOff:
124         case RadarMode::AnimationRadarOn: {
125             SDL_Rect source = calcSpriteSourceRect( radarStaticAnimation,
126                                                     animFrame % NUM_STATIC_ANIMATIONS_PER_ROW,
127                                                     NUM_STATIC_ANIMATIONS_PER_ROW,
128                                                     animFrame / NUM_STATIC_ANIMATIONS_PER_ROW,
129                                                     (NUM_STATIC_FRAMES + NUM_STATIC_ANIMATIONS_PER_ROW - 1) / NUM_STATIC_ANIMATIONS_PER_ROW);
130             SDL_Rect dest = calcSpriteDrawingRect(  radarStaticAnimation,
131                                                     radarPosition.x,
132                                                     radarPosition.y,
133                                                     NUM_STATIC_ANIMATIONS_PER_ROW,
134                                                     (NUM_STATIC_FRAMES + NUM_STATIC_ANIMATIONS_PER_ROW - 1) / NUM_STATIC_ANIMATIONS_PER_ROW);
135             SDL_RenderCopy(renderer, radarStaticAnimation, &source, &dest);
136         } break;
137     }
138 }
139 
update()140 void RadarView::update() {
141     if(pLocalHouse->hasRadarOn()) {
142         if(currentRadarMode != RadarMode::RadarOn && currentRadarMode != RadarMode::AnimationRadarOn && currentRadarMode != RadarMode::AnimationRadarOff) {
143             switchRadarMode(true);
144         }
145     } else {
146         if(currentRadarMode != RadarMode::RadarOff && currentRadarMode != RadarMode::AnimationRadarOn && currentRadarMode != RadarMode::AnimationRadarOff) {
147             switchRadarMode(false);
148         }
149     }
150 
151     switch(currentRadarMode) {
152         case RadarMode::RadarOff: {
153 
154         } break;
155 
156         case RadarMode::RadarOn: {
157 
158         } break;
159 
160         case RadarMode::AnimationRadarOff: {
161             if(animFrame >= NUM_STATIC_FRAMES-1) {
162                 currentRadarMode = RadarMode::RadarOff;
163             } else {
164                 animCounter--;
165                 if(animCounter <= 0) {
166                     animFrame++;
167                     animCounter = NUM_STATIC_FRAME_TIME;
168                 }
169             }
170         } break;
171 
172         case RadarMode::AnimationRadarOn: {
173             if(animFrame <= 0) {
174                 currentRadarMode = RadarMode::RadarOn;
175             } else {
176                 animCounter--;
177                 if(animCounter <= 0) {
178                     animFrame--;
179                     animCounter = NUM_STATIC_FRAME_TIME;
180                 }
181             }
182         } break;
183     }
184 }
185 
switchRadarMode(bool bOn)186 void RadarView::switchRadarMode(bool bOn) {
187     soundPlayer->playSound(Sound_RadarNoise);
188 
189     if(bOn == true) {
190         soundPlayer->playVoice(RadarActivated,pLocalHouse->getHouseID());
191         currentRadarMode = RadarMode::AnimationRadarOn;
192     } else {
193         soundPlayer->playVoice(RadarDeactivated,pLocalHouse->getHouseID());
194         currentRadarMode = RadarMode::AnimationRadarOff;
195     }
196 }
197 
updateRadarSurface(int mapSizeX,int mapSizeY,int scale,int offsetX,int offsetY)198 void RadarView::updateRadarSurface(int mapSizeX, int mapSizeY, int scale, int offsetX, int offsetY) {
199 
200     // Lock radarSurface for direct access to the pixels
201     if(!SDL_MUSTLOCK(radarSurface) || (SDL_LockSurface(radarSurface) == 0)) {
202         for(int x = 0; x <  mapSizeX; x++) {
203             for(int y = 0; y <  mapSizeY; y++) {
204 
205                 Tile* pTile = currentGameMap->getTile(x,y);
206 
207                 /* Selecting the right color is handled in Tile::getRadarColor() */
208                 Uint32 color = pTile->getRadarColor(pLocalHouse, ((currentRadarMode == RadarMode::RadarOn) || (currentRadarMode == RadarMode::AnimationRadarOff)));
209                 color = MapRGBA(radarSurface->format, color);
210 
211                 for(int j = 0; j < scale; j++) {
212                     Uint32* p = ((Uint32*) ((Uint8 *) radarSurface->pixels + (offsetY + scale*y + j) * radarSurface->pitch)) + (offsetX + scale*x);
213 
214                     for(int i = 0; i < scale; i++, p++) {
215                         // Do not use putPixel here to avoid overhead
216                         *p = color;
217                     }
218                 }
219             }
220         }
221 
222         if(SDL_MUSTLOCK(radarSurface)) {
223             SDL_UnlockSurface(radarSurface);
224         }
225     }
226 }
227