1 /*
2 Copyright (C) 2007, 2010 - Bit-Blot
3
4 This file is part of Aquaria.
5
6 Aquaria is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (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.
14
15 See the 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 Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 #include "AquariaMenuItem.h"
22 #include "DSQ.h"
23 #include "Game.h"
24
25 float AquariaGuiElement::guiMoveTimer = 0;
26 AquariaGuiElement::GuiElements AquariaGuiElement::guiElements;
27 bool AquariaGuiElement::canDirMoveGlobal = true;
28
29 int AquariaGuiElement::currentGuiInputLevel = 0;
30
31 AquariaGuiElement *AquariaGuiElement::currentFocus = 0;
32
AquariaGuiElement()33 AquariaGuiElement::AquariaGuiElement()
34 {
35 for (int i = 0; i < DIR_MAX; i++)
36 {
37 dirMove[i] = 0;
38 }
39 hasFocus = false;
40
41 guiMoveTimer = 0;
42
43 guiElements.push_back(this);
44
45 canDirMove = true;
46
47 guiInputLevel = 0;
48 }
49
hasInput()50 bool AquariaGuiElement::hasInput()
51 {
52 if (guiInputLevel >= AquariaGuiElement::currentGuiInputLevel)
53 {
54 return true;
55 }
56 return false;
57 }
58
clean()59 void AquariaGuiElement::clean()
60 {
61 guiElements.remove(this);
62 }
63
setDirMove(int dir,AquariaGuiElement * item)64 void AquariaGuiElement::setDirMove(int dir, AquariaGuiElement *item)
65 {
66 if (dir >= 0 && dir < DIR_MAX)
67 {
68 dirMove[dir] = item;
69 }
70 }
71
setCanDirMove(bool on)72 void AquariaGuiElement::setCanDirMove(bool on)
73 {
74 canDirMove = on;
75 }
76
setFocus(bool v)77 void AquariaGuiElement::setFocus(bool v)
78 {
79 hasFocus = v;
80
81 if (v)
82 {
83 currentFocus = this;
84 if (dsq->inputMode == INPUT_JOYSTICK)
85 core->setMousePosition(getGuiPosition());
86
87 AquariaGuiElement *gui=0, *guiThis = (AquariaGuiElement*)this;
88 for (GuiElements::iterator i = guiElements.begin(); i != guiElements.end(); i++)
89 {
90 gui = (*i);
91 if (gui && gui != guiThis)
92 {
93 gui->setFocus(false);
94 }
95 }
96 }
97 else if(this == currentFocus)
98 currentFocus = 0;
99 }
100
updateMovement(float dt)101 void AquariaGuiElement::updateMovement(float dt)
102 {
103 //debugLog("in update movement");
104 if (hasFocus && isGuiVisible() && canDirMove && canDirMoveGlobal && hasInput())
105 {
106 //debugLog("has focus");
107 /*
108 if (alpha.x <= 0 || alphaMod <= 0)
109 {
110 setFocus(false);
111 return;
112 }
113 */
114
115 if (guiMoveTimer > 0)
116 {
117 guiMoveTimer -= dt;
118 if (guiMoveTimer < 0) guiMoveTimer = 0;
119 }
120
121 if (guiMoveTimer==0)
122 {
123 Direction dir = DIR_NONE;
124 Vector p = core->joystick.position;
125 if (!p.isLength2DIn(0.4))
126 {
127 if (fabsf(p.x) > fabsf(p.y))
128 {
129 if (p.x > 0)
130 dir = DIR_RIGHT;
131 else
132 dir = DIR_LEFT;
133 }
134 else
135 {
136 if (p.y > 0)
137 dir = DIR_DOWN;
138 else
139 dir = DIR_UP;
140 }
141 }
142 else
143 {
144 StateObject *obj = dsq->getTopStateObject();
145 if (obj)
146 {
147 if (obj->isActing(ACTION_MENULEFT)) dir = DIR_LEFT;
148 else if (obj->isActing(ACTION_MENURIGHT)) dir = DIR_RIGHT;
149 else if (obj->isActing(ACTION_MENUUP)) dir = DIR_UP;
150 else if (obj->isActing(ACTION_MENUDOWN)) dir = DIR_DOWN;
151 }
152 }
153
154 if (dir == DIR_NONE) return;
155
156 const float moveDelay = 0.2;
157
158 AquariaGuiElement *gui = 0;
159 if (dir > DIR_NONE && dir < DIR_MAX)
160 {
161 gui = dirMove[dir];
162 if (gui)
163 {
164 gui->setFocus(true);
165 //this->setFocus(false);
166
167
168
169 guiMoveTimer = moveDelay;
170 }
171 }
172
173 if (!gui)
174 {
175 debugLog("updating closest");
176 int smallDist = -1, dist = 0;
177
178 AquariaGuiElement *gui = 0, *closest = 0;
179 int ch = 64;
180 for (GuiElements::iterator i = guiElements.begin(); i != guiElements.end(); i++)
181 {
182 gui = (*i);
183 if (gui != this && gui->isGuiVisible() && gui->canDirMove)
184 {
185 int go = 0;
186 Vector p1 = getGuiPosition();
187 Vector p2 = gui->getGuiPosition();
188
189 if (dir == DIR_DOWN)
190 {
191 if (fabsf(p1.x - p2.x) < ch)
192 {
193 if (p2.y > p1.y) go = 1;
194 p1.x = p2.x = 0;
195 }
196 }
197 else if (dir == DIR_UP)
198 {
199 if (fabsf(p1.x - p2.x) < ch)
200 {
201 if (p2.y < p1.y) go = 1;
202 p1.x = p2.x = 0;
203 }
204 }
205 else if (dir == DIR_RIGHT)
206 {
207 if (fabsf(p1.y - p2.y) < ch)
208 {
209 if (p2.x > p1.x) go = 1;
210 p1.y = p2.y = 0;
211 }
212 }
213 else if (dir == DIR_LEFT)
214 {
215 if (fabsf(p1.y - p2.y) < ch)
216 {
217 if (p2.x < p1.x) go = 1;
218 p1.y = p2.y = 0;
219 }
220 }
221 else
222 {
223 continue;
224 }
225
226 if (go)
227 {
228 dist = (p1 - p2).getSquaredLength2D();
229
230 if (smallDist == -1 || dist < smallDist)
231 {
232 closest = gui;
233 smallDist = dist;
234 }
235 }
236 else
237 {
238 continue;
239 }
240 }
241 }
242
243 if (closest)
244 {
245 closest->setFocus(true);
246
247 guiMoveTimer = moveDelay;
248 }
249 }
250 }
251 }
252 }
253
getClosestGuiElement(const Vector & pos)254 AquariaGuiElement *AquariaGuiElement::getClosestGuiElement(const Vector& pos)
255 {
256 AquariaGuiElement *gui = 0, *closest = 0;
257 float minlen = 0;
258 for (GuiElements::iterator i = guiElements.begin(); i != guiElements.end(); i++)
259 {
260 gui = (*i);
261 if (gui->isGuiVisible() && gui->hasInput())
262 {
263 Vector dist = gui->getGuiPosition() - pos;
264 float len = dist.getSquaredLength2D();
265 if(!closest || len < minlen)
266 {
267 closest = gui;
268 minlen = len;
269 }
270 }
271 }
272 return closest;
273 }
274
275
AquariaGuiQuad()276 AquariaGuiQuad::AquariaGuiQuad() : Quad(), AquariaGuiElement()
277 {
278 }
279
destroy()280 void AquariaGuiQuad::destroy()
281 {
282 Quad::destroy();
283 AquariaGuiElement::clean();
284 }
285
getGuiPosition()286 Vector AquariaGuiQuad::getGuiPosition()
287 {
288 return getWorldPosition();
289 }
290
isGuiVisible()291 bool AquariaGuiQuad::isGuiVisible()
292 {
293 return !isHidden() && alpha.x > 0 && alphaMod > 0 && renderQuad;
294 }
295
update(float dt)296 void AquariaGuiQuad::update(float dt)
297 {
298 // super hacky
299 if (hasInput())
300 {
301 Quad::update(dt);
302 }
303 else
304 {
305 updateMovement(dt);
306 Quad::onUpdate(dt);
307 }
308 }
309
onUpdate(float dt)310 void AquariaGuiQuad::onUpdate(float dt)
311 {
312 updateMovement(dt);
313 Quad::onUpdate(dt);
314 }
315
316 // Joystick input threshold at which we start sliding (0.0-1.0); must be
317 // less than updateMovement() threshold.
318 const float SLIDER_JOY_THRESHOLD = 0.39;
319 // Initial delay before repeating for slider input (seconds).
320 const float SLIDER_REPEAT_DELAY = 0.4;
321 // Scale factor for delay as repeats continue.
322 const float SLIDER_REPEAT_ACCEL = 0.8;
323
AquariaSlider()324 AquariaSlider::AquariaSlider()
325 : Slider(90, 12, "gui/slider-bg", "gui/slider-fg"), AquariaGuiElement()
326 // len, grab radius
327 {
328 inputTimer = inputDelay = 0;
329 _hadInput = false;
330 }
331
onUpdate(float dt)332 void AquariaSlider::onUpdate(float dt)
333 {
334 if (!hasInput())
335 {
336 inputTimer = inputDelay = 0;
337 AquariaGuiElement::updateMovement(dt);
338 RenderObject::onUpdate(dt);
339 }
340 else
341 {
342 if (!doSliderInput(dt))
343 AquariaGuiElement::updateMovement(dt);
344 Slider::onUpdate(dt);
345 }
346 }
347
doSliderInput(float dt)348 bool AquariaSlider::doSliderInput(float dt)
349 {
350 if (!(core->mouse.position - this->position).isLength2DIn(5))
351 return false;
352
353 float inputAmount; // How much to adjust by?
354
355 StateObject *obj = dsq->getTopStateObject();
356 if (core->joystick.position.x <= -SLIDER_JOY_THRESHOLD)
357 inputAmount = -0.1f;
358 else if (core->joystick.position.x >= SLIDER_JOY_THRESHOLD)
359 inputAmount = +0.1f;
360 else if (core->joystick.dpadLeft)
361 inputAmount = -0.1f;
362 else if (core->joystick.dpadRight)
363 inputAmount = +0.1f;
364 else if (obj && obj->isActing(ACTION_MENULEFT))
365 inputAmount = -0.1f;
366 else if (obj && obj->isActing(ACTION_MENURIGHT))
367 inputAmount = +0.1f;
368 else
369 inputAmount = 0;
370
371 if (inputAmount != 0)
372 {
373 inputTimer += dt;
374 if (inputTimer >= inputDelay)
375 {
376 float oldValue = value;
377 setValue(value + inputAmount);
378 if (value != oldValue)
379 _hadInput = true;
380
381 inputTimer = 0;
382 if (inputDelay == 0)
383 inputDelay = SLIDER_REPEAT_DELAY;
384 else
385 inputDelay *= SLIDER_REPEAT_ACCEL;
386 }
387 return true;
388 }
389 else
390 {
391 inputTimer = inputDelay = 0;
392 return false;
393 }
394 }
395
destroy()396 void AquariaSlider::destroy()
397 {
398 Slider::destroy();
399 AquariaGuiElement::clean();
400 }
401
getGuiPosition()402 Vector AquariaSlider::getGuiPosition()
403 {
404 return getWorldPosition();
405 }
406
isGuiVisible()407 bool AquariaSlider::isGuiVisible()
408 {
409 return !isHidden() && alpha.x > 0 && alphaMod > 0;
410 }
411
AquariaCheckBox()412 AquariaCheckBox::AquariaCheckBox()
413 : CheckBox(12, "gui/check-bg", "gui/check-fg", "Click"), AquariaGuiElement()
414 {
415 }
416
onUpdate(float dt)417 void AquariaCheckBox::onUpdate(float dt)
418 {
419 AquariaGuiElement::updateMovement(dt);
420 if (!hasInput())
421 {
422 RenderObject::onUpdate(dt);
423 }
424 else
425 {
426 CheckBox::onUpdate(dt);
427 }
428 }
429
destroy()430 void AquariaCheckBox::destroy()
431 {
432 CheckBox::destroy();
433 AquariaGuiElement::clean();
434 }
435
getGuiPosition()436 Vector AquariaCheckBox::getGuiPosition()
437 {
438 return getWorldPosition();
439 }
440
isGuiVisible()441 bool AquariaCheckBox::isGuiVisible()
442 {
443 return !isHidden() && alpha.x > 0 && alphaMod > 0;
444 }
445
446
447 AquariaKeyConfig *AquariaKeyConfig::waitingForInput = 0;
448
449
AquariaKeyConfig(const std::string & actionInputName,InputSetType inputSetType,int inputIdx)450 AquariaKeyConfig::AquariaKeyConfig(const std::string &actionInputName, InputSetType inputSetType, int inputIdx)
451 : AquariaGuiElement(), RenderObject(), actionInputName(actionInputName), inputSetType(inputSetType), inputIdx(inputIdx)
452 {
453
454 bg = new Quad();
455 if (inputSetType == INPUTSET_OTHER)
456 bg->setWidthHeight(40, 20);
457 else
458 bg->setWidthHeight(100, 20);
459
460 bg->color = Vector(0.5, 0.5, 0.5);
461 bg->alphaMod = 0;
462 addChild(bg, PM_POINTER);
463
464 /*
465 label = new BitmapText(&dsq->smallFont);
466 label->setText("KeyConfig");
467 label->parentManagedPointer = 1;
468 label->position = Vector(0, -10);
469 label->scale = Vector(0.8, 0.8);
470 addChild(label);
471 */
472
473 //keyConfigFont = new DebugFont(6, "keyConfig");
474
475 keyConfigFont = new TTFText(&dsq->fontArialSmallest);
476
477 keyConfigFont->setAlign(ALIGN_CENTER);
478 //keyConfigFont->position = Vector(0, -10);
479 addChild(keyConfigFont, PM_POINTER);
480
481
482 keyDown = false;
483
484 locked = 0;
485
486
487 toggleEnterKey(false);
488 }
489
destroy()490 void AquariaKeyConfig::destroy()
491 {
492 AquariaGuiElement::clean();
493 RenderObject::destroy();
494
495 if (waitingForInput == this)
496 waitingForInput = 0;
497 }
498
getGuiPosition()499 Vector AquariaKeyConfig::getGuiPosition()
500 {
501 return getWorldPosition();
502 }
503
isGuiVisible()504 bool AquariaKeyConfig::isGuiVisible()
505 {
506 return !isHidden() && alpha.x > 0 && alphaMod > 0;
507 }
508
toggleEnterKey(int on)509 void AquariaKeyConfig::toggleEnterKey(int on)
510 {
511 if (on==1)
512 {
513 bg->color = Vector(0.75, 0.75, 0.75);
514 bg->alphaMod = 0.25;
515 }
516 else if (on == 0)
517 {
518 bg->alphaMod = 0;
519 bg->color = Vector(0.1, 0.1, 0.1);
520 }
521 else
522 {
523 bg->alphaMod = 0.5;
524 bg->color = Vector(0.5, 0.5, 0.5);
525 }
526 /*
527 if (on)
528 {
529 label->scale = Vector(2, 2);
530 }
531 else
532 {
533 label->scale = Vector(1, 1);
534 }
535 */
536 }
537
setLock(int lock)538 void AquariaKeyConfig::setLock(int lock)
539 {
540 locked = lock;
541 }
542
onUpdate(float dt)543 void AquariaKeyConfig::onUpdate(float dt)
544 {
545 static bool inLoop = false;
546
547 if (inLoop) return;
548
549
550
551
552
553 AquariaGuiElement::updateMovement(dt);
554
555 RenderObject::onUpdate(dt);
556
557
558 if (!hasInput() || alpha.x <= 0) return;
559
560 inLoop = true;
561
562 int *k = 0;
563
564 ActionInput *ai = 0;
565
566 if (inputSetType != INPUTSET_OTHER)
567 {
568 ai = dsq->user.control.actionSet.getActionInputByName(actionInputName);
569
570 if (!ai)
571 {
572 exit_error("Could not find actionInput: " + actionInputName);
573 }
574 switch(inputSetType)
575 {
576 case INPUTSET_KEY:
577 k = &ai->key[inputIdx];
578 break;
579 case INPUTSET_MOUSE:
580 k = &ai->mse[inputIdx];
581 break;
582 case INPUTSET_JOY:
583 k = &ai->joy[inputIdx];
584 break;
585 default:
586 k = 0;
587 break;
588 }
589 }
590
591 int *value = 0;
592
593 if (inputSetType == INPUTSET_OTHER)
594 {
595 if (actionInputName == "s1ax")
596 value = &dsq->user.control.s1ax;
597 else if (actionInputName == "s1ay")
598 value = &dsq->user.control.s1ay;
599 else if (actionInputName == "s2ax")
600 value = &dsq->user.control.s2ax;
601 else if (actionInputName == "s2ay")
602 value = &dsq->user.control.s2ay;
603 }
604
605 if (waitingForInput == this)
606 {
607 std::string s;
608 s = "_";
609 for (int i = 0; i < int(dsq->game->getTimer(5)); i++)
610 {
611 s += "_";
612 }
613 keyConfigFont->setText(s);
614 }
615 else
616 {
617 if (k)
618 {
619 keyConfigFont->setText(getInputCodeToString(*k));
620 }
621 else if (value)
622 {
623 std::ostringstream os;
624 os << (*value);
625 keyConfigFont->setText(os.str());
626 }
627 }
628
629 if (waitingForInput == this)
630 {
631 switch(inputSetType)
632 {
633 case INPUTSET_OTHER:
634 {
635 if (value)
636 {
637 for (int i = 0; i < KEY_MAXARRAY; i++)
638 {
639 if (core->getKeyState(i))
640 {
641 if (i != KEY_ESCAPE)
642 {
643 /*
644 if (i == KEY_DELETE || i == KEY_BACKSPACE)
645 else
646 {
647 */
648 /*
649 if (i == KEY_0 || i == KEY_1 || i == KEY_2 || i == KEY_3 || i == KEY_4 || i == KEY_5 || i == KEY_6 || i == KEY_7
650 || i == KEY_8 || i == KEY_9)
651 */
652 if (i >= KEY_0 && i <= KEY_9)
653 {
654 *value = i-KEY_0;
655 }
656 }
657
658 while (dsq->game->getKeyState(i))
659 {
660 dsq->main(0.1);
661 }
662
663 toggleEnterKey(0);
664 waitingForInput = 0;
665 AquariaGuiElement::canDirMoveGlobal = true;
666 break;
667 }
668 }
669 }
670 }
671 break;
672 case INPUTSET_KEY:
673 {
674 for (int i = 0; i < KEY_MAXARRAY; i++)
675 {
676 if (core->getKeyState(i))
677 {
678 if (i != KEY_ESCAPE)
679 {
680 if (i == KEY_DELETE || i == KEY_BACKSPACE)
681 *k = 0;
682 else
683 *k = i;
684 }
685
686 while (dsq->game->getKeyState(i))
687 {
688 dsq->main(0.1);
689 }
690
691 toggleEnterKey(0);
692 waitingForInput = 0;
693 AquariaGuiElement::canDirMoveGlobal = true;
694 break;
695 }
696 }
697 }
698 break;
699 case INPUTSET_MOUSE:
700 break;
701 case INPUTSET_JOY:
702 {
703 if (core->getKeyState(KEY_DELETE) || core->getKeyState(KEY_BACKSPACE))
704 {
705 *k = 0;
706 toggleEnterKey(0);
707 waitingForInput = 0;
708 AquariaGuiElement::canDirMoveGlobal = true;
709 }
710 else
711 {
712 for (int i = ActionMapper::JOY1_BUTTON_0; i <= ActionMapper::JOY1_BUTTON_16; i++)
713 {
714 if (dsq->game->getKeyState(i))
715 {
716 *k = i;
717
718 while (dsq->game->getKeyState(i))
719 {
720 dsq->main(0.1);
721 }
722
723 toggleEnterKey(0);
724 waitingForInput = 0;
725 AquariaGuiElement::canDirMoveGlobal = true;
726 break;
727 }
728 }
729 }
730 }
731 break;
732 }
733 }
734
735 Vector p = getWorldPosition();
736
737 if (waitingForInput == this || (!waitingForInput &&
738 (core->mouse.position.x > (p.x - bg->getWidth()*0.5f) && core->mouse.position.x < (p.x + bg->getWidth()*0.5f)
739 && core->mouse.position.y > (p.y - bg->getHeight()*0.5f) && core->mouse.position.y < (p.y + bg->getHeight()*0.5f)
740 )))
741 {
742 if (waitingForInput != this)
743 {
744 toggleEnterKey(-1);
745 }
746
747
748 if (!keyDown && (core->mouse.buttons.left || core->mouse.buttons.right/* || core->getKeyState(KEY_RETURN)*/))
749 {
750 keyDown = true;
751 }
752 else if (keyDown && (!core->mouse.buttons.left && !core->mouse.buttons.right /*&& !core->getKeyState(KEY_RETURN)*/))
753 {
754 keyDown = false;
755
756 if (!locked)
757 {
758 if (waitingForInput == this)
759 {
760 waitingForInput = 0;
761 toggleEnterKey(0);
762 AquariaGuiElement::canDirMoveGlobal = true;
763 }
764 else
765 {
766 waitingForInput = this;
767 toggleEnterKey(1);
768 AquariaGuiElement::canDirMoveGlobal = false;
769 }
770 }
771 else
772 {
773 dsq->sound->playSfx("denied");
774 }
775 }
776 }
777 else
778 {
779 toggleEnterKey(0);
780 keyDown = false;
781 }
782
783 inLoop = false;
784 }
785
AquariaMenuItem()786 AquariaMenuItem::AquariaMenuItem() : Quad(), ActionMapper(), AquariaGuiElement()
787 {
788 quad = glow = 0;
789 choice = -1;
790 ability = 0;
791 xmlItem = 0;
792 int sz = 20;
793
794 shareAlpha = 0;
795
796 font = 0;
797
798 font = new BitmapText(&dsq->font);
799 font->setFontSize(sz);
800 font->position = Vector(0, -sz/2, 0);
801 addChild(font, PM_POINTER, RBP_ON);
802
803 glowFont = new BitmapText(&dsq->font);
804 glowFont->setFontSize(sz);
805 glowFont->position = Vector(0, -sz/2, 0);
806 glowFont->setBlendType(BLEND_ADD);
807 glowFont->alpha = 0;
808 //glowFont->scale.interpolateTo(Vector(1.1,1.1), 0.5, -1, 1, 1);
809 addChild(glowFont, PM_POINTER, RBP_OFF);
810
811 //setTexture("bubble");
812 //this->shareAlphaWithChildren = true;
813 width = 0;
814 height = 0;
815 highlighted = false;
816 /*
817 width = 256;
818 height = 64;
819 */
820 cull = false;
821 followCamera = 1;
822 addAction(MakeFunctionEvent(AquariaMenuItem, onClick), ActionMapper::MOUSE_BUTTON_LEFT, 0);
823 addAction(MakeFunctionEvent(AquariaMenuItem, onClick), ActionMapper::MOUSE_BUTTON_RIGHT, 0);
824
825 renderQuad = false;
826 }
827
destroy()828 void AquariaMenuItem::destroy()
829 {
830 setFocus(false);
831 Quad::destroy();
832 AquariaGuiElement::clean();
833 }
834
getGuiPosition()835 Vector AquariaMenuItem::getGuiPosition()
836 {
837 return getWorldPosition();
838 }
839
isGuiVisible()840 bool AquariaMenuItem::isGuiVisible()
841 {
842 return !isHidden() && alpha.x > 0 && alphaMod > 0;
843 }
844
useSound(const std::string & tex)845 void AquariaMenuItem::useSound(const std::string &tex)
846 {
847 useSfx = tex;
848 }
849
useQuad(const std::string & tex)850 bool AquariaMenuItem::useQuad(const std::string &tex)
851 {
852 if (quad)
853 {
854 debugLog("trying to call useQuad twice on the same object");
855 return true;
856 }
857 quad = new Quad;
858 bool good = quad->setTexture(tex);
859 addChild(quad, PM_POINTER);
860 return good;
861 }
862
useGlow(const std::string & tex,int w,int h)863 void AquariaMenuItem::useGlow(const std::string &tex, int w, int h)
864 {
865 if (glow)
866 {
867 debugLog("trying to call useGlow twice on the same object");
868 return;
869 }
870 glow = new Quad;
871 glow->setTexture(tex);
872 glow->setWidthHeight(w, h);
873 glow->setBlendType(BLEND_ADD);
874 glow->alpha = 0;
875 addChild(glow, PM_POINTER);
876 }
877
onClick()878 void AquariaMenuItem::onClick()
879 {
880 if (hasInput() && highlighted && dsq->menuSelectDelay == 0)
881 {
882 dsq->menuSelectDelay = MENUSELECTDELAY;
883
884 if (!useSfx.empty())
885 dsq->sound->playSfx(useSfx);
886 else
887 dsq->playMenuSelectSfx();
888
889 event.call();
890
891 //glowFont->scale.interpolateTo(Vector(4,4), 0.5, 1, 1);
892 //glowFont->alpha.interpolateTo(0, 0.5);
893 //scale.interpolateTo(Vector(4, 4), 3);
894 }
895 }
896
setLabel(const std::string & label)897 void AquariaMenuItem::setLabel(const std::string &label)
898 {
899 font->setText(label);
900 glowFont->setText(label);
901 }
902
toggleHighlight(bool state)903 void AquariaMenuItem::toggleHighlight(bool state)
904 {
905 highlighted = state;
906 if (highlighted)
907 {
908 if (glow)
909 {
910 glow->alpha.interpolateTo(0.3, 0.2);
911 }
912 else
913 {
914 glowFont->alpha.interpolateTo(0.3, 0.2);
915 }
916 //scale.interpolateTo(Vector(1.1, 1.1), 0.2);
917 }
918 else
919 {
920 if (glow)
921 glow->alpha.interpolateTo(0, 0.2);
922 else
923 glowFont->alpha.interpolateTo(0, 0.2);
924 }
925 //scale.interpolateTo(Vector(1,1), 0.2);
926 }
927
onUpdate(float dt)928 void AquariaMenuItem::onUpdate(float dt)
929 {
930 AquariaGuiElement::updateMovement(dt);
931
932 if (font)
933 {
934 font->alpha = this->alpha;
935 }
936 Quad::onUpdate(dt);
937
938 if (shareAlpha)
939 {
940 if (quad) quad->alphaMod = alpha.x;
941 if (glow) glow->alphaMod = alpha.x;
942 }
943
944 if (this->alpha.x < 1.0) return;
945
946 if (hasInput())
947 ActionMapper::onUpdate(dt);
948
949 if (quad)
950 {
951 quad->alpha.x = alpha.x;
952 }
953
954 /*
955 font->position = this->position;
956 font->alpha = this->alpha;
957 */
958 if (hasInput())
959 {
960 if (alpha.x == 1)
961 {
962 bool on = true;
963
964
965 if (isCursorInMenuItem())
966 {
967 if (!highlighted)
968 toggleHighlight(true);
969 }
970 else
971 on = false;
972
973 if (!on && highlighted)
974 toggleHighlight(false);
975 }
976 else
977 {
978 if (highlighted)
979 toggleHighlight(false);
980 }
981 }
982 }
983
isCursorInMenuItem()984 bool AquariaMenuItem::isCursorInMenuItem()
985 {
986 Vector v = dsq->mouse.position;
987 int hw = font->getWidthOnScreen()/2;
988 int hh = 20;
989 if (hw < 64)
990 hw = 64;
991 if (glow)
992 {
993 hw = glow->getWidth()/2.0f;
994 hh = glow->getHeight()/2.0f;
995 }
996 if (rotation.z == 90)
997 {
998 std::swap(hw, hh);
999 }
1000 Vector pos = getWorldPosition();
1001 if (v.y > pos.y - hh && v.y < pos.y + hh)
1002 {
1003 if (v.x > pos.x - hw && v.x < pos.x + hw)
1004 {
1005 return true;
1006 }
1007 }
1008 return false;
1009 }
1010