1 /*
2 ===========================================================================
3 blockattack - Block Attack - Rise of the Blocks
4 Copyright (C) 2005-2016 Poul Sander
5 
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see http://www.gnu.org/licenses/
18 
19 Source information and contacts persons can be found at
20 https://blockattack.net
21 ===========================================================================
22 */
23 
24 #include "levelselect.hpp"
25 #include "SDL.h"
26 #include "common.h"
27 #include "global.hpp"
28 #include "puzzlehandler.hpp"
29 #include "stageclearhandler.hpp"
30 #include "MenuSystem.h"
31 
32 
33 static bool bMouseUp;              //true if the mouse(1) is unpressed
34 
35 static std::map<std::string, std::shared_ptr<sago::SagoTextField> > fieldCache;
36 
getCachedText(const std::string & text)37 static sago::SagoTextField* getCachedText(const std::string& text) {
38 	std::shared_ptr<sago::SagoTextField> ptr = fieldCache[text];
39 	if (!ptr) {
40 		std::shared_ptr<sago::SagoTextField> newText = std::make_shared<sago::SagoTextField>();
41 		sagoTextSetBlueFont(*newText.get());
42 		newText->SetText(text);
43 		fieldCache[text] = newText;
44 	}
45 	return fieldCache[text].get();
46 }
47 
Write(SDL_Renderer * target,int x,int y,const char * text)48 static void Write(SDL_Renderer* target, int x, int y, const char* text) {
49 	getCachedText(text)->Draw(target, x, y);
50 }
51 
52 //The function that allows the player to choose PuzzleLevel
PuzzleLevelSelect(int Type)53 int PuzzleLevelSelect(int Type) {
54 	const int xplace = 200;
55 	const int yplace = 300;
56 	int levelNr = 0;
57 	int oldmousex = 0;
58 	int oldmousey = 0;
59 	bool levelSelected = false;
60 	int nrOfLevels = 0;
61 	Uint32 totalScore = 0;
62 	Uint32 totalTime = 0;
63 	int selected = 0;
64 	fieldCache.clear();
65 
66 	//Loads the levels, if they havn't been loaded:
67 	if (Type == 0) {
68 		LoadPuzzleStages();
69 		nrOfLevels = PuzzleGetNumberOfPuzzles();
70 	}
71 	if (Type == 1) {
72 		LoadStageClearStages();
73 		totalScore = GetTotalScore();
74 		totalTime = GetTotalTime();
75 		nrOfLevels = GetNrOfLevels();
76 	}
77 
78 	while (!levelSelected) {
79 		SDL_Delay(1);
80 		auto ticks = SDL_GetTicks();
81 		DrawBackground(globalData.screen);
82 		globalData.iCheckBoxArea.Draw(globalData.screen,ticks,xplace,yplace);
83 		if (Type == 0) {
84 			Write(globalData.screen, xplace+12,yplace+2,_("Select Puzzle") );
85 		}
86 		if (Type == 1) {
87 			Write(globalData.screen, xplace+12,yplace+2, _("Stage Clear Level Select") );
88 		}
89 		//Now drow the fields you click in (and a V if clicked):
90 		for (int i = 0; i < nrOfLevels; i++) {
91 			globalData.iLevelCheckBox.Draw(globalData.screen, ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50);
92 			if (i==selected) {
93 				globalData.iLevelCheckBoxMarked.Draw(globalData.screen, ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50);
94 			}
95 			if (Type == 0 && PuzzleIsCleared(i)) {
96 				globalData.iLevelCheck.Draw(globalData.screen,ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50);
97 			}
98 			if (Type == 1 && IsStageCleared(i)) {
99 				globalData.iLevelCheck.Draw(globalData.screen, ticks, xplace+10+(i%10)*50, yplace+60+(i/10)*50);
100 			}
101 		}
102 
103 		SDL_Event event;
104 		while ( SDL_PollEvent(&event) ) {
105 			UpdateMouseCoordinates(event, globalData.mousex, globalData.mousey);
106 
107 			if ( event.type == SDL_QUIT ) {
108 				Config::getInstance()->setShuttingDown(5);
109 				levelNr = -1;
110 				levelSelected = true;
111 			}
112 			if (isEscapeEvent(event)) {
113 				levelNr = -1;
114 				levelSelected = true;
115 			}
116 			if (isConfirmEvent(event)) {
117 				levelNr = selected;
118 				levelSelected = true;
119 			}
120 			if (isRightEvent(event)) {
121 				++selected;
122 				if (selected >= nrOfLevels) {
123 					selected = 0;
124 				}
125 			}
126 			if (isLeftEvent(event)) {
127 				--selected;
128 				if (selected < 0) {
129 					selected = nrOfLevels-1;
130 				}
131 			}
132 			if (isDownEvent(event)) {
133 				selected+=10;
134 				if (selected >= nrOfLevels) {
135 					selected-=10;
136 				}
137 			}
138 			if (isUpEvent(event)) {
139 				selected-=10;
140 				if (selected < 0) {
141 					selected+=10;
142 				}
143 			}
144 		}
145 
146 		SDL_GetKeyboardState(nullptr);
147 
148 		if (globalData.mousex != oldmousex || globalData.mousey != oldmousey) {
149 			int tmpSelected = -1;
150 			int j;
151 			for (j = 0; (tmpSelected == -1) && ( (j<nrOfLevels/10)||((j<nrOfLevels/10+1)&&(nrOfLevels%10 != 0)) ); j++) {
152 				if ((60+j*50<globalData.mousey-yplace)&&(globalData.mousey-yplace<j*50+92)) {
153 					tmpSelected = j*10;
154 				}
155 			}
156 			if (tmpSelected != -1) {
157 				for (int k = 0; (( (!(nrOfLevels%10) || k<nrOfLevels-10*(j-1)) )&&(k<10)); k++) {
158 					if ((10+k*50<globalData.mousex-xplace)&&(globalData.mousex-xplace<k*50+42)) {
159 						tmpSelected +=k;
160 						selected = tmpSelected;
161 					}
162 				}
163 			}
164 		}
165 		oldmousey = globalData.mousey;
166 		oldmousex= globalData.mousex;
167 
168 		// If the mouse button is released, make bMouseUp equal true
169 		if ( !(SDL_GetMouseState(nullptr, nullptr)&SDL_BUTTON(1)) ) {
170 			bMouseUp=true;
171 		}
172 
173 		if (SDL_GetMouseState(nullptr,nullptr)&SDL_BUTTON(1) && bMouseUp) {
174 			bMouseUp = false;
175 
176 			int levelClicked = -1;
177 			int i;
178 			for (i = 0; (i<nrOfLevels/10)||((i<nrOfLevels/10+1)&&(nrOfLevels%10 != 0)); i++)
179 				if ((60+i*50<globalData.mousey-yplace)&&(globalData.mousey-yplace<i*50+92)) {
180 					levelClicked = i*10;
181 				}
182 			i++;
183 			if (levelClicked != -1)
184 				for (int j = 0; ((j<nrOfStageLevels%(i*10))&&(j<10)); j++)
185 					if ((10+j*50<globalData.mousex-xplace)&&(globalData.mousex-xplace<j*50+42)) {
186 						levelClicked +=j;
187 						levelSelected = true;
188 						levelNr = levelClicked;
189 					}
190 		}
191 
192 		if (Type == 1) {
193 			std::string scoreString = SPrintStringF(_("Best score: %i"), GetStageScores(selected)) ;
194 			std::string timeString = SPrintStringF(_("Time used: %s"),"-- : --");
195 
196 			if (GetStageTime(selected)>0) {
197 				timeString = SPrintStringF(_("Time used: %d : %02d"), GetStageTime(selected)/1000/60, (GetStageTime(selected)/1000)%60);
198 			}
199 
200 			Write(globalData.screen, 200,200,scoreString.c_str());
201 			Write(globalData.screen, 200,250,timeString.c_str());
202 			std::string totalString = SPrintStringF(_("Total score: %i in %i:%02i"), totalScore, totalTime/1000/60, ((totalTime/1000)%60) );
203 			Write(globalData.screen, 200,600,totalString.c_str());
204 		}
205 
206 		globalData.mouse.Draw(globalData.screen, SDL_GetTicks(), globalData.mousex, globalData.mousey);
207 		SDL_RenderPresent(globalData.screen); //draws it all to the screen
208 
209 	}
210 	DrawBackground(globalData.screen);
211 	return levelNr;
212 }
213