135 |
listener = al; |
listener = al; |
136 |
} |
} |
137 |
void trigger_action() { |
void trigger_action() { |
138 |
if( (iselected) < (max_available)) { |
const LevelInfo *levelinfo = level_pack->get_info(iselected); |
139 |
|
LevelStatus *ls = GetLevelStatus(level_pack->get_name(), levelinfo->filename); |
140 |
|
|
141 |
|
if (iselected <= max_available || (ls && ls->finished >= Difficulty)) { |
142 |
cache.clear(); |
cache.clear(); |
143 |
if (listener) listener->on_action(this); |
if (listener) { |
144 |
recalc_availavle(); |
listener->on_action(this); |
145 |
|
recalc_available(); |
146 |
|
} |
147 |
|
} |
148 |
|
else { |
149 |
|
show_text("You are not allowed to play this level yet."); |
150 |
} |
} |
151 |
} |
} |
152 |
|
|
175 |
set_selected(new_first, new_sel); |
set_selected(new_first, new_sel); |
176 |
} |
} |
177 |
|
|
178 |
|
void show_text(const string& text); |
179 |
|
|
180 |
private: |
private: |
181 |
// Private functions. |
// Private functions. |
182 |
void scroll_up(int lines); |
void scroll_up(int lines); |
183 |
void scroll_down(int lines); |
void scroll_down(int lines); |
184 |
void set_selected (int newfirst, int newsel); |
void set_selected (int newfirst, int newsel); |
185 |
void recalc_availavle (); |
void recalc_available (); |
186 |
|
|
187 |
// Event handling. |
// Event handling. |
188 |
bool handle_keydown (const SDL_Event *e); |
bool handle_keydown (const SDL_Event *e); |
197 |
|
|
198 |
int ifirst; // Index of "upper left" level |
int ifirst; // Index of "upper left" level |
199 |
int iselected; // Index of selected level |
int iselected; // Index of selected level |
200 |
int max_available; // Index of the last available level (one can coose out of x unsolved levels) |
int max_available; // Index of the last available level (one can choose out of x unsolved levels) |
201 |
int width, height; |
int width, height; |
202 |
vector<px::Rect> m_areas; // Screen areas occupied by level previews |
vector<px::Rect> m_areas; // Screen areas occupied by level previews |
203 |
ActionListener *listener; |
ActionListener *listener; |
228 |
levelwidget->set_position(pos & 0xffff); |
levelwidget->set_position(pos & 0xffff); |
229 |
} |
} |
230 |
|
|
231 |
|
void show_text(const string& text) { |
232 |
|
shown_text = text; |
233 |
|
shown_text_ttl = 2.0; // show for two seconds |
234 |
|
} |
235 |
|
|
236 |
private: |
private: |
237 |
|
|
238 |
void update_info(); |
void update_info(); |
253 |
|
|
254 |
Widget *pgup, *pgdown, *start, *end, *unsolved; |
Widget *pgup, *pgdown, *start, *end, *unsolved; |
255 |
|
|
256 |
Widget *newgame; |
Widget *newgame; |
257 |
Widget *back; |
Widget *back; |
258 |
Widget *m_nextlp, *m_prevlp; // Next/previous level pack |
Widget *m_nextlp, *m_prevlp; // Next/previous level pack |
259 |
TextButton *m_lpbutton; // Current level pack |
TextButton *m_lpbutton; // Current level pack |
260 |
Label *m_infobutton; |
Label *m_infobutton; |
261 |
Label *m_levelinfo, *m_levelinfo2; |
Label *m_levelinfo, *m_levelinfo2; |
262 |
LevelWidget *levelwidget; |
LevelWidget *levelwidget; |
263 |
LevelPack *level_pack; |
LevelPack *level_pack; |
264 |
unsigned m_ilevelpack; |
unsigned m_ilevelpack; |
265 |
|
string shown_text; // info text (disappears automatically) |
266 |
|
double shown_text_ttl; // rest duration for shown_text |
267 |
}; |
}; |
268 |
|
|
269 |
class MainMenu : public Menu { |
class MainMenu : public Menu { |
304 |
{} |
{} |
305 |
|
|
306 |
LevelMenu * |
LevelMenu * |
307 |
LevelWidget::get_menu() { |
LevelWidget::get_menu() |
308 |
|
{ |
309 |
if (Menu *m = Widget::get_menu()) |
if (Menu *m = Widget::get_menu()) |
310 |
return dynamic_cast<LevelMenu*>(m); |
return dynamic_cast<LevelMenu*>(m); |
311 |
else { |
else { |
315 |
} |
} |
316 |
|
|
317 |
void |
void |
318 |
|
LevelWidget::show_text(const string& text) |
319 |
|
{ |
320 |
|
get_menu()->show_text(text); |
321 |
|
} |
322 |
|
|
323 |
|
void |
324 |
LevelWidget::scroll_up(int nlines) |
LevelWidget::scroll_up(int nlines) |
325 |
{ |
{ |
326 |
for (; nlines; --nlines) { |
for (; nlines; --nlines) { |
346 |
redraw(); |
redraw(); |
347 |
} |
} |
348 |
|
|
349 |
void LevelWidget::page_up() { |
void |
350 |
|
LevelWidget::page_up() |
351 |
|
{ |
352 |
set_selected (ifirst - width*height, iselected - width*height); |
set_selected (ifirst - width*height, iselected - width*height); |
353 |
} |
} |
354 |
void LevelWidget::page_down() { |
void |
355 |
|
LevelWidget::page_down() |
356 |
|
{ |
357 |
set_selected (ifirst + width*height, iselected + width*height); |
set_selected (ifirst + width*height, iselected + width*height); |
358 |
} |
} |
359 |
|
|
360 |
void |
void |
361 |
LevelWidget::recalc_availavle() |
LevelWidget::recalc_available() |
362 |
{ |
{ |
363 |
max_available = HighestAvailableLevel( level_pack); |
max_available = HighestAvailableLevel(level_pack); |
364 |
} |
} |
365 |
|
|
366 |
void |
void |
372 |
oxyd::ChangeSoundset(options::SoundSet, level_pack->get_default_SoundSet()); |
oxyd::ChangeSoundset(options::SoundSet, level_pack->get_default_SoundSet()); |
373 |
cache.clear(); |
cache.clear(); |
374 |
preview_cache.clear(); |
preview_cache.clear(); |
375 |
recalc_availavle(); |
recalc_available(); |
376 |
redraw(); |
redraw(); |
377 |
sound::PlaySound("menumove"); |
sound::PlaySound("menumove"); |
378 |
} |
} |
380 |
void |
void |
381 |
LevelWidget::next_unsolved() |
LevelWidget::next_unsolved() |
382 |
{ |
{ |
383 |
unsigned next = NextLevel(level_pack, iselected, true, false); |
unsigned next = NextLevel(level_pack, iselected, max_available, true, false); |
384 |
|
|
385 |
if (next) |
if (next) |
386 |
set_current(next); |
set_current(next); |
387 |
else |
else |
388 |
printf("No unsolved level found.\n"); |
show_text("No further unsolved level available!"); |
389 |
} |
} |
390 |
|
|
391 |
void |
void |
460 |
else |
else |
461 |
blit (gc, imgx, imgy, img_unknown); |
blit (gc, imgx, imgy, img_unknown); |
462 |
|
|
463 |
if( i >= (max_available)) |
int finished = 0; |
464 |
{ |
bool level_changed = false; |
465 |
blit (gc, imgx, imgy, img_unavailable); |
if (LevelStatus *ls = GetLevelStatus(level_pack->get_name(), levelinfo->filename)) { |
466 |
|
finished = ls->finished; |
467 |
|
if (finished) |
468 |
|
level_changed = level_pack->get_modtime(i) > ls->solved_at; |
469 |
} |
} |
470 |
|
|
471 |
|
// Shade unavailable levels |
472 |
|
if (i > (unsigned)max_available && finished<Difficulty) |
473 |
|
blit (gc, imgx, imgy, img_unavailable); |
474 |
|
|
475 |
// Draw solved/changed icons on top of level preview |
// Draw solved/changed icons on top of level preview |
476 |
if (LevelStatus *ls=GetLevelStatus(level_pack->get_name(), |
if (finished) |
477 |
levelinfo->filename)) |
blit (gc, imgx, imgy, (finished&DIFFICULTY_HARD) ? img_hard : img_easy); |
478 |
{ |
|
479 |
if (ls->finished != 0) { |
// Add warning sign if level has been changed since player solved it |
480 |
bool hardp = ls->finished & DIFFICULTY_HARD; |
if (level_changed) |
481 |
blit (gc, imgx, imgy, hardp ? img_hard : img_easy); |
blit (gc, imgx-3, imgy-3, img_changed); |
|
|
|
|
// Add warning sign if level has been changed since player solved it |
|
|
if (level_pack->get_modtime(i) > ls->solved_at) |
|
|
blit (gc, imgx-3, imgy-3, img_changed); |
|
|
} |
|
|
} |
|
482 |
|
|
483 |
// Draw level name |
// Draw level name |
484 |
const char *caption = levelinfo->name.c_str(); |
const char *caption = levelinfo->name.c_str(); |
515 |
if (newfirst != ifirst) { |
if (newfirst != ifirst) { |
516 |
ifirst = newfirst; |
ifirst = newfirst; |
517 |
iselected = newsel; |
iselected = newsel; |
518 |
|
|
519 |
if (!m_areas.empty()) { |
if (!m_areas.empty()) { |
520 |
sound::PlaySound("menumove"); |
sound::PlaySound("menumove"); |
521 |
if (oldsel != newsel) sound::PlaySound("menuswitch"); |
if (oldsel != newsel) sound::PlaySound("menuswitch"); |
1182 |
set_position(pos); |
set_position(pos); |
1183 |
} |
} |
1184 |
|
|
1185 |
void LevelMenu::tick(double) |
void LevelMenu::tick(double dtime) |
1186 |
{ |
{ |
1187 |
|
// info texts disappear after some time |
1188 |
|
if (shown_text_ttl>0.0) { |
1189 |
|
shown_text_ttl -= dtime; |
1190 |
|
if (shown_text_ttl <= 0.0) |
1191 |
|
shown_text = ""; |
1192 |
|
} |
1193 |
update_info(); |
update_info(); |
1194 |
} |
} |
1195 |
|
|
1241 |
} |
} |
1242 |
} |
} |
1243 |
|
|
1244 |
|
#define BUFFERSIZE 200 |
1245 |
|
|
1246 |
void |
void |
1247 |
LevelMenu::update_info() |
LevelMenu::update_info() |
1248 |
{ |
{ |
1249 |
char txt[100]; |
char txt[BUFFERSIZE]; |
1250 |
enigma::LevelPack *lp = enigma::LevelPacks[m_ilevelpack]; |
enigma::LevelPack *lp = enigma::LevelPacks[m_ilevelpack]; |
1251 |
int iselected = levelwidget->selected_level(); |
int iselected = levelwidget->selected_level(); |
1252 |
|
|
1253 |
if (const enigma::LevelInfo *li = lp->get_info (iselected)) { |
if (const enigma::LevelInfo *li = lp->get_info (iselected)) { |
1254 |
if (options::WizardMode) { |
if (options::WizardMode) { |
1255 |
snprintf (txt, sizeof(txt), "#%d: %s (%s)", |
snprintf (txt, sizeof(txt), "#%d: %s (%s)", |
1256 |
iselected+1, li->name.c_str(), li->filename.c_str()); |
iselected+1, li->name.c_str(), li->filename.c_str()); |
1257 |
} else { |
} else { |
1258 |
snprintf (txt, sizeof(txt), "#%d: %s", |
snprintf (txt, sizeof(txt), "#%d: %s", |
1259 |
iselected+1, li->name.c_str()); //, li->filename.c_str()); |
iselected+1, li->name.c_str()); |
1260 |
} |
} |
1261 |
m_levelinfo->set_text(txt); |
m_levelinfo->set_text(txt); |
1262 |
|
assert(strlen(txt)<BUFFERSIZE); |
1263 |
|
|
1264 |
int par_time = li->best_time; |
if (shown_text.length()) { |
1265 |
if (LevelStatus *ls= options::GetLevelStatus (lp->get_name(), li->filename)) { |
m_levelinfo2->set_text(shown_text); |
1266 |
if (options::Difficulty == DIFFICULTY_HARD) { |
} |
1267 |
if (ls->par_hard > 0) |
else { |
1268 |
par_time = ls->par_hard; |
int par_time = li->best_time; |
1269 |
} else { |
if (LevelStatus *ls= options::GetLevelStatus (lp->get_name(), li->filename)) { |
1270 |
if (ls->par_easy > 0) |
if (options::Difficulty == DIFFICULTY_HARD) { |
1271 |
par_time = ls->par_easy; |
if (ls->par_hard > 0) |
1272 |
|
par_time = ls->par_hard; |
1273 |
|
} else { |
1274 |
|
if (ls->par_easy > 0) |
1275 |
|
par_time = ls->par_easy; |
1276 |
|
} |
1277 |
} |
} |
1278 |
|
snprintf (txt, sizeof(txt), "Time to beat: %d:%02d", |
1279 |
|
par_time/60, par_time % 60); |
1280 |
|
|
1281 |
|
m_levelinfo2->set_text(txt); |
1282 |
|
assert(strlen(txt)<BUFFERSIZE); |
1283 |
} |
} |
|
snprintf (txt, sizeof(txt), "Time to beat: %d:%02d", |
|
|
par_time/60, par_time % 60); |
|
|
m_levelinfo2->set_text(txt); |
|
1284 |
} |
} |
1285 |
} |
} |
1286 |
|
|
1287 |
|
#undef BUFFERSIZE |
1288 |
|
|
1289 |
void |
void |
1290 |
LevelMenu::set_levelpack (unsigned index) |
LevelMenu::set_levelpack (unsigned index) |
1291 |
{ |
{ |