1 /***************************************************************************
2 * Copyright (C) 2009 by Andrey Afletdinov <fheroes2@gmail.com> *
3 * *
4 * Part of the Free Heroes2 Engine: *
5 * http://sourceforge.net/projects/fheroes2 *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22
23 #include "agg_image.h"
24 #include "cursor.h"
25 #include "dialog.h"
26 #include "game.h"
27 #include "game_delays.h"
28 #include "game_interface.h"
29 #include "icn.h"
30 #include "maps.h"
31 #include "settings.h"
32 #include "ui_tool.h"
33 #include "world.h"
34
Basic()35 Interface::Basic::Basic()
36 : gameArea( *this )
37 , radar( *this )
38 , iconsPanel( *this )
39 , buttonsArea( *this )
40 , statusWindow( *this )
41 , controlPanel( *this )
42 , redraw( 0 )
43 {
44 Reset();
45 }
46
Reset()47 void Interface::Basic::Reset()
48 {
49 const fheroes2::Display & display = fheroes2::Display::instance();
50 const Settings & conf = Settings::Get();
51
52 SetHideInterface( conf.ExtGameHideInterface() );
53
54 scrollLeft = fheroes2::Rect( 0, 0, BORDERWIDTH, display.height() );
55 scrollRight = fheroes2::Rect( display.width() - BORDERWIDTH, 0, BORDERWIDTH, display.height() );
56 scrollTop = fheroes2::Rect( 0, 0, display.width(), BORDERWIDTH );
57 scrollBottom = fheroes2::Rect( 0, display.height() - BORDERWIDTH, display.width(), BORDERWIDTH );
58 }
59
GetGameArea(void)60 Interface::GameArea & Interface::Basic::GetGameArea( void )
61 {
62 return gameArea;
63 }
64
GetRadar(void)65 Interface::Radar & Interface::Basic::GetRadar( void )
66 {
67 return radar;
68 }
69
GetIconsPanel(void)70 Interface::IconsPanel & Interface::Basic::GetIconsPanel( void )
71 {
72 return iconsPanel;
73 }
74
GetButtonsArea(void)75 Interface::ButtonsArea & Interface::Basic::GetButtonsArea( void )
76 {
77 return buttonsArea;
78 }
79
GetStatusWindow(void)80 Interface::StatusWindow & Interface::Basic::GetStatusWindow( void )
81 {
82 return statusWindow;
83 }
84
GetControlPanel(void)85 Interface::ControlPanel & Interface::Basic::GetControlPanel( void )
86 {
87 return controlPanel;
88 }
89
SetHideInterface(bool f)90 void Interface::Basic::SetHideInterface( bool f )
91 {
92 const fheroes2::Display & display = fheroes2::Display::instance();
93 Settings & conf = Settings::Get();
94 const u32 px = display.width() - BORDERWIDTH - RADARWIDTH;
95
96 conf.SetHideInterface( f );
97
98 if ( f ) {
99 conf.SetShowPanel( true );
100
101 fheroes2::Point pos_radr = conf.PosRadar();
102 fheroes2::Point pos_bttn = conf.PosButtons();
103 fheroes2::Point pos_icon = conf.PosIcons();
104 fheroes2::Point pos_stat = conf.PosStatus();
105
106 if ( 0 == pos_radr.x && 0 == pos_radr.y )
107 pos_radr = fheroes2::Point( BORDERWIDTH, BORDERWIDTH );
108 if ( 0 == pos_icon.x && 0 == pos_icon.y )
109 pos_icon = fheroes2::Point( px - BORDERWIDTH, radar.GetArea().y + radar.GetArea().height );
110 if ( 0 == pos_bttn.x && 0 == pos_bttn.y )
111 pos_bttn = fheroes2::Point( px - BORDERWIDTH, iconsPanel.GetArea().y + iconsPanel.GetArea().height );
112 if ( 0 == pos_stat.x && 0 == pos_stat.y )
113 pos_stat = fheroes2::Point( px - BORDERWIDTH, buttonsArea.GetArea().y + buttonsArea.GetArea().height );
114
115 controlPanel.SetPos( display.width() - controlPanel.GetArea().width - BORDERWIDTH, 0 );
116 radar.SetPos( pos_radr.x, pos_radr.y );
117 iconsPanel.SetPos( pos_icon.x, pos_icon.y );
118 buttonsArea.SetPos( pos_bttn.x, pos_bttn.y );
119 statusWindow.SetPos( pos_stat.x, pos_stat.y );
120 }
121 else {
122 radar.SetPos( px, BORDERWIDTH );
123 iconsPanel.SetPos( px, radar.GetArea().y + radar.GetArea().height + BORDERWIDTH );
124
125 buttonsArea.SetPos( px, iconsPanel.GetArea().y + iconsPanel.GetArea().height + BORDERWIDTH );
126 statusWindow.SetPos( px, buttonsArea.GetArea().y + buttonsArea.GetArea().height );
127 }
128
129 gameArea.generate( { display.width(), display.height() }, conf.ExtGameHideInterface() );
130 }
131
Get(void)132 Interface::Basic & Interface::Basic::Get( void )
133 {
134 static Basic basic;
135 return basic;
136 }
137
GetScrollLeft(void) const138 const fheroes2::Rect & Interface::Basic::GetScrollLeft( void ) const
139 {
140 return scrollLeft;
141 }
142
GetScrollRight(void) const143 const fheroes2::Rect & Interface::Basic::GetScrollRight( void ) const
144 {
145 return scrollRight;
146 }
147
GetScrollTop(void) const148 const fheroes2::Rect & Interface::Basic::GetScrollTop( void ) const
149 {
150 return scrollTop;
151 }
152
GetScrollBottom(void) const153 const fheroes2::Rect & Interface::Basic::GetScrollBottom( void ) const
154 {
155 return scrollBottom;
156 }
157
NeedRedraw(void) const158 bool Interface::Basic::NeedRedraw( void ) const
159 {
160 return redraw != 0;
161 }
162
SetRedraw(int f)163 void Interface::Basic::SetRedraw( int f )
164 {
165 redraw |= f;
166 }
167
GetRedrawMask() const168 int Interface::Basic::GetRedrawMask() const
169 {
170 return redraw;
171 }
172
Redraw(int force)173 void Interface::Basic::Redraw( int force )
174 {
175 const Settings & conf = Settings::Get();
176
177 const int combinedRedraw = redraw | force;
178 const bool hideInterface = conf.ExtGameHideInterface();
179
180 if ( combinedRedraw & REDRAW_GAMEAREA )
181 gameArea.Redraw( fheroes2::Display::instance(), LEVEL_ALL );
182
183 if ( ( hideInterface && conf.ShowRadar() ) || ( combinedRedraw & REDRAW_RADAR ) )
184 radar.Redraw();
185
186 if ( ( hideInterface && conf.ShowIcons() ) || ( combinedRedraw & REDRAW_ICONS ) )
187 iconsPanel.Redraw();
188 else if ( combinedRedraw & REDRAW_HEROES )
189 iconsPanel.RedrawIcons( ICON_HEROES );
190 else if ( combinedRedraw & REDRAW_CASTLES )
191 iconsPanel.RedrawIcons( ICON_CASTLES );
192
193 if ( ( hideInterface && conf.ShowButtons() ) || ( combinedRedraw & REDRAW_BUTTONS ) )
194 buttonsArea.Redraw();
195
196 if ( ( hideInterface && conf.ShowStatus() ) || ( combinedRedraw & REDRAW_STATUS ) )
197 statusWindow.Redraw();
198
199 if ( hideInterface && conf.ShowControlPanel() && ( redraw & REDRAW_GAMEAREA ) )
200 controlPanel.Redraw();
201
202 if ( combinedRedraw & REDRAW_BORDER )
203 GameBorderRedraw( false );
204
205 redraw = 0;
206 }
207
GetDimensionDoorDestination(const int32_t from,const int32_t distance,const bool water)208 int32_t Interface::Basic::GetDimensionDoorDestination( const int32_t from, const int32_t distance, const bool water )
209 {
210 fheroes2::Display & display = fheroes2::Display::instance();
211
212 const fheroes2::Rect & radarArea = Interface::Basic::Get().GetRadar().GetArea();
213 const Settings & conf = Settings::Get();
214 const bool isEvilInterface = conf.ExtGameEvilInterface();
215 const bool isNoInterface = conf.ExtGameHideInterface();
216
217 fheroes2::ImageRestorer back( display, radarArea.x, radarArea.y, radarArea.width, radarArea.height );
218
219 const fheroes2::Sprite & viewDoor = fheroes2::AGG::GetICN( ( isEvilInterface ? ICN::EVIWDDOR : ICN::VIEWDDOR ), 0 );
220 fheroes2::Blit( viewDoor, 0, 0, display, radarArea.x, radarArea.y, radarArea.width, radarArea.height );
221
222 const fheroes2::Rect & visibleArea = gameArea.GetROI();
223 const bool isFadingEnabled = ( gameArea.GetROI().width > TILEWIDTH * distance ) || ( gameArea.GetROI().height > TILEWIDTH * distance );
224
225 // We need to add an extra one cell as a hero stands exactly in the middle of a cell
226 const fheroes2::Point heroPos( gameArea.GetRelativeTilePosition( Maps::GetPoint( from ) ) );
227 const fheroes2::Point heroPosOffset( heroPos.x - TILEWIDTH * ( distance / 2 ), heroPos.y - TILEWIDTH * ( distance / 2 ) );
228 const fheroes2::Rect spellROI( heroPosOffset.x, heroPosOffset.y, TILEWIDTH * ( distance + 1 ), TILEWIDTH * ( distance + 1 ) );
229
230 if ( isFadingEnabled ) {
231 fheroes2::InvertedFadeWithPalette( display, visibleArea, spellROI, 5, 300, 9 );
232 }
233
234 // setup cursor
235 const CursorRestorer cursorRestorer( true, Cursor::POINTER );
236 Cursor & cursor = Cursor::Get();
237
238 LocalEvent & le = LocalEvent::Get();
239 int32_t returnValue = -1;
240
241 const fheroes2::Point exitButtonPos( radarArea.x + 32, radarArea.y + radarArea.height - 37 );
242 fheroes2::Button buttonExit( exitButtonPos.x, exitButtonPos.y, ( isEvilInterface ? ICN::LGNDXTRE : ICN::LGNDXTRA ), 4, 5 );
243 buttonExit.draw();
244
245 while ( le.HandleEvents() ) {
246 const fheroes2::Point & mp = le.GetMouseCursor();
247
248 if ( radarArea & mp ) {
249 cursor.SetThemes( Cursor::POINTER );
250
251 le.MousePressLeft( buttonExit.area() ) ? buttonExit.drawOnPress() : buttonExit.drawOnRelease();
252 if ( le.MouseClickLeft( buttonExit.area() ) || HotKeyCloseWindow )
253 break;
254 }
255 else if ( visibleArea & mp ) {
256 const int32_t dst = gameArea.GetValidTileIdFromPoint( mp );
257
258 bool valid = ( dst >= 0 );
259
260 if ( valid ) {
261 const Maps::Tiles & tile = world.GetTiles( dst );
262
263 const MP2::MapObjectType objectType = tile.GetObject( true );
264 const bool isActionObject = MP2::isActionObject( objectType );
265
266 valid = ( ( spellROI & mp ) && !isActionObject && ( tile.GetPassable() & Direction::CENTER ) != 0 && water == tile.isWater() );
267 }
268
269 cursor.SetThemes( valid ? ( water ? static_cast<int>( Cursor::CURSOR_HERO_BOAT ) : static_cast<int>( Cursor::CURSOR_HERO_MOVE ) )
270 : static_cast<int>( Cursor::WAR_NONE ) );
271
272 if ( dst >= 0 && le.MousePressRight() ) {
273 const Maps::Tiles & tile = world.GetTiles( dst );
274 Dialog::QuickInfo( tile );
275 }
276 else if ( le.MouseClickLeft() && valid ) {
277 returnValue = dst;
278 break;
279 }
280 }
281 else {
282 cursor.SetThemes( Cursor::POINTER );
283 }
284
285 if ( Game::validateAnimationDelay( Game::MAPS_DELAY ) ) {
286 uint32_t & frame = Game::MapsAnimationFrame();
287 ++frame;
288 gameArea.SetRedraw();
289 Redraw();
290
291 if ( isFadingEnabled ) {
292 InvertedShadow( display, visibleArea, spellROI, 5, 9 );
293
294 if ( isNoInterface ) {
295 fheroes2::Blit( viewDoor, 0, 0, display, radarArea.x, radarArea.y, radarArea.width, radarArea.height );
296 buttonExit.draw();
297 }
298 }
299
300 display.render();
301 }
302 }
303
304 if ( isFadingEnabled ) {
305 gameArea.SetRedraw();
306 Redraw();
307 display.render();
308 }
309
310 back.restore();
311 display.render();
312
313 return returnValue;
314 }
315