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 "../BBGE/MathFunctions.h"
22 #include "../ExternalLibs/glpng.h"
23 #include "../BBGE/Gradient.h"
24 #include "../BBGE/DebugFont.h"
25
26 #include "Game.h"
27 #include "DSQ.h"
28 #include "Avatar.h"
29 #include "GridRender.h"
30
31
32 #ifdef AQUARIA_BUILD_SCENEEDITOR // Through end of file
33
34
35 #ifdef BBGE_BUILD_WINDOWS
36 #include <shellapi.h>
37 #endif
38
39 const int minSelectionSize = 64;
40 PathRender *pathRender;
41
42
SelectedEntity()43 SelectedEntity::SelectedEntity()
44 {
45 clear();
46 }
47
setSelectEntity(const SelectedEntity & ent)48 void SelectedEntity::setSelectEntity(const SelectedEntity &ent)
49 {
50 (*this) = ent;
51 }
52
clear()53 void SelectedEntity::clear()
54 {
55 typeListIndex = -1;
56 prevScale = 1;
57 nameBased = false;
58 index = -1;
59 name = "";
60 prevGfx="";
61 }
62
setIndex(int idx)63 void SelectedEntity::setIndex(int idx)
64 {
65 clear();
66 if (idx > -1)
67 {
68 nameBased = false;
69 typeListIndex = idx;
70 index = dsq->game->entityTypeList[idx].idx;
71 prevGfx = dsq->game->entityTypeList[idx].prevGfx;
72 prevScale = dsq->game->entityTypeList[idx].prevScale;
73 name = dsq->game->entityTypeList[idx].name;
74 }
75 }
76
setName(const std::string & name,const std::string & prevGfx)77 void SelectedEntity::setName(const std::string &name, const std::string &prevGfx)
78 {
79 clear();
80 nameBased = true;
81 this->name = name;
82 this->prevGfx = prevGfx;
83 }
84
getMapTemplateFilename()85 std::string getMapTemplateFilename()
86 {
87 if (dsq->mod.isActive())
88 return std::string(dsq->mod.getPath() + "maptemplates/" + dsq->game->sceneName + ".png");
89 else
90 return std::string("maptemplates/" + dsq->game->sceneName + ".png");
91 return "";
92 }
93
onRender()94 void WarpAreaRender::onRender()
95 {
96 #ifdef BBGE_BUILD_OPENGL
97 for (int i = 0; i < dsq->game->warpAreas.size(); i++)
98 {
99 WarpArea *a = &dsq->game->warpAreas[i];
100 glTranslatef(a->position.x, a->position.y,0);
101
102 if (a->warpAreaType == "Brown")
103 glColor4f(0.5, 0.25, 0, alpha.getValue());
104 else
105 {
106 switch (a->warpAreaType[0])
107 {
108 case 'B':
109 glColor4f(0,0,1,alpha.getValue());
110 break;
111 case 'R':
112 glColor4f(1,0,0,alpha.getValue());
113 break;
114 case 'G':
115 glColor4f(0, 1, 0,alpha.getValue());
116 break;
117 case 'Y':
118 glColor4f(1,1,0,alpha.getValue());
119 break;
120 case 'P':
121 glColor4f(1,0,1,alpha.getValue());
122 break;
123 case 'O':
124 glColor4f(1,0.5,0,alpha.getValue());
125 break;
126 }
127 }
128
129 if (a->radius)
130 drawCircle(a->radius);
131 else
132 {
133 glBegin(GL_QUADS);
134 {
135 glVertex2f(-a->w,-a->h);
136 glVertex2f(-a->w,a->h);
137 glVertex2f(a->w,a->h);
138 glVertex2f(a->w,-a->h);
139 }
140 glEnd();
141 }
142 glTranslatef(-a->position.x, -a->position.y,0);
143 }
144 #endif
145 #ifdef BBGE_BUILD_DIRECTX
146 for (int i = 0; i < dsq->game->warpAreas.size(); i++)
147 {
148 WarpArea *a = &dsq->game->warpAreas[i];
149 core->translateMatrixStack(a->position.x, a->position.y);
150 switch (a->warpAreaType[0])
151 {
152 case 'B':
153 core->setColor(0, 0, 1, alpha.x);
154 break;
155 case 'R':
156 core->setColor(1,0,0,alpha.x);
157 break;
158 case 'G':
159 core->setColor(0,1,0,alpha.x);
160 break;
161 case 'Y':
162 core->setColor(1,1,0,alpha.x);
163 break;
164 case 'P':
165 core->setColor(1,0,1,alpha.x);
166 break;
167 }
168 if (a->radius)
169 {
170 // drawCircle(a->radius);
171 }
172 else
173 {
174 core->applyMatrixStackToWorld();
175 core->blitD3D(0, a->w*2, a->h*2);
176 /*
177 glBegin(GL_QUADS);
178 {
179 glVertex2f(-a->w,-a->h);
180 glVertex2f(-a->w,a->h);
181 glVertex2f(a->w,a->h);
182 glVertex2f(a->w,-a->h);
183 }
184 glEnd();
185 */
186 }
187 core->translateMatrixStack(-a->position.x, -a->position.y);
188 //glTranslatef(-a->position.x, -a->position.y,0);
189 }
190 #endif
191 }
192
SceneEditor()193 SceneEditor::SceneEditor() : ActionMapper(), on(false)
194 {
195 autoSaveFile = 0;
196 selectedIdx = -1;
197 }
198
setBackgroundGradient()199 void SceneEditor::setBackgroundGradient()
200 {
201 float g1r, g1g, g1b;
202 float g2r, g2g, g2b;
203 std::string gtop = dsq->getUserInputString("Set Gradient Top (3 rgb, spaced)", "");
204 std::string gbtm = dsq->getUserInputString("Set Gradient Bottom (3 rgb, spaced)", "");
205 std::istringstream is1(gtop);
206 is1 >> g1r >> g1g >> g1b;
207 std::istringstream is2(gbtm);
208 is2 >> g2r >> g2g >> g2b;
209
210 if (dsq->game->grad)
211 {
212 dsq->game->grad->makeVertical(Vector(g1r, g1g, g1b), Vector(g2r, g2g, g2b));
213 }
214 }
215
changeDepth()216 void SceneEditor::changeDepth()
217 {
218 if (editingElement)
219 {
220 //editingElement->parallax = 0.9;
221 //editingElement->followCamera = 0.001;
222 editingElement->followCamera = 0.9;
223 editingElement->cull = false;
224 }
225 }
226
updateSelectedElementPosition(Vector dist)227 void SceneEditor::updateSelectedElementPosition(Vector dist)
228 {
229 if (state == ES_MOVING)
230 {
231 if (!selectedElements.empty())
232 {
233 dummy.position = oldPosition + dist;
234 }
235 else if (editingElement)
236 {
237 editingElement->position = oldPosition + dist;
238 }
239 }
240 }
241
242 bool se_changedEntityType = false;
243 class SEQuad : public Quad
244 {
245 public:
246 int entType;
247 Quad *glow;
248 DebugFont *label;
249 float doubleClickTimer;
250 std::string entName;
251 bool mbld;
252 SelectedEntity selectedEntity;
253
SEQuad(std::string tex,Vector pos,int entType,std::string name)254 SEQuad(std::string tex, Vector pos, int entType, std::string name) : Quad(tex, pos), entType(entType)
255 {
256 glow = new Quad;
257 addChild(glow, PM_POINTER, RBP_ON);
258 glow->setWidthHeight(48, 64);
259 glow->alpha = 0;
260 glow->setBlendType(RenderObject::BLEND_ADD);
261 scale = Vector(0.5, 0.5);
262 scale.interpolateTo(Vector(1,1), 0.5, 0, 0, 1);
263
264 label = new DebugFont();
265 label->setFontSize(5);
266 label->position = Vector(-32,12);
267 label->setText(name);
268 label->alpha = 0;
269 addChild(label, PM_POINTER);
270
271 doubleClickTimer = 0;
272 entName = name;
273 mbld = false;
274 selectedEntity.prevGfx = tex;
275 selectedEntity.name = name;
276 }
277
onUpdate(float dt)278 void onUpdate(float dt)
279 {
280 if (doubleClickTimer > 0)
281 doubleClickTimer -= dt;
282 Quad::onUpdate(dt);
283 //if ()
284
285 if (dsq->game->sceneEditor.selectedEntity.name == selectedEntity.name
286 || (entType != -1 && dsq->game->sceneEditor.selectedEntity.typeListIndex == entType))
287 {
288 glow->alpha.interpolateTo(0.2, 0.2);
289 }
290 else
291 {
292 glow->alpha.interpolateTo(0, 0.1);
293 }
294 if ((core->mouse.position - position).isLength2DIn(32))
295 {
296 label->alpha.interpolateTo(1, 0.1);
297 alpha.interpolateTo(1, 0.2);
298 scale.interpolateTo(Vector(1.5, 1.5), 0.3);
299
300 if (!core->mouse.buttons.left && mbld)
301 {
302 mbld = false;
303 }
304 else if (core->mouse.buttons.left && !mbld)
305 {
306 mbld = true;
307
308 if (entType > -1)
309 dsq->game->sceneEditor.selectedEntity.setIndex(entType);
310 else
311 {
312 dsq->game->sceneEditor.selectedEntity.setName(selectedEntity.name, selectedEntity.prevGfx);
313 }
314 //se_changedEntityType = true;
315 if (doubleClickTimer > 0)
316 {
317 doubleClickTimer = 0;
318 if (!dsq->isFullscreen())
319 {
320 std::string fn = "scripts/entities/" + entName + ".lua";
321 #ifdef BBGE_BUILD_WINDOWS
322 debugLog("SHELL EXECUTE!");
323 ShellExecute(dsq->hWnd, "open", fn.c_str(), NULL, NULL, SW_SHOWNORMAL);
324 #endif
325 }
326 }
327 else
328 {
329 doubleClickTimer = 0.4;
330 }
331 }
332 }
333 else
334 {
335 label->alpha.interpolateTo(0, 0.1);
336 alpha.interpolateTo(0.7, 0.2);
337 scale.interpolateTo(Vector(1.0, 1.0), 0.3);
338 doubleClickTimer = 0;
339 }
340 }
341 };
342
343
344 std::vector<DebugButton*> mainMenu;
345 int execID = 0;
346 bool inMainMenu = false;
347
348 std::vector<SEQuad*> qs;
349 DebugFont *se_label=0;
350
351
352
buttonPress(DebugButton * db)353 void SceneEditorMenuReceiver::buttonPress(DebugButton *db)
354 {
355 execID = db->buttonID;
356
357 switch(execID)
358 {
359 case 200:
360 {
361 if (inMainMenu)
362 {
363 dsq->game->sceneEditor.closeMainMenu();
364 }
365 else
366 {
367 dsq->game->sceneEditor.openMainMenu();
368 }
369 execID = 0;
370 }
371 break;
372 }
373 }
374
executeButtonID(int bid)375 void SceneEditor::executeButtonID(int bid)
376 {
377 switch(bid)
378 {
379 case 100:
380 loadSceneByName();
381 break;
382 case 101:
383 reloadScene();
384 break;
385 case 102:
386 saveScene();
387 break;
388 case 103:
389 // regen collision
390 dsq->game->reconstructGrid(true);
391 break;
392 case 104:
393 generateLevel();
394 break;
395 case 105:
396 skinLevel();
397 break;
398 case 106:
399 editModeElements();
400 break;
401 case 107:
402 editModeEntities();
403 break;
404 case 108:
405 editModePaths();
406 break;
407 case 110:
408 {
409 std::ostringstream os;
410 os << dsq->game->gradTop.x << " " << dsq->game->gradTop.y << " " << dsq->game->gradTop.z;
411 std::string read;
412 read = dsq->getUserInputString("Enter Spaced R G B 0-1 Values for the Top Color (e.g. 1 0.5 0.5 for bright red)", os.str());
413
414 if (!read.empty())
415 {
416 std::istringstream is(read);
417 is >> dsq->game->gradTop.x >> dsq->game->gradTop.y >> dsq->game->gradTop.z;
418 }
419
420 std::ostringstream os2;
421 os2 << dsq->game->gradBtm.x << " " << dsq->game->gradBtm.y << " " << dsq->game->gradBtm.z;
422 read = dsq->getUserInputString("Enter Spaced R G B 0-1 Values for the Bottom Color (e.g. 0 0 0 for black)", os2.str());
423
424 if (!read.empty())
425 {
426 std::istringstream is2(read);
427 is2 >> dsq->game->gradBtm.x >> dsq->game->gradBtm.y >> dsq->game->gradBtm.z;
428 }
429
430 dsq->game->createGradient();
431 }
432 break;
433 case 111:
434 {
435 std::string track = dsq->getUserInputString("Set Background Music Track", dsq->game->saveMusic);
436 if (!track.empty())
437 {
438 dsq->game->setMusicToPlay(track);
439 dsq->game->saveMusic = track;
440 dsq->game->updateMusic();
441 }
442 }
443 break;
444 case 112:
445 {
446 selectEntityFromGroups();
447 }
448 break;
449 case 113:
450 dsq->game->toggleGridRender();
451 break;
452 case 114:
453 dsq->screenshot();
454 break;
455 case 115:
456 {
457 dsq->returnToScene = dsq->game->sceneName;
458 core->enqueueJumpState("AnimationEditor");
459 }
460 break;
461 case 120:
462 {
463 dsq->returnToScene = dsq->game->sceneName;
464 core->enqueueJumpState("ParticleEditor");
465 }
466 break;
467 case 116:
468 regenLevel();
469 break;
470 case 130:
471 dsq->mod.recache();
472 break;
473 }
474 }
475
addMainMenuItem(const std::string & label,int bid)476 void SceneEditor::addMainMenuItem(const std::string &label, int bid)
477 {
478 DebugButton *b = new DebugButton(bid, &menuReceiver, 350);
479 b->label->setText(label);
480 b->followCamera = 1;
481 b->position.x = btnMenu->position.x + 20;
482 b->position.y = btnMenu->position.y + (mainMenu.size()+1)*22;
483 dsq->game->addRenderObject(b, LR_HUD);
484 mainMenu.push_back(b);
485 }
486
openMainMenu()487 void SceneEditor::openMainMenu()
488 {
489 /*
490 core->clearDebugMenu();
491 core->addDebugMenuItem("", bid);
492 core->doModalDebugMenu();
493 */
494
495 if (core->getNestedMains()>1)
496 {
497 return;
498 }
499
500 inMainMenu = true;
501
502 if (placer)
503 placer->renderQuad = 0;
504
505 execID = -1;
506 debugLog("Open Main Menu");
507
508 mainMenu.clear();
509
510 while (core->mouse.buttons.left)
511 {
512 core->main(FRAME_TIME);
513 }
514
515 addMainMenuItem("LOAD LEVEL... (SHIFT-F1)", 100);
516 addMainMenuItem("RELOAD LEVEL (F1)", 101);
517 addMainMenuItem("SAVE LEVEL (F2)", 102);
518 addMainMenuItem("EDIT TILES (F5)", 106);
519 addMainMenuItem("EDIT ENTITIES (F6)", 107);
520 addMainMenuItem("EDIT NODES (F7)", 108);
521 addMainMenuItem("REGEN COLLISIONS (ALT-R)", 103);
522 addMainMenuItem("RECACHE TEXTURES (CTRL-R)", 130);
523 // addMainMenuItem("REFRESH DATAFILES (F11)", 117);
524 addMainMenuItem("REGEN ROCK FROM MAPTEMPLATE (F11+F12)", 116);
525 /*
526 addMainMenuItem("RE-TEMPLATE (F11)", 104);
527 addMainMenuItem("RE-SKIN (F12)", 105);
528 */
529 addMainMenuItem("SET BG GRADIENT", 110);
530 addMainMenuItem("SET MUSIC", 111);
531 addMainMenuItem("ENTITY GROUPS (CTRL-E)", 112);
532 if (dsq->game->gridRender)
533 addMainMenuItem(std::string("TOGGLE TILE COLLISION RENDER ") + ((dsq->game->gridRender->alpha!=0) ? "OFF" : "ON ") + std::string(" (F9)"), 113);
534 addMainMenuItem("SCREENSHOT ", 114);
535
536
537
538 addMainMenuItem("PARTICLE VIEWER ", 120);
539 addMainMenuItem("ANIMATION EDITOR ", 115);
540
541 while (1 && !core->getKeyState(KEY_TAB))
542 {
543 core->main(FRAME_TIME);
544 if (execID != -1)
545 break;
546 }
547
548 closeMainMenu();
549
550 executeButtonID(execID);
551 }
552
closeMainMenu()553 void SceneEditor::closeMainMenu()
554 {
555 inMainMenu = false;
556 for (int i = 0; i < mainMenu.size(); i++)
557 {
558 mainMenu[i]->alpha = 0;
559 mainMenu[i]->safeKill();
560 }
561 mainMenu.clear();
562
563
564 if (placer)
565 placer->renderQuad = 1;
566
567 core->quitNestedMain();
568 }
569
init()570 void SceneEditor::init()
571 {
572 entityPageNum = 0;
573 multiSelecting = false;
574 selectedElements.clear();
575 autoSaveTimer = 0;
576 skinMinX = skinMinY = skinMaxX = skinMaxY = -1;
577 editingElement = 0;
578 editingEntity = 0;
579 pathRender = new PathRender();
580 core->getTopStateData()->addRenderObject(pathRender, LR_DEBUG_TEXT);
581 pathRender->alpha = 0;
582
583 editType = ET_ELEMENTS;
584 state = ES_SELECTING;
585 drawingWarpArea = 'N';
586
587 btnMenu = new DebugButton(200, &menuReceiver, 700);
588 btnMenu->position = Vector(20, 20);
589 btnMenu->label->setText("Menu");
590 btnMenu->followCamera = 1;
591 btnMenu->alpha = 0;
592 //btnMenu->event.set(MakeFunctionEvent(SceneEditor, openMainMenu));
593 dsq->game->addRenderObject(btnMenu, LR_HUD);
594
595 selectedEntityType = 0;
596 zoom = Vector(0.2,0.2);
597 drawingBox = false;
598 bgLayer = 5;
599 text = new DebugFont();
600 text->setFontSize(6);
601
602 text->followCamera = 1;
603 text->position = Vector(125,20,4.5);
604 //text->setAlign(ALIGN_CENTER);
605 dsq->game->addRenderObject(text, LR_HUD);
606 text->alpha = 0;
607 selectedVariation = -1;
608
609 boxPromo = new Quad;
610 boxPromo->color = 0;
611 boxPromo->alpha =0;
612 boxPromo->cull = false;
613 dsq->game->addRenderObject(boxPromo, LR_HUD);
614 on = false;
615
616 //addAction(MakeFunctionEvent(SceneEditor, addSpringPlant), KEY_K, 0);
617
618 addAction(MakeFunctionEvent(SceneEditor, loadScene), KEY_F1, 0);
619 addAction(MakeFunctionEvent(SceneEditor, saveScene), KEY_F2, 0);
620
621 // removed in fc3
622 //addAction(MakeFunctionEvent(SceneEditor, setGroup), KEY_G, 0);
623
624 addAction(MakeFunctionEvent(SceneEditor, moveToBack), KEY_Z, 0);
625 addAction(MakeFunctionEvent(SceneEditor, moveToFront), KEY_X, 0);
626
627 addAction(MakeFunctionEvent(SceneEditor, toggleWarpAreaRender), KEY_F4, 0);
628
629 addAction(MakeFunctionEvent(SceneEditor, editModeElements), KEY_F5, 0);
630 addAction(MakeFunctionEvent(SceneEditor, editModeEntities), KEY_F6, 0);
631 addAction(MakeFunctionEvent(SceneEditor, editModePaths), KEY_F7, 0);
632
633 addAction(MakeFunctionEvent(SceneEditor, mouseButtonLeft), MOUSE_BUTTON_LEFT, 1);
634 addAction(MakeFunctionEvent(SceneEditor, mouseButtonRight), MOUSE_BUTTON_RIGHT, 1);
635 addAction(MakeFunctionEvent(SceneEditor, mouseButtonLeftUp), MOUSE_BUTTON_LEFT, 0);
636 addAction(MakeFunctionEvent(SceneEditor, mouseButtonRightUp), MOUSE_BUTTON_RIGHT, 0);
637
638 addAction(MakeFunctionEvent(SceneEditor, alignHorz), KEY_C, 1);
639 addAction(MakeFunctionEvent(SceneEditor, alignVert), KEY_V, 1);
640
641
642
643 /*
644 addAction(MakeFunctionEvent(SceneEditor, placeEntity), KEY_U, 0);
645 addAction(MakeFunctionEvent(SceneEditor, removeEntity), KEY_I, 0);
646 */
647 //addAction(MakeFunctionEvent(SceneEditor, changeDepth), KEY_N, 0);
648
649 addAction(MakeFunctionEvent(SceneEditor, placeElement), KEY_SPACE, 1);
650
651 addAction(MakeFunctionEvent(SceneEditor, enterName), KEY_N, 0);
652 addAction(MakeFunctionEvent(SceneEditor, changeShape), KEY_Y, 0);
653 addAction(MakeFunctionEvent(SceneEditor, reversePath), KEY_T, 0);
654
655
656 addAction(MakeFunctionEvent(SceneEditor, moveLayer), KEY_F10, 0);
657
658 addAction(MakeFunctionEvent(SceneEditor, nextElement), KEY_R, 1);
659 addAction(MakeFunctionEvent(SceneEditor, prevElement), KEY_E, 1);
660 addAction(MakeFunctionEvent(SceneEditor, selectZero), KEY_HOME, 1);
661 addAction(MakeFunctionEvent(SceneEditor, selectEnd), KEY_END, 1);
662
663 addAction(MakeFunctionEvent(SceneEditor, placeAvatar), KEY_P, 0);
664 addAction(MakeFunctionEvent(SceneEditor, deleteSelected), KEY_DELETE, 0);
665 addAction(MakeFunctionEvent(SceneEditor, deleteSelected), KEY_BACKSPACE, 0);
666
667 addAction(MakeFunctionEvent(SceneEditor, generateLevel), KEY_F11, 0);
668 addAction(MakeFunctionEvent(SceneEditor, skinLevel), KEY_F12, 0);
669
670 //addAction(MakeFunctionEvent(SceneEditor, regenLevel), KEY_F12, 0);
671
672 addAction(MakeFunctionEvent(SceneEditor, nextEntityType), KEY_RIGHT, 0);
673 addAction(MakeFunctionEvent(SceneEditor, prevEntityType), KEY_LEFT, 0);
674 addAction(MakeFunctionEvent(SceneEditor, down), KEY_DOWN, 0);
675 addAction(MakeFunctionEvent(SceneEditor, up), KEY_UP, 0);
676
677
678 addAction(MakeFunctionEvent(SceneEditor, flipElementHorz), KEY_T, 0);
679 addAction(MakeFunctionEvent(SceneEditor, flipElementVert), KEY_Y, 0);
680
681 addAction(MakeFunctionEvent(SceneEditor, toggleElementSolid), KEY_O, 0);
682 addAction(MakeFunctionEvent(SceneEditor, toggleElementHurt), KEY_I, 0);
683 addAction(MakeFunctionEvent(SceneEditor, toggleElementRepeat), KEY_L, 0);
684
685 addAction(MakeFunctionEvent(SceneEditor, setGridPattern0), KEY_NUMPAD0, 0);
686 addAction(MakeFunctionEvent(SceneEditor, setGridPattern1), KEY_NUMPAD1, 0);
687 addAction(MakeFunctionEvent(SceneEditor, setGridPattern2), KEY_NUMPAD2, 0);
688 addAction(MakeFunctionEvent(SceneEditor, setGridPattern3), KEY_NUMPAD3, 0);
689 addAction(MakeFunctionEvent(SceneEditor, setGridPattern4), KEY_NUMPAD4, 0);
690 addAction(MakeFunctionEvent(SceneEditor, setGridPattern5), KEY_NUMPAD5, 0);
691 addAction(MakeFunctionEvent(SceneEditor, setGridPattern6), KEY_NUMPAD6, 0);
692 addAction(MakeFunctionEvent(SceneEditor, setGridPattern7), KEY_NUMPAD7, 0);
693 addAction(MakeFunctionEvent(SceneEditor, setGridPattern8), KEY_NUMPAD8, 0);
694 addAction(MakeFunctionEvent(SceneEditor, setGridPattern9), KEY_NUMPAD9, 0);
695
696
697 addAction(MakeFunctionEvent(SceneEditor, createAquarian), KEY_F, 0);
698
699 addAction(MakeFunctionEvent(SceneEditor, dumpObs), KEY_F8, 0);
700
701
702 /*
703 // OLD CRAP
704 addAction(MakeFunctionEvent(SceneEditor, rotateElement), KEY_MULTIPLY, 0);
705 addAction(MakeFunctionEvent(SceneEditor, rotateElement2), KEY_DIVIDE, 0);
706 addAction(MakeFunctionEvent(SceneEditor, scaleElementUp), KEY_NUMPAD7, 0);
707 addAction(MakeFunctionEvent(SceneEditor, scaleElementDown), KEY_NUMPAD1, 0);
708 addAction(MakeFunctionEvent(SceneEditor, scaleElement1), KEY_NUMPAD0, 0);
709 addAction(MakeFunctionEvent(SceneEditor, nextVariation), KEY_UP, 0);
710 addAction(MakeFunctionEvent(SceneEditor, prevVariation), KEY_DOWN, 0);
711 */
712
713
714 addAction(ACTION_ZOOMIN, KEY_PGUP);
715 addAction(ACTION_ZOOMOUT, KEY_PGDN);
716
717 addAction(ACTION_CAMLEFT, KEY_A);
718 addAction(ACTION_CAMRIGHT, KEY_D);
719 addAction(ACTION_CAMUP, KEY_W);
720 addAction(ACTION_CAMDOWN, KEY_S);
721
722 addAction(ACTION_BGLAYEREND, KEY_0);
723
724 addAction(ACTION_BGLAYER1, KEY_1);
725 addAction(ACTION_BGLAYER2, KEY_2);
726 addAction(ACTION_BGLAYER3, KEY_3);
727 addAction(ACTION_BGLAYER4, KEY_4);
728 addAction(ACTION_BGLAYER5, KEY_5);
729 addAction(ACTION_BGLAYER6, KEY_6);
730 addAction(ACTION_BGLAYER7, KEY_7);
731 addAction(ACTION_BGLAYER8, KEY_8);
732 addAction(ACTION_BGLAYER9, KEY_9);
733
734 addAction(ACTION_BGLAYER10, KEY_B);
735 addAction(ACTION_BGLAYER11, KEY_N);
736 addAction(ACTION_BGLAYER12, KEY_M);
737
738 addAction(ACTION_BGLAYER13, KEY_J);
739
740 addAction(ACTION_BGLAYER14, KEY_COMMA);
741 addAction(ACTION_BGLAYER15, KEY_PERIOD);
742 addAction(ACTION_BGLAYER16, KEY_SLASH);
743 addAction(ACTION_BGLAYER16, KEY_MINUS); // HACK: for german keyboard layout -- FG
744
745 addAction(ACTION_MULTISELECT, KEY_LALT);
746
747 placer = new Quad;
748 dsq->game->addRenderObject(placer, LR_HUD);
749 placer->alpha = 0;
750 curElement = 0;
751 selectedEntity.clear();
752 nextElement();
753
754
755 if (curElement < dsq->game->elementTemplates.size())
756 {
757 placer->setTexture(dsq->game->elementTemplates[curElement].gfx);
758 placer->scale = Vector(1,1);
759 }
760 else
761 {
762 placer->setTexture("missingimage");
763 }
764
765 warpAreaRender = new WarpAreaRender;
766 warpAreaRender->alpha = 0;
767 warpAreaRender->toggleCull(false);
768 dsq->game->addRenderObject(warpAreaRender, LR_HUD);
769
770 updateText();
771
772 doPrevElement();
773 }
774
alignHorz()775 void SceneEditor::alignHorz()
776 {
777 if (core->getShiftState()) return;
778 if (editType == ET_ELEMENTS && state == ES_SELECTING && editingElement)
779 {
780 TileVector t(editingElement->position);
781 int startOn = dsq->game->getGrid(t);
782 TileVector c=t;
783 bool found = false;
784 int dir = -1;
785 for (int i = 1; i < 5; i++)
786 {
787 // search down
788 c.y = t.y + i;
789 if (dsq->game->getGrid(c) != startOn)
790 {
791 found = true;
792 dir = 1;
793 break;
794 }
795 c.y = t.y - i;
796 if (dsq->game->getGrid(c) != startOn)
797 {
798 found = true;
799 dir = -1;
800 break;
801 }
802 }
803 if (found)
804 {
805 editingElement->position.y = c.worldVector().y + (editingElement->texture->getPixelHeight()/2)*(-dir);
806 }
807 }
808 }
809
alignVert()810 void SceneEditor::alignVert()
811 {
812 if (core->getShiftState()) return;
813 if (editType == ET_ELEMENTS && state == ES_SELECTING && editingElement)
814 {
815 TileVector t(editingElement->position);
816 int startOn = dsq->game->getGrid(t);
817 TileVector c=t;
818 bool found = false;
819 int dir = -1;
820 for (int i = 1; i < 5; i++)
821 {
822 // search down
823 c.x = t.x + i;
824 if (dsq->game->getGrid(c) != startOn)
825 {
826 found = true;
827 dir = 1;
828 break;
829 }
830 c.x = t.x - i;
831 if (dsq->game->getGrid(c) != startOn)
832 {
833 found = true;
834 dir = -1;
835 break;
836 }
837 }
838 if (found)
839 {
840 editingElement->position.x = c.worldVector().x + (editingElement->texture->getPixelWidth()/2)*(-dir);
841 }
842 }
843 }
844
createAquarian()845 void SceneEditor::createAquarian()
846 {
847 //if (dsq->mod.isActive()) return;
848 static bool inCreateAqurian = false;
849 if (inCreateAqurian) return;
850 //if (dsq->game->isPaused()) return;
851 inCreateAqurian = true;
852 std::string t = dsq->getUserInputString("Enter Aquarian:", "");
853 stringToUpper(t);
854 Vector startPos = dsq->getGameCursorPosition();
855 for (int i = 0; i < t.size(); i++)
856 {
857 int v = 0;
858 if (t[i] >= 'A' && t[i] <= 'Z')
859 {
860 v = 1024+int(t[i] - 'A');
861 }
862 if (t[i] == '.' || t[i] == ' ')
863 {
864 v = 1024+26;
865 }
866 //ElementTemplate et = dsq->game->getElementTemplateForLetter(v);
867 dsq->game->createElement(v, startPos + Vector(64*i,0), this->bgLayer);
868 }
869 inCreateAqurian = false;
870 }
871
getSelectedPath()872 Path *SceneEditor::getSelectedPath()
873 {
874 if (selectedIdx >= 0 && selectedIdx < dsq->game->getNumPaths())
875 {
876 return dsq->game->getPath(selectedIdx);
877 }
878 return 0;
879 }
880
enterName()881 void SceneEditor::enterName()
882 {
883 if (editType == ET_PATHS)
884 {
885 Path *p = getSelectedPath();
886 if (p)
887 {
888 std::string newname = dsq->getUserInputString("PathName", p->name);
889 bool changed = newname != p->name;
890 p->name = newname;
891 if (changed)
892 {
893 p->refreshScript();
894 p->init();
895 }
896 }
897 }
898 }
899
changeShape()900 void SceneEditor::changeShape()
901 {
902 if (editType == ET_PATHS)
903 {
904 Path *p = getSelectedPath();
905 if (p)
906 {
907 switch (p->pathShape)
908 {
909 case PATHSHAPE_RECT:
910 p->pathShape = PATHSHAPE_CIRCLE;
911 break;
912 case PATHSHAPE_CIRCLE:
913 p->pathShape = PATHSHAPE_RECT;
914 break;
915 }
916 }
917 }
918 }
919
reversePath()920 void SceneEditor::reversePath()
921 {
922 if (editType == ET_PATHS)
923 {
924 Path *p = getSelectedPath();
925 if (p)
926 {
927 p->reverseNodes();
928 }
929 }
930 }
931
toggleWarpAreaRender()932 void SceneEditor::toggleWarpAreaRender()
933 {
934 if (warpAreaRender->alpha.x == 0)
935 warpAreaRender->alpha.x = 0.5;
936 else if (warpAreaRender->alpha.x >= 0.5f)
937 warpAreaRender->alpha.x = 0;
938 //warpAreaRender->alpha.interpolateTo(1, 0.2);
939 }
940
941
setGridPattern(int gi)942 void SceneEditor::setGridPattern(int gi)
943 {
944 if (selectedElements.size())
945 for (int i = 0; i < selectedElements.size(); ++i)
946 selectedElements[i]->setElementEffectByIndex(gi);
947 else if (editingElement)
948 editingElement->setElementEffectByIndex(gi);
949 }
950
setGridPattern0()951 void SceneEditor::setGridPattern0()
952 { setGridPattern(-1); }
953
setGridPattern1()954 void SceneEditor::setGridPattern1()
955 { setGridPattern(0); }
956
setGridPattern2()957 void SceneEditor::setGridPattern2()
958 { setGridPattern(1); }
959
setGridPattern3()960 void SceneEditor::setGridPattern3()
961 { setGridPattern(2); }
962
setGridPattern4()963 void SceneEditor::setGridPattern4()
964 { setGridPattern(3); }
965
setGridPattern5()966 void SceneEditor::setGridPattern5()
967 { setGridPattern(4); }
968
setGridPattern6()969 void SceneEditor::setGridPattern6()
970 { setGridPattern(5); }
971
setGridPattern7()972 void SceneEditor::setGridPattern7()
973 { setGridPattern(6); }
974
setGridPattern8()975 void SceneEditor::setGridPattern8()
976 { setGridPattern(7); }
977
setGridPattern9()978 void SceneEditor::setGridPattern9()
979 { setGridPattern(8); }
980
moveToFront()981 void SceneEditor::moveToFront()
982 {
983 if (editingElement && !core->getShiftState())
984 {
985 std::vector<Element*> copy = dsq->getElementsCopy();
986 dsq->clearElements();
987
988 // move to the foreground ... this means that the editing element should be last in the list (Added last)
989 for (int i = 0; i < copy.size(); i++)
990 {
991 if (copy[i] != editingElement)
992 dsq->addElement(copy[i]);
993 }
994 dsq->addElement(editingElement);
995
996 editingElement->moveToFront();
997 }
998 }
999
moveToBack()1000 void SceneEditor::moveToBack()
1001 {
1002 if (editingElement && !core->getShiftState())
1003 {
1004 std::vector<Element*> copy = dsq->getElementsCopy();
1005 dsq->clearElements();
1006
1007 // move to the background ... this means that the editing element should be first in the list (Added first)
1008 dsq->addElement(editingElement);
1009 for (int i = 0; i < copy.size(); i++)
1010 {
1011 if (copy[i] != editingElement)
1012 dsq->addElement(copy[i]);
1013 }
1014
1015 editingElement->moveToBack();
1016 }
1017 }
1018
editModeElements()1019 void SceneEditor::editModeElements()
1020 {
1021 selectedIdx = -1;
1022 editType = ET_ELEMENTS;
1023 if (curElement < dsq->game->elementTemplates.size())
1024 {
1025 placer->setTexture(dsq->game->elementTemplates[curElement].gfx);
1026 placer->scale = Vector(1,1);
1027 }
1028 placer->alpha = 0.5;
1029 pathRender->alpha = 0;
1030 editingEntity = NULL;
1031 editingPath = NULL;
1032 }
1033
editModeEntities()1034 void SceneEditor::editModeEntities()
1035 {
1036 selectedIdx = -1;
1037 //HACK: methinks target is useless now
1038 //target->alpha.interpolateTo(0, 0.5);
1039 editType = ET_ENTITIES;
1040
1041 //dsq->game->entityTypeList[curEntity].prevGfx
1042 placer->setTexture(selectedEntity.prevGfx);
1043 placer->alpha = 0.5;
1044 pathRender->alpha = 0;
1045 selectedElements.clear();
1046 editingElement = NULL;
1047 editingPath = NULL;
1048 }
1049
editModePaths()1050 void SceneEditor::editModePaths()
1051 {
1052 selectedIdx = -1;
1053 editType = ET_PATHS;
1054 placer->alpha = 0;
1055 pathRender->alpha = 0.5;
1056 selectedElements.clear();
1057 editingElement = NULL;
1058 editingEntity = NULL;
1059 }
1060
getElementAtCursor()1061 Element *SceneEditor::getElementAtCursor()
1062 {
1063 int minDist = -1;
1064 Element *selected = 0;
1065 for (Element *e = dsq->getFirstElementOnLayer(this->bgLayer); e; e = e->bgLayerNext)
1066 {
1067 if (e->life == 1)
1068 {
1069 if (e->isCoordinateInside(dsq->getGameCursorPosition()))//, minSelectionSize
1070 {
1071 Vector v = dsq->getGameCursorPosition() - e->position;
1072 int dist = v.getSquaredLength2D();
1073 if (dist < minDist || minDist == -1)
1074 {
1075 minDist = dist;
1076 selected = e;
1077 }
1078 }
1079 }
1080 }
1081 return selected;
1082 }
1083
getEntityAtCursor()1084 Entity *SceneEditor::getEntityAtCursor()
1085 {
1086 int minDist = -1;
1087 Entity *selected = 0;
1088 FOR_ENTITIES(i)
1089 {
1090 Entity *e = *i;
1091 if (e->life == 1)
1092 {
1093 if (e->isCoordinateInside(dsq->getGameCursorPosition(), minSelectionSize))
1094 {
1095 Vector v = dsq->getGameCursorPosition() - e->position;
1096 int dist = v.getSquaredLength2D();
1097 if (dist < minDist || minDist == -1)
1098 {
1099 minDist = dist;
1100 selected = e;
1101 }
1102 }
1103 }
1104 }
1105 return selected;
1106 }
1107
deleteSelected()1108 void SceneEditor::deleteSelected()
1109 {
1110 if (state != ES_SELECTING) return;
1111 if (editType == ET_ELEMENTS)
1112 {
1113 if (selectedElements.size()>0)
1114 {
1115 for (int i = 0; i < selectedElements.size(); i++)
1116 {
1117 selectedElements[i]->safeKill();
1118 dsq->removeElement(selectedElements[i]);
1119 }
1120 selectedElements.clear();
1121 dsq->game->reconstructGrid();
1122 }
1123 else if (editingElement)
1124 {
1125 editingElement->safeKill();
1126 dsq->removeElement(editingElement);
1127 editingElement = 0;
1128 dsq->game->reconstructGrid();
1129 }
1130 }
1131 else if (editType == ET_ENTITIES)
1132 {
1133 if (editingEntity)
1134 {
1135 if (editingEntity->getEntityType() != ET_AVATAR)
1136 {
1137 dsq->game->removeEntity(editingEntity);
1138 editingEntity = 0;
1139 }
1140 }
1141 }
1142 else if (editType == ET_PATHS)
1143 {
1144 if (core->getShiftState())
1145 {
1146 dsq->game->removePath(selectedIdx);
1147 }
1148 else
1149 {
1150 if (selectedIdx != -1)
1151 {
1152 Path *p = dsq->game->getPath(selectedIdx);
1153 if (p->nodes.size() == 1)
1154 {
1155 dsq->game->removePath(selectedIdx);
1156 selectedIdx = -1;
1157 }
1158 else
1159 p->removeNode(selectedNode);
1160 /*
1161 if (p->nodes.size() > 1)
1162 p->nodes.resize(p->nodes.size()-1);
1163 */
1164 //selectedIdx = -1;
1165 }
1166 }
1167 }
1168 }
1169
updateSaveFileEnemyPosition(Entity * ent)1170 void SceneEditor::updateSaveFileEnemyPosition(Entity *ent)
1171 {
1172 XMLElement *exml = dsq->game->saveFile->FirstChildElement("Enemy");
1173 while (exml)
1174 {
1175 int x = atoi(exml->Attribute("x"));
1176 int y = atoi(exml->Attribute("y"));
1177 if (ent->startPos.x == x && ent->startPos.y == y)
1178 {
1179 ent->startPos = Vector(int(ent->position.x), int(ent->position.y));
1180 exml->SetAttribute("x", int(ent->startPos.x));
1181 exml->SetAttribute("y", int(ent->startPos.y));
1182 return;
1183 }
1184 exml = exml->NextSiblingElement("Enemy");
1185 }
1186 exml = dsq->game->saveFile->FirstChildElement("Entity");
1187 while (exml)
1188 {
1189 int x = atoi(exml->Attribute("x"));
1190 int y = atoi(exml->Attribute("y"));
1191 if (ent->startPos.x == x && ent->startPos.y == y)
1192 {
1193 ent->startPos = Vector(int(ent->position.x), int(ent->position.y));
1194 exml->SetAttribute("x", int(ent->startPos.x));
1195 exml->SetAttribute("y", int(ent->startPos.y));
1196 return;
1197 }
1198 exml = exml->NextSiblingElement("Entity");
1199 }
1200
1201 }
1202
checkForRebuild()1203 void SceneEditor::checkForRebuild()
1204 {
1205 if (editType == ET_ELEMENTS && state != ES_SELECTING && !selectedElements.empty())
1206 {
1207 bool rebuild = false;
1208 for (int i = 0; i < selectedElements.size(); i++)
1209 {
1210 if (selectedElements[i]->elementFlag == EF_SOLID || selectedElements[i]->elementFlag == EF_HURT)
1211 {
1212 rebuild = true;
1213 break;
1214 }
1215 }
1216 if (rebuild)
1217 {
1218 dsq->game->reconstructGrid();
1219 }
1220 }
1221 else if (editType == ET_ELEMENTS && state != ES_SELECTING && editingElement != 0 && (editingElement->elementFlag == EF_SOLID || editingElement->elementFlag == EF_HURT))
1222 {
1223 dsq->game->reconstructGrid();
1224 }
1225 }
1226
exitMoveState()1227 void SceneEditor::exitMoveState()
1228 {
1229 if (!selectedElements.empty())
1230 {
1231 for (int i = 0; i < selectedElements.size(); i++)
1232 {
1233 selectedElements[i]->position = selectedElements[i]->getWorldPosition();
1234 dummy.removeChild(selectedElements[i]);
1235 }
1236 core->removeRenderObject(&dummy, Core::DO_NOT_DESTROY_RENDER_OBJECT);
1237 }
1238 checkForRebuild();
1239 state = ES_SELECTING;
1240 }
1241
enterMoveState()1242 void SceneEditor::enterMoveState()
1243 {
1244 if (state != ES_SELECTING) return;
1245 state = ES_MOVING;
1246 if (editType == ET_ELEMENTS)
1247 {
1248 if (!selectedElements.empty())
1249 {
1250 dummy.rotation = Vector(0,0,0);
1251 cursorOffset = dsq->getGameCursorPosition();
1252 groupCenter = getSelectedElementsCenter();
1253 for (int i = 0; i < selectedElements.size(); i++)
1254 {
1255 selectedElements[i]->position -= groupCenter;
1256 dummy.addChild(selectedElements[i], PM_NONE);
1257 }
1258 core->addRenderObject(&dummy, selectedElements[0]->layer);
1259 dummy.cull = false;
1260 dummy.position = groupCenter;
1261 oldPosition = dummy.position;
1262 dummy.scale = Vector(1,1,1);
1263 }
1264 else if (editingElement)
1265 {
1266 oldPosition = editingElement->position;
1267 cursorOffset = dsq->getGameCursorPosition();
1268 }
1269 }
1270 else if (editType == ET_ENTITIES)
1271 {
1272 oldPosition = editingEntity->position;
1273 cursorOffset = editingEntity->position - dsq->getGameCursorPosition();
1274 }
1275 else if (editType == ET_PATHS)
1276 {
1277 oldPosition = dsq->game->getPath(selectedIdx)->nodes[selectedNode].position;
1278 cursorOffset = oldPosition - dsq->getGameCursorPosition();
1279 }
1280 }
1281
enterRotateState()1282 void SceneEditor::enterRotateState()
1283 {
1284 if (state != ES_SELECTING) return;
1285 if (editType == ET_ENTITIES)
1286 {
1287 state = ES_ROTATING;
1288 oldRotation = editingEntity->rotation;
1289 oldPosition = editingEntity->position;
1290 cursorOffset = dsq->getGameCursorPosition();
1291 }
1292 if (editType == ET_ELEMENTS)
1293 {
1294 if (!selectedElements.empty())
1295 {
1296 state = ES_ROTATING;
1297 dummy.rotation = Vector(0,0,0);
1298 oldRotation = dummy.rotation;
1299 cursorOffset = dsq->getGameCursorPosition();
1300 groupCenter = getSelectedElementsCenter();
1301 for (int i = 0; i < selectedElements.size(); i++)
1302 {
1303 selectedElements[i]->position -= groupCenter;
1304 dummy.addChild(selectedElements[i], PM_NONE);
1305 }
1306 core->addRenderObject(&dummy, selectedElements[0]->layer);
1307 dummy.cull = false;
1308 dummy.position = groupCenter;
1309 dummy.scale = Vector(1,1,1);
1310 }
1311 else if (editingElement)
1312 {
1313 state = ES_ROTATING;
1314 oldRotation = editingElement->rotation;
1315 cursorOffset = dsq->getGameCursorPosition();
1316 }
1317 }
1318 }
1319
enterScaleState()1320 void SceneEditor::enterScaleState()
1321 {
1322 if (state != ES_SELECTING) return;
1323 if (editType == ET_ELEMENTS)
1324 {
1325 if (!selectedElements.empty())
1326 {
1327 state = ES_SCALING;
1328 dummy.rotation = Vector(0,0,0);
1329 dummy.scale = Vector(1,1,1);
1330 oldScale = dummy.scale;
1331 oldRepeatScale = Vector(1, 1); // not handled for multi-selection
1332 cursorOffset = dsq->getGameCursorPosition();
1333 groupCenter = getSelectedElementsCenter();
1334 for (int i = 0; i < selectedElements.size(); i++)
1335 {
1336 selectedElements[i]->position -= groupCenter;
1337 dummy.addChild(selectedElements[i], PM_NONE);
1338 }
1339 core->addRenderObject(&dummy, selectedElements[0]->layer);
1340 dummy.cull = false;
1341 dummy.position = groupCenter;
1342 }
1343 else if (editingElement)
1344 {
1345 oldPosition = editingElement->position;
1346 state = ES_SCALING;
1347 oldScale = editingElement->scale;
1348 oldRepeatScale = editingElement->repeatToFillScale;
1349 cursorOffset = dsq->getGameCursorPosition();
1350 }
1351 }
1352 else if (editType == ET_PATHS)
1353 {
1354 state = ES_SCALING;
1355 oldScale = Vector(editingPath->rect.x2-editingPath->rect.x1,
1356 editingPath->rect.y2-editingPath->rect.y1);
1357 cursorOffset = dsq->getGameCursorPosition();
1358 }
1359 }
1360
updateEntitySaveData(Entity * editingEntity)1361 void SceneEditor::updateEntitySaveData(Entity *editingEntity)
1362 {
1363 if (editingEntity)
1364 {
1365 /*
1366 std::ostringstream os;
1367 os << "oldPos (" << oldPosition.x << ", " << oldPosition.y << ")";
1368 debugLog(os.str());
1369 */
1370 EntitySaveData *d = dsq->game->getEntitySaveDataForEntity(editingEntity, oldPosition);
1371 if (d)
1372 {
1373 std::ostringstream os;
1374 os << "idx1: " << d->idx << " ";
1375 os << "idx2: " << editingEntity->entityTypeIdx << " ";
1376 os << "name: " << editingEntity->name;
1377 //os << "state: " << editingEntity->getState();
1378 debugLog(os.str());
1379 //debugLog("changing entity save data");
1380 d->x = editingEntity->position.x;
1381 d->y = editingEntity->position.y;
1382 editingEntity->startPos = Vector(d->x, d->y);
1383 /*
1384 std::ostringstream os2;
1385 os2 << "setting savedata rot to: " << d->rot;
1386 debugLog(os2.str());
1387 */
1388 d->rot = editingEntity->rotation.z;
1389 }
1390 else
1391 {
1392 //debugLog("didn't get entity save data");
1393 }
1394 }
1395 }
1396
mouseButtonLeftUp()1397 void SceneEditor::mouseButtonLeftUp()
1398 {
1399 if (multiSelecting || core->mouse.buttons.right) return;
1400
1401 if (editType == ET_ENTITIES)
1402 {
1403 updateEntitySaveData(editingEntity);
1404 }
1405 if (state == ES_MOVING)
1406 {
1407 exitMoveState();
1408 }
1409 state = ES_SELECTING;
1410 }
1411
mouseButtonRightUp()1412 void SceneEditor::mouseButtonRightUp()
1413 {
1414 if (multiSelecting || core->mouse.buttons.left) return;
1415
1416 if (editType == ET_ENTITIES)
1417 updateEntitySaveData(editingEntity);
1418 if (editType == ET_ELEMENTS)
1419 {
1420
1421 if (state == ES_ROTATING)
1422 {
1423 if (!selectedElements.empty())
1424 {
1425 for (int i = 0; i < selectedElements.size(); i++)
1426 {
1427 selectedElements[i]->position = selectedElements[i]->getWorldPosition();
1428 selectedElements[i]->rotation = selectedElements[i]->getAbsoluteRotation();
1429 dummy.removeChild(selectedElements[i]);
1430 }
1431 core->removeRenderObject(&dummy, Core::DO_NOT_DESTROY_RENDER_OBJECT);
1432 }
1433 }
1434 else if (state == ES_SCALING)
1435 {
1436
1437 if (!selectedElements.empty())
1438 {
1439 for (int i = 0; i < selectedElements.size(); i++)
1440 {
1441 selectedElements[i]->position = selectedElements[i]->getWorldPosition();
1442 selectedElements[i]->scale = selectedElements[i]->scale * dummy.scale;
1443 selectedElements[i]->rotation = selectedElements[i]->getAbsoluteRotation();
1444 dummy.removeChild(selectedElements[i]);
1445 }
1446 core->removeRenderObject(&dummy, Core::DO_NOT_DESTROY_RENDER_OBJECT);
1447 }
1448 else if (editingElement)
1449 {
1450 Vector add = editingElement->beforeScaleOffset;
1451 Vector newScale = editingElement->scale;
1452 editingElement->beforeScaleOffset = Vector(0,0,0);
1453 editingElement->scale = Vector(1,1,1);
1454 editingElement->position = editingElement->getWorldCollidePosition(add);
1455 editingElement->scale = newScale;
1456 }
1457 }
1458 checkForRebuild();
1459 }
1460 state = ES_SELECTING;
1461 //dsq->game->reconstructGrid();
1462 }
1463
1464
toggleElementSolid()1465 void SceneEditor::toggleElementSolid()
1466 {
1467 if (editingElement)
1468 {
1469 switch(editingElement->elementFlag)
1470 {
1471 default:
1472 case EF_NONE:
1473 {
1474 std::ostringstream os;
1475 os << "elementFlag: " << editingElement->elementFlag;
1476 debugLog(os.str());
1477 debugLog("Solid");
1478 editingElement->elementFlag = EF_SOLID;
1479 }
1480 break;
1481 case EF_SOLID:
1482 debugLog("Solid2");
1483 editingElement->elementFlag = EF_SOLID2;
1484 break;
1485 case EF_SOLID2:
1486 debugLog("Solid3");
1487 editingElement->elementFlag = EF_SOLID3;
1488 break;
1489 case EF_SOLID3:
1490 debugLog("None");
1491 editingElement->elementFlag = EF_NONE;
1492 break;
1493 }
1494 dsq->game->reconstructGrid(true);
1495 }
1496 }
1497
toggleElementHurt()1498 void SceneEditor::toggleElementHurt()
1499 {
1500 if (editingElement)
1501 {
1502 if (editingElement->elementFlag == EF_HURT)
1503 editingElement->elementFlag = EF_NONE;
1504 else
1505 editingElement->elementFlag = EF_HURT;
1506 dsq->game->reconstructGrid(true);
1507 }
1508 }
1509
toggleElementRepeat()1510 void SceneEditor::toggleElementRepeat()
1511 {
1512 if (editingElement)
1513 {
1514 editingElement->repeatTextureToFill(!editingElement->isRepeatingTextureToFill());
1515 }
1516 }
1517
mouseButtonLeft()1518 void SceneEditor::mouseButtonLeft()
1519 {
1520 if (multiSelecting || state != ES_SELECTING || !dummy.children.empty() || core->mouse.buttons.right) return;
1521 if (editType == ET_ELEMENTS)
1522 {
1523 if (selectedElements.empty() || editingElement)
1524 {
1525 if (core->getShiftState())
1526 {
1527 cloneSelectedElement();
1528 }
1529 else
1530 {
1531 enterMoveState();
1532 }
1533 }
1534 }
1535 else if (editType == ET_ENTITIES)
1536 {
1537 if (editingEntity)
1538 {
1539 if (core->getShiftState())
1540 {
1541 cloneSelectedElement();
1542 }
1543 else
1544 {
1545 enterMoveState();
1546 }
1547 }
1548 }
1549 else if (editType == ET_PATHS)
1550 {
1551 if (selectedIdx != -1)
1552 {
1553 Path *p = getSelectedPath();
1554 editingPath = p;
1555 if (p && selectedNode >= 0 && selectedNode < p->nodes.size())
1556 {
1557 if (core->getShiftState())
1558 {
1559 cloneSelectedElement();
1560 }
1561 else
1562 {
1563 enterMoveState();
1564 }
1565 }
1566 }
1567 }
1568 }
1569
mouseButtonRight()1570 void SceneEditor::mouseButtonRight()
1571 {
1572 if (multiSelecting || state != ES_SELECTING || !dummy.children.empty() || core->mouse.buttons.left) return;
1573 if (editType == ET_ENTITIES)
1574 {
1575 if (editingEntity)
1576 {
1577 if (core->getShiftState())
1578 enterScaleState();
1579 else
1580 enterRotateState();
1581 }
1582 }
1583 if (editType == ET_PATHS)
1584 {
1585 if (selectedIdx != -1)
1586 {
1587 debugLog("path scaling HERE!");
1588 Path *p = dsq->game->getPath(selectedIdx);
1589 editingPath = p;
1590 if (core->getShiftState())
1591 {
1592 enterScaleState();
1593 }
1594 }
1595 }
1596 if (editType == ET_ELEMENTS)
1597 {
1598 if (selectedElements.empty() || editingElement)
1599 {
1600 if (core->getShiftState())
1601 enterScaleState();
1602 else
1603 enterRotateState();
1604 }
1605 }
1606 if (editType == ET_ELEMENTS && state == ES_MOVING)
1607 {
1608 }
1609 }
1610
startMoveEntity()1611 void SceneEditor::startMoveEntity()
1612 {
1613 movingEntity = dsq->game->getEntityAtCursor();
1614 }
1615
endMoveEntity()1616 void SceneEditor::endMoveEntity()
1617 {
1618 if (movingEntity)
1619 {
1620 updateSaveFileEnemyPosition(movingEntity);
1621 movingEntity = 0;
1622 }
1623 }
1624
up()1625 void SceneEditor::up()
1626 {
1627 if (editType == ET_ELEMENTS && state == ES_SELECTING)
1628 {
1629 if (editingElement || !selectedElements.empty())
1630 {
1631 enterMoveState();
1632 updateSelectedElementPosition(Vector(0,-1));
1633 exitMoveState();
1634 }
1635 }
1636 }
1637
down()1638 void SceneEditor::down()
1639 {
1640 if (editType == ET_ELEMENTS && state == ES_SELECTING)
1641 {
1642 if (editingElement || !selectedElements.empty())
1643 {
1644 enterMoveState();
1645 updateSelectedElementPosition(Vector(0,1));
1646 exitMoveState();
1647 }
1648 }
1649 }
1650
1651 class Row
1652 {
1653 public:
Row()1654 Row()
1655 {
1656 x1=x2=y=0;
1657 rows=1;
1658 }
1659 int x1, x2, y;
1660 int rows;
1661 };
1662
getGrassPixel(pngRawInfo * png,int x,int y)1663 bool getGrassPixel(pngRawInfo *png, int x, int y)
1664 {
1665 if (x >= png->Width || y >= png->Height || x < 0 || y < 0) return false;
1666
1667 //int c = ((x*png->Width)*3)+y*3;
1668 int c = (y*png->Width)*png->Components + x*png->Components;
1669 if (png->Data[c] == 128 &&
1670 png->Data[c+1] == 255 &&
1671 png->Data[c+2] == 128)
1672 {
1673 return true;
1674 }
1675 return false;
1676 }
1677
regenLevel()1678 void SceneEditor::regenLevel()
1679 {
1680 generateLevel();
1681 skinLevel();
1682 }
1683
skinLevel()1684 void SceneEditor::skinLevel()
1685 {
1686 if (skinMinX == -1)
1687 {
1688 dsq->screenMessage("Cannot skin without generated level.");
1689 return;
1690 }
1691 pngRawInfo rawinfo;
1692 std::string file = getMapTemplateFilename();
1693 bool success = pngLoadRaw(file.c_str(), &rawinfo);
1694 if (success)
1695 {
1696 skinLevel(&rawinfo, skinMinX, skinMinY, skinMaxX, skinMaxY);
1697 if (rawinfo.Data != NULL)
1698 free(rawinfo.Data);
1699 }
1700 }
1701
skinLevel(pngRawInfo * png,int minX,int minY,int maxX,int maxY)1702 void SceneEditor::skinLevel(pngRawInfo *png, int minX, int minY, int maxX, int maxY)
1703 {
1704 std::vector<Element*> deleteElements;
1705 int i = 0;
1706 for (i = 0; i < dsq->getNumElements(); i++)
1707 {
1708 Element *e = dsq->getElement(i);
1709 if (e->bgLayer==4 && e->templateIdx >= 1 && e->templateIdx <= 4)
1710 {
1711 e->safeKill();
1712 deleteElements.push_back(e);
1713 }
1714 }
1715 for (i = 0; i < deleteElements.size(); i++)
1716 {
1717 dsq->removeElement(deleteElements[i]);
1718 }
1719 deleteElements.clear();
1720
1721 int idx=1;
1722 int idxCount = 0;
1723 for (int x = minX; x < maxX-2; x++)
1724 {
1725 for (int y = minY; y < maxY; y++)
1726 {
1727 Vector offset, pOffset;
1728 Vector wallNormal;
1729 float rot=0;
1730 bool addTile = false;
1731 TileVector t(x,y);
1732 if (dsq->game->isObstructed(t, OT_MASK_BLACK)
1733 && (
1734 !dsq->game->isObstructed(TileVector(x+1,y), OT_MASK_BLACK) ||
1735 !dsq->game->isObstructed(TileVector(x-1,y), OT_MASK_BLACK) ||
1736 !dsq->game->isObstructed(TileVector(x,y-1), OT_MASK_BLACK) ||
1737 !dsq->game->isObstructed(TileVector(x,y+1), OT_MASK_BLACK)
1738 )
1739 )
1740 {
1741 // do color check
1742 /*
1743 int ci = x+(y*png->Height);
1744 if (png->data[ci] < pixelColor.x &&
1745 png->data[ci+1] < pixelColor.y &&
1746 png->data[ci+2] < pixelColor.z)
1747 {
1748 */
1749 float dist=0;
1750 wallNormal = dsq->game->getWallNormal(t.worldVector(), 5, &dist, OT_MASK_BLACK);
1751 offset = wallNormal*(-TILE_SIZE*0.6f);
1752 MathFunctions::calculateAngleBetweenVectorsInDegrees(Vector(0,0,0), wallNormal, rot);
1753 rot = 180-(360-rot);
1754 addTile = true;
1755 //}
1756 }
1757
1758 if (addTile)
1759 {
1760 TileVector t(x,y);
1761 Vector p = t.worldVector();
1762 Quad q;
1763 q.rotation.z = rot;
1764 p += Vector(TILE_SIZE/2, TILE_SIZE/2,0);
1765 offset.z = 0;
1766
1767 bool skip = false;
1768 for (int i = 0; i < dsq->getNumElements(); i++)
1769 {
1770 Element *e = dsq->getElement(i);
1771 if (e->templateIdx <= 4 && e->templateIdx >= 1)
1772 {
1773 if ((p - e->position).getSquaredLength2D() < sqr(50))
1774 {
1775 skip = true;
1776 break;
1777 }
1778 }
1779 }
1780
1781 if (!skip)
1782 {
1783 std::vector<int> cantUse;
1784 cantUse.resize(4);
1785 int i = 0;
1786 for (i = 0; i < dsq->getNumElements(); i++)
1787 {
1788 Element *e = dsq->getElement(i);
1789 if (e->templateIdx <= 4 && e->templateIdx >= 1)
1790 {
1791 if ((p - e->position).getSquaredLength2D() < sqr(120))//sqr(60*3+10)) // 120
1792 {
1793 cantUse[e->templateIdx-1]++;
1794 }
1795 }
1796 }
1797 int useIdx = rand()%cantUse.size()+1;
1798 for (i = 0; i < cantUse.size(); i++)
1799 {
1800 int check = i + idxCount;
1801 if (check >= cantUse.size())
1802 check -= cantUse.size();
1803 if (cantUse[check]<=0)
1804 {
1805 useIdx = check+1;
1806 }
1807 }
1808 idxCount = rand()%cantUse.size();
1809
1810 Element *e = dsq->game->createElement(useIdx, p, 4, &q);
1811 e->offset = offset;
1812
1813
1814 /*
1815 bool addGrass = false;
1816 int search = 2;
1817 for (int dx = -search; dx < search; dx++)
1818 {
1819 for (int dy = -search; dy < search; dy++)
1820 {
1821 if (getGrassPixel(png, x+dx, y+dy))
1822 {
1823 //std::ostringstream os;
1824 //os << "found grass pixel at (" << x+dx << ", " << y+dy << ")";
1825 //debugLog(os.str());
1826 //errorLog ("add grass");
1827 addGrass = true;
1828 break;
1829 }
1830 }
1831 }
1832
1833 if (addGrass)
1834 {
1835 //Vector detailPos = p + wallNormal*48;
1836 Element *grassE = dsq->game->createElement(5, p, 0, &q);
1837 //dsq->game->createElement(5, detailPos, 6, &q);
1838 //grassE->offset = offset;
1839 }
1840 */
1841
1842
1843 /*
1844 float sz = ((rand()%1000)/4000.0f);
1845 e->scale = Vector(1+sz, 1+sz, 1);
1846 */
1847
1848
1849 idx++;
1850 if(idx > 4)
1851 idx = 1;
1852 }
1853 }
1854 }
1855 for (int i = 0; i < dsq->getNumElements(); i++)
1856 {
1857 Element *e = dsq->getElement(i);
1858 if (e->bgLayer == 4 && e->templateIdx >= 1 && e->templateIdx <= 4)
1859 {
1860 e->position += e->offset;
1861 e->offset = Vector(0,0,0);
1862 }
1863 }
1864 }
1865 }
1866
fixEntityIDs()1867 void SceneEditor::fixEntityIDs()
1868 {
1869 FOR_ENTITIES(i)
1870 {
1871 Entity *e = *i;
1872 e->assignUniqueID();
1873 }
1874 }
1875
generateLevel()1876 void SceneEditor::generateLevel()
1877 {
1878 //pngSetStandardOrientation(0);
1879 std::string file=getMapTemplateFilename();
1880 //pngInfo info;
1881 //PNG_ALPHA
1882
1883 //errorLog("generate level");
1884 // Y R G B P
1885 int maxX=0, maxY=0;
1886 const int YELLOW=0, RED=1, GREEN=2, BLUE=3, PURPLE=4, ORANGE=5, BROWN=6, MAX=7;
1887 int firstColorX[MAX], firstColorY[MAX];
1888 int lastColorX[MAX], lastColorY[MAX];
1889 Vector colorVects[MAX];
1890 colorVects[YELLOW] = Vector(1,1,0);
1891 colorVects[RED] = Vector(1,0,0);
1892 colorVects[GREEN] = Vector(0,1,0);
1893 colorVects[BLUE] = Vector(0,0,1);
1894 colorVects[PURPLE] = Vector(1,0,1);
1895 colorVects[ORANGE] = Vector(1,0.5,0);
1896 colorVects[BROWN] = Vector(0.5,0.25,0);
1897 for (int i = 0; i < MAX; i++)
1898 {
1899 firstColorX[i] = firstColorY[i] = -1;
1900 lastColorX[i] = lastColorY[i] = -1;
1901 }
1902 pngRawInfo rawinfo;
1903 bool success = pngLoadRaw(file.c_str(), &rawinfo);
1904 if (success)
1905 {
1906 //dsq->elements.clear();
1907 std::vector<Row> rows;
1908 std::vector<Vector> positions;
1909 const int maxRowCount = 9999;//9999;//9999;
1910 int rowCount = 0;
1911 if (rawinfo.Components < 3)
1912 {
1913 errorLog("png color depth ( < 3 bit) not supported by generate level");
1914 }
1915 int scale = TILE_SIZE;
1916 int c = 0;
1917 //for (int y = rawinfo.Height-1; y >= 0; y--)
1918 for (int y = 0; y < rawinfo.Height; y++)
1919 {
1920 Vector lastElement;
1921 lastElement = Vector(0,0,0);
1922 bool hasLastElement = false;
1923 Vector *firstRowElement = 0;
1924 Row row;
1925 rowCount = 0;
1926 positions.clear();
1927 for (int x = 0; x < rawinfo.Width; x++)
1928 {
1929 Vector *e = 0;
1930 if
1931 (
1932 (
1933 rawinfo.Data[c] < 48 &&
1934 rawinfo.Data[c+1] < 48 &&
1935 rawinfo.Data[c+2] < 48
1936 )
1937 ||
1938 (
1939 rawinfo.Data[c] == 128
1940 &&
1941 rawinfo.Data[c+1] == 255
1942 &&
1943 rawinfo.Data[c+2] == 128
1944 )
1945 )
1946 {
1947 if (x > maxX)
1948 maxX = x;
1949 if (y > maxY)
1950 maxY = y;
1951 positions.push_back(Vector(x*scale+(scale/2.0f),y*scale+(scale/2.0f)));
1952 e = &positions[positions.size()-1];
1953 }
1954 if (rawinfo.Data[c] < 32 &&
1955 rawinfo.Data[c+1] > 200 &&
1956 rawinfo.Data[c+2] > 200)
1957 {
1958 dsq->game->saveWaterLevel = dsq->game->waterLevel.x = y*TILE_SIZE;
1959 }
1960 for (int i = 0; i < MAX; i++)
1961 {
1962 //if (checkWarpPixel(rawinfo.Data, c, colorVects[i]))
1963 bool p1, p2, p3;
1964 p1=p2=p3=false;
1965 int diff;
1966 diff = fabsf((colorVects[i].x*255) - rawinfo.Data[c]);
1967 p1 = (diff < 5);
1968 diff = fabsf((colorVects[i].y*255) - rawinfo.Data[c+1]);
1969 p2 = (diff < 5);
1970 diff = fabsf((colorVects[i].z*255) - rawinfo.Data[c+2]);
1971 p3 = (diff < 5);
1972 /*
1973 p1 = (colorVects[i].x == 1 && rawinfo.Data[c] > 200);
1974 if (!p1)
1975 {
1976 p1 = (colorVects[i].x == 0 && rawinfo.Data[c] < 32);
1977 }
1978 p2 = (colorVects[i].y == 1 && rawinfo.Data[c+1] > 200);
1979 if (!p2)
1980 {
1981 p2 = (colorVects[i].y == 0 && rawinfo.Data[c+1] < 32);
1982 if (!p2)
1983 {
1984 p2 = (colorVects[i].y == 0.5f && rawinfo.Data[c+1] > 96 && rawinfo.Data[c+1] < 164);
1985 }
1986 }
1987 p3 = (colorVects[i].z == 1 && rawinfo.Data[c+2] > 200);
1988 if (!p3)
1989 p3 = (colorVects[i].z == 0 && rawinfo.Data[c+2] < 32);
1990 */
1991 if (p1 && p2 && p3)
1992 {
1993 lastColorX[i] = x;
1994 lastColorY[i] = y;
1995 if (firstColorX[i] == -1)
1996 {
1997 firstColorX[i] = x;
1998 firstColorY[i] = y;
1999 }
2000 }
2001 }
2002 /*
2003 else if (checkPixel(1, 0, 0))
2004 {
2005 lastColorX[RED] = x;
2006 lastColorY[RED] = y;
2007 if (firstColorX[RED] == -1)
2008 {
2009 firstColorX[RED] = x;
2010 firstColorY[RED] = y;
2011 }
2012 }
2013 */
2014 /*
2015 else if ( rawinfo.Data[c] > 200 &&
2016 rawinfo.Data[c+1] < 32 &&
2017 rawinfo.Data[c+2] < 32)
2018 {
2019
2020 }
2021 else if (rawinfo.
2022 */
2023
2024 c += rawinfo.Components;
2025 if ((e==0 && firstRowElement) || (firstRowElement && rowCount >= maxRowCount && hasLastElement)
2026 || (firstRowElement && x == rawinfo.Width-1))
2027 {
2028 /*
2029 if (x == rawinfo.Width-1)
2030 row.x2 = rawinfo.Width-1;
2031 else
2032 {
2033 */
2034 // HACK: it crashes here:
2035 // because lastElement is garbage data
2036 // fixed!
2037 if (hasLastElement)
2038 row.x2 = lastElement.x;
2039 //}
2040
2041 hasLastElement = false;
2042 firstRowElement = 0;
2043
2044 bool add = true;
2045 /*
2046 for (int i = 0; i < rows.size(); i++)
2047 {
2048 if (rows[i].x1 == row.x1 && rows[i].x2 == row.x2)
2049 {
2050 if (abs(rows[i].y - row.y) <= TILE_SIZE+1)
2051 {
2052 rows[i].rows++;
2053 add = false;
2054 break;
2055 }
2056 }
2057 }
2058 */
2059 if (add)
2060 rows.push_back(row);
2061 }
2062 if (!firstRowElement && e)
2063 {
2064 row.x1 = e->x;
2065 row.y = e->y;
2066 firstRowElement = e;
2067 rowCount = 1;
2068 }
2069 if (e)
2070 {
2071 lastElement = *e;
2072 hasLastElement = true;
2073 }
2074 else
2075 hasLastElement = false;
2076 rowCount ++ ;
2077 }
2078 }
2079
2080 dsq->game->clearObsRows();
2081 int i = 0;
2082 for (i = 0; i < rows.size(); i++)
2083 {
2084 int w = rows[i].x2 - rows[i].x1;
2085 //int h = scale * rows[i].rows;
2086 int useY = rows[i].y;
2087 if (rows[i].rows > 1)
2088 {
2089 useY += (rows[i].rows-1)*TILE_SIZE/2;
2090 }
2091
2092 dsq->game->addObsRow(rows[i].x1/TILE_SIZE, rows[i].y/TILE_SIZE, w/TILE_SIZE);
2093 }
2094
2095 dsq->game->reconstructGrid(true);
2096
2097 // create warp areas
2098 dsq->game->warpAreas.clear();
2099 for (i = 0; i < MAX; i++)
2100 {
2101 if (firstColorX[i] != -1)
2102 {
2103 WarpArea warpArea;
2104 int w = lastColorX[i] - firstColorX[i];
2105 int h = lastColorY[i] - firstColorY[i];
2106
2107 warpArea.w = w*TILE_SIZE;
2108 warpArea.h = h*TILE_SIZE;
2109 warpArea.position = Vector(firstColorX[i]*TILE_SIZE + warpArea.w/2, firstColorY[i]*TILE_SIZE + warpArea.h/2);
2110 warpArea.w += TILE_SIZE*4;
2111 warpArea.h += TILE_SIZE*4;
2112
2113 switch (i)
2114 {
2115 case RED: warpArea.warpAreaType = "Red"; break;
2116 case BLUE: warpArea.warpAreaType = "Blue"; break;
2117 case GREEN: warpArea.warpAreaType = "Green"; break;
2118 case YELLOW: warpArea.warpAreaType = "Yellow"; break;
2119 case PURPLE: warpArea.warpAreaType = "Purple"; break;
2120 case ORANGE: warpArea.warpAreaType = "Orange"; break;
2121 case BROWN: warpArea.warpAreaType = "Brown"; break;
2122 }
2123
2124 dsq->game->setWarpAreaSceneName(warpArea);
2125
2126 warpArea.generated = true;
2127
2128 std::ostringstream os;
2129 os << "WarpArea (" << warpArea.w << ", " << warpArea.h << ") - pos(" << warpArea.position.x << ", " <<
2130 warpArea.position.y << ")";
2131 debugLog(os.str());
2132
2133 dsq->game->warpAreas.push_back(warpArea);
2134 }
2135 }
2136
2137 maxX--;
2138 maxY--;
2139 this->skinMinX = 4;
2140 this->skinMinY = 4;
2141 this->skinMaxX = maxX;
2142 this->skinMaxY = maxY;
2143 //skinLevel(&rawinfo, 4, 4, maxX, maxY);
2144 if (rawinfo.Data != NULL)
2145 free(rawinfo.Data);
2146 }
2147 else
2148 {
2149 debugLog("generateLevel: Failed to load mapTemplate");
2150 }
2151 // pngSetStandardOrientation(1);
2152 }
2153
removeEntity()2154 void SceneEditor::removeEntity()
2155 {
2156 debugLog("remove entity at cursor");
2157 dsq->game->removeEntityAtCursor();
2158 }
2159
placeAvatar()2160 void SceneEditor::placeAvatar()
2161 {
2162 dsq->game->avatar->position = dsq->getGameCursorPosition();
2163 dsq->game->action(ACTION_PLACE_AVATAR, 0);
2164 }
2165
scaleElementUp()2166 void SceneEditor::scaleElementUp()
2167 {
2168 placer->scale += Vector(0.25, 0.25,0);
2169 }
2170
scaleElementDown()2171 void SceneEditor::scaleElementDown()
2172 {
2173 placer->scale -= Vector(0.25, 0.25,0);
2174 }
2175
scaleElement1()2176 void SceneEditor::scaleElement1()
2177 {
2178 placer->scale = Vector(1,1,1);
2179 }
2180
flipElementHorz()2181 void SceneEditor::flipElementHorz()
2182 {
2183 if (editType != ET_ELEMENTS)
2184 return;
2185
2186 if (editingElement)
2187 editingElement->flipHorizontal();
2188 else
2189 this->placer->flipHorizontal();
2190 }
2191
flipElementVert()2192 void SceneEditor::flipElementVert()
2193 {
2194 if (editType != ET_ELEMENTS)
2195 return;
2196
2197 if (editingElement)
2198 editingElement->flipVertical();
2199 else
2200 this->placer->flipVertical();
2201 }
2202
moveElementToLayer(Element * e,int bgLayer)2203 void SceneEditor::moveElementToLayer(Element *e, int bgLayer)
2204 {
2205 if (!selectedElements.empty())
2206 {
2207 for (int i = 0; i < selectedElements.size(); i++)
2208 {
2209 Element *e = selectedElements[i];
2210 core->removeRenderObject(e, Core::DO_NOT_DESTROY_RENDER_OBJECT);
2211 dsq->removeElement(e);
2212 e->bgLayer = bgLayer;
2213 dsq->addElement(e);
2214 core->addRenderObject(e, LR_ELEMENTS1+bgLayer);
2215 }
2216 }
2217 else if (e)
2218 {
2219 core->removeRenderObject(e, Core::DO_NOT_DESTROY_RENDER_OBJECT);
2220 dsq->removeElement(e);
2221 e->bgLayer = bgLayer;
2222 dsq->addElement(e);
2223 core->addRenderObject(e, LR_ELEMENTS1+bgLayer);
2224 }
2225 }
2226
updateMultiSelect()2227 void SceneEditor::updateMultiSelect()
2228 {
2229 if (!multiSelecting) return;
2230 Vector secondPoint = dsq->getGameCursorPosition();
2231 if (!(multiSelectPoint-secondPoint).isLength2DIn(64))
2232 {
2233 Vector p1, p2;
2234
2235 if (secondPoint.x < multiSelectPoint.x)
2236 {
2237 p1.x = secondPoint.x;
2238 p2.x = multiSelectPoint.x;
2239 }
2240 else
2241 {
2242 p1.x = multiSelectPoint.x;
2243 p2.x = secondPoint.x;
2244 }
2245
2246 if (secondPoint.y < multiSelectPoint.y)
2247 {
2248 p1.y = secondPoint.y;
2249 p2.y = multiSelectPoint.y;
2250 }
2251 else
2252 {
2253 p1.y = multiSelectPoint.y;
2254 p2.y = secondPoint.y;
2255 }
2256
2257 selectedElements.clear();
2258
2259 for (int i = 0; i < dsq->getNumElements(); i++)
2260 {
2261 Element *e = dsq->getElement(i);
2262 if (e->bgLayer == bgLayer && e->position.x >= p1.x && e->position.y >= p1.y && e->position.x <= p2.x && e->position.y <= p2.y)
2263 {
2264 selectedElements.push_back(e);
2265 }
2266 }
2267 }
2268 }
2269
action(int id,int state)2270 void SceneEditor::action(int id, int state)
2271 {
2272 if (core->getCtrlState() && editingElement)
2273 {
2274 if (id == ACTION_BGLAYEREND)
2275 {
2276 editingElement->setElementEffectByIndex(-1);
2277 }
2278 else if (id >= ACTION_BGLAYER1 && id < ACTION_BGLAYER10)
2279 {
2280 editingElement->setElementEffectByIndex(id - ACTION_BGLAYER1);
2281 }
2282 }
2283 else if (editType == ET_ELEMENTS && state && id >= ACTION_BGLAYER1 && id < ACTION_BGLAYEREND)
2284 {
2285 int newLayer = id - ACTION_BGLAYER1;
2286
2287 updateText();
2288
2289 if (core->getAltState())
2290 {
2291 dsq->game->setElementLayerVisible(newLayer, !dsq->game->isElementLayerVisible(newLayer));
2292 return; // do not switch to the layer that was just hidden
2293 }
2294 else if (core->getShiftState() && (editingElement || !selectedElements.empty()))
2295 {
2296 moveElementToLayer(editingElement, newLayer);
2297 }
2298 else
2299 {
2300 selectedElements.clear();
2301 }
2302
2303 this->bgLayer = newLayer;
2304
2305 }
2306 /*
2307 Vector multiSelectPoint, secondMultiSelectPoint;
2308 */
2309 if (id == ACTION_MULTISELECT && this->state == ES_SELECTING)
2310 {
2311 if (state)
2312 {
2313 if (!multiSelecting)
2314 selectedElements.clear();
2315 multiSelecting = true;
2316 multiSelectPoint = dsq->getGameCursorPosition();
2317 }
2318 else
2319 {
2320 multiSelecting = false;
2321 }
2322 }
2323 }
2324
rotateElement()2325 void SceneEditor::rotateElement()
2326 {
2327 placer->rotation += Vector(0, 0, 45);
2328 if (placer->rotation.z > 360)
2329 placer->rotation.z -= 360;
2330 }
2331
rotateElement2()2332 void SceneEditor::rotateElement2()
2333 {
2334 placer->rotation -= Vector(0, 0, 45);
2335 if (placer->rotation.z < 0)
2336 placer->rotation.z += 360;
2337 }
2338
loadSceneByName()2339 void SceneEditor::loadSceneByName()
2340 {
2341 std::string s = dsq->getUserInputString("Enter Name of Map to Load");
2342 if (!s.empty())
2343 dsq->game->transitionToScene(s);
2344 }
2345
reloadScene()2346 void SceneEditor::reloadScene()
2347 {
2348 debugLog("reloadScene");
2349 dsq->game->positionToAvatar = dsq->game->avatar->position;
2350 dsq->game->transitionToScene(dsq->game->sceneName);
2351 }
2352
2353
loadScene()2354 void SceneEditor::loadScene()
2355 {
2356 if (core->getShiftState())
2357 {
2358 loadSceneByName();
2359 }
2360 else
2361 {
2362 reloadScene();
2363 }
2364
2365 // HACK: reload stuff when (re-) loading a map this way
2366 particleManager->loadParticleBank(dsq->particleBank1, dsq->particleBank2);
2367 Shot::loadShotBank(dsq->shotBank1, dsq->shotBank2);
2368 dsq->game->loadEntityTypeList();
2369 dsq->loadElementEffects();
2370 dsq->continuity.loadSongBank();
2371 dsq->continuity.stringBank.load();
2372 }
2373
saveScene()2374 void SceneEditor::saveScene()
2375 {
2376 if(dsq->game->saveScene(dsq->game->sceneName))
2377 dsq->screenMessage(dsq->game->sceneName + " Saved!");
2378 else
2379 dsq->screenMessage(dsq->game->sceneName + " FAILED to save!");
2380 }
2381
deleteSelectedElement()2382 void SceneEditor::deleteSelectedElement()
2383 {
2384 deleteElement(selectedIdx);
2385 selectedIdx = -1;
2386 }
2387
deleteElement(int selectedIdx)2388 void SceneEditor::deleteElement(int selectedIdx)
2389 {
2390 if (selectedIdx == -1) return;
2391 Element *e = dsq->getElement(selectedIdx);
2392 e->setLife(0.5);
2393 e->setDecayRate(1);
2394 e->fadeAlphaWithLife = true;
2395 dsq->removeElement(selectedIdx);
2396 dsq->game->reconstructGrid();
2397 }
2398
2399 Quad *se_grad = 0;
2400
destroyEntityPage()2401 void destroyEntityPage()
2402 {
2403 if (se_label)
2404 {
2405 se_label->safeKill();
2406 se_label = 0;
2407 }
2408 if (se_grad)
2409 {
2410 //se_grad->safeKill();
2411 se_grad->setLife(1);
2412 se_grad->setDecayRate(10);
2413 se_grad->fadeAlphaWithLife = 1;
2414 se_grad = 0;
2415 }
2416 for (int i = 0; i < qs.size(); i++)
2417 {
2418 qs[i]->safeKill();
2419 }
2420 qs.clear();
2421 }
2422
createEntityPage()2423 void createEntityPage()
2424 {
2425 int c = 0;
2426 int rowSize = 12;
2427 int sizing = 64;
2428 Vector basePos = Vector(48, 164);
2429
2430 destroyEntityPage();
2431
2432 se_grad = new Quad();
2433 //Gradient()
2434 //se_grad->makeHorizontal(Vector(0,0,0.3), Vector(0,0,0.1));
2435 se_grad->scale = Vector(800, 500);
2436 se_grad->position = Vector(400,350);
2437 se_grad->followCamera = 1;
2438 se_grad->alpha = 0;
2439 se_grad->color = Vector(0,0,0);
2440 se_grad->alpha.interpolateTo(0.8, 0.2);
2441 dsq->game->addRenderObject(se_grad, LR_HUD);
2442
2443 EntityGroup &group = game->entityGroups[game->sceneEditor.entityPageNum];
2444
2445 for (int i = 0; i < group.entities.size(); i++)
2446 {
2447 EntityGroupEntity ent = group.entities[i];
2448 EntityClass *ec = dsq->game->getEntityClassForEntityType(ent.name);
2449 if (!ec && !dsq->mod.isActive())
2450 {
2451 errorLog("Entity Page List Error: Typo in Entities.txt?");
2452 }
2453 int type = -1;
2454 if (ec)
2455 {
2456 int j=0;
2457 for (j = 0; j < dsq->game->entityTypeList.size(); j++)
2458 {
2459 if (ec->idx == dsq->game->entityTypeList[j].idx)
2460 break;
2461 }
2462 type = j;
2463 }
2464
2465 int bit = int(floorf(float(c/rowSize))); // FIXME: Not float(c)/rowSize? --achurch
2466 std::string prevGfx = ent.gfx;
2467 if (prevGfx.empty() && ec)
2468 prevGfx = ec->prevGfx;
2469 std::string ecName = ent.name;
2470 if (ec)
2471 ecName = ec->name;
2472 if (!ecName.empty())
2473 {
2474 SEQuad *q = new SEQuad(prevGfx, Vector((c-(bit*rowSize)), bit)*sizing, type, ecName);
2475 q->position += basePos;
2476 if (q->getWidth() > q->getHeight())
2477 {
2478 q->setWidthHeight(sizing, (q->getHeight()*sizing) / q->getWidth());
2479 }
2480 else
2481 {
2482 q->setWidthHeight((q->getWidth()*sizing) / q->getHeight(), sizing);
2483 }
2484 //q->setWidthHeight(sizing, sizing);
2485 q->followCamera = 1;
2486 dsq->game->addRenderObject(q, LR_HUD);
2487 qs.push_back(q);
2488 c++;
2489 }
2490 }
2491
2492 se_label = new DebugFont();
2493 se_label->setFontSize(10);
2494 se_label->setText(group.name);
2495 se_label->position = Vector(20,90);
2496 se_label->followCamera = 1;
2497 dsq->game->addRenderObject(se_label, LR_HUD);
2498 }
2499
nextEntityPage()2500 void nextEntityPage()
2501 {
2502 game->sceneEditor.entityPageNum++;
2503 if (game->sceneEditor.entityPageNum >= game->entityGroups.size())
2504 game->sceneEditor.entityPageNum = 0;
2505
2506 createEntityPage();
2507 }
2508
2509
prevEntityPage()2510 void prevEntityPage()
2511 {
2512 game->sceneEditor.entityPageNum--;
2513 if (game->sceneEditor.entityPageNum < 0)
2514 game->sceneEditor.entityPageNum = game->entityGroups.size()-1;
2515
2516 createEntityPage();
2517 }
2518
selectEntityFromGroups()2519 void SceneEditor::selectEntityFromGroups()
2520 {
2521 createEntityPage();
2522
2523 placer->alpha = 0;
2524 se_changedEntityType = false;
2525 editType = ET_SELECTENTITY;
2526
2527 bool mbld = false;
2528 bool ld = false, rd = false;
2529 ld = core->getKeyState(KEY_E);
2530 while (!se_changedEntityType)
2531 {
2532 if (core->mouse.buttons.left && !mbld)
2533 mbld = true;
2534 else if (!core->mouse.buttons.left && mbld)
2535 {
2536 mbld = false;
2537 if (core->mouse.position.y < 100)
2538 break;
2539 }
2540
2541 if (core->getKeyState(KEY_ESCAPE))
2542 break;
2543 if (core->getKeyState(KEY_SPACE))
2544 break;
2545
2546 if (!core->getKeyState(KEY_E))
2547 ld = false;
2548 else if (!ld)
2549 {
2550 ld=true;
2551 nextEntityPage();
2552 }
2553
2554 if (!core->getKeyState(KEY_R))
2555 rd = !true;
2556 else if (!rd)
2557 {
2558 rd=!false;
2559 prevEntityPage();
2560 }
2561
2562 core->main(FRAME_TIME);
2563 }
2564
2565 destroyEntityPage();
2566
2567 editType = ET_ENTITIES;
2568 updateEntityPlacer();
2569 placer->alpha = 1;
2570 }
2571
2572
updateEntityPlacer()2573 void SceneEditor::updateEntityPlacer()
2574 {
2575 placer->setTexture(selectedEntity.prevGfx);
2576 placer->scale = Vector(selectedEntity.prevScale,selectedEntity.prevScale);
2577 }
2578
cycleElementNext(Element * e1)2579 Element* SceneEditor::cycleElementNext(Element *e1)
2580 {
2581 int ce = e1->templateIdx;
2582 int idx=0;
2583 for (int i = 0; i < dsq->game->elementTemplates.size(); i++)
2584 {
2585 if (dsq->game->elementTemplates[i].idx == ce)
2586 idx = i;
2587 }
2588 ce = idx;
2589 ce++;
2590 if (ce >= dsq->game->elementTemplates.size())
2591 ce = 0;
2592 idx = dsq->game->elementTemplates[ce].idx;
2593 if (idx < 1024)
2594 {
2595 Element *e = dsq->game->createElement(idx, e1->position, e1->bgLayer, e1);
2596 e1->safeKill();
2597 dsq->removeElement(e1);
2598 return e;
2599 }
2600 return e1;
2601 }
2602
cycleElementPrev(Element * e1)2603 Element* SceneEditor::cycleElementPrev(Element *e1)
2604 {
2605 int ce = e1->templateIdx;
2606 int idx=0;
2607 for (int i = 0; i < dsq->game->elementTemplates.size(); i++)
2608 {
2609 if (dsq->game->elementTemplates[i].idx == ce)
2610 {
2611 idx = i;
2612 break;
2613 }
2614 }
2615 ce = idx;
2616 ce--;
2617 if (ce < 0)
2618 ce = dsq->game->elementTemplates.size()-1;
2619 idx = dsq->game->elementTemplates[ce].idx;
2620 if (idx < 1024)
2621 {
2622 Element *e = dsq->game->createElement(idx, e1->position, e1->bgLayer, e1);
2623 e1->safeKill();
2624 dsq->removeElement(e1);
2625 return e;
2626 }
2627 return e1;
2628 }
2629
nextElement()2630 void SceneEditor::nextElement()
2631 {
2632 if (state != ES_SELECTING) return;
2633
2634
2635 if (core->getCtrlState())
2636 {
2637 dsq->mod.recache();
2638 return;
2639 }
2640
2641 if (core->getAltState())
2642 {
2643 debugLog("rebuilding level!");
2644 dsq->game->reconstructGrid(true);
2645 return;
2646 }
2647
2648 if (editType == ET_ELEMENTS)
2649 {
2650 if (dsq->game->elementTemplates.empty()) return;
2651 if (core->getCtrlState())
2652 {
2653 if (!selectedElements.empty())
2654 {
2655 for (int i = 0; i < selectedElements.size(); i++)
2656 {
2657 selectedElements[i]->rotation.z = 0;
2658 }
2659 }
2660 else if (editingElement)
2661 {
2662 editingElement->rotation.z = 0;
2663 }
2664 }
2665 else if (!selectedElements.empty())
2666 {
2667 for (int i = 0; i < selectedElements.size(); i++)
2668 {
2669 selectedElements[i] = cycleElementNext(selectedElements[i]);
2670 }
2671 }
2672 else if (editingElement)
2673 {
2674 cycleElementNext(editingElement);
2675 editingElement = 0;
2676 }
2677 else
2678 {
2679 int oldCur = curElement;
2680 curElement++;
2681 if (curElement >= dsq->game->elementTemplates.size())
2682 curElement = 0;
2683
2684 if (dsq->game->elementTemplates[curElement].idx < 1024)
2685 {
2686 placer->setTexture(dsq->game->elementTemplates[curElement].gfx);
2687 }
2688 else
2689 {
2690 curElement = oldCur;
2691 }
2692 }
2693 }
2694 }
2695
prevElement()2696 void SceneEditor::prevElement()
2697 {
2698 if (state != ES_SELECTING) return;
2699
2700 if (editType != ET_SELECTENTITY)
2701 {
2702 if (core->getCtrlState())
2703 {
2704 debugLog("SELECT ENTITY FROM GROUPS!");
2705 selectEntityFromGroups();
2706 return;
2707 }
2708 }
2709
2710 if (editType == ET_ELEMENTS)
2711 {
2712 if (dsq->game->elementTemplates.empty()) return;
2713 if (!selectedElements.empty())
2714 {
2715 for (int i = 0; i < selectedElements.size(); i++)
2716 {
2717 selectedElements[i] = cycleElementPrev(selectedElements[i]);
2718 }
2719 }
2720 else if (editingElement)
2721 {
2722 cycleElementPrev(editingElement);
2723 editingElement = 0;
2724 }
2725 else
2726 {
2727 doPrevElement();
2728 }
2729 }
2730 }
2731
doPrevElement()2732 void SceneEditor::doPrevElement()
2733 {
2734 int oldCur = curElement;
2735 curElement--;
2736 if (curElement < 0)
2737 curElement = dsq->game->elementTemplates.size()-1;
2738
2739 if (curElement < 0)
2740 return;
2741
2742 if (dsq->game->elementTemplates[curElement].idx < 1024)
2743 {
2744 placer->setTexture(dsq->game->elementTemplates[curElement].gfx);
2745 }
2746 else
2747 {
2748 curElement = oldCur;
2749 }
2750 }
2751
moveLayer()2752 void SceneEditor::moveLayer()
2753 {
2754 std::string s = dsq->getUserInputString("Enter 'fromLayer toLayer' (space inbetween, ESC/m-ty to cancel)");
2755 if (!s.empty())
2756 {
2757 std::istringstream is(s);
2758 int fromLayer, toLayer;
2759 is >> fromLayer >> toLayer;
2760 toLayer--;
2761 fromLayer--;
2762 for (int i = 0; i < dsq->getNumElements(); i++)
2763 {
2764 Element *e = dsq->getElement(i);
2765 if (e)
2766 {
2767 if (e->bgLayer == fromLayer)
2768 {
2769 moveElementToLayer(e, toLayer);
2770 }
2771 }
2772 }
2773 }
2774 }
2775
selectZero()2776 void SceneEditor::selectZero()
2777 {
2778 if (state != ES_SELECTING) return;
2779
2780 if (editType == ET_ELEMENTS)
2781 {
2782 if (dsq->game->elementTemplates.empty()) return;
2783 if (editingElement)
2784 {
2785 }
2786 else
2787 {
2788 curElement = 0;
2789 placer->setTexture(dsq->game->elementTemplates[curElement].gfx);
2790 }
2791 }
2792 }
2793
selectEnd()2794 void SceneEditor::selectEnd()
2795 {
2796 if (state != ES_SELECTING) return;
2797 if (editType == ET_ELEMENTS)
2798 {
2799 if (dsq->game->elementTemplates.empty()) return;
2800 if (!editingElement)
2801 {
2802 int largest = 0;
2803 for (int i = 0; i < dsq->game->elementTemplates.size(); i++)
2804 {
2805 ElementTemplate et = dsq->game->elementTemplates[i];
2806 if (et.idx < 1024 && i > largest)
2807 {
2808 largest = i;
2809 }
2810 }
2811 curElement = largest;
2812 placer->setTexture(dsq->game->elementTemplates[curElement].gfx);
2813 }
2814 }
2815 }
2816
placeElement()2817 void SceneEditor::placeElement()
2818 {
2819 if (editType == ET_ELEMENTS)
2820 {
2821 if (!core->getShiftState() && !core->getKeyState(KEY_LALT) && !drawingBox)
2822 {
2823 dsq->game->createElement(dsq->game->elementTemplates[curElement].idx, placer->position, bgLayer, placer);
2824 updateText();
2825 dsq->game->reconstructGrid();
2826 }
2827 }
2828 else if (editType == ET_ENTITIES)
2829 {
2830 if (!selectedEntity.nameBased)
2831 dsq->game->createEntity(selectedEntity.index, 0, dsq->getGameCursorPosition(), 0, true, "", ET_ENEMY, true);
2832 else
2833 dsq->game->createEntity(selectedEntity.name, 0, dsq->getGameCursorPosition(), 0, true, "", ET_ENEMY, true);
2834 }
2835 else if (editType == ET_PATHS)
2836 {
2837 if (core->getCtrlState())
2838 {
2839 // new path
2840 Path *p = new Path;
2841 p->name = "";
2842 PathNode n;
2843 n.position = dsq->getGameCursorPosition();
2844 p->nodes.push_back(n);
2845 dsq->game->addPath(p);
2846 selectedIdx = dsq->game->getNumPaths()-1;
2847 }
2848 else
2849 {
2850 Path *p = getSelectedPath();
2851 if (p)
2852 {
2853 p->addNode(selectedNode);
2854 }
2855 }
2856 }
2857 }
2858
cloneSelectedElement()2859 void SceneEditor::cloneSelectedElement()
2860 {
2861 if (editType == ET_ELEMENTS)
2862 {
2863 if (!selectedElements.empty())
2864 {
2865 std::vector<Element*>copy;
2866 Vector groupCenter = this->getSelectedElementsCenter();
2867 for (int i = 0; i < selectedElements.size(); i++)
2868 {
2869 Element *e1 = selectedElements[i];
2870 Vector dist = e1->position - groupCenter;
2871 Element *e = dsq->game->createElement(e1->templateIdx, placer->position + Vector(40,40) + dist, e1->bgLayer, e1);
2872 e->elementFlag = e1->elementFlag;
2873 e->setElementEffectByIndex(e1->getElementEffectIndex());
2874 copy.push_back(e);
2875 }
2876 selectedElements.clear();
2877 selectedElements = copy;
2878 copy.clear();
2879 }
2880 else if (editingElement)
2881 {
2882 Element *e1 = editingElement;
2883 Element *e = dsq->game->createElement(e1->templateIdx, placer->position + Vector(40,40), e1->bgLayer, e1);
2884 e->elementFlag = e1->elementFlag;
2885 e->setElementEffectByIndex(e1->getElementEffectIndex());
2886 //e->repeatTextureToFill(e1->isRepeatingTextureToFill());
2887 }
2888 dsq->game->reconstructGrid();
2889 }
2890 else if (editType == ET_ENTITIES)
2891 {
2892
2893 }
2894 else if (editType == ET_PATHS)
2895 {
2896 if (editingPath)
2897 {
2898 Path *p = editingPath;
2899 Path *newp = new Path;
2900 newp->name = p->name;
2901 newp->nodes = p->nodes;
2902 newp->rect = p->rect;
2903 newp->refreshScript();
2904 newp->pathShape = p->pathShape;
2905 newp->nodes[0].position += Vector(64,64);
2906
2907 dsq->game->addPath(newp);
2908 selectedIdx = dsq->game->getNumPaths()-1;
2909 newp->init();
2910 }
2911 }
2912 }
2913
shutdown()2914 void SceneEditor::shutdown()
2915 {
2916 clearActions();
2917 text = 0;
2918 placer = 0;
2919 }
2920
toggle()2921 void SceneEditor::toggle()
2922 {
2923 toggle(!on);
2924 }
2925
toggle(bool on)2926 void SceneEditor::toggle(bool on)
2927 {
2928 if (core->getNestedMains() > 1) return;
2929 if (dsq->game->isInGameMenu()) return;
2930 if (!on && editType == ET_SELECTENTITY) return;
2931 if (dsq->game->worldMapRender && dsq->game->worldMapRender->isOn()) return;
2932 this->on = on;
2933 autoSaveTimer = 0;
2934
2935 execID = -1;
2936 if (on)
2937 {
2938 btnMenu->alpha = 1;
2939 dsq->getRenderObjectLayer(LR_BLACKGROUND)->update = true;
2940
2941 warpAreaRender->alpha = 0.5;
2942 dsq->game->togglePause(on);
2943 if (dsq->game->avatar)
2944 dsq->game->avatar->disableInput();
2945 text->alpha.interpolateTo(1, 0.5);
2946 placer->alpha.interpolateTo(0.5, 0.5);
2947 movingEntity = 0;
2948 dsq->toggleCursor(true);
2949 dsq->setCursor(CURSOR_NORMAL);
2950 //core->flags.set(CF_CLEARBUFFERS);
2951
2952 dsq->darkLayer.toggle(false);
2953
2954 dsq->game->rebuildElementUpdateList();
2955
2956 for (int i = LR_ELEMENTS1; i <= LR_ELEMENTS8; i++)
2957 {
2958 dsq->getRenderObjectLayer(i)->update = true;
2959 }
2960
2961 oldGlobalScale = core->globalScale;
2962 const float cameraOffset = 1/oldGlobalScale.x - 1/zoom.x;
2963 core->cameraPos.x += cameraOffset * core->getVirtualWidth()/2;
2964 core->cameraPos.y += cameraOffset * core->getVirtualHeight()/2;
2965 core->globalScale = zoom;
2966 core->globalScaleChanged();
2967 }
2968 else
2969 {
2970 btnMenu->alpha = 0;
2971 //dsq->game->reconstructGrid();
2972 selectedElements.clear();
2973 for (int i = 0; i < 9; i++)
2974 dsq->getRenderObjectLayer(LR_ELEMENTS1+i)->visible = true;
2975
2976 if (movingEntity)
2977 endMoveEntity();
2978 movingEntity = 0;
2979
2980 dsq->getRenderObjectLayer(LR_BLACKGROUND)->update = false;
2981
2982 warpAreaRender->alpha = 0;
2983 dsq->game->togglePause(on);
2984 if (dsq->game->avatar)
2985 dsq->game->avatar->enableInput();
2986 text->alpha.interpolateTo(0, 0.2);
2987 placer->alpha.interpolateTo(0, 0.2);
2988 //core->flags.unset(CF_CLEARBUFFERS);
2989 dsq->darkLayer.toggle(true);
2990
2991 dsq->game->rebuildElementUpdateList();
2992
2993 const float cameraOffset = 1/oldGlobalScale.x - 1/zoom.x;
2994 core->cameraPos.x -= cameraOffset * core->getVirtualWidth()/2;
2995 core->cameraPos.y -= cameraOffset * core->getVirtualHeight()/2;
2996 core->globalScale = oldGlobalScale;
2997 }
2998 }
2999
isOn()3000 bool SceneEditor::isOn()
3001 {
3002 return on;
3003 }
3004
updateText()3005 void SceneEditor::updateText()
3006 {
3007 std::ostringstream os;
3008 os << dsq->game->sceneName << " bgL[" << bgLayer << "] (" <<
3009 (int)dsq->cameraPos.x << "," << (int)dsq->cameraPos.y << ") ("
3010 //<< (int)dsq->game->avatar->position.x
3011 //<< "," << (int)dsq->game->avatar->position.y << "," << (int)dsq->game->avatar->position.z << ")" << " ("
3012 << (int)dsq->getGameCursorPosition().x << "," << (int)dsq->getGameCursorPosition().y << ")" << " ";
3013 switch(editType)
3014 {
3015 case ET_ELEMENTS:
3016 os << "elements (" << dsq->getNumElements() << ")";
3017 if (selectedElements.size() > 1)
3018 {
3019 os << " - " << selectedElements.size() << " selected";
3020 }
3021 else
3022 {
3023 Element *e;
3024 if (!selectedElements.empty())
3025 e = selectedElements[0];
3026 else
3027 e = editingElement;
3028 if (e)
3029 {
3030 os << " id: " << e->templateIdx;
3031 ElementTemplate *et = game->getElementTemplateByIdx(e->templateIdx);
3032 if (et)
3033 os << " gfx: " << et->gfx;
3034 os << " efx: " << (e->getElementEffectIndex() + 1); // +1 so that it resembles the layout on numpad
3035 }
3036 }
3037 break;
3038 case ET_ENTITIES:
3039 os << "entities (" << dsq->entities.size() << ")";
3040 if (editingEntity)
3041 {
3042 os.precision(1);
3043 os << std::fixed;
3044 os << " id: " << editingEntity->getID()
3045 << " name: " << editingEntity->name
3046 << " flag:" << dsq->continuity.getEntityFlag(dsq->game->sceneName, editingEntity->getID())
3047 << " fh:" << editingEntity->isfh()
3048 << " fv:" << editingEntity->isfv()
3049 << " state:" << editingEntity->getState()
3050 << " et:" << editingEntity->getEntityType()
3051 << " hp:" << editingEntity->health << "/" << editingEntity->maxHealth;
3052 }
3053 break;
3054 case ET_PATHS:
3055 os << "paths (" << dsq->game->getNumPaths()<< ") si[" << selectedIdx << "]";
3056 if (getSelectedPath())
3057 os << " name: " << getSelectedPath()->name;
3058 break;
3059 }
3060 text->setText(os.str());
3061 }
3062
startDrawingWarpArea(char c)3063 void SceneEditor::startDrawingWarpArea(char c)
3064 {
3065 if (drawingWarpArea == 'N')
3066 {
3067 boxPos = dsq->getGameCursorPosition();
3068 boxPromo->alpha = 1;
3069 switch(c)
3070 {
3071 case 'Y': boxPromo->color = Vector(1,1,0); break;
3072 case 'U': boxPromo->color = Vector(1,0,0); break;
3073 case 'I': boxPromo->color = Vector(0,1,0); break;
3074 case 'O': boxPromo->color = Vector(0,0,1); break;
3075 case 'P': boxPromo->color = Vector(1,0,1); break;
3076 }
3077 drawingWarpArea = c;
3078 }
3079 if (drawingWarpArea == c)
3080 {
3081 Vector diff = dsq->getGameCursorPosition() - boxPos;
3082 boxPromo->setWidthHeight(diff.x, diff.y);
3083 boxPromo->position = boxPos + diff/2;
3084 }
3085 }
3086
updateDrawingWarpArea(char c,int k)3087 void SceneEditor::updateDrawingWarpArea(char c, int k)
3088 {
3089 if (core->getKeyState(k))
3090 {
3091 startDrawingWarpArea(c);
3092 }
3093 else
3094 {
3095 endDrawingWarpArea(c);
3096 }
3097 }
3098
endDrawingWarpArea(char c)3099 void SceneEditor::endDrawingWarpArea(char c)
3100 {
3101 if (drawingWarpArea == c)
3102 {
3103 drawingWarpArea = 'N';
3104 boxPromo->alpha = 0;
3105 if (boxPromo->getWidth() > TILE_SIZE && boxPromo->getHeight() > TILE_SIZE)
3106 {
3107 WarpArea a;
3108 a.position = boxPromo->position;
3109 a.w = boxPromo->getWidth()/2;
3110 a.h = boxPromo->getHeight()/2;
3111 switch (c)
3112 {
3113 case 'Y': a.warpAreaType = "Yellow"; break;
3114 case 'U': a.warpAreaType = "Red"; break;
3115 case 'I': a.warpAreaType = "Green"; break;
3116 case 'O': a.warpAreaType = "Blue"; break;
3117 case 'P': a.warpAreaType = "Purple"; break;
3118 }
3119
3120 a.sceneName = dsq->getUserInputString("Enter map to warp to");
3121 a.spawnOffset = dsq->getUserInputDirection("Enter warp direction");
3122 dsq->game->warpAreas.push_back(a);
3123 }
3124 }
3125 }
3126
getSelectedElementsCenter()3127 Vector SceneEditor::getSelectedElementsCenter()
3128 {
3129 Vector c;
3130 for (int i = 0; i < selectedElements.size(); i++)
3131 {
3132 c += selectedElements[i]->position;
3133 }
3134 c /= float(selectedElements.size());
3135 return c;
3136 }
3137
update(float dt)3138 void SceneEditor::update(float dt)
3139 {
3140 if (on)
3141 {
3142 if (core->getNestedMains() > 1) return;
3143
3144 autoSaveTimer += dt;
3145 if (autoSaveTimer > vars->autoSaveTime && state == ES_SELECTING)
3146 {
3147 autoSaveTimer = 0;
3148 std::ostringstream os;
3149 os << "auto/AUTO_" << autoSaveFile << "_" << dsq->game->sceneName;
3150 if(dsq->game->saveScene(os.str()))
3151 {
3152 std::string m = "Map AutoSaved to " + os.str();
3153 dsq->debugLog(m);
3154 dsq->screenMessage(m);
3155 }
3156
3157 autoSaveFile++;
3158 if (autoSaveFile > vars->autoSaveFiles)
3159 autoSaveFile = 0;
3160 }
3161
3162 updateMultiSelect();
3163 switch (editType)
3164 {
3165 case ET_ELEMENTS:
3166 editingEntity = 0;
3167 if (isActing(ACTION_MULTISELECT) || !selectedElements.empty())
3168 {
3169 editingElement = 0;
3170 }
3171 if (state == ES_SELECTING && !isActing(ACTION_MULTISELECT))
3172 editingElement = this->getElementAtCursor();
3173
3174 if (editingElement)
3175 placer->alpha = 0;
3176 else
3177 placer->alpha = 0.5;
3178 break;
3179 case ET_ENTITIES:
3180 editingElement = 0;
3181 if (state == ES_SELECTING)
3182 editingEntity = this->getEntityAtCursor();
3183 if (editingEntity)
3184 placer->alpha = 0;
3185 else
3186 placer->alpha = 0.5;
3187 break;
3188 }
3189
3190 updateText();
3191 ActionMapper::onUpdate(dt);
3192
3193 TileVector cursorTile(dsq->getGameCursorPosition());
3194 Vector p = Vector(cursorTile.x*TILE_SIZE+TILE_SIZE/2, cursorTile.y*TILE_SIZE+TILE_SIZE/2);
3195 placer->position = p;
3196
3197 int camSpeed = 500/zoom.x;
3198 if (core->getShiftState())
3199 camSpeed = 5000/zoom.x;
3200 if (isActing(ACTION_CAMLEFT))
3201 dsq->cameraPos.x -= dt*camSpeed;
3202 if (isActing(ACTION_CAMRIGHT))
3203 dsq->cameraPos.x += dt*camSpeed;
3204 if (isActing(ACTION_CAMUP))
3205 dsq->cameraPos.y -= dt*camSpeed;
3206 if (isActing(ACTION_CAMDOWN))
3207 dsq->cameraPos.y += dt*camSpeed;
3208 if (core->mouse.buttons.middle && !core->mouse.change.isZero())
3209 {
3210 dsq->cameraPos += core->mouse.change*(4/zoom.x);
3211 core->setMousePosition(core->mouse.lastPosition);
3212 }
3213
3214 float spd = 0.5;
3215 const Vector oldZoom = zoom;
3216 if (isActing(ACTION_ZOOMOUT))
3217 zoom /= (1 + spd*dt);
3218 else if (isActing(ACTION_ZOOMIN))
3219 zoom *= (1 + spd*dt);
3220 else if (core->mouse.scrollWheelChange < 0)
3221 {
3222 if (core->getShiftState() && !core->getCtrlState()) // hackish: to prevent accidental recache()
3223 nextElement();
3224 else
3225 zoom /= 1.12f;
3226 }
3227 else if (core->mouse.scrollWheelChange > 0)
3228 {
3229 if (core->getShiftState() && !core->getCtrlState()) // hackish: to prevent accidental entity selection
3230 prevElement();
3231 else
3232 zoom *= 1.12f;
3233 }
3234 if (zoom.x < 0.04f)
3235 zoom.x = zoom.y = 0.04f;
3236 core->globalScale = zoom;
3237 core->globalScaleChanged();
3238 if (zoom.x != oldZoom.x)
3239 {
3240 const float mouseX = core->mouse.position.x;
3241 const float mouseY = core->mouse.position.y;
3242 dsq->cameraPos.x += mouseX/oldZoom.x - mouseX/zoom.x;
3243 dsq->cameraPos.y += mouseY/oldZoom.y - mouseY/zoom.y;
3244 }
3245
3246 if (this->editType == ET_PATHS)
3247 {
3248 switch(state)
3249 {
3250 case ES_SELECTING:
3251 {
3252 selectedIdx = -1;
3253 selectedNode = -1;
3254 float smallestDist = sqr(64);
3255 for (int i = 0; i < dsq->game->getNumPaths(); i++)
3256 {
3257 for (int n = dsq->game->getPath(i)->nodes.size()-1; n >=0; n--)
3258 {
3259 Vector v = dsq->game->getPath(i)->nodes[n].position - dsq->getGameCursorPosition();
3260 float dist = v.getSquaredLength2D();
3261 if (dist < smallestDist)
3262 {
3263 smallestDist = dist;
3264 selectedIdx = i;
3265 selectedNode = n;
3266 //return;
3267 }
3268 }
3269 }
3270 }
3271 break;
3272 case ES_SCALING:
3273 {
3274 if (editingPath)
3275 {
3276 float factor = 1;
3277 Vector add = Vector((dsq->getGameCursorPosition().x - cursorOffset.x)*factor,
3278 (dsq->getGameCursorPosition().y - cursorOffset.y)*factor);
3279 Vector sz = oldScale + add;
3280 if (sz.x < 32)
3281 sz.x = 32;
3282 if (sz.y < 32)
3283 sz.y = 32;
3284 editingPath->rect.x1 = -sz.x/2;
3285 editingPath->rect.x2 = sz.x/2;
3286 editingPath->rect.y1 = -sz.y/2;
3287 editingPath->rect.y2 = sz.y/2;
3288 }
3289 }
3290 break;
3291 case ES_MOVING:
3292 if (selectedIdx >= 0)
3293 dsq->game->getPath(selectedIdx)->nodes[selectedNode].position = dsq->getGameCursorPosition() + cursorOffset;
3294 break;
3295 }
3296 }
3297 else if (editType == ET_ENTITIES)
3298 {
3299 switch(state)
3300 {
3301 case ES_MOVING:
3302 if (editingEntity)
3303 editingEntity->position = dsq->getGameCursorPosition() + cursorOffset;
3304 break;
3305 case ES_ROTATING:
3306 {
3307 if (editingEntity)
3308 {
3309 float add = (dsq->getGameCursorPosition().x - cursorOffset.x)/2.4f;
3310 if (core->getCtrlState())
3311 {
3312 int a = (oldRotation.z + add)/45;
3313 add = a * 45;
3314 editingEntity->rotation.z = add;
3315 }
3316 else
3317 {
3318 editingEntity->rotation.z = oldRotation.z + add;
3319 }
3320 }
3321 }
3322 }
3323 }
3324 else if (editType == ET_ELEMENTS)
3325 {
3326 switch(state)
3327 {
3328 case ES_SELECTING:
3329 {
3330 float closest = sqr(800);
3331 int idx = -1, i = 0;
3332 for (i = 0; i < dsq->getNumElements(); i++)
3333 {
3334 Vector dist = dsq->getElement(i)->getFollowCameraPosition() - dsq->getGameCursorPosition();
3335 float len = dist.getSquaredLength2D();
3336 if (len < closest)
3337 {
3338 closest = len;
3339 idx = i;
3340 }
3341 }
3342 }
3343 break;
3344 case ES_MOVING:
3345 updateSelectedElementPosition(dsq->getGameCursorPosition() - cursorOffset);
3346 break;
3347 case ES_ROTATING:
3348 {
3349 if (!selectedElements.empty())
3350 {
3351
3352 float add = (dsq->getGameCursorPosition().x - cursorOffset.x)/2.4f;
3353 if (core->getCtrlState())
3354 {
3355 int a = (oldRotation.z + add)/45;
3356 add = a * 45;
3357 dummy.rotation.z = add;
3358 }
3359 else
3360 {
3361 dummy.rotation.z = oldRotation.z + add;
3362 }
3363 }
3364 else if (editingElement)
3365 {
3366 float add = (dsq->getGameCursorPosition().x - cursorOffset.x)/2.4f;
3367 if (core->getCtrlState())
3368 {
3369 int a = (oldRotation.z + add)/45;
3370 add = a * 45;
3371 editingElement->rotation.z = add;
3372 }
3373 else
3374 {
3375 editingElement->rotation.z = oldRotation.z + add;
3376 }
3377 }
3378 }
3379 break;
3380 case ES_SCALING:
3381 {
3382 bool right=false, middle=false, down=false, uni=false, repeatScale=false;
3383 bool noSide = 0;
3384 if (cursorOffset.x > oldPosition.x+10)
3385 right = true;
3386 else if (cursorOffset.x < oldPosition.x-10)
3387 right = false;
3388 else
3389 noSide++;
3390 if (cursorOffset.y > oldPosition.y+10)
3391 down = true;
3392 else if (cursorOffset.y < oldPosition.y-10)
3393 down = false;
3394 else if (noSide)
3395 middle = true;
3396
3397 Vector add = Vector((dsq->getGameCursorPosition().x - cursorOffset.x)/100.0f,
3398 (dsq->getGameCursorPosition().y - cursorOffset.y)/100.0f);
3399 {
3400 if (!selectedElements.empty())
3401 add.y = add.x;
3402 else
3403 {
3404 if (core->getKeyState(KEY_C))
3405 {
3406 add.y = 0;
3407 if (!right && !middle)
3408 add.x *= -1;
3409 }
3410 else if (core->getKeyState(KEY_V))
3411 {
3412 add.x = 0;
3413 if (!down && !middle)
3414 add.y *= -1;
3415 }
3416 else
3417 {
3418 add.y = add.x;
3419 uni = true;
3420 }
3421
3422 repeatScale = core->getKeyState(KEY_X);
3423 if(repeatScale)
3424 add *= 0.1f;
3425 }
3426 }
3427 if (!selectedElements.empty())
3428 {
3429 if (core->getCtrlState())
3430 {
3431 dummy.scale = Vector(1,1);
3432 }
3433 else
3434 {
3435 dummy.scale=oldScale + add;
3436 if (dummy.scale.x < MIN_SIZE)
3437 dummy.scale.x = MIN_SIZE;
3438 if (dummy.scale.y < MIN_SIZE)
3439 dummy.scale.y = MIN_SIZE;
3440 }
3441
3442 for (int i = 0; i < selectedElements.size(); i++)
3443 selectedElements[i]->refreshRepeatTextureToFill();
3444 }
3445 else if (editingElement)
3446 {
3447 Vector& editVec = repeatScale ? editingElement->repeatToFillScale : editingElement->scale;
3448 if (core->getCtrlState())
3449 {
3450 editVec = Vector(1,1);
3451 }
3452 else
3453 {
3454 //editingElement->scale=oldScale + add;
3455 editVec = (repeatScale ? oldRepeatScale : oldScale) + add;
3456 if (!uni && !repeatScale)
3457 {
3458 if (!middle)
3459 {
3460 Vector offsetChange = (add*Vector(editingElement->getWidth(), editingElement->getHeight()))*0.5f;
3461 if (add.y == 0)
3462 {
3463 if (right)
3464 editingElement->beforeScaleOffset = offsetChange;
3465 else
3466 editingElement->beforeScaleOffset = -offsetChange;
3467 }
3468 else
3469 {
3470 if (down)
3471 editingElement->beforeScaleOffset = offsetChange;
3472 else
3473 editingElement->beforeScaleOffset = -offsetChange;
3474 }
3475 }
3476 }
3477 if (editVec.x < MIN_SIZE)
3478 editVec.x = MIN_SIZE;
3479 if (editVec.y < MIN_SIZE)
3480 editVec.y = MIN_SIZE;
3481 }
3482
3483 editingElement->refreshRepeatTextureToFill();
3484 }
3485 }
3486 break;
3487 }
3488 }
3489 }
3490 }
3491
nextEntityType()3492 void SceneEditor::nextEntityType()
3493 {
3494 if (editType == ET_ELEMENTS && state == ES_SELECTING)
3495 {
3496 if (editingElement || !selectedElements.empty())
3497 {
3498 enterMoveState();
3499 updateSelectedElementPosition(Vector(1,0));
3500 exitMoveState();
3501 }
3502 }
3503 else if (editType == ET_SELECTENTITY)
3504 {
3505 nextEntityPage();
3506 }
3507 }
3508
prevEntityType()3509 void SceneEditor::prevEntityType()
3510 {
3511 if (editType == ET_ELEMENTS && state == ES_SELECTING)
3512 {
3513 if (editingElement || !selectedElements.empty())
3514 {
3515 enterMoveState();
3516 updateSelectedElementPosition(Vector(-1,0));
3517 exitMoveState();
3518 }
3519 }
3520 else if (editType == ET_SELECTENTITY)
3521 {
3522 prevEntityPage();
3523 }
3524 }
3525
dumpObs()3526 void SceneEditor::dumpObs()
3527 {
3528 TileVector tv;
3529 unsigned char *data = new unsigned char[MAX_GRID * MAX_GRID * sizeof(uint32)];
3530 uint32 *ptr = (uint32*)data;
3531 for(tv.y = MAX_GRID - 1; ; --tv.y)
3532 {
3533 for(tv.x = 0; tv.x < MAX_GRID; ++tv.x)
3534 *ptr++ = game->isObstructed(tv, OT_MASK_BLACK) ? 0xFF000000 : 0xFFFFFFFF;
3535 if(tv.y == 0)
3536 break;
3537 }
3538 std::string outfn = dsq->getUserDataFolder() + "/griddump-" + game->sceneName + ".tga";
3539 core->tgaSave(outfn.c_str(), MAX_GRID, MAX_GRID, 32, data);
3540 dsq->screenMessage("Saved grid image to " + outfn);
3541 }
3542
3543
3544 #endif // AQUARIA_BUILD_SCENEEDITOR
3545