1 /***************************************************************************
2 blatt.cpp - description
3 -------------------
4 begin : Mit Jul 12 22:54:51 MEST 2000
5 copyright : (C) 2006 by Immi
6 email : cuyo@pcpool.mathematik.uni-freiburg.de
7
8 Modified 2006-2008,2010,2011,2014 by the cuyo developers
9 Maintenance modifications 2012 by Bernhard R. Link
10 Maintenance modifications 2012 by the cuyo developers
11
12 ***************************************************************************/
13
14 /***************************************************************************
15 * *
16 * This program is free software; you can redistribute it and/or modify *
17 * it under the terms of the GNU General Public License as published by *
18 * the Free Software Foundation; either version 2 of the License, or *
19 * (at your option) any later version. *
20 * *
21 ***************************************************************************/
22
23 #include <cstdio>
24 #include <cmath>
25
26 #include "../config.h"
27
28 #include "sdltools.h"
29
30 #include "font.h"
31
32
33 #include "cuyointl.h"
34 #include "ui.h"
35 #include "ui2cuyo.h"
36 #include "cuyo.h"
37 #include "punktefeld.h"
38 #include "fehler.h"
39 #include "global.h"
40 #include "sound.h"
41
42 #include "prefsdaten.h"
43
44 #include "layout.h"
45 #include "blatt.h"
46 #include "menueintrag.h"
47
48
49 #define border_pic_laenge 640
50
51
52
53 /********************************************************************************/
54 /* Ein paar Malfunktionen und so */
55
56
chooseX(int x10,int x20,int x21,int spz,int sp)57 int chooseX(int x10, int x20, int x21, int spz, int sp) {
58 if (spz == 1) return x10;
59 else if (sp == 0) return x20;
60 else return x21;
61 }
62
63
malVertRand(int x,int end_icon=2)64 void malVertRand(int x, int end_icon = 2) {
65 Blatt::gBlattPics[blattpic_borderv]->malStreifenV(
66 x, 0, L_fenster_hoehe, SDLTools::rect(0, 0, L_rand, border_pic_laenge));
67 Blatt::gBlattPics[blattpic_border]->malBildAusschnitt(
68 x, -L_rand, SDLTools::rect(end_icon * L_rand, L_rand, L_rand, L_rand));
69 Blatt::gBlattPics[blattpic_border]->malBildAusschnitt(
70 x, L_fenster_hoehe, SDLTools::rect(end_icon * L_rand, 3 * L_rand, L_rand, L_rand));
71 }
72
malInfosRand(int x,int y)73 void malInfosRand(int x, int y) {
74 Blatt::gBlattPics[blattpic_borderh]->malStreifenH(
75 x, y, L_infos_breite, SDLTools::rect(0, 0, border_pic_laenge, L_rand));
76 Blatt::gBlattPics[blattpic_border]->malBildAusschnitt(
77 x - L_rand, y, SDLTools::rect(L_rand, 2 * L_rand, L_rand, L_rand));
78 Blatt::gBlattPics[blattpic_border]->malBildAusschnitt(
79 x + L_infos_breite, y, SDLTools::rect(3 * L_rand, 2 * L_rand, L_rand, L_rand));
80 }
81
82
malRahmen(int w)83 void malRahmen(int w) {
84 /* Ober- und Unterkante */
85 Blatt::gBlattPics[blattpic_borderh]->malStreifenH(
86 0, -L_rand, w, SDLTools::rect(0, 0, border_pic_laenge, L_rand));
87 Blatt::gBlattPics[blattpic_borderh]->malStreifenH(
88 0, L_fenster_hoehe, w, SDLTools::rect(0, 0, border_pic_laenge, L_rand));
89
90 /* Linke und rechte Kante */
91 malVertRand(-L_rand, 1);
92 malVertRand(w, 3);
93 }
94
95
96
97 /********************************************************************************/
98
99
doEvent(const SDL_Event & evt)100 void Blatt::doEvent(const SDL_Event & evt) {
101 switch (evt.type) {
102 case SDL_KEYDOWN:
103 keyEvent(evt.key.keysym);
104 break;
105 case SDL_MOUSEMOTION:
106 mouseMotionEvent(evt.motion.state & SDL_BUTTON(SDL_BUTTON_LEFT),
107 evt.motion.x, evt.motion.y,
108 evt.motion.x - evt.motion.xrel, evt.motion.y - evt.motion.yrel);
109 break;
110 case SDL_MOUSEBUTTONUP:
111 case SDL_MOUSEBUTTONDOWN:
112 if (evt.button.button == SDL_BUTTON_LEFT) {
113 mouseButtonEvent(evt.button.state == SDL_PRESSED, evt.button.x, evt.button.y);
114 }
115 break;
116 case SDL_VIDEORESIZE:
117 /* Bildschirminhalt neu malen */
118 resizeEvent();
119 break;
120 default:
121 break;
122 }
123 }
124
125
126
127 Bilddatei * Blatt::gBlattPics[anz_blattpics];
128
initBlaetter()129 void Blatt::initBlaetter() {
130
131 for (int i=0; i<anz_blattpics; i++)
132 gBlattPics[i] = new Bilddatei();
133
134 gBlattPics[blattpic_pfeile]->laden("menupics.xpm");
135 gBlattPics[blattpic_highlight]->laden("highlight.xpm");
136 gBlattPics[blattpic_titel]->laden("titel.xpm");
137 gBlattPics[blattpic_scroll]->laden("scroll.xpm");
138 gBlattPics[blattpic_scrollbright]->klonen(*gBlattPics[blattpic_scroll]);
139 gBlattPics[blattpic_scrolldimmed]->klonen(*gBlattPics[blattpic_scroll]);
140
141 gBlattPics[blattpic_scroll]->setFaerbung(Color(130,130,220));
142 gBlattPics[blattpic_scrollbright]->setFaerbung(Color(255,255,128));
143 gBlattPics[blattpic_scrolldimmed]->setFaerbung(Color(80,80,145));
144
145 gBlattPics[blattpic_border]->laden("border.xpm");
146 gBlattPics[blattpic_borderh]->laden("borderh.xpm");
147 gBlattPics[blattpic_borderv]->laden("borderv.xpm");
148 AutoColor::gGame.addUser(gBlattPics[blattpic_border]);
149 AutoColor::gGame.addUser(gBlattPics[blattpic_borderh]);
150 AutoColor::gGame.addUser(gBlattPics[blattpic_borderv]);
151
152 gBlattPics[blattpic_infoicons]->laden("infoicons.xpm");
153
154 }
155
destroyBlaetter()156 void Blatt::destroyBlaetter() {
157 for (int i=0; i<anz_blattpics; i++)
158 delete gBlattPics[i];
159 }
160
161
162
163 /********************************************************************************/
164
165
BlattSpiel()166 BlattSpiel::BlattSpiel() {
167 mPunktefeld[0] = new Punktefeld();
168 mPunktefeld[1] = new Punktefeld();
169 mDekoUpdaten = false;
170 }
171
172
173
~BlattSpiel()174 BlattSpiel::~BlattSpiel() {
175 delete mPunktefeld[0];
176 delete mPunktefeld[1];
177 }
178
179
oeffnen(int lnr)180 void BlattSpiel::oeffnen(int lnr) {
181 UI::setBlatt(this);
182 SDLTools::setVirtualWindowSize(
183 Cuyo::getSpielerZahl() == 1 ? L_fenster_breite_1sp : L_fenster_breite_2sp,
184 L_fenster_hoehe);
185 Cuyo::startSpiel(lnr);
186 }
187
188
189
190
191
keyEvent(const SDL_keysym & taste)192 void BlattSpiel::keyEvent(const SDL_keysym & taste) {
193 Cuyo::keyEvent(taste);
194 }
195
196
resizeEvent()197 void BlattSpiel::resizeEvent() {
198 mDekoUpdaten = true;
199 Cuyo::setUpdateAlles();
200 UI::nachEventAllesAnzeigen();
201 }
202
203
204
205
malInfos(int sp,int x)206 void BlattSpiel::malInfos(int sp, int x) {
207 Color c = ld->mHintergrundFarbe;
208
209 malInfosRand(x, L_naechstesfall_hoehe); /*------------*/
210
211
212 Area::fillRect(x, L_naechstesfall_hoehe + L_rand, L_infos_breite, L_punkte_y - 2 * L_rand - L_naechstesfall_hoehe, c);
213 Str p =
214 Cuyo::getSpielerModus() == spielermodus_computer && sp == 1 ?
215 _("Computer") : _sprintf(_("Player %d"), sp + 1);
216 Font::gGame->drawText(p, x + L_infos_breite / 2, L_player_y + gric / 2, AlignCenter);
217
218 malInfosRand(x, L_punkte_y - L_rand); /*------------*/
219
220 Area::enter(SDLTools::rect(x, L_punkte_y,
221 L_infos_breite, L_punkte_hoehe));
222 /* Wenn sich die Randfarbe ge�ndert hat, dann Punkte auf
223 jeden Fall neu malen */
224 mPunktefeld[sp]->updateGraphik(mDekoUpdaten);
225 Area::leave();
226
227 malInfosRand(x, L_punkte_y + L_punkte_hoehe); /*------------*/
228
229 int pu = L_punkte_y + L_punkte_hoehe + L_rand;
230 Area::fillRect(x, pu, L_infos_breite, L_infoblobs_y - L_rand - pu, c);
231
232 malInfosRand(x, L_infoblobs_y - L_rand); /*------------*/
233
234 /* Level name does not really fit in */
235 // malInfosRand(x, L_levelname_y - L_rand); /*------------*/
236 // /* Put text in an area so that it gets clipped if it is too long */
237 // Area::enter(SDLTools::rect(x, L_levelname_y,
238 // L_infos_breite, gric));
239 // Font::gGame->drawText(ld->mLevelName, L_infos_breite / 2, gric / 2, AlignCenter);
240 // Area::leave();
241
242 Area::fillRect(x + L_infoblobs_breite, L_infoblobs_y, L_infos_breite - L_infoblobs_breite, L_fenster_hoehe - L_infoblobs_y, c);
243
244 if (ld->mLevelGeladen) {
245 /* To be cleaned: Instead of being the full height, the following area should rather
246 * go from L_infoblobs_y to the bottom */
247 Area::enter(SDLTools::rect(x, 0, L_infos_breite, L_fenster_hoehe));
248 Spielfeld* spielfeld = Cuyo::getSpielfeld(sp);
249 if (ld->mGreysAtAll)
250 Font::gGame->drawText(_sprintf("%d", spielfeld->getGrauAnz()),
251 L_greygrass_x2,L_grey_y+gric/2,AlignLeft);
252 Font::gGame->drawText(_sprintf("%d", spielfeld->getGrasAnz()),
253 L_greygrass_x2,L_grass_y+gric/2,AlignLeft);
254
255 Str PlatzAnzahlFormat;
256 if (ld->mPlatzAnzahlMin == ld->mPlatzAnzahlMax) {
257 /* TRANSLATORS: During game: short version of "%d blops explode" */
258 PlatzAnzahlFormat=_sprintf(_("%d"), ld->mPlatzAnzahlMin);
259 } else {
260 if (ld->mPlatzAnzahlAndere) {
261 /* TRANSLATORS: During game: short version of
262 "between %d and %d blops explode" */
263 PlatzAnzahlFormat=_sprintf(_("%d-%d"),
264 ld->mPlatzAnzahlMin,ld->mPlatzAnzahlMax);
265 } else {
266 /* TRANSLATORS: During game: short version of
267 "%d or %d blops explode" */
268 PlatzAnzahlFormat=_sprintf(_("%d/%d"),
269 ld->mPlatzAnzahlMin,ld->mPlatzAnzahlMax);
270 }
271 }
272 Font::gGame->drawText(PlatzAnzahlFormat, L_levelexplode_x2, L_levelexplode_y + gric / 2, AlignLeft);
273 Area::updateRect(L_greygrass_x2, L_infoblobs_y,
274 L_infos_breite-L_greygrass_x2, L_infoblobs_hoehe);
275 Area::leave();
276 }
277 }
278
279
anzeigen()280 void BlattSpiel::anzeigen() {
281 Color c = Color(150, 150, 150);
282
283 Area::fillBorder(c);
284
285 int spz = Cuyo::getSpielerZahl();
286
287 malRahmen(spz == 1 ? L_fenster_breite_1sp : L_fenster_breite_2sp);
288
289 if (spz == 1) {
290 malVertRand(chooseX(L_spielfeld_x, 1, 0) - L_rand);
291 } else {
292 malVertRand(chooseX(L_spielfeld_x, 2, 0) - L_rand);
293 malVertRand(chooseX(L_spielfeld_x, 2, 1) - L_rand);
294 malVertRand(chooseX(L_infos_x, 2, 1) - L_rand);
295 }
296
297 for (int i = 0; i < spz; i++) {
298
299 Area::enter(SDLTools::rect(chooseX(L_spielfeld_x, spz, i), L_spielfeld_y,
300 L_spielfeld_breite, L_spielfeld_hoehe));
301 Cuyo::malSpielfeld(i);
302 Area::leave();
303
304 malInfos(i, chooseX(L_infos_x, spz, i));
305
306 Area::enter(SDLTools::rect(chooseX(L_infos_x, spz, i), 0,
307 L_infos_breite, L_infos_hoehe));
308 Cuyo::malNaechstesFall(i);
309 Area::leave();
310 }
311
312 /* Neue Randfarbe? Dann alles an den xserver schicken */
313 if (mDekoUpdaten) {
314 Area::updateAll();
315 }
316 mDekoUpdaten = false;
317 }
318
319
320
zeitSchritt()321 void BlattSpiel::zeitSchritt() {
322 Cuyo::zeitSchritt();
323
324 for (int i = 0; i < max_spielerzahl; i++)
325 mPunktefeld[i]->zwinkerSchritt();
326
327 /* Den folgenden Aufruf sollte man eigentlich
328 Cuyo und den Punktefeldern ueberlassen; dann
329 wuerd's nur passieren, wenn's muss */
330 UI::nachEventAllesAnzeigen();
331 }
332
333
randNeuMalen()334 void BlattSpiel::randNeuMalen() {
335 mDekoUpdaten = true;
336 }
337
setPunkte(int sp,int pt)338 void BlattSpiel::setPunkte(int sp, int pt) {
339 mPunktefeld[sp]->setPunkte(pt);
340 }
341
342
343
344 /*****************************************************************************/
345
346
BlattMenu(bool immerscrollleiste)347 BlattMenu::BlattMenu(bool immerscrollleiste /* = false */) :
348 mImmerScrollleiste(immerscrollleiste),
349 mEintraege(), mEintraegeY(1,0),
350 mObermenu(NULL), mObereintrag(NULL), mWahl(eintrag_keiner), mHyperaktiv(eintrag_keiner),
351 mInfoText(""), mInfoW(-1),
352 mRahmenUpdaten(false), mRaenderUpdaten(false), mInfozeileUpdaten(false)
353 {
354 }
355
356
~BlattMenu()357 BlattMenu::~BlattMenu() {
358 menuLoeschen();
359 }
360
361
362 /* Gleich nach dem Konstruktor aufrufen, wenn das Obermenu nicht NULL
363 sein soll. Schoener waers, obermenu direkt dem Konstruktor zu
364 uebergeben. Das wuerde aber bedeuten, dass man gezwungen ist, in
365 *jeder* Klasse, die von BlattMenu erbt, einen Konstruktor zu
366 schreiben. Liefert einfach this zurueck, damit man
367 (new BlattMenuXXX())->setObermenu(...)
368 schreiben kann */
setObermenu(BlattMenu * obermenu)369 BlattMenu * BlattMenu::setObermenu(BlattMenu * obermenu) {
370 mObermenu = obermenu;
371 return this;
372 }
373
374
setObereintrag(MenuEintragSubmenu * obereintrag)375 void BlattMenu::setObereintrag(MenuEintragSubmenu * obereintrag) {
376 mObereintrag = obereintrag;
377 }
378
379
380
neuerEintrag(MenuEintrag * eintrag)381 void BlattMenu::neuerEintrag(MenuEintrag* eintrag) {
382 mEintraegeY.push_back(mEintraegeY[mEintraege.size()]+eintrag->mHoehe);
383 mEintraege.push_back(eintrag);
384 /* Check for duplicate hotkeys */
385 int hot=eintrag->getAccel();
386 for (size_t i=mEintraege.size()-1; i-->0;)
387 if (mEintraege[i]->getAccel()==hot)
388 eintrag->deactivateAccel();
389 }
390
391
oeffnen(bool,int wahl)392 void BlattMenu::oeffnen(bool /*durchMaus*/, int wahl /*= eintrag_keiner*/) {
393
394 SDLTools::setVirtualWindowSize(L_fenster_breite_menus, L_fenster_hoehe);
395
396 mHyperaktiv = eintrag_keiner;
397 mWahl = MausBereich(wahl);
398 /* Nicht die nachfolgenden Setzroutinen verwenden, weil sonst
399 evtl. ein nicht-mehr existenter voriger gew�hlter Men�punkt neu
400 gemalt wird. */
401 //setHyperaktiv(eintrag_keiner);
402 //setWahl(wahl);
403
404 /* Jetzt manuell alles updaten */
405 for (size_t i = 0; i < mEintraege.size(); i++)
406 updateEintrag(i);
407
408 /* Daf�r manuell der Infozeile sagen, dass sie geupdatet werden muss */
409 updateInfo();
410
411 /* Zentrierlinien berechnen */
412 int xsum[zl_anzahl];
413 for (int i = 0; i < zl_anzahl; i++) xsum[i] = 0;
414 for (size_t i = 0; i < mEintraege.size(); i++) {
415 int zl = mEintraege[i]->getZentrierLinie();
416 xsum[zl] += mEintraege[i]->getX0() + mEintraege[i]->getX1();
417 }
418 CASSERT(mEintraege.size());
419 for (int i = 0; i < zl_anzahl; i++)
420 mX0[i] = L_fenster_breite_menus/2 - xsum[i]/((int) mEintraege.size());
421
422
423 setScrollZielHigh(ynw_mitte, true);
424 //if (durchMaus)
425 // setWahl(eintrag_keiner);
426
427 /* Chaning AutoColor::gGame automatically recolors the
428 border pictures */
429 AutoColor::gGame = Color(0, 0, 70);
430
431
432 UI::setBlatt(this);
433 sichtbaresUpdaten();
434 mRahmenUpdaten = true;
435 }
436
437
438
439
440 int keypadersatz[10] = {
441 SDLK_INSERT, SDLK_END, SDLK_DOWN, SDLK_PAGEDOWN, SDLK_LEFT,
442 SDLK_KP5, SDLK_RIGHT, SDLK_HOME, SDLK_UP, SDLK_PAGEUP};
443
keyEvent(const SDL_keysym & taste)444 void BlattMenu::keyEvent(const SDL_keysym & taste) {
445
446 /* Wenn die Taste einen Ascii-Code hat, dann wollen wir mit
447 dem weiterarbeiten. (d.h. shift-& auf franzoesischer Tastatur
448 ist 1) */
449 int t = taste.unicode;
450 /* Fuer sonstige Tasten (Pfeile, etc.) nehmen wir den SDL-Code */
451 if (t <= 0 || t > 255)
452 t = taste.sym;
453 /* Aber Buchstaben haetten wir gerne als Grossbuchstaben.
454 (Wenn wir auch Umlaute als Tastenkuerzel haetten, muessten
455 wir uns auch darum kuemmern) */
456 if (t >= 'a' && t <= 'z')
457 t = t-'a'+'A';
458 /* Wenn eine Ziffernblock-Taste gedrueckt wurde aber kein
459 Uni-Code mitgeliefert wurde, dann soll das auf die uebliche
460 Art wie Pfeiltasten wirken.
461 (Manchmal macht SDL das automatisch; das scheint aber buggy
462 zu sein.) */
463 if (t>=SDLK_KP0 && t<=SDLK_KP9)
464 t = keypadersatz[t-SDLK_KP0];
465
466
467 // /* Keycode normalisieren */
468 // int t = taste.sym;
469 // if (t >= 'a' && t <= 'z')
470 // t = t-'a'+'A';
471 // if (t>=SDLK_KP0 && t<=SDLK_KP9) {
472 // if (taste.mod & KMOD_NUM)
473 // t = t-SDLK_KP0+'0';
474 // else
475 // t = keypadersatz[t-SDLK_KP0];
476 // }
477 // if (t==SDLK_KP_ENTER || t==SDLK_SPACE)
478 // t=SDLK_RETURN;
479 //
480 // if (t == SDLK_ESCAPE) {
481 // doEscape();
482 // return;
483 // }
484
485 //print_to_stderr(_sprintf("sym %d = '%c' ", taste.sym, taste.sym));
486 //print_to_stderr(_sprintf("unicode %d = '%c' ", taste.unicode, taste.unicode));
487 //print_to_stderr(_sprintf("taste %d = '%c'\n", t, t));
488
489 /* Jeder Tastendruck stellt den Subbereich auf default;
490 selbst solche, die nix bewirken */
491 setWahl(mWahl.mEintrag);
492
493 if (mHyperaktiv >= 0) {
494 mEintraege[mHyperaktiv]->doHyperaktiv(taste,t);
495 setWahl(mHyperaktiv);
496 setHyperaktiv(eintrag_keiner);
497 return;
498 }
499
500 switch (t) {
501 case SDLK_UP: navigiere(-1); break;
502 case SDLK_DOWN: navigiere(1); break;
503 case SDLK_PAGEUP: navigiere(-1,mZeigVon); break;
504 case SDLK_PAGEDOWN: navigiere(1,mZeigBis-1); break;
505 case SDLK_HOME: navigiere(1,0); break;
506 case SDLK_END: navigiere(-1,mEintraege.size()-1); break;
507 case SDLK_ESCAPE:
508 doEscape();
509 break;
510 case SDLK_RETURN:
511 case SDLK_KP_ENTER:
512 case SDLK_SPACE:
513 doReturn(false);
514 break;
515 default:
516 /* Accelerator-Taste gedr�ckt? */
517 for (int i = 0; i < (int) mEintraege.size(); i++) {
518 if (t == mEintraege[i]->getAccel() && mEintraege[i]->getWaehlbar()) {
519
520 setWahl(i);
521 doReturn(false);
522 return;
523 }
524 }
525 /* Vielleicht ist der gew�hlte Eintrag aktiv? */
526 if (mWahl.mEintrag >= 0)
527 if (mEintraege[mWahl.mEintrag]->getAktiv()) {
528 mEintraege[mWahl.mEintrag]->doHyperaktiv(taste,t);
529 /* Tastatur-User wollen nix von Subbereichen wissen */
530 UI::nachEventAllesAnzeigen();
531 }
532 break;
533 }
534
535 }
536
537
538
resizeEvent()539 void BlattMenu::resizeEvent() {
540 sichtbaresUpdaten();
541 mRahmenUpdaten = true;
542 UI::nachEventAllesAnzeigen();
543 }
544
545
546
getMausPos(int x,int y)547 MausBereich BlattMenu::getMausPos(int x, int y) {
548 /* Befindet sich die Maus in der Scrollbar? */
549 bool sc = istScrollbar();
550 if (sc || mImmerScrollleiste) {
551 if (x >= L_scrollleiste_x && x < L_scrollleiste_x + gric) {
552 /* Das mit dem 1000 ist weil negative Zahlen in die falsche Richtung gerundet werden */
553 int yy = (y - L_scrollleiste_y + 1000 * gric) / gric - 1000;
554 if (yy >= 0 && yy < L_scrollleiste_buttonzahl) {
555 if (!sc && yy < 4) {
556 /* Auf grauem Scrollbarbutton */
557 return MausBereich();
558 } else
559 return MausBereich(eintrag_scrollleiste, yy);
560 }
561 }
562 }
563
564 int e=mEintraege.size();
565 for (y-=mY0; e>=0 && y<mEintraegeY[e]; e--) {}
566 /* ~~ C garantiert, dass die rechte Seite nur
567 ausgef�hrt wird, wenn's n�tig ist */
568 if (e < mAnimZeigVon || e >= mAnimZeigBis)
569 return MausBereich();
570 if (!mEintraege[e]->getWaehlbar())
571 return MausBereich();
572 int sb = mEintraege[e]->getMausPos(x - mX0[mEintraege[e]->getZentrierLinie()],
573 y - mEintraegeY[e]);
574 if (sb == subbereich_keiner)
575 return MausBereich();
576 else
577 return MausBereich(e, sb);
578 }
579
580
581 /* befindet sich der Cursor aus Sicht von Tastatur-Usern? */
getTastenCursorPos()582 int BlattMenu::getTastenCursorPos() {
583 if (mHyperaktiv >= 0)
584 return mHyperaktiv;
585 else
586 return mWahl.mEintrag;
587 }
588
589
590
mouseMotionEvent(bool press,int x,int y,int x_alt,int y_alt)591 void BlattMenu::mouseMotionEvent(bool press, int x, int y, int x_alt, int y_alt) {
592
593 /* Bei gedr�ckter Maustaste rumfahren
594 => Dort, wo der Knopf runter ging bleibt's ausgew�hlt */
595 if (press) {
596 return;
597 }
598
599 MausBereich mausAlt = getMausPos(x_alt, y_alt);
600 MausBereich mausNeu = getMausPos(x, y);
601
602 if (mausNeu == mausAlt)
603 return;
604
605 setWahl(mausNeu);
606 UI::nachEventAllesAnzeigen();
607 }
608
609
mouseButtonEvent(bool press,int x,int y)610 void BlattMenu::mouseButtonEvent(bool press, int x, int y) {
611
612 mPress = press;
613
614 if (!press)
615 return;
616
617 MausBereich mausNeu = getMausPos(x, y);
618
619 /* Wenn was hyperaktiv war, dann kann man's durch Mausklick
620 enthyperaktivieren (selbst wenn man irgendwo anders ins
621 Fenster klickt) */
622 setHyperaktiv(eintrag_keiner);
623 setWahl(mausNeu);
624
625 if (mWahl.mEintrag >= 0)
626 doReturn(true);
627 else if (mWahl.mEintrag == eintrag_scrollleiste) {
628 /* Um ganz hoch oder runter zu scrollen, k�nnen wir einfach auf
629 viel zu weit setzen; setScrollZielLow macht das dann schon richtig */
630 switch (mWahl.mSubBereich) {
631 case 0: setScrollZielLow(99999); break;
632 case 1: scrollleisteScroll(1); break;
633 case 2: scrollleisteScroll(-1); break;
634 case 3: setScrollZielLow(-99999); break;
635 case 4: doEscape();
636 }
637 }
638 }
639
640
641
642
643
anzeigen()644 void BlattMenu::anzeigen() {
645
646 //Area::fillRect(0, 0, L_fenster_breite_menus, L_fenster_hoehe, Color(30, 30, 70));
647
648 if (mRahmenUpdaten) {
649 Area::fillBorder(Color(30, 30, 70));
650 //malRahmen(L_fenster_breite_menus);
651 Area::updateAll();
652 mRahmenUpdaten = false;
653 }
654
655 /* Oberer und unterer Rand */
656 if (mRaenderUpdaten) {
657 /* Rand oberhalb des Men�s */
658 Area::fillRect(0, 0, L_fenster_breite_menus, mAnimY0+mEintraegeY[mAnimZeigVon],
659 Color(30, 30, 70));
660 Area::updateRect(0, 0,
661 L_fenster_breite_menus, mAnimY0+mEintraegeY[mAnimZeigVon]);
662
663 /* Zwischen Men� und Infozeile */
664 /* Mark: H�h, ist das nicht das gleiche wie
665 mAnimY0+mEintraegeY[mAnimZeigBis] ? */
666 /* Immi: Wei� auch nicht mehr. Vielleicht wusste ich nicht, dass
667 mEintraegeY eins weiter geht als Gesamtzahl der Eintr�ge */
668 int y_u = mAnimY0+mEintraegeY[mAnimZeigBis - 1]
669 + mEintraege[mAnimZeigBis - 1]->mHoehe;
670 /* Provisorisch: Das Hauptmen� ist zu lang, wenn "debug-mode" drunter steht;
671 das produziert graphik-Fehler... */
672 if (L_fenster_hoehe - L_info_hoehe - y_u > 0) {
673 Area::fillRect(0, y_u, L_fenster_breite_menus, L_fenster_hoehe - L_info_hoehe - y_u,
674 Color(30, 30, 70));
675 Area::updateRect(0, y_u, L_fenster_breite_menus, L_fenster_hoehe - L_info_hoehe - y_u);
676 }
677
678 /* Wenn diese Farbe ge�ndert wird, mu� das auch in
679 some_pic_sources/highlight.pov und some_pic_sources/Makefile
680 geschehen. Und in menueintrag.cpp */
681
682 mRaenderUpdaten = false;
683 }
684
685 int tc = getTastenCursorPos();
686
687 for (int i = mAnimZeigVon; i < mAnimZeigBis; i++) {
688 mEintraege[i]->anzeigen(mX0[mEintraege[i]->getZentrierLinie()],
689 mAnimY0+mEintraegeY[i], tc == i);
690 }
691
692 if (mInfozeileUpdaten) {
693 Area::enter(SDLTools::rect
694 (0, L_fenster_hoehe-L_info_hoehe,
695 L_fenster_breite_menus,L_info_hoehe));
696 Area::fillRect(0,0,L_fenster_breite_menus,L_info_hoehe, Color(30, 30, 70));
697 if (mInfoW>=0) {
698 Font::gMenu->drawText(mInfoText,
699 mInfoX+L_info_hspace,
700 L_info_hoehe-L_infosep,
701 AlignBottomLeft);
702 Font::gMenu->drawText(mInfoText,
703 mInfoX+L_info_hspace+mInfoW,
704 L_info_hoehe-L_infosep,
705 AlignBottomLeft);
706 } else
707 Font::gMenu->drawText(mInfoText, L_infosep, L_info_hoehe-L_infosep,
708 AlignBottomLeft);
709 Area::updateRect(0,0,L_fenster_breite_menus,L_info_hoehe);
710 Area::leave();
711 mInfozeileUpdaten = false;
712 }
713
714 bool sc = istScrollbar();
715 if (sc || mImmerScrollleiste) {
716
717 /* Provisorisch: Graphik wird noch jedes Mal neu gemalt */
718
719 int scrollwahl = mWahl.mEintrag == eintrag_scrollleiste ? mWahl.mSubBereich : -1;
720 for (int i = 0; i < L_scrollleiste_buttonzahl; i++) {
721 int scrollbildchen[] = {2, 0, 1, 3, 6};
722 int helligkeit = scrollwahl == i ? blattpic_scrollbright : blattpic_scroll;
723 if (!sc && i < 4) helligkeit = blattpic_scrolldimmed;
724 gBlattPics[helligkeit]->malBildchen(L_scrollleiste_x,
725 L_scrollleiste_y + i * gric,
726 scrollbildchen[i]);
727 }
728
729 Area::updateRect(L_scrollleiste_x, L_scrollleiste_y,
730 gric, L_scrollleiste_buttonzahl * gric);
731 }
732 }
733
doEscape()734 void BlattMenu::doEscape() {
735 if (mObermenu) {
736 Sound::playSample(sample_menuclick,so_fenster);
737 UI::setBlatt(mObermenu);
738 mObermenu->sichtbaresUpdaten();
739 if (mObereintrag)
740 mObereintrag->doUntermenuSchliessen();
741 }
742 }
743
doReturn(bool durchMaus)744 void BlattMenu::doReturn(bool durchMaus) {
745 if (mWahl.mEintrag == eintrag_keiner)
746 return;
747 if (mEintraege[mWahl.mEintrag]->getHyper()) {
748 setHyperaktiv(mWahl.mEintrag);
749 } else {
750 mEintraege[mWahl.mEintrag]->doReturn(durchMaus);
751 }
752 }
753
754
zeitSchritt()755 void BlattMenu::zeitSchritt() {
756 /* Infozeile */
757 if (mInfoW>=0) {
758 mInfoX -= L_info_scrollspeed;
759 if (mInfoX<=-mInfoW)
760 mInfoX += mInfoW;
761 mInfozeileUpdaten = true;
762 UI::nachEventAllesAnzeigen();
763 }
764
765 /* Men�eintr�ge d�rfen ihre Privat-Animation haben */
766 for (size_t i=0; i<mEintraege.size(); i++)
767 mEintraege[i]->zeitSchritt();
768
769 /* Maus auf Scrollpfeil gedr�ckt? */
770 if (mWahl.mEintrag == eintrag_scrollleiste && mPress) {
771 if (mWahl.mSubBereich == 1) scrollleisteScroll(1); // hoch
772 else if (mWahl.mSubBereich == 2) scrollleisteScroll(-1); // runter
773 }
774
775 /* Echte Scrollpos an gew�nschte anpassen */
776 scrollZeitSchritt();
777 }
778
779
780
781
navigiere(int d,int vorschlag)782 void BlattMenu::navigiere(int d, int vorschlag /*=-1*/) {
783 int sgn = d > 0 ? 1 : -1;
784
785 int neu_wahl = mWahl.mEintrag;
786
787 if (vorschlag >= 0) neu_wahl = vorschlag;
788 else if (neu_wahl >= 0) neu_wahl += d;
789 else if (sgn == 1) neu_wahl = -1 + d;
790 else neu_wahl = mEintraege.size() + d;
791
792 sgn = -sgn; /* Erstmal auf den alten Wert zulaufen */
793 int angestossen = 0; /* Flags: 1=oben, 2=unten, 4=mitte */
794 while (1) {
795 if ((angestossen & 3) == 3) {
796 /* Wenn wir beim Suchen eines passenden Menupunkts oben *und*
797 unten anstossen, dann aufgeben */
798 neu_wahl = -1;
799 break;
800 } else if (neu_wahl < 0) {
801 neu_wahl = 0; sgn = 1; angestossen |= 5;
802 } else if (neu_wahl >= (int) mEintraege.size()) {
803 neu_wahl = mEintraege.size() - 1; sgn = -1; angestossen |= 6;
804 } else if (neu_wahl==mWahl.mEintrag && !(angestossen & 4)) {
805 sgn = -sgn; neu_wahl += sgn; angestossen |= 4;
806 } else if (!mEintraege[neu_wahl]->getWaehlbar())
807 neu_wahl += sgn;
808 else
809 break;
810 }
811
812 if (neu_wahl == mWahl.mEintrag) return;
813 setWahl(neu_wahl);
814 setScrollZielHigh(d>0 ? ynw_oben : ynw_unten);
815 sichtbaresUpdaten();
816 UI::nachEventAllesAnzeigen();
817 }
818
819
820
menuLoeschen()821 void BlattMenu::menuLoeschen() {
822 for (int i = 0; i < (int) mEintraege.size(); i++)
823 delete(mEintraege[i]);
824 mEintraege.clear();
825 mEintraegeY.clear();
826 mEintraegeY.push_back(0);
827 }
828
829
830
831 /* �ndert wahl und k�mmert sich drum, dass Graphik geupdatet wird */
setWahl(MausBereich wahl)832 void BlattMenu::setWahl(MausBereich wahl) {
833 int walt = mWahl.mEintrag;
834 mWahl = wahl;
835 updateEintrag(walt);
836 if (walt != wahl.mEintrag)
837 updateEintrag(wahl.mEintrag);
838 updateInfo();
839 }
840
setWahl(int eintrag,int subBereich)841 void BlattMenu::setWahl(int eintrag, int subBereich /*= subbereich_default*/) {
842 setWahl(MausBereich(eintrag, subBereich));
843 }
844
845
setHyperaktiv(int ha)846 void BlattMenu::setHyperaktiv(int ha) {
847 int halt = mHyperaktiv;
848 mHyperaktiv = ha;
849 updateEintrag(halt);
850 if (halt != ha)
851 updateEintrag(ha);
852 updateInfo();
853 }
854
855
updateInfo()856 void BlattMenu::updateInfo() {
857 Str neu = (mHyperaktiv >= 0
858 ? mEintraege[mHyperaktiv]->getInfo()
859 : (mWahl.mEintrag >= 0
860 ? mEintraege[mWahl.mEintrag]->getInfo()
861 : ""));
862 if (neu != mInfoText) {
863 mInfoText = neu;
864 mInfoW = Font::gMenu->getLineWidth(mInfoText.data());
865 if (mInfoW > L_fenster_breite_menus-2*L_infosep) {
866 mInfoW+=L_info_hspace;
867 mInfoX=0;
868 } else
869 mInfoW=-1;
870 mInfozeileUpdaten = true;
871 }
872 }
873
874
875
876 /* Teilt dem Eintrag seinen neuen Subbereich mit. Der Eintrag k�mmert
877 sich dann um sein Graphik-Update */
updateEintrag(int e)878 void BlattMenu::updateEintrag(int e) {
879 if (e < 0) return;
880 mEintraege[e]->setSubBereich(
881 mHyperaktiv == e ? subbereich_hyperaktiv :
882 mWahl.mEintrag == e ? mWahl.mSubBereich :
883 subbereich_keiner
884 );
885 }
886
887
sichtbaresUpdaten()888 void BlattMenu::sichtbaresUpdaten() {
889 for (int i = mAnimZeigVon; i < mAnimZeigBis; i++)
890 mEintraege[i]->setUpdateFlag();
891 mRaenderUpdaten = true;
892 mInfozeileUpdaten = true;
893 }
894
895
istScrollbar() const896 bool BlattMenu::istScrollbar() const {
897 return mEintraegeY[mEintraege.size()] > L_menu_hoehe;
898 }
899
900
901
scrollleisteScroll(int sgn)902 void BlattMenu::scrollleisteScroll(int sgn) {
903 setScrollZielLow(mY0 + sgn * L_maus_scroll_geschwindigkeit);
904 }
905
906
907
908 /* Gleicht mY0, mZeigVon und mZeigBis an mWahl an.
909 sprung = true => keine Animation, sondern direkt dort hin. */
setScrollZielHigh(yneuwahl ynw,bool sprung)910 void BlattMenu::setScrollZielHigh(yneuwahl ynw /*=ynw_mitte*/, bool sprung /* = false */) {
911
912 /* Kein Men�punkt gew�hlt? Dann nach oben */
913 int w = mWahl.mEintrag < 0 ? 0 : mWahl.mEintrag;
914
915 /* Erstmal nehmen wir an, da� wir mWahl gem�� ynw ausrichten wollen */
916 int neuy = (L_menu_hoehe - mEintraege[w]->mHoehe)/2 - mEintraegeY[w];
917 switch (ynw) {
918 case ynw_mitte: break;
919 case ynw_oben: neuy-=L_menu_scroll_vorsprung; break;
920 case ynw_unten: neuy+=L_menu_scroll_vorsprung; break;
921 }
922
923 setScrollZielLow(neuy, sprung);
924 }
925
926
927
928
929 /* Setzt mY0 und gleicht mZeigVon und mZeigBis an.
930 sprung = true => keine Animation, sondern direkt dort hin. */
setScrollZielLow(int neuy,bool sprung)931 void BlattMenu::setScrollZielLow(int neuy, bool sprung /* = false */) {
932
933 if (!istScrollbar()) {
934 /* Das Men� passt komplett auf den Bildschirm. Dann wird der Scrollwunsch ignoriert. */
935 neuy = (L_menu_hoehe-mEintraegeY[mEintraege.size()])/2;
936
937 } else {
938 /* Wenn scrollbar, dann aber nicht weiter rausscrollen als gesund w�re */
939 if (neuy>L_menu_scroll_freiraum) {
940 neuy = L_menu_scroll_freiraum;
941 } else if (neuy+mEintraegeY[mEintraege.size()]+L_menu_scroll_freiraum<L_menu_hoehe) {
942 neuy = L_menu_hoehe-L_menu_scroll_freiraum-mEintraegeY[mEintraege.size()];
943 }
944 }
945
946 mY0 = neuy;
947
948 calcZeigVonBis(mY0, mZeigVon, mZeigBis);
949
950 if (sprung) {
951 mAnimY0 = mY0;
952 mAnimZeigVon = mZeigVon;
953 mAnimZeigBis = mZeigBis;
954 mScrollGesch = 0;
955 sichtbaresUpdaten();
956 } else {
957 scrollZeitSchritt();
958 }
959 }
960
961
962
963 /* Berechnet zeigVon und zeigBis aus Y0... mit oder ohne anim */
calcZeigVonBis(int y0,int & von,int & bis)964 void BlattMenu::calcZeigVonBis(int y0, int & von, int & bis) {
965 for (von = mEintraege.size();
966 von>0 && y0+mEintraegeY[von-1]>=0;
967 von--) {}
968 for (bis = 0;
969 bis<(int)mEintraege.size() && y0+mEintraegeY[bis+1]<=L_menu_hoehe;
970 bis++) {}
971 }
972
973
974
scrollZeitSchritt()975 void BlattMenu::scrollZeitSchritt() {
976 if (mAnimY0 == mY0) {
977 mScrollGesch = 0;
978 return;
979 }
980
981 /* Wie schnell w�ren wir am liebsten, unter Ber�cksichtigung des Bremswegs?
982 Die Formel mit der Wurzel und dem Abrunden sollte aufs Pixel genau stimmen. */
983 int diff = mY0 - mAnimY0;
984 int sgn = diff > 0 ? 1 : -1;
985 int ziel_gesch = (int) floor((-0.5 + sqrt(0.25 + 2 * diff * sgn / L_scroll_beschleunigung))
986 * L_scroll_beschleunigung) * sgn;
987
988 /* Versuchen, diese Geschwindigkeit zu erreichen. */
989 if (mScrollGesch + L_scroll_beschleunigung < ziel_gesch)
990 mScrollGesch += L_scroll_beschleunigung;
991 else if (mScrollGesch - L_scroll_beschleunigung > ziel_gesch)
992 mScrollGesch -= L_scroll_beschleunigung;
993 else
994 mScrollGesch = ziel_gesch;
995
996 mAnimY0 += mScrollGesch;
997
998 calcZeigVonBis(mAnimY0, mAnimZeigVon, mAnimZeigBis);
999 sichtbaresUpdaten();
1000 UI::nachEventAllesAnzeigen();
1001 }
1002
1003
1004
1005
1006 /*****************************************************************************/
1007
oeffnen(bool durchMaus,int)1008 void BlattStartAt::oeffnen(bool durchMaus, int) {
1009 /* Zu umstaendlich:
1010 Im Moment liefert getMoeglicheLevel einen Vector von Strings zur�ck,
1011 der hier in einen Vector von Menueintraegen konvertiert werden muss.
1012 Besser waere, wenn direkt das Menu erzeugt werden koennte. */
1013 //std::vector<Str> levNamen;
1014 //int lev, nichtGewonnen;
1015 //Cuyo::getMoeglicheLevel(levNamen, lev, nichtGewonnen);
1016
1017 ld->ladLevelSummary(false,Cuyo::berechneVersion());
1018 menuLoeschen();
1019 bool waehlbar = true;
1020 int spz = Cuyo::getSpielerZahl();
1021 int lanz = ld->getLevelAnz();
1022 int wanz = 0;
1023 bool ungeordnet = gDebug || !ld->getAngeordnet();
1024 for (int l = 1; l <= lanz; l++) {
1025 bool gew = PrefsDaten::getLevelGewonnen(spz == 2, l);
1026 if (waehlbar || gew)
1027 neuerEintrag(new MenuEintragLevel(this, ld->getLevelName(l),
1028 gew, waehlbar));
1029 if (waehlbar) wanz++;
1030 waehlbar &= gew || ungeordnet;
1031 }
1032 CASSERT(wanz > 0);
1033 int gewaehlt = (ungeordnet ? 1 : wanz);
1034 /* MenuEintragAuswahl kann hier nicht verwendet werden: MenuEintragAuswahl()
1035 setzt das Blatt nach Return-Dr�cken auf Obermen� zur�ck; hier muss das
1036 Blatt aber auf Spiel gesetzt werden.
1037 (=> Im Moment kommt MenuEintragAuswahl nur noch an einer Stelle vor. Daf�r
1038 lohnt sich eigentlich keine eigene Klasse.) */
1039
1040 /* Darf erst jetzt aufgerufen werden; das Men� muss vorher schon aufgebaut
1041 worden sein */
1042
1043 int lnr = Cuyo::getLetzterLevel();
1044 if (lnr != 0 && lnr<=wanz) gewaehlt = lnr;
1045 /* Wahl z�hlt bei 0 los, level bei 1 */
1046 BlattMenu::oeffnen(durchMaus, gewaehlt - 1);
1047 }
1048
1049
doReturn(bool)1050 void BlattStartAt::doReturn(bool) {
1051 Sound::playSample(sample_menuclick,so_fenster);
1052 /* Wahl z�hlt bei 0 los, level bei 1 */
1053 UI::startSpiel(mWahl.mEintrag + 1);
1054 }
1055
1056
1057
1058
1059 /*****************************************************************************/
1060
doNewGame()1061 void doNewGame() { UI::startSpiel(1); }
doRestartLastLevel()1062 void doRestartLastLevel() {
1063 int lnr = Cuyo::getLetzterLevel();
1064 if (lnr != 0) {
1065 UI::startSpiel(lnr);
1066 }
1067 }
doQuit()1068 void doQuit() { UI::quit(); }
1069
1070
stromRestartLastLevel()1071 bool stromRestartLastLevel() {
1072 int lastLevel = Cuyo::getLetzterLevel();
1073 return lastLevel != 0 && ld->levelAccessible(lastLevel);
1074 }
1075
1076
1077 static MenuEintrag * gRestartLastLevel;
1078
updateRestartLastLevel()1079 void updateRestartLastLevel() {
1080 ld->ladLevelSummary(false,Cuyo::berechneVersion());
1081 gRestartLastLevel->updateStrom();
1082 }
1083
setSchwierig(int i)1084 void setSchwierig(int i) {
1085 Cuyo::setSchwierig(i);
1086 updateRestartLastLevel();
1087 }
1088
setLevelpack(int p)1089 void setLevelpack(int p) {
1090 Cuyo::setLevelpack(p);
1091 updateRestartLastLevel();
1092 }
1093
getVersionString()1094 Str getVersionString() {
1095 /* The following should be done at compile time. */
1096 Str ret;
1097 for (const char * v = VERSION; *v; v++) {// VERSION is defined in config.h
1098 if (*v != '~')
1099 ret += *v;
1100 }
1101 return ret;
1102 }
1103
1104
BlattHauptmenu()1105 BlattHauptmenu::BlattHauptmenu() {
1106 neuerEintrag(new MenuEintragBild(this, blattpic_titel));
1107 if (gDebug) {
1108 neuerEintrag(new MenuEintrag(this,
1109 _sprintf(_("%s - Debug mode; Press alt-h for help."), getVersionString().data()),
1110 MenuEintrag::Art_deko));
1111 } else {
1112 neuerEintrag(new MenuEintrag(this, getVersionString().data(),
1113 MenuEintrag::Art_deko));
1114 }
1115 neuerEintrag(new MenuEintrag(this, "", MenuEintrag::Art_deko, L_medskip));
1116
1117 /* TRANSLATORS: Now follows the main menu. The characters preceded by a tilde
1118 are hotkeys. Please choose them disjoint within the menu. If this
1119 cannot be achieved in a sensible manner, feel free to leave some out. */
1120 neuerEintrag(new MenuEintrag(this,_("~New Game"), doNewGame));
1121 /* We need to make the "Restart last level" menu entry known
1122 to other entries which may change its "electricity" status. */
1123 gRestartLastLevel = new MenuEintrag(this,_("~Restart last level"),
1124 doRestartLastLevel);
1125 gRestartLastLevel->setGetStrom(stromRestartLastLevel);
1126 neuerEintrag(gRestartLastLevel);
1127
1128 neuerEintrag(new MenuEintragSubmenu(this,_("Start ~at level..."),
1129 (new BlattStartAt())->setObermenu(this)));
1130 neuerEintrag(new MenuEintrag(this,"", MenuEintrag::Art_deko, L_medskip));
1131 neuerEintrag(new MenuEintragSpielerModus(this,_("~1 Player"),
1132 &updateRestartLastLevel, 1));
1133 neuerEintrag(new MenuEintragSpielerModus(this,_("~2 Players"),
1134 &updateRestartLastLevel, 2));
1135 neuerEintrag(new MenuEintragSpielerModus(this,_("Player vs. ~Computer"),
1136 &updateRestartLastLevel,
1137 spielermodus_computer));
1138 neuerEintrag(new MenuEintrag(this,"", MenuEintrag::Art_deko, L_medskip));
1139 neuerEintrag(new MenuEintragAuswahlmenu(this,
1140 _("~Level track"),
1141 &Version::gLevelpack.mProsaNamen,
1142 &Version::gLevelpack.mErklaerungen,
1143 &Cuyo::getLevelpack,
1144 &setLevelpack));
1145 neuerEintrag(new MenuEintragAuswahlmenu(this,
1146 _("~Difficulty"),
1147 &Version::gSchwierig.mProsaNamen,
1148 &Version::gSchwierig.mErklaerungen,
1149 &Cuyo::getSchwierig,
1150 &setSchwierig,
1151 _("Setting the difficulty affects some, but not all levels.\n"
1152 "On difficulty \"Easy\", the \"Standard\" level track\n"
1153 "consists of levels which are affected by that difficulty,\n"
1154 "and of levels which are easy in themselves.\n"
1155 "The same holds for \"Hard\".")));
1156 neuerEintrag(new MenuEintrag(this,"", MenuEintrag::Art_deko, L_medskip));
1157 neuerEintrag(new MenuEintragSubmenu(this,_("~Preferences..."),
1158 (new BlattPrefs())->setObermenu(this)));
1159 neuerEintrag(new MenuEintrag(this, "", MenuEintrag::Art_deko, L_medskip));
1160
1161
1162
1163 // The empty lines before this are to prevent us from adding menu entries
1164 // at the end, without moving the following comment to the new end.
1165 /* TRANSLATORS: This is the last entry of the main menu. */
1166 neuerEintrag(new MenuEintrag(this, _("~Quit"), doQuit));
1167 }
1168
1169
1170 /********************************************************************************/
1171
1172
BlattPrefs()1173 BlattPrefs::BlattPrefs(): BlattMenu() {
1174
1175 for (int i = 0; i < 2; i++) {
1176 Str s = _sprintf(_("Keys Player %d:"), i + 1);
1177 neuerEintrag(new MenuEintrag(this, s, MenuEintrag::Art_deko));
1178 neuerEintrag(new MenuEintragTaste(this, _("Left"), i, 0));
1179 neuerEintrag(new MenuEintragTaste(this, _("Right"), i, 1));
1180 neuerEintrag(new MenuEintragTaste(this, _("Turn"), i, 2));
1181 neuerEintrag(new MenuEintragTaste(this, _("Down"), i, 3));
1182 neuerEintrag(new MenuEintrag(this, "", MenuEintrag::Art_deko, L_medskip));
1183 }
1184
1185 neuerEintrag(new MenuEintragAI(this, _("AI Speed")));
1186 neuerEintrag(new MenuEintrag(this, "", MenuEintrag::Art_deko, L_medskip));
1187 neuerEintrag(new MenuEintragSound(this, _("Sound")));
1188 neuerEintrag(new MenuEintrag(this, "", MenuEintrag::Art_deko, L_medskip));
1189 neuerEintrag(new MenuEintragEscape(this));
1190 }
1191
1192
1193
1194
doEscape()1195 void BlattPrefs::doEscape() {
1196 PrefsDaten::schreibPreferences();
1197 BlattMenu::doEscape();
1198 }
1199
1200
1201