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 "DSQ.h"
22 #include "Game.h"
23 #include "Avatar.h"
24 #include "GridRender.h"
25 #include "Gradient.h"
26 #include "TTFFont.h"
27 #include "RoundedRect.h"
28
29 #define GEM_GRAB 10
30
31 namespace WorldMapRenderNamespace
32 {
33 const float WORLDMAP_UNDERLAY_ALPHA = 0.8;
34
35 float baseMapSegAlpha = 0.4;
36 float visibleMapSegAlpha = 0.8;
37
38 const float blinkPeriod = 0.2;
39
40 // Fraction of the screen width and height we consider "visited".
41 // (We don't mark the entire screen "visited" because the player may
42 // overlook things on the edge of the screen while moving.)
43 const float visitedFraction = 0.8;
44
45 enum VisMethod
46 {
47 VIS_VERTEX = 0, // Uses the RenderObject tile grid (RenderObject::setSegs()) to display visited areas
48 VIS_WRITE = 1 // Uses render-to-texture instead
49 };
50
51 const VisMethod visMethod = VIS_VERTEX;
52 WorldMapRevealMethod revMethod = REVEAL_DEFAULT;
53
54 std::vector<Quad *> tiles;
55
56 Quad *activeQuad=0, *lastActiveQuad=0, *originalActiveQuad=0;
57 Quad *lastVisQuad=0, *visQuad=0;
58 WorldMapTile *lastVisTile=0;
59
60 float xMin, yMin, xMax, yMax;
61
62 float zoomMin = 0.2;
63 float zoomMax = 3.0;
64 const float exteriorZoomMax = 3.0;
65 const float interiorZoomMax = 3.0;
66
67 bool editorActive=false;
68
69 Quad *tophud=0;
70
71 Gradient *underlay = 0;
72 }
73
74 using namespace WorldMapRenderNamespace;
75
76 std::vector <Quad*> grid;
77
78 class GemMover;
79
80 GemMover *mover=0;
81
82 WorldMapTile *activeTile=0;
83
84 const float beaconSpawnBitTime = 0.05;
85
86
setRevealMethod(WorldMapRevealMethod m)87 void WorldMapRender::setRevealMethod(WorldMapRevealMethod m)
88 {
89 switch(m)
90 {
91 case REVEAL_PARTIAL:
92 revMethod = REVEAL_PARTIAL;
93 baseMapSegAlpha = 0;
94 break;
95
96 default:
97 revMethod = REVEAL_DEFAULT;
98 baseMapSegAlpha = 0.4;
99 }
100 }
101
102
103 class WorldMapBoundQuad : public Quad
104 {
105 public:
WorldMapBoundQuad(const Vector & posToUse)106 WorldMapBoundQuad(const Vector &posToUse)
107 {
108 position = posToUse;
109 truePosition = posToUse;
110 followCamera = 1;
111 }
112
render()113 void render()
114 {
115 setProperPosition();
116 Quad::render();
117 }
118
119 protected:
120 Vector truePosition;
setProperPosition()121 void setProperPosition()
122 {
123 Vector wp = parent->getWorldCollidePosition(truePosition);
124 Vector diff = wp - core->center;
125
126 float w2 = core->getVirtualWidth()/2;
127 float h2 = core->getVirtualHeight()/2;
128
129 if (diff.x < -w2)
130 wp.x = core->center.x - w2;
131 if (diff.x > w2)
132 wp.x = core->center.x + w2;
133 if (diff.y < -h2)
134 wp.y = core->center.y - h2;
135 if (diff.y > h2)
136 wp.y = core->center.y + h2;
137
138 Vector move = wp - getWorldPosition();
139 // FIXME: This is a quick HACK to get the current world map
140 // scale factor so we can set the position properly, without
141 // having to play with multiple levels of parent pointers or
142 // anything like that. (If we don't scale the move vector
143 // properly, the dots overshoot at high zoom or don't go far
144 // enough at low zoom and we can end up with a weird "disco"
145 // effect -- see icculus bug 4542.)
146 const float x0 = getWorldPosition().x;
147 position.x += 1;
148 const float x1 = getWorldPosition().x;
149 position.x -= 1;
150 position += move / (x1-x0);
151 }
152 };
153
154 class BeaconRender : public Quad
155 {
156 public:
BeaconRender(BeaconData * beaconData)157 BeaconRender(BeaconData *beaconData) : Quad(), beaconData(beaconData)
158 {
159 renderQuad = false;
160 setTexture("gui/minimap/ripple"); //"particles/softring"); // or whatever
161 position = beaconData->pos;
162 truePosition = beaconData->pos;
163 followCamera = 1;
164 /*
165 scale = Vector(0.2, 0.2);
166 scale.interpolateTo(Vector(0.5, 0.5), 0.75, -1, 1, 1);
167 */
168 alpha = 0.5;
169 color = beaconData->color;
170
171 /*
172 pe = new ParticleEffect();
173 pe->load("sparkle");
174 pe->followCamera = 1;
175 pe->start();
176 core->addRenderObject(pe, LR_PARTICLES);
177 */
178 spawnBitTimer = 0;
179 }
180
181 //float spawnBitTimer;
182 Vector truePosition;
183
184 ParticleEffect *pe;
185
186 float spawnBitTimer;
187
188
render()189 void render()
190 {
191 //setProperPosition();
192 Quad::render();
193 }
194
195 protected:
196 BeaconData *beaconData;
197
setProperPosition()198 void setProperPosition()
199 {
200 Vector wp = parent->getWorldCollidePosition(truePosition);
201 Vector diff = wp - core->center;
202
203 float w2 = core->getVirtualWidth()/2;
204 float h2 = core->getVirtualHeight()/2;
205
206 if (diff.x < -w2)
207 wp.x = core->center.x - w2;
208 if (diff.x > w2)
209 wp.x = core->center.x + w2;
210 if (diff.y < -h2)
211 wp.y = core->center.y - h2;
212 if (diff.y > h2)
213 wp.y = core->center.y + h2;
214
215 Vector move = wp - getWorldPosition();
216 position += move;
217 }
218
219
onUpdate(float dt)220 void onUpdate(float dt)
221 {
222 Quad::onUpdate(dt);
223
224 //setProperPosition();
225
226 if (!dsq->game->worldMapRender->isOn()) return;
227
228 const int lenRange = 125;
229 const float pscale = 0.7;
230
231 float leftOver = dt;
232
233 while (leftOver)
234 {
235 spawnBitTimer -= leftOver;
236 if (spawnBitTimer <= 0)
237 {
238 leftOver = -spawnBitTimer;
239 spawnBitTimer = beaconSpawnBitTime;
240
241 float r = (rand()%100)/100.0f;
242 float radius = r * 2*PI;
243 float len = (rand()%lenRange);
244 int x = sinf(radius)*len;
245 int y = cosf(radius)*len;
246
247 //truePosition +
248 float t = 0.75;
249 WorldMapBoundQuad *q = new WorldMapBoundQuad(Vector(x, y, 0));
250 q->setTexture("particles/glow");
251 q->alpha.ensureData();
252 q->alpha.data->path.addPathNode(0.0, 0.0);
253 q->alpha.data->path.addPathNode(1.0, 0.5);
254 q->alpha.data->path.addPathNode(0.0, 1.0);
255 q->alpha.startPath(0.5);
256 q->alphaMod = 0.5;
257 q->color = color;
258
259 q->scale = Vector(pscale, pscale);
260 //q->fadeAlphaWithLife = 1;
261 q->setLife(1);
262 q->setDecayRate(1.0f/t);
263
264 q->setBlendType(BLEND_ADD);
265 addChild(q, PM_POINTER);
266
267 //std::ostringstream os;
268 //os << "children: " << children.size();
269 //debugLog(os.str());
270 }
271 else
272 {
273 leftOver = 0;
274 }
275 }
276
277
278
279 /*
280
281 */
282 }
283
284 };
285
286 class GemMover : public Quad
287 {
288 public:
GemMover(GemData * gemData)289 GemMover(GemData *gemData) : Quad(), gemData(gemData)
290 {
291 setTexture("Gems/" + gemData->name);
292 position = gemData->pos;
293 followCamera = 1;
294 blink = false;
295 blinkTimer = 0;
296 alphaMod = 0.66;
297 canMove = gemData->canMove;
298 //canMove = true;
299 //gemData->userString = "HI THERE!";
300
301 std::string useString = gemData->userString;
302
303 /*
304 if (gemData->userString.empty())
305 {
306 if (gemData->name == "savepoint")
307 useString = "Memory Crystal";
308 if (gemData->name == "cook")
309 useString = "Kitchen";
310 }
311 */
312
313 /*
314 text = new BitmapText(&dsq->smallFont);
315 text->position = Vector(0, -20);
316 text->setText(gemData->userString);
317 addChild(text, PM_POINTER);
318 */
319
320 text = new TTFText(&dsq->fontArialSmall);//new DebugFont(10, useString);
321 text->offset = Vector(0, 4); //Vector(0,5);
322 text->setText(useString);
323 text->setAlign(ALIGN_CENTER);
324
325 textBG = new RoundedRect();
326 textBG->setWidthHeight(text->getActualWidth() + 20, 25, 10); // 30
327 textBG->alpha = 0;
328 textBG->followCamera = 1;
329 game->addRenderObject(textBG, LR_WORLDMAPHUD);
330
331 textBG->addChild(text, PM_POINTER);
332 //game->addRenderObject(text, LR_WORLDMAPHUD);
333 }
334
destroy()335 void destroy()
336 {
337 if (textBG)
338 {
339 textBG->safeKill();
340 textBG = 0;
341 }
342 Quad::destroy();
343 }
344
getGemData()345 GemData *getGemData() { return gemData; }
346
setBlink(bool blink)347 void setBlink(bool blink)
348 {
349 this->blink = blink;
350
351 //if (blink)
352 //{
353 // scale = Vector(0.5, 0.5);
354 // scale.interpolateTo(Vector(1,1), 0.5, -1, 1);
355 // /*
356 // alpha = 0.5;
357 // alpha.interpolateTo(1, 0.5, -1, 1);
358 // */
359 //}
360 //else
361 //{
362 // scale.stop();
363 // scale = Vector(1,1);
364 // /*
365 // alpha.stop();
366 // alpha = 1;
367 // */
368 //}
369 }
370 bool canMove;
371 protected:
372
373 float blinkTimer;
374 bool blink;
375 GemData *gemData;
376 //BitmapText *text;
377 TTFText *text;
378 RoundedRect *textBG;
onUpdate(float dt)379 void onUpdate(float dt)
380 {
381 Quad::onUpdate(dt);
382
383 Vector sz = parent->scale;
384
385 if (sz.x < zoomMin)
386 sz.x = sz.y = zoomMin;
387 if (sz.x > zoomMax)
388 sz.x = sz.y = zoomMax;
389
390 if (sz.x > 1.0f)
391 {
392 scale.x = (1.0f/sz.x);
393 scale.y = (1.0f/sz.y);
394 }
395 else
396 {
397 scale = Vector(1,1);
398 }
399
400 Vector wp = getWorldPosition();
401
402 if (blink)
403 {
404 blinkTimer += dt;
405 if (blinkTimer > blinkPeriod)
406 {
407 if (alphaMod == 0)
408 alphaMod = 1;
409 else
410 alphaMod = 0;
411
412 blinkTimer = 0;
413 }
414 }
415
416 if (canMove)
417 {
418 if (mover == 0)
419 {
420 if (core->mouse.buttons.left && (core->mouse.position - wp).isLength2DIn(GEM_GRAB))
421 {
422 core->sound->playSfx("Gem-Move");
423 mover = this;
424 //offset = Vector(position - core->mouse.position);
425 //position += core->mouse.position - wp;
426 //offset = Vector(0, 4);
427 }
428 }
429 else if (mover == this)
430 {
431 //position = core->mouse.position;
432 position += (core->mouse.position - wp)/parent->scale.x;
433 if (!core->mouse.buttons.left)
434 {
435 mover = 0;
436 core->sound->playSfx("Gem-Place");
437 //position += offset;
438 //offset = Vector(0,0);
439 //offset = Vector(0,0);
440 gemData->pos = position;
441 }
442 }
443 }
444
445
446 if (textBG)
447 {
448 textBG->position = getWorldPosition() + Vector(0, -20);
449 }
450
451 if ((core->mouse.position - wp).isLength2DIn(GEM_GRAB))
452 {
453 //text->alpha.interpolateTo(1, 0.1);
454 /*
455 if (!gemData->userString.empty())
456 textBG->alpha.interpolateTo(1, 0.1);
457 */
458 if (!gemData->userString.empty())
459 textBG->show();
460 }
461 else
462 {
463 /*
464 text->alpha.interpolateTo(0, 0.1);
465 textBG->alpha.interpolateTo(0, 0.1);
466 */
467 if (textBG->alpha == 1)
468 textBG->hide();
469 }
470 }
471 };
472
473 typedef std::list <GemMover*> GemMovers;
474 GemMovers gemMovers;
475
476 typedef std::list <BeaconRender*> BeaconRenders;
477 BeaconRenders beaconRenders;
478
479 std::vector<Quad*> quads;
480
setProperTileColor(WorldMapTile * tile)481 void WorldMapRender::setProperTileColor(WorldMapTile *tile)
482 {
483 if (tile)
484 {
485 if (tile->q)
486 {
487 if (!tile->revealed)
488 tile->q->alphaMod = 0;
489
490 if (tile->revealed)
491 tile->q->alphaMod = 0.5;
492
493 if (activeTile && (tile->layer != activeTile->layer || (tile->layer > 0 && activeTile != tile)))
494 tile->q->alphaMod *= 0.5;
495
496 tile->q->color = Vector(0.7, 0.8, 1);
497 }
498 else
499 {
500 debugLog("no Q!");
501 }
502 }
503 }
504
505 #ifdef AQUARIA_BUILD_MAPVIS
506
tileDataToVis(WorldMapTile * tile,Vector ** vis)507 static void tileDataToVis(WorldMapTile *tile, Vector **vis)
508 {
509 const unsigned char *data = tile->getData();
510
511 if (data != 0)
512 {
513 const float a = tile->prerevealed ? 0.4f : baseMapSegAlpha;
514 const unsigned int rowSize = MAPVIS_SUBDIV/8;
515 for (unsigned int y = 0; y < MAPVIS_SUBDIV; y++, data += rowSize)
516 {
517 for (unsigned int x = 0; x < MAPVIS_SUBDIV; x += 8)
518 {
519 unsigned char dataByte = data[x/8];
520 for (unsigned int x2 = 0; x2 < 8; x2++)
521 {
522 vis[x+x2][y].z = (dataByte & (1 << x2)) ? visibleMapSegAlpha : a;
523 }
524 }
525 }
526 }
527 else
528 {
529 const float a = tile->prerevealed ? 0.4f : baseMapSegAlpha;
530 for (int x = 0; x < MAPVIS_SUBDIV; x++)
531 {
532 for (int y = 0; y < MAPVIS_SUBDIV; y++)
533 {
534 vis[x][y].z = a;
535 }
536 }
537 return;
538 }
539 }
540
541 // Returns a copy of the original texture data.
tileDataToAlpha(WorldMapTile * tile)542 static unsigned char *tileDataToAlpha(WorldMapTile *tile)
543 {
544 const unsigned char *data = tile->getData();
545 const unsigned int ab = int(baseMapSegAlpha * (1<<8) + 0.5f);
546 const unsigned int av = int(visibleMapSegAlpha * (1<<8) + 0.5f);
547
548 const unsigned int texWidth = tile->q->texture->width;
549 const unsigned int texHeight = tile->q->texture->height;
550 if (texWidth % MAPVIS_SUBDIV != 0 || texHeight % MAPVIS_SUBDIV != 0)
551 {
552 std::ostringstream os;
553 os << "Texture size " << texWidth << "x" << texHeight
554 << " not a multiple of MAPVIS_SUBDIV " << MAPVIS_SUBDIV
555 << ", can't edit";
556 debugLog(os.str());
557 return 0;
558 }
559 const unsigned int scaleX = texWidth / MAPVIS_SUBDIV;
560 const unsigned int scaleY = texHeight / MAPVIS_SUBDIV;
561
562 unsigned char *savedTexData = new unsigned char[texWidth * texHeight * 4];
563 tile->q->texture->read(0, 0, texWidth, texHeight, savedTexData);
564
565 unsigned char *texData = new unsigned char[texWidth * texHeight * 4];
566 memcpy(texData, savedTexData, texWidth * texHeight * 4);
567
568 if (data != 0)
569 {
570 const unsigned int rowSize = MAPVIS_SUBDIV/8;
571 for (unsigned int y = 0; y < MAPVIS_SUBDIV; y++, data += rowSize)
572 {
573 unsigned char *texOut = &texData[(y*scaleY) * texWidth * 4];
574 for (unsigned int x = 0; x < MAPVIS_SUBDIV; x += 8)
575 {
576 unsigned char dataByte = data[x/8];
577 for (unsigned int x2 = 0; x2 < 8; x2++, texOut += scaleX*4)
578 {
579 const bool visited = (dataByte & (1 << x2)) != 0;
580 const unsigned int alphaMod = visited ? av : ab;
581 for (unsigned int pixelY = 0; pixelY < scaleY; pixelY++)
582 {
583 unsigned char *ptr = &texOut[pixelY * texWidth * 4];
584 for (unsigned int pixelX = 0; pixelX < scaleX; pixelX++, ptr += 4)
585 {
586 if (ptr[3] == 0)
587 continue;
588 ptr[3] = (ptr[3] * alphaMod + 128) >> 8;
589 }
590 }
591 }
592 }
593 }
594 }
595 else
596 {
597 unsigned char *texOut = texData;
598 for (unsigned int y = 0; y < texHeight; y++)
599 {
600 for (unsigned int x = 0; x < texWidth; x++, texOut += 4)
601 {
602 texOut[3] = (texOut[3] * ab + 128) >> 8;
603 }
604 }
605 }
606
607 tile->q->texture->write(0, 0, texWidth, texHeight, texData);
608 delete[] texData;
609
610 return savedTexData;
611 }
612
resetTileAlpha(WorldMapTile * tile,const unsigned char * savedTexData)613 static void resetTileAlpha(WorldMapTile *tile, const unsigned char *savedTexData)
614 {
615 tile->q->texture->write(0, 0, tile->q->texture->width, tile->q->texture->height, savedTexData);
616 }
617
618 #endif // AQUARIA_BUILD_MAPVIS
619
620
setVis(WorldMapTile * tile)621 void WorldMapRender::setVis(WorldMapTile *tile)
622 {
623 if (!tile) return;
624 #ifdef AQUARIA_BUILD_MAPVIS
625 /*
626 if (lastVisQuad)
627 {
628 lastVisQuad->alphaMod = 0.5;
629 lastVisQuad->color = Vector(0.7, 0.8, 1);
630 }
631 */
632
633 tile->q->color = Vector(1,1,1);
634 tile->q->alphaMod = 1;
635
636 if (visMethod == VIS_VERTEX)
637 {
638 tile->q->setSegs(MAPVIS_SUBDIV, MAPVIS_SUBDIV, 0, 0, 0, 0, 2.0, 1);
639 tileDataToVis(tile, tile->q->getDrawGrid());
640 }
641 else if (visMethod == VIS_WRITE)
642 {
643 savedTexData = tileDataToAlpha(tile);
644 }
645
646 lastVisQuad = tile->q;
647 lastVisTile = tile;
648 #endif
649 }
650
clearVis(WorldMapTile * tile)651 void WorldMapRender::clearVis(WorldMapTile *tile)
652 {
653 if (!tile) return;
654 #ifdef AQUARIA_BUILD_MAPVIS
655 if (visMethod == VIS_VERTEX)
656 {
657 if (tile->q)
658 tile->q->deleteGrid();
659 }
660 else if (visMethod == VIS_WRITE)
661 {
662 if (savedTexData)
663 {
664 resetTileAlpha(tile, savedTexData);
665 delete[] savedTexData;
666 savedTexData = 0;
667 }
668 }
669 #endif
670 }
671
672
WorldMapRender()673 WorldMapRender::WorldMapRender() : RenderObject(), ActionMapper()
674 {
675 doubleClickTimer = 0;
676 inputDelay = 0;
677 editorActive=false;
678 mb = false;
679 activeQuad=0;
680 lastActiveQuad=0;
681 originalActiveQuad=0;
682 lastVisQuad=0;
683 visQuad=0;
684 lastVisTile=0;
685
686 originalActiveTile = activeTile = 0;
687
688 areaLabel = 0;
689
690 on = false;
691 alpha = 0;
692
693 scale = Vector(1, 1);
694 followCamera = 1;
695 cull = false;
696 position = Vector(400,300);
697
698 activeTile = 0;
699 activeQuad = 0;
700
701 lastMousePosition = core->mouse.position;
702
703 bg = 0;
704
705 savedTexData = 0;
706
707 /*
708 bg = new Quad("", Vector(400,300));
709 bg->setWidthHeight(810, 610);
710 bg->setSegs(32, 32, 0.5, 0.5, 0.008, 0.008, 2.0, 1);
711 bg->alphaMod = 0.5;
712 bg->alpha = 0;
713 bg->followCamera = 1;
714 bg->repeatTextureToFill(true);
715 //bg->parentManagedPointer = 1;
716 dsq->game->addRenderObject(bg, LR_MESSAGEBOX);
717
718 bg->renderQuad = false;
719 */
720
721 int num = dsq->continuity.worldMap.getNumWorldMapTiles();
722 std::string n = dsq->game->sceneName;
723 stringToUpper(n);
724 for (int i = 0; i < num; i++)
725 {
726 WorldMapTile *tile = dsq->continuity.worldMap.getWorldMapTile(i);
727 if (tile)
728 {
729 if (tile->name == n)
730 {
731 activeTile = tile;
732 break;
733 }
734 }
735 }
736
737 tiles.clear();
738
739 for (int i = 0; i < num; i++)
740 {
741 WorldMapTile *tile = dsq->continuity.worldMap.getWorldMapTile(i);
742 if (tile)
743 {
744 Vector pos(tile->gridPos.x, tile->gridPos.y);
745
746 Quad *q = new Quad;
747 std::string tn = "Gui/WorldMap/" + tile->name;
748 q->setTexture(tn);
749 q->position = pos;
750 q->alphaMod = 0;
751
752 tile->q = q;
753
754 q->setWidthHeight(q->getWidth()*tile->scale, q->getHeight()*tile->scale);
755 q->scale = Vector(0.25f*tile->scale2, 0.25f*tile->scale2);
756
757 if (tile == activeTile)
758 activeQuad = q;
759
760 if (revMethod == REVEAL_PARTIAL || activeQuad == q)
761 {
762 setVis(tile);
763 }
764
765 setProperTileColor(tile);
766
767 if(activeQuad == q)
768 {
769 activeTile->q->color = Vector(1,1,1);
770 activeTile->q->alphaMod = 1;
771 }
772
773 addChild(q, PM_POINTER);
774
775 tiles.push_back(q);
776 }
777 }
778 shareAlphaWithChildren = 1;
779
780 dsq->user.control.actionSet.importAction(this, "SwimLeft", ACTION_SWIMLEFT);
781 dsq->user.control.actionSet.importAction(this, "SwimRight", ACTION_SWIMRIGHT);
782 dsq->user.control.actionSet.importAction(this, "SwimUp", ACTION_SWIMUP);
783 dsq->user.control.actionSet.importAction(this, "SwimDown", ACTION_SWIMDOWN);
784
785 // where old scale + position set were
786
787 tophud = new Quad("gui/worldmap-ui", Vector(400,64));
788 tophud->followCamera = 1;
789 tophud->alpha = 0;
790 dsq->game->addRenderObject(tophud, LR_WORLDMAPHUD);
791
792 //int fontSize = 6;
793 float aly = 26, aly2 = 18;
794 float sz = 0.6;
795
796 //hover
797 areaLabel = new BitmapText(&dsq->smallFont);
798 areaLabel->scale = Vector(sz,sz);
799 //areaLabel->setFontSize(fontSize);
800 areaLabel->setAlign(ALIGN_CENTER);
801 areaLabel->followCamera = 1;
802 areaLabel->position = Vector(150,aly);
803 dsq->game->addRenderObject(areaLabel, LR_WORLDMAPHUD);
804 areaLabel->alpha = 0;
805
806 //in
807 areaLabel2 = new BitmapText(&dsq->smallFont);
808 //areaLabel2->setFontSize(fontSize);
809 areaLabel2->scale = Vector(sz,sz);
810 areaLabel2->followCamera = 1;
811 areaLabel2->setAlign(ALIGN_CENTER);
812 areaLabel2->position = Vector(400,aly2);
813 dsq->game->addRenderObject(areaLabel2, LR_WORLDMAPHUD);
814 areaLabel2->alpha = 0;
815
816 //select
817 areaLabel3 = new BitmapText(&dsq->smallFont);
818 areaLabel3->scale = Vector(sz,sz);
819 //areaLabel3->setFontSize(fontSize);
820 areaLabel3->followCamera = 1;
821 areaLabel3->setAlign(ALIGN_CENTER);
822 areaLabel3->position = Vector(650, aly);
823 areaLabel3->alpha = 0;
824 dsq->game->addRenderObject(areaLabel3, LR_WORLDMAPHUD);
825
826 if (activeTile)
827 {
828 areaLabel2->setText(dsq->continuity.stringBank.get(activeTile->stringIndex));
829 }
830
831 originalActiveTile = activeTile;
832
833 bindInput();
834
835 underlay = new Gradient;
836 //underlay->makeVertical(Vector(0.5,0.5,1), Vector(0,0,0.5));
837 underlay->makeVertical(Vector(0.25,0.25,0.5), Vector(0,0,0.25));
838 underlay->position = Vector(400,300);
839 underlay->autoWidth = AUTO_VIRTUALWIDTH;
840 underlay->autoHeight = AUTO_VIRTUALHEIGHT;
841 underlay->followCamera = 1;
842 underlay->alpha = 0;
843 dsq->game->addRenderObject(underlay, LR_HUDUNDERLAY);
844
845 addHintQuad1 = new Quad("gems/pyramidyellow", Vector(0,0));
846 addHintQuad1->followCamera = 1;
847 addHintQuad1->alpha = 0;
848 dsq->game->addRenderObject(addHintQuad1, LR_WORLDMAPHUD);
849
850 addHintQuad2 = new Quad("gems/pyramidpurple", Vector(0,0));
851 addHintQuad2->followCamera = 1;
852 addHintQuad2->alpha = 0;
853 dsq->game->addRenderObject(addHintQuad2, LR_WORLDMAPHUD);
854
855 //helpButton->event.set(MakeFunctionEvent(WorldMapRender, onToggleHelpScreen));
856 helpButton = new AquariaMenuItem;
857 helpButton->event.setActionMapperCallback(this, ACTION_TOGGLEHELPSCREEN, 0);
858 helpButton->useQuad("gui/icon-help");
859 helpButton->useGlow("particles/glow", 40, 40);
860 helpButton->useSound("Click");
861 helpButton->alpha = 0;
862 //helpButton->position = Vector(800-20, 20);
863 dsq->game->addRenderObject(helpButton, LR_WORLDMAPHUD);
864 }
865
onToggleHelpScreen()866 void WorldMapRender::onToggleHelpScreen()
867 {
868 game->toggleHelpScreen();
869 }
870
bindInput()871 void WorldMapRender::bindInput()
872 {
873 clearActions();
874 clearCreatedEvents();
875
876 addAction(ACTION_TOGGLEWORLDMAPEDITOR, KEY_TAB);
877
878 dsq->user.control.actionSet.importAction(this, "PrimaryAction", ACTION_PRIMARY);
879 dsq->user.control.actionSet.importAction(this, "SecondaryAction", ACTION_SECONDARY);
880
881 dsq->user.control.actionSet.importAction(this, "SwimLeft", ACTION_SWIMLEFT);
882 dsq->user.control.actionSet.importAction(this, "SwimRight", ACTION_SWIMRIGHT);
883 dsq->user.control.actionSet.importAction(this, "SwimUp", ACTION_SWIMUP);
884 dsq->user.control.actionSet.importAction(this, "SwimDown", ACTION_SWIMDOWN);
885 }
886
destroy()887 void WorldMapRender::destroy()
888 {
889 //clearVis(activeTile);
890 for (int i = 0; i < dsq->continuity.worldMap.getNumWorldMapTiles(); i++)
891 {
892 WorldMapTile *tile = dsq->continuity.worldMap.getWorldMapTile(i);
893 clearVis(tile);
894 }
895
896 RenderObject::destroy();
897 delete[] savedTexData;
898 }
899
isCursorOffHud()900 bool WorldMapRender::isCursorOffHud()
901 {
902 if (helpButton && helpButton->isCursorInMenuItem())
903 {
904 return false;
905 }
906 return true;
907 }
908
onUpdate(float dt)909 void WorldMapRender::onUpdate(float dt)
910 {
911 if (AquariaGuiElement::currentGuiInputLevel > 0) return;
912
913 RenderObject::onUpdate(dt);
914 ActionMapper::onUpdate(dt);
915
916 if (areaLabel)
917 areaLabel->alpha.x = this->alpha.x;
918
919 if (areaLabel2)
920 areaLabel2->alpha.x = this->alpha.x;
921
922 if (areaLabel3)
923 areaLabel3->alpha.x = this->alpha.x;
924
925 if (tophud)
926 tophud->alpha.x = this->alpha.x;
927
928 const float mmWidth = game->miniMapRender->getMiniMapWidth();
929 const float mmHeight = game->miniMapRender->getMiniMapHeight();
930 if (addHintQuad1)
931 addHintQuad1->position = game->miniMapRender->position + Vector(-mmWidth*3/22, -mmHeight/2-10);
932
933 if (addHintQuad2)
934 addHintQuad2->position = game->miniMapRender->position + Vector(mmWidth*3/22, -mmHeight/2-10);
935
936 int offset = 26;
937 if (helpButton)
938 helpButton->position = Vector(core->getVirtualWidth()-core->getVirtualOffX()-offset, offset);
939
940 if (alpha.x > 0)
941 {
942 //if (activeTile && activeTile==originalActiveTile && !gemMovers.empty())
943 if (originalActiveTile && !gemMovers.empty())
944 {
945 gemMovers.back()->position = getAvatarWorldMapPosition();
946 }
947 }
948
949 if (doubleClickTimer > 0)
950 {
951 doubleClickTimer -= dt;
952 if (doubleClickTimer < 0)
953 doubleClickTimer = 0;
954 }
955
956 if (isOn())
957 {
958 if (inputDelay > 0)
959 {
960 inputDelay -= dt;
961 if (inputDelay < 0) inputDelay = 0;
962 }
963 else
964 {
965 WorldMapTile *selectedTile = 0;
966 int sd=-1,d=0;
967 for (int i = 0; i < dsq->continuity.worldMap.getNumWorldMapTiles(); i++)
968 {
969 WorldMapTile *tile = dsq->continuity.worldMap.getWorldMapTile(i);
970 if (tile && tile != activeTile)
971 {
972 if (tile->revealed || tile->prerevealed)
973 {
974 Quad *q = tile->q;
975 if (q)
976 {
977 d = (q->getWorldPosition() - core->mouse.position).getSquaredLength2D();
978
979 if (q->isCoordinateInsideWorld(core->mouse.position) && (sd == -1 || d < sd))
980 {
981 sd = d;
982 selectedTile = tile;
983 break;
984 }
985 }
986 }
987 }
988 }
989
990 if (!editorActive)
991 {
992 if (activeTile)
993 {
994 areaLabel3->setText(dsq->continuity.stringBank.get(activeTile->stringIndex));
995 }
996
997 if (selectedTile)
998 {
999 areaLabel->setText(dsq->continuity.stringBank.get(selectedTile->stringIndex));
1000
1001 if (activeTile && !mover && !dsq->isNested() && isCursorOffHud())
1002 {
1003 if (!core->mouse.buttons.left && mb)
1004 {
1005 if ((activeTile != selectedTile) && selectedTile->q)
1006 {
1007 if(revMethod == REVEAL_DEFAULT)
1008 clearVis(activeTile);
1009
1010 activeTile = selectedTile;
1011 activeQuad = activeTile->q;
1012 //activeTile->gridPos = activeTile->q->position;
1013 if (activeQuad)
1014 {
1015 dsq->clickRingEffect(activeQuad->getWorldPosition(), 0);
1016
1017 dsq->sound->playSfx("bubble-lid");
1018 dsq->sound->playSfx("menuselect");
1019 }
1020
1021 int num = dsq->continuity.worldMap.getNumWorldMapTiles();
1022 for (int i = 0; i < num; i++)
1023 {
1024 WorldMapTile *tile = dsq->continuity.worldMap.getWorldMapTile(i);
1025 setProperTileColor(tile);
1026 }
1027
1028 setVis(selectedTile);
1029 }
1030
1031 mb = false;
1032 }
1033 else if (core->mouse.buttons.left && !mb)
1034 {
1035 mb = true;
1036 }
1037 }
1038 else
1039 {
1040 mb = false;
1041 }
1042 }
1043 else
1044 {
1045 areaLabel->setText("");
1046 }
1047 }
1048 }
1049
1050 if (!core->mouse.buttons.left && mb)
1051 mb = false;
1052
1053 if (core->mouse.buttons.middle || core->mouse.buttons.right)
1054 {
1055 // FIXME: For some reason, not all mouse movement events reach
1056 // this handler (at least under Linux/SDL), so when moving the
1057 // mouse quickly, the world map scrolling tends to lag behind.
1058 // We work around this by keeping our own "last position" vector
1059 // and calculating the mouse movement from that. --achurch
1060 Vector mouseChange = core->mouse.position - lastMousePosition;
1061 internalOffset += mouseChange / scale.x;
1062 }
1063
1064 if(!editorActive)
1065 {
1066 float scrollSpeed = 2.0f;
1067 float amt = (400*dt)/scale.x;
1068 if (isActing(ACTION_SWIMLEFT))
1069 {
1070 internalOffset += Vector(amt, 0);
1071 }
1072 if (isActing(ACTION_SWIMRIGHT))
1073 {
1074 internalOffset += Vector(-amt, 0);
1075 }
1076 if (isActing(ACTION_SWIMDOWN))
1077 {
1078 if (core->getShiftState())
1079 {
1080 scale.stop();
1081 scale -= Vector(scrollSpeed*dt, scrollSpeed*dt);
1082 }
1083 else
1084 {
1085 internalOffset += Vector(0, -amt);
1086 }
1087 }
1088 if (isActing(ACTION_SWIMUP))
1089 {
1090 if (core->getShiftState())
1091 {
1092 scale.stop();
1093 scale += Vector(scrollSpeed*dt, scrollSpeed*dt);
1094 }
1095 else
1096 {
1097 internalOffset += Vector(0, amt);
1098 }
1099 }
1100
1101 if (core->joystickEnabled)
1102 {
1103 if (isActing(ACTION_SECONDARY))
1104 {
1105 if (core->joystick.position.y >= 0.6f)
1106 scale.interpolateTo(scale / 1.2f, 0.1f);
1107 else if (core->joystick.position.y <= -0.6f)
1108 scale.interpolateTo(scale * 1.2f, 0.1f);
1109 }
1110 else
1111 {
1112 // The negative multiplier is deliberate -- it makes the
1113 // map scroll as though the joystick was controlling the
1114 // cursor (which is fixed in the center of the screen).
1115 internalOffset += core->joystick.position * (-400*dt / scale.x);
1116 }
1117 }
1118 }
1119
1120 if (activeTile && activeTile->layer == 1)
1121 {
1122 zoomMax = interiorZoomMax;
1123 }
1124 else
1125 {
1126 zoomMax = exteriorZoomMax;
1127 }
1128
1129 float scrollAmount = 0.2;//0.25;
1130
1131 if (core->mouse.scrollWheelChange)
1132 {
1133 Vector target = scale;
1134 int changeLeft = core->mouse.scrollWheelChange;
1135 for (; changeLeft > 0; changeLeft--)
1136 target *= 1 + scrollAmount;
1137 for (; changeLeft < 0; changeLeft++)
1138 target /= 1 + scrollAmount;
1139 scale.interpolateTo(target, 0.1);
1140 }
1141
1142 if (scale.x < zoomMin)
1143 {
1144 scale.stop();
1145 scale.x = scale.y = zoomMin;
1146 }
1147 if (scale.x > zoomMax)
1148 {
1149 scale.stop();
1150 scale.x = scale.y = zoomMax;
1151 }
1152
1153 if (-internalOffset.x < xMin - 300/scale.x)
1154 internalOffset.x = -(xMin - 300/scale.x);
1155 else if (-internalOffset.x > xMax + 300/scale.x)
1156 internalOffset.x = -(xMax + 300/scale.x);
1157 if (-internalOffset.y < yMin - 225/scale.x)
1158 internalOffset.y = -(yMin - 225/scale.x);
1159 else if (-internalOffset.y > yMax + 150/scale.x)
1160 internalOffset.y = -(yMax + 150/scale.x);
1161
1162 if (dsq->canOpenEditor())
1163 {
1164 if (editorActive)
1165 {
1166 if (activeTile && activeQuad)
1167 {
1168 float amt = dt*4;
1169 float a2 = dt*0.1f;
1170
1171 if (core->getShiftState())
1172 {
1173 if (core->getCtrlState())
1174 a2 *= 10.0f;
1175 if (core->getKeyState(KEY_UP))
1176 activeTile->scale2 += -a2;
1177 if (core->getKeyState(KEY_DOWN))
1178 activeTile->scale2 += a2;
1179 }
1180 else if (core->getAltState())
1181 {
1182 if (core->getCtrlState())
1183 a2 *= 10.0f;
1184 if (core->getKeyState(KEY_UP))
1185 activeTile->scale += -a2;
1186 if (core->getKeyState(KEY_DOWN))
1187 activeTile->scale += a2;
1188 }
1189 else
1190 {
1191 if (core->getCtrlState())
1192 {
1193 amt *= 50;
1194 }
1195 if (core->getKeyState(KEY_LEFT))
1196 activeTile->gridPos += Vector(-amt, 0);
1197 if (core->getKeyState(KEY_RIGHT))
1198 activeTile->gridPos += Vector(amt, 0);
1199 if (core->getKeyState(KEY_UP))
1200 activeTile->gridPos += Vector(0, -amt);
1201 if (core->getKeyState(KEY_DOWN))
1202 activeTile->gridPos += Vector(0, amt);
1203 }
1204
1205 if (core->getKeyState(KEY_F2))
1206 {
1207 dsq->continuity.worldMap.save();
1208 }
1209
1210 activeQuad->position = activeTile->gridPos;
1211 activeQuad->scale = Vector(0.25f*activeTile->scale2, 0.25f*activeTile->scale2);
1212 if(activeQuad->texture)
1213 activeQuad->setWidthHeight(activeQuad->texture->width*activeTile->scale, // FG: HACK force resize proper
1214 activeQuad->texture->height*activeTile->scale);
1215 }
1216 updateEditor();
1217 }
1218 }
1219 }
1220 else
1221 {
1222 #ifdef AQUARIA_BUILD_MAPVIS
1223 if (!dsq->isInCutscene() && dsq->game->avatar && activeTile
1224 #ifdef AQUARIA_BUILD_SCENEEDITOR
1225 && !dsq->game->sceneEditor.isOn()
1226 #endif
1227 )
1228 {
1229 const float screenWidth = core->getVirtualWidth() * core->invGlobalScale;
1230 const float screenHeight = core->getVirtualHeight() * core->invGlobalScale;
1231 Vector camera = core->cameraPos;
1232 camera.x += screenWidth/2;
1233 camera.y += screenHeight/2;
1234 const float visWidth = screenWidth * visitedFraction;
1235 const float visHeight = screenHeight * visitedFraction;
1236 Vector tl, br;
1237 tl.x = (camera.x - visWidth/2 ) / dsq->game->cameraMax.x;
1238 tl.y = (camera.y - visHeight/2) / dsq->game->cameraMax.y;
1239 br.x = (camera.x + visWidth/2 ) / dsq->game->cameraMax.x;
1240 br.y = (camera.y + visHeight/2) / dsq->game->cameraMax.y;
1241 const int x0 = int(tl.x * MAPVIS_SUBDIV);
1242 const int y0 = int(tl.y * MAPVIS_SUBDIV);
1243 const int x1 = int(br.x * MAPVIS_SUBDIV);
1244 const int y1 = int(br.y * MAPVIS_SUBDIV);
1245 activeTile->markVisited(x0, y0, x1, y1);
1246 if (activeQuad)
1247 {
1248 if (visMethod == VIS_VERTEX)
1249 {
1250 for (int x = x0; x <= x1; x++)
1251 {
1252 for (int y = y0; y <= y1; y++)
1253 {
1254 activeQuad->setDrawGridAlpha(x, y, visibleMapSegAlpha);
1255 }
1256 }
1257 }
1258 else if (visMethod == VIS_WRITE)
1259 {
1260 // Do nothing -- we regenerate the tile on opening the map.
1261 }
1262 }
1263 }
1264 #endif
1265 }
1266
1267 lastMousePosition = core->mouse.position;
1268 }
1269
getAvatarWorldMapPosition()1270 Vector WorldMapRender::getAvatarWorldMapPosition()
1271 {
1272 Vector p;
1273 if (originalActiveTile && dsq->game && dsq->game->avatar)
1274 {
1275 Vector p = dsq->game->avatar->position;
1276 if (!dsq->game->avatar->warpInLocal.isZero())
1277 {
1278 p = dsq->game->avatar->warpInLocal;
1279 }
1280 return getWorldToTile(originalActiveTile, p, true, true);
1281 }
1282 return p;
1283 }
1284
getWorldToTile(WorldMapTile * tile,Vector position,bool fromCenter,bool tilePos)1285 Vector WorldMapRender::getWorldToTile(WorldMapTile *tile, Vector position, bool fromCenter, bool tilePos)
1286 {
1287 const float sizew = (float)tile->q->texture->width;
1288 const float halfw = sizew / 2.0f;
1289 const float sizeh = (float)tile->q->texture->height;
1290 const float halfh = sizeh / 2.0f;
1291 Vector p;
1292 p = Vector((position.x/TILE_SIZE) / (sizew*tile->scale), (position.y/TILE_SIZE) / (sizeh*tile->scale));
1293 p.x *= sizew*tile->scale*0.25f*tile->scale2;
1294 p.y *= sizeh*tile->scale*0.25f*tile->scale2;
1295 if (fromCenter)
1296 p -= Vector((halfw*tile->scale)*(0.25f*tile->scale2), (halfh*tile->scale)*(0.25f*tile->scale2));
1297 if (tilePos)
1298 p += tile->gridPos;
1299 return p;
1300 }
1301
onRender()1302 void WorldMapRender::onRender()
1303 {
1304 RenderObject::onRender();
1305 }
1306
isOn()1307 bool WorldMapRender::isOn()
1308 {
1309 return this->on;
1310 }
1311
addGem(GemData * gemData)1312 GemMover *WorldMapRender::addGem(GemData *gemData)
1313 {
1314 GemMover *g = new GemMover(gemData);
1315 addChild(g, PM_POINTER);
1316 gemMovers.push_back(g);
1317 g->update(0);
1318 return g;
1319 }
1320
removeGem(GemMover * gem)1321 void WorldMapRender::removeGem(GemMover *gem)
1322 {
1323 dsq->continuity.removeGemData(gem->getGemData());
1324 fixGems();
1325 }
1326
fixGems()1327 void WorldMapRender::fixGems()
1328 {
1329 for (GemMovers::iterator i = gemMovers.begin(); i != gemMovers.end(); i++)
1330 {
1331 removeChild(*i);
1332 (*i)->destroy();
1333 delete *i;
1334 }
1335 gemMovers.clear();
1336 addAllGems();
1337 }
1338
addAllGems()1339 void WorldMapRender::addAllGems()
1340 {
1341 int c = 0;
1342 for (Continuity::Gems::reverse_iterator i = dsq->continuity.gems.rbegin(); i != dsq->continuity.gems.rend(); i++)
1343 {
1344 GemMover *g = addGem(&(*i));
1345 if (c == dsq->continuity.gems.size()-1 || i->blink)
1346 g->setBlink(true);
1347 else
1348 g->setBlink(false);
1349 c++;
1350 }
1351 }
1352
toggle(bool turnON)1353 void WorldMapRender::toggle(bool turnON)
1354 {
1355 if (AquariaGuiElement::currentGuiInputLevel > 0) return;
1356 if (dsq->game->miniMapRender->isRadarHide()) return;
1357 if (alpha.isInterpolating()) return;
1358
1359 if (dsq->mod.isActive() && !dsq->mod.hasWorldMap()) return;
1360
1361 if (dsq->isNested()) return;
1362
1363 if (!dsq->game->avatar) return;
1364
1365 if (turnON && dsq->game->avatar->isSinging()) return;
1366
1367 if (dsq->game->isInGameMenu()) return;
1368
1369 if (!dsq->game->isActive()) return;
1370
1371 if (turnON && dsq->game->isPaused()) return;
1372
1373 if (!this->on && !dsq->game->avatar->isInputEnabled()) return;
1374
1375 const SeeMapMode mapmode = dsq->game->avatar->getSeeMapMode();
1376
1377 if (mapmode == SEE_MAP_NEVER
1378 || (mapmode == SEE_MAP_DEFAULT && dsq->game->avatar->isInDarkness() && dsq->continuity.form != FORM_SUN))
1379 {
1380 core->sound->playSfx("denied");
1381 return;
1382 }
1383
1384 mb = false;
1385 this->on = turnON;
1386 if (on)
1387 {
1388 restoreVel = dsq->game->avatar->vel;
1389 dsq->game->avatar->vel = Vector(0,0,0);
1390 //dsq->game->avatar->idle();
1391 dsq->game->togglePause(true);
1392
1393 core->sound->playSfx("menu-open");
1394
1395 originalActiveTile = activeTile;
1396
1397 if (activeTile)
1398 {
1399 internalOffset = -activeTile->gridPos;
1400 if (activeTile->layer == 1)
1401 scale = Vector(1.5,1.5);
1402 else
1403 scale = Vector(1,1);
1404 if (visMethod == VIS_WRITE)
1405 {
1406 // Texture isn't updated while moving, so force an update here
1407 clearVis(activeTile);
1408 setVis(activeTile);
1409 }
1410 }
1411
1412 xMin = xMax = -internalOffset.x;
1413 yMin = yMax = -internalOffset.y;
1414 for (int i = 0; i < dsq->continuity.worldMap.getNumWorldMapTiles(); i++)
1415 {
1416 WorldMapTile *tile = dsq->continuity.worldMap.getWorldMapTile(i);
1417 if (tile && (tile->revealed || tile->prerevealed) && tile->q)
1418 {
1419 Quad *q = tile->q;
1420 const float width = q->getWidth() * q->scale.x;
1421 const float height = q->getHeight() * q->scale.y;
1422 if (xMin > tile->gridPos.x - width/2)
1423 xMin = tile->gridPos.x - width/2;
1424 if (xMax < tile->gridPos.x + width/2)
1425 xMax = tile->gridPos.x + width/2;
1426 if (yMin > tile->gridPos.y - height/2)
1427 yMin = tile->gridPos.y - height/2;
1428 if (yMax < tile->gridPos.y + height/2)
1429 yMax = tile->gridPos.y + height/2;
1430 }
1431 }
1432
1433 if (bg)
1434 bg->alpha.interpolateTo(1, 0.2);
1435
1436 alpha.interpolateTo(1, 0.2);
1437
1438
1439 //dsq->game->hudUnderlay->alpha.interpolateTo(WORLDMAP_UNDERLAY_ALPHA, 0.2);
1440 underlay->alpha.interpolateTo(WORLDMAP_UNDERLAY_ALPHA, 0.2);
1441
1442 addHintQuad1->alpha.interpolateTo(1.0, 0.2);
1443 addHintQuad2->alpha.interpolateTo(1.0, 0.2);
1444 helpButton->alpha.interpolateTo(1.0, 0.2);
1445
1446 addAllGems();
1447
1448 for (Continuity::Beacons::reverse_iterator i = dsq->continuity.beacons.rbegin(); i != dsq->continuity.beacons.rend(); i++)
1449 {
1450 if ((*i).on)
1451 {
1452 BeaconRender *b = new BeaconRender(&(*i));
1453 //b->position = (*i).pos;
1454 //game->addRenderObject(b, layer+1);
1455 addChild(b, PM_POINTER);
1456 beaconRenders.push_back(b);
1457 }
1458 }
1459
1460 inputDelay = 0.5;
1461 }
1462 else if (!on)
1463 {
1464 inputDelay = 0.5;
1465
1466 if (originalActiveTile && activeTile)
1467 {
1468 if (activeTile != originalActiveTile)
1469 {
1470 if(revMethod == REVEAL_DEFAULT)
1471 {
1472 clearVis(activeTile);
1473 setVis(originalActiveTile);
1474 }
1475 activeTile = originalActiveTile;
1476 activeQuad = activeTile->q;
1477 }
1478 }
1479
1480 int num = dsq->continuity.worldMap.getNumWorldMapTiles();
1481 for (int i = 0; i < num; i++)
1482 {
1483 WorldMapTile *tile = dsq->continuity.worldMap.getWorldMapTile(i);
1484 setProperTileColor(tile);
1485 }
1486
1487 // again to set the correct color
1488 // lame, don't do that
1489 //setVis(activeTile);
1490
1491 // just set the color
1492 if (activeTile)
1493 {
1494 activeTile->q->color = Vector(1,1,1);
1495 activeTile->q->alphaMod = 1;
1496 }
1497
1498
1499 //setVis(activeTile);
1500 /*
1501 for (int i = 0; i < LR_MENU; i++)
1502 {
1503 RenderObjectLayer *rl = dsq->getRenderObjectLayer(i);
1504 rl->visible = true;
1505 }
1506 */
1507
1508 core->sound->playSfx("Menu-Close");
1509
1510 if (bg)
1511 bg->alpha.interpolateTo(0, 0.2);
1512
1513 alpha.interpolateTo(0, 0.2);
1514
1515 dsq->game->togglePause(false);
1516 //dsq->game->hudUnderlay->alpha.interpolateTo(0, 0.2);
1517 underlay->alpha.interpolateTo(0, 0.2);
1518 addHintQuad1->alpha.interpolateTo(0, 0.2);
1519 addHintQuad2->alpha.interpolateTo(0, 0.2);
1520 helpButton->alpha.interpolateTo(0, 0.2);
1521
1522
1523 for (GemMovers::iterator i = gemMovers.begin(); i != gemMovers.end(); i++)
1524 {
1525 //removeChild(*i);
1526 (*i)->safeKill();
1527 }
1528 gemMovers.clear();
1529
1530 for (BeaconRenders::iterator i = beaconRenders.begin(); i != beaconRenders.end(); i++)
1531 {
1532 //removeChild(*i);
1533 (*i)->safeKill();
1534 }
1535 beaconRenders.clear();
1536
1537 dsq->game->avatar->vel = restoreVel;
1538 }
1539 }
1540
createGemHint(const std::string & gfx)1541 void WorldMapRender::createGemHint(const std::string &gfx)
1542 {
1543 std::string useString = dsq->getUserInputString(dsq->continuity.stringBank.get(860), "", true);
1544 if (!useString.empty())
1545 {
1546 doubleClickTimer = 0;
1547 GemData *g = dsq->continuity.pickupGem(gfx, false);
1548 g->canMove = 1;
1549 g->pos = getAvatarWorldMapPosition();// + Vector(0, -20);
1550 g->userString = useString;
1551 addGem(g);
1552 fixGems();
1553 }
1554 }
1555
updateEditor()1556 void WorldMapRender::updateEditor()
1557 {
1558 std::ostringstream os;
1559 os << "EDITING... ";
1560 if(activeTile)
1561 {
1562 os << "x=" << activeTile->gridPos.x << "; y=" << activeTile->gridPos.y << std::endl;
1563 os << "scale=" << activeTile->scale << "; scale2=" << activeTile->scale2;
1564 }
1565 areaLabel->setText(os.str());
1566 }
1567
action(int id,int state)1568 void WorldMapRender::action (int id, int state)
1569 {
1570 if (isOn())
1571 {
1572 if (id == ACTION_TOGGLEHELPSCREEN && !state)
1573 {
1574 onToggleHelpScreen();
1575 }
1576 if (id == ACTION_TOGGLEWORLDMAPEDITOR && !state)
1577 {
1578 if (dsq->canOpenEditor())
1579 {
1580 editorActive = !editorActive;
1581
1582 if (editorActive)
1583 {
1584 updateEditor();
1585 }
1586 }
1587 }
1588
1589 if (id == ACTION_PRIMARY && state)
1590 {
1591 if (addHintQuad1->isCoordinateInRadius(core->mouse.position, 10))
1592 {
1593 createGemHint("pyramidyellow");
1594 }
1595 if (addHintQuad2->isCoordinateInRadius(core->mouse.position, 10))
1596 {
1597 createGemHint("pyramidpurple");
1598 }
1599 }
1600
1601 if (id == ACTION_SECONDARY && !state)
1602 {
1603 if (!mover)
1604 {
1605 for (GemMovers::iterator i = gemMovers.begin(); i != gemMovers.end(); i++)
1606 {
1607 if ((*i)->canMove && (core->mouse.position - (*i)->getWorldPosition()).isLength2DIn(GEM_GRAB))
1608 {
1609 removeGem(*i);
1610 break;
1611 }
1612 }
1613 }
1614
1615 }
1616
1617 /*
1618 if (id == ACTION_PRIMARY && state)
1619 {
1620 if (doubleClickTimer > 0)
1621 {
1622 doubleClickTimer = 0;
1623 GemData *g = dsq->continuity.pickupGem("pyramidyellow", false);
1624 g->canMove = 1;
1625 g->userString = dsq->getUserInputString("Enter Map Hint Name:", "");
1626 addGem(g);
1627 }
1628 else
1629 {
1630 if (doubleClickTimer == 0)
1631 {
1632 doubleClickTimer = DOUBLE_CLICK_DELAY;
1633 }
1634 }
1635 }
1636 */
1637 }
1638 }
1639