TDME2 1.9.121
TerrainEditorTabController.cpp
Go to the documentation of this file.
2
3#include <array>
4#include <string>
5#include <unordered_map>
6#include <vector>
7
8#include <tdme/tdme.h>
14#include <tdme/engine/Engine.h>
24#include <tdme/gui/GUI.h>
25#include <tdme/gui/GUIParser.h>
47
48#include <ext/tinyxml/tinyxml.h>
49
51
52using std::array;
53using std::string;
54using std::unordered_map;
55using std::vector;
56
71using tdme::gui::GUI;
94
98
99#define AVOID_NULLPTR_STRING(arg) (arg == nullptr?"":arg)
100
101TerrainEditorTabController::TerrainEditorTabController(TerrainEditorTabView* view)
102{
103 this->view = view;
105 this->popUps = view->getPopUps();
106 this->currentTerrainBrushTextureFileName = "resources/engine/textures/terrain_brush_soft.png";
107 this->currentTerrainBrushTexture = TextureReader::read(Tools::getPathName(currentTerrainBrushTextureFileName), Tools::getFileName(currentTerrainBrushTextureFileName), false, false);
108 this->rampTerrainBrushTexture = TextureReader::read("./resources/engine/textures", "terrain_ramp.png", false, false);
109}
110
113}
114
116 return view;
117}
118
120{
121 return screenNode;
122}
123
125{
126 this->screenNode = screenNode;
129}
130
132{
133}
134
136{
137 //
138 auto prototype = view->getPrototype();
139 if (prototype == nullptr) return;
140
141 //
142 try {
143 if (prototype->getFileName().empty() == true) throw ExceptionBase("Could not save file. No filename known");
144 view->saveFile(
145 Tools::getPathName(prototype->getFileName()),
146 Tools::getFileName(prototype->getFileName())
147 );
148 } catch (Exception& exception) {
149 showErrorPopUp("Warning", (string(exception.what())));
150 }
151}
152
154{
155 class OnModelSave: public virtual Action
156 {
157 public:
158 void performAction() override {
159 try {
160 modelEditorTabController->view->saveFile(
161 modelEditorTabController->popUps->getFileDialogScreenController()->getPathName(),
162 modelEditorTabController->popUps->getFileDialogScreenController()->getFileName()
163 );
164 } catch (Exception& exception) {
165 modelEditorTabController->showErrorPopUp("Warning", (string(exception.what())));
166 }
167 modelEditorTabController->popUps->getFileDialogScreenController()->close();
168 }
169
170 /**
171 * Public constructor
172 * @param modelEditorTabController model editor tab controller
173 */
174 OnModelSave(TerrainEditorTabController* modelEditorTabController): modelEditorTabController(modelEditorTabController) {
175 }
176
177 private:
178 TerrainEditorTabController* modelEditorTabController;
179 };
180
181 //
182 auto prototype = view->getPrototype();
183 if (prototype == nullptr) return;
184
185 //
187 prototype->getFileName().empty() == false?Tools::getPathName(prototype->getFileName()):string(),
188 "Save to: ",
189 {{ "tterrain" }},
190 Tools::getFileName(prototype->getFileName()),
191 false,
192 new OnModelSave(this)
193 );
194}
195
197 required_dynamic_cast<GUITextNode*>(screenNode->getNodeById(view->getTabId() + "_tab_text_info"))->setText(text);
198}
199
200void TerrainEditorTabController::showErrorPopUp(const string& caption, const string& message)
201{
202 popUps->getInfoDialogScreenController()->show(caption, message);
203}
204
206{
207 if (node->getId() == "selectbox_outliner") {
208 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
209 updateDetails(outlinerNode);
210 } else
211 if (StringTools::startsWith(node->getId(), view->getTabId() + "_tab_terrain_add") == true) {
212 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_ADD;
213 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
215 updateDetails("terrain.brush");
217 } else
218 if (StringTools::startsWith(node->getId(), view->getTabId() + "_tab_terrain_substract") == true) {
219 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_SUBTRACT;
220 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
222 updateDetails("terrain.brush");
224 } else
225 if (StringTools::startsWith(node->getId(), view->getTabId() + "_tab_terrain_flatten") == true) {
226 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_FLATTEN;
227 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
229 updateDetails("terrain.brush");
231 } else
232 if (StringTools::startsWith(node->getId(), view->getTabId() + "_tab_terrain_smooth") == true) {
233 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_SMOOTH;
234 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
236 updateDetails("terrain.brush");
238 } else
239 if (StringTools::startsWith(node->getId(), view->getTabId() + "_tab_terrain_ramp") == true) {
240 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_RAMP;
241 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
243 updateDetails("terrain.brush");
245 } else
246 if (StringTools::startsWith(node->getId(), view->getTabId() + "_tab_terrain_delete") == true) {
247 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_DELETE;
248 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
250 updateDetails("terrain.brush");
252 } else
253 if (StringTools::startsWith(node->getId(), view->getTabId() + "_tab_water_water") == true) {
254 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_WATER_ADD;
255 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
257 updateDetails("terrain.waters");
258 view->unsetBrush();
259 } else
260 if (StringTools::startsWith(node->getId(), view->getTabId() + "_tab_water_delete") == true) {
261 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_WATER_DELETE;
262 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
264 updateDetails("terrain.waters");
265 view->unsetBrush();
266 } else
267 if (StringTools::startsWith(node->getId(), view->getTabId() + "_tab_foliage_add") == true) {
268 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_NONE;
269 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_ADD;
270 view->unsetBrush();
273 } else
274 if (StringTools::startsWith(node->getId(), view->getTabId() + "_tab_foliage_delete") == true) {
275 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_NONE;
276 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_DELETE;
277 view->unsetBrush();
280 } else {
281 for (auto& textureBrushApplyNode: textureBrushApplyNodes) {
282 if (node->getId() == textureBrushApplyNode) {
284 break;
285 }
286 }
287 for (auto& foliageBrushApplyNode: foliageBrushApplyNodes) {
288 if (node->getId() == foliageBrushApplyNode) {
291 break;
292 }
293 }
294 for (auto& foliageBrushPrototypeApplyNode: foliageBrushPrototypeApplyNodes) {
295 if (node->getId() == foliageBrushPrototypeApplyNode) {
298 break;
299 }
300 }
301 }
303}
304
307}
308
311}
312
314 if (node->getId() == "selectbox_outliner") {
315 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
316 if (StringTools::startsWith(outlinerNode, "terrain.waters.") == true) {
317 // clear
319 // delete
320 class OnTerrainWaterDelete: public virtual Action
321 {
322 public:
323 void performAction() override {
324 auto outlinerNode = terrainEditorTabController->view->getEditorView()->getScreenController()->getOutlinerSelection();
325 auto waterIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.waters.").size(), outlinerNode.size()));
326 terrainEditorTabController->deleteWater(waterIdx);
327 //
328 class ReloadOutlinerAction: public Action {
329 public:
330 void performAction() override {
331 terrainEditorTabController->view->getEditorView()->reloadTabOutliner("terrain.waters");
332 }
333 ReloadOutlinerAction(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
334 }
335 private:
336 TerrainEditorTabController* terrainEditorTabController;
337 };
338 Engine::getInstance()->enqueueAction(new ReloadOutlinerAction(terrainEditorTabController));
339 }
340 OnTerrainWaterDelete(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
341 }
342 private:
343 TerrainEditorTabController* terrainEditorTabController;
344 };
345 popUps->getContextMenuScreenController()->addMenuItem("Delete Water", "contextmenu_delete", new OnTerrainWaterDelete(this));
346
347 //
348 popUps->getContextMenuScreenController()->show(mouseX, mouseY);
349 } else
350 if (outlinerNode == "terrain.foliage") {
351 // clear
353 // add
354 class OnTerrainFoliageAddBrush: public virtual Action
355 {
356 public:
357 void performAction() override {
358 auto prototype = terrainEditorTabController->view->getPrototype();
359 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
360 if (terrain == nullptr) return;
361 auto brush = terrain->addBrush();
362 //
363 class ReloadOutlinerAction: public Action {
364 public:
365 void performAction() override {
366 string outlinerNode = "terrain.foliage";
367 auto prototype = terrainEditorTabController->view->getPrototype();
368 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
369 if (terrain != nullptr) outlinerNode = "terrain.foliage." + to_string(terrain->getBrushes().size() - 1);
370 terrainEditorTabController->view->getEditorView()->reloadTabOutliner(outlinerNode);
371 }
372 ReloadOutlinerAction(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
373 }
374 private:
375 TerrainEditorTabController* terrainEditorTabController;
376 };
377 Engine::getInstance()->enqueueAction(new ReloadOutlinerAction(terrainEditorTabController));
378 }
379 OnTerrainFoliageAddBrush(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
380 }
381 private:
382 TerrainEditorTabController* terrainEditorTabController;
383 };
384 popUps->getContextMenuScreenController()->addMenuItem("Add Foliage Brush", "contextmenu_add", new OnTerrainFoliageAddBrush(this));
385
386 //
387 popUps->getContextMenuScreenController()->show(mouseX, mouseY);
388 } else
389 if (StringTools::startsWith(outlinerNode, "terrain.foliagebrushes.") == true) {
390 // clear
392
393 // delete
394 class OnTerrainDeleteFoliageBrush: public virtual Action
395 {
396 public:
397 void performAction() override {
398 auto outlinerNode = terrainEditorTabController->view->getEditorView()->getScreenController()->getOutlinerSelection();
399 auto foliageBrushIdx = -1;
400 auto foliageBrushPrototypeIdx = -1;
401 if (terrainEditorTabController->checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
402 auto prototype = terrainEditorTabController->view->getPrototype();
403 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
404 if (terrain == nullptr) return;
405 auto brush = terrain->getBrush(foliageBrushIdx);
406 brush->removePrototype(foliageBrushPrototypeIdx);
407 auto newOutlinerNode = "terrain.brushes." + to_string(foliageBrushIdx);
408
409 //
410 class ReloadOutlinerAction: public Action {
411 public:
412 void performAction() override {
413 terrainEditorTabController->view->getEditorView()->reloadTabOutliner(outlinerNode);
414 }
415 ReloadOutlinerAction(TerrainEditorTabController* terrainEditorTabController, const string& outlinerNode): terrainEditorTabController(terrainEditorTabController), outlinerNode(outlinerNode) {
416 }
417 private:
418 TerrainEditorTabController* terrainEditorTabController;
419 string outlinerNode;
420 };
421 Engine::getInstance()->enqueueAction(new ReloadOutlinerAction(terrainEditorTabController, newOutlinerNode));
422 }
423 OnTerrainDeleteFoliageBrush(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
424 }
425 private:
426 TerrainEditorTabController* terrainEditorTabController;
427 };
428 popUps->getContextMenuScreenController()->addMenuItem("Delete Foliage Brush Prototype", "contextmenu_delete", new OnTerrainDeleteFoliageBrush(this));
429
430 //
431 popUps->getContextMenuScreenController()->show(mouseX, mouseY);
432 } else
433 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == true) {
434 // clear
436
437
438 // add prototype
439 class OnTerrainAddFoliageBrushPrototype: public virtual Action
440 {
441 public:
442 void performAction() override {
443 auto outlinerNode = terrainEditorTabController->view->getEditorView()->getScreenController()->getOutlinerSelection();
444 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == false) return;
445 auto foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
446 auto prototype = terrainEditorTabController->view->getPrototype();
447 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
448 if (terrain == nullptr) return;
449 auto brush = terrain->getBrush(foliageBrushIdx);
450 if (brush == nullptr) return;
451 auto brushPrototype = brush->addPrototype();
452 auto newOutlinerNode = "terrain.foliagebrushes." + to_string(foliageBrushIdx) + "." + to_string(brush->getPrototypes().size() - 1);
453
454 //
455 class ReloadOutlinerAction: public Action {
456 public:
457 void performAction() override {
458 terrainEditorTabController->view->getEditorView()->reloadTabOutliner(outlinerNode);
459 }
460 ReloadOutlinerAction(TerrainEditorTabController* terrainEditorTabController, const string& outlinerNode): terrainEditorTabController(terrainEditorTabController), outlinerNode(outlinerNode) {
461 }
462 private:
463 TerrainEditorTabController* terrainEditorTabController;
464 string outlinerNode;
465 };
466 Engine::getInstance()->enqueueAction(new ReloadOutlinerAction(terrainEditorTabController, newOutlinerNode));
467 }
468 OnTerrainAddFoliageBrushPrototype(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
469 }
470 private:
471 TerrainEditorTabController* terrainEditorTabController;
472 };
473 popUps->getContextMenuScreenController()->addMenuItem("Add Foliage Prototype", "contextmenu_add", new OnTerrainAddFoliageBrushPrototype(this));
474
475
476 // delete
477 class OnTerrainDeleteFoliageBrush: public virtual Action
478 {
479 public:
480 void performAction() override {
481 auto outlinerNode = terrainEditorTabController->view->getEditorView()->getScreenController()->getOutlinerSelection();
482 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == false) return;
483 auto foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
484 auto prototype = terrainEditorTabController->view->getPrototype();
485 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
486 if (terrain == nullptr) return;
487 terrain->removeBrush(foliageBrushIdx);
488
489 //
490 class ReloadOutlinerAction: public Action {
491 public:
492 void performAction() override {
493 terrainEditorTabController->view->getEditorView()->reloadTabOutliner("terrain.foliage");
494 }
495 ReloadOutlinerAction(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
496 }
497 private:
498 TerrainEditorTabController* terrainEditorTabController;
499 };
500 Engine::getInstance()->enqueueAction(new ReloadOutlinerAction(terrainEditorTabController));
501 }
502 OnTerrainDeleteFoliageBrush(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
503 }
504 private:
505 TerrainEditorTabController* terrainEditorTabController;
506 };
507 popUps->getContextMenuScreenController()->addMenuItem("Delete Foliage Brush", "contextmenu_delete", new OnTerrainDeleteFoliageBrush(this));
508
509 //
510 popUps->getContextMenuScreenController()->show(mouseX, mouseY);
511 }
512 }
514}
515
517{
519 if (node->getId() == "terrain_create") {
521 } else
522 if (node->getId() == "foliagebrush_texture_open") {
523 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
524 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == false) return;
525 auto foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
526 auto prototype = view->getPrototype();
527 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
528 if (terrain == nullptr) return;
529 auto brush = terrain->getBrush(foliageBrushIdx);
530 if (brush == nullptr) return;
531
532 //
533 class OnFoliageBrushFileOpenAction: public virtual Action
534 {
535 public:
536 void performAction() override {
537 auto outlinerNode = terrainEditorTabController->view->getEditorView()->getScreenController()->getOutlinerSelection();
538 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == false) return;
539 auto foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
540 auto prototype = terrainEditorTabController->view->getPrototype();
541 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
542 if (terrain == nullptr) return;
543 auto brush = terrain->getBrush(foliageBrushIdx);
544 if (brush == nullptr) return;
545 brush->setFileName(
546 terrainEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() +
547 "/" +
548 terrainEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
549 );
550 required_dynamic_cast<GUIImageNode*>(terrainEditorTabController->screenNode->getNodeById("foliagebrush_texture"))->setSource(brush->getFileName());
551 terrainEditorTabController->updateFoliageBrush();
552 terrainEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
553 }
554
555 /**
556 * Public constructor
557 * @param terrainEditorTabController terrain editor tab controller
558 */
559 OnFoliageBrushFileOpenAction(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
560 }
561
562 private:
563 TerrainEditorTabController* terrainEditorTabController;
564 };
565
566 vector<string> extensions = TextureReader::getTextureExtensions();
568 brush->getFileName().empty() == false?Tools::getPathName(brush->getFileName()):string(),
569 "Load foliage brush texture from: ",
570 extensions,
571 Tools::getFileName(brush->getFileName()),
572 true,
573 new OnFoliageBrushFileOpenAction(this)
574 );
575 } else
576 if (node->getId() == "foliagebrush_texture_remove") {
577 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
578 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == false) return;
579 auto foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
580 auto prototype = view->getPrototype();
581 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
582 if (terrain == nullptr) return;
583 auto brush = terrain->getBrush(foliageBrushIdx);
584 if (brush == nullptr) return;
585 brush->setFileName(string());
586 required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("foliagebrush_texture"))->setSource(brush->getFileName());
588 } else
589 if (node->getId() == "foliagebrush_texture_browseto") {
590
591 } else
592 if (node->getId() == "foliagebrush_prototype_file_open") {
593 class OnTerrainBrushPrototypeFileOpenAction: public virtual Action
594 {
595 public:
596 void performAction() override {
597 auto prototype = terrainEditorTabController->view->getPrototype();
598 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
599 if (terrain == nullptr) return;
600
601 auto outlinerNode = terrainEditorTabController->view->getEditorView()->getScreenController()->getOutlinerSelection();
602 auto foliageBrushIdx = -1;
603 auto foliageBrushPrototypeIdx = -1;
604 if (terrainEditorTabController->checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
605 auto brush = terrain->getBrush(foliageBrushIdx);
606 if (brush == nullptr) return;
607 auto brushPrototype = brush->getPrototype(foliageBrushPrototypeIdx);
608 brushPrototype->setFileName(
609 terrainEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() +
610 "/" +
611 terrainEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
612 );
613 try {
614 required_dynamic_cast<GUIImageNode*>(terrainEditorTabController->screenNode->getNodeById("foliagebrush_prototype_file"))->setSource(brushPrototype->getFileName());
615 } catch (Exception& exception) {
616 Console::println(string("OnTerrainBrushPrototypeFileOpenAction::performAction(): ") + exception.what());
617 }
618 terrainEditorTabController->updateFoliageBrush();
619 terrainEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
620 }
621
622 /**
623 * Public constructor
624 * @param terrainEditorTabController terrain editor tab controller
625 */
626 OnTerrainBrushPrototypeFileOpenAction(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
627 }
628
629 private:
630 TerrainEditorTabController* terrainEditorTabController;
631 };
632
633 auto prototype = view->getPrototype();
634 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
635 if (terrain == nullptr) return;
636
637 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
638 auto foliageBrushIdx = -1;
639 auto foliageBrushPrototypeIdx = -1;
640 if (checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
641 auto brush = terrain->getBrush(foliageBrushIdx);
642 if (brush == nullptr) return;
643 auto brushPrototype = brush->getPrototype(foliageBrushPrototypeIdx);
644 if (brushPrototype == nullptr) return;
645
646 vector<string> extensions = {"tmodel"};
648 brushPrototype->getFileName().empty() == false?Tools::getPathName(brushPrototype->getFileName()):string(),
649 "Load terrain brush texture from: ",
650 extensions,
651 Tools::getFileName(brushPrototype->getFileName()),
652 true,
653 new OnTerrainBrushPrototypeFileOpenAction(this)
654 );
655 } else
656 if (node->getId() == "foliagebrush_prototype_file_remove") {
657 auto prototype = view->getPrototype();
658 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
659 if (terrain == nullptr) return;
660
661 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
662 auto foliageBrushIdx = -1;
663 auto foliageBrushPrototypeIdx = -1;
664 if (checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
665 auto brush = terrain->getBrush(foliageBrushIdx);
666 if (brush == nullptr) return;
667 auto brushPrototype = brush->getPrototype(foliageBrushPrototypeIdx);
668 if (brushPrototype == nullptr) return;
669 brushPrototype->setFileName(string());
671 try {
672 required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("foliagebrush_prototype_file"))->setSource(brushPrototype->getFileName());
673 } catch (Exception& exception) {
674 Console::println(string("TerrainEditorTabController::onActionPerformed(): ") + exception.what());
675 }
676 } else
677 if (node->getId() == "terrainbrush_texture_open") {
678 class OnTerrainBrushFileOpenAction: public virtual Action
679 {
680 public:
681 void performAction() override {
682 if (terrainEditorTabController->currentTerrainBrushTexture != nullptr) terrainEditorTabController->currentTerrainBrushTexture->releaseReference();
683 terrainEditorTabController->currentTerrainBrushTexture = nullptr;
684 terrainEditorTabController->currentTerrainBrushTextureFileName =
685 terrainEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() +
686 "/" +
687 terrainEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName();
688 terrainEditorTabController->currentTerrainBrushTexture =
689 TextureReader::read(
690 Tools::getPathName(terrainEditorTabController->currentTerrainBrushTextureFileName),
691 Tools::getFileName(terrainEditorTabController->currentTerrainBrushTextureFileName),
692 false,
693 false
694 );
695 required_dynamic_cast<GUITextureNode*>(terrainEditorTabController->screenNode->getNodeById("terrainbrush_texture"))->setTexture(terrainEditorTabController->currentTerrainBrushTexture);
696 terrainEditorTabController->view->setBrush(
697 terrainEditorTabController->currentTerrainBrushTexture,
698 terrainEditorTabController->currentTerrainBrushScale,
699 terrainEditorTabController->currentTerrainBrushStrength
700 );
701 terrainEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
702 }
703
704 /**
705 * Public constructor
706 * @param terrainEditorTabController terrain editor tab controller
707 */
708 OnTerrainBrushFileOpenAction(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
709 }
710
711 private:
712 TerrainEditorTabController* terrainEditorTabController;
713 };
714
715 vector<string> extensions = TextureReader::getTextureExtensions();
717 currentTerrainBrushTextureFileName.empty() == false?Tools::getPathName(currentTerrainBrushTextureFileName):string(),
718 "Load terrain brush texture from: ",
719 extensions,
720 Tools::getFileName(currentTerrainBrushTextureFileName),
721 true,
722 new OnTerrainBrushFileOpenAction(this)
723 );
724 } else
725 if (node->getId() == "terrainbrush_texture_remove") {
728 required_dynamic_cast<GUITextureNode*>(screenNode->getNodeById("terrainbrush_texture"))->setTexture(currentTerrainBrushTexture);
729 } else
730 if (node->getId() == "terrainbrush_texture_browseto") {
731 } else
732 if (node->getId() == "terrain_mirrormode_apply") {
733 auto prototype = view->getPrototype();
734 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
735 if (terrain == nullptr) return;
736 auto mirrorMode = required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("terrain_mirrormode"))->getController()->getValue().getString();
737 auto flipped = required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("terrain_mirrormode_flipped"))->getController()->getValue().getString() == "1";
738 view->reset();
739 if (mirrorMode == "1") {
740 // no op
741 } else
742 if (mirrorMode == "2") {
743 Terrain2::mirrorXAxis(
744 flipped,
745 terrain->getWidth(),
746 terrain->getDepth(),
747 terrain->getHeightVector(),
748 terrain->getWaterPositionMapsHeight(),
749 terrain->getWaterPositionMaps(),
750 terrain->getFoliageMaps()
751 );
752 terrain->setWidth(terrain->getWidth() * 2.0f);
753 } else
754 if (mirrorMode == "3") {
755 Terrain2::mirrorZAxis(
756 flipped,
757 terrain->getWidth(),
758 terrain->getDepth(),
759 terrain->getHeightVector(),
760 terrain->getWaterPositionMapsHeight(),
761 terrain->getWaterPositionMaps(),
762 terrain->getFoliageMaps()
763 );
764 terrain->setDepth(terrain->getDepth() * 2.0f);
765 } else
766 if (mirrorMode == "4") {
767 Terrain2::mirrorXAxis(
768 flipped,
769 terrain->getWidth(),
770 terrain->getDepth(),
771 terrain->getHeightVector(),
772 terrain->getWaterPositionMapsHeight(),
773 terrain->getWaterPositionMaps(),
774 terrain->getFoliageMaps()
775 );
776 terrain->setWidth(terrain->getWidth() * 2.0f);
777 Terrain2::mirrorZAxis(
778 flipped,
779 terrain->getWidth(),
780 terrain->getDepth(),
781 terrain->getHeightVector(),
782 terrain->getWaterPositionMapsHeight(),
783 terrain->getWaterPositionMaps(),
784 terrain->getFoliageMaps()
785 );
786 terrain->setDepth(terrain->getDepth() * 2.0f);
787 }
789 }
790 }
792}
793
795 auto prototype = view->getPrototype();
796 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
797 string xml;
798 xml+= "<selectbox-parent-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escapeQuotes("Terrain") + "\" value=\"" + GUIParser::escapeQuotes("terrain") + "\">\n";
800 xml+= "<selectbox-option image=\"resources/engine/images/terrain.png\" text=\"" + GUIParser::escapeQuotes("Terrain Brush") + "\" value=\"" + GUIParser::escapeQuotes("terrain.brush") + "\" />\n";
801 if (terrain != nullptr && terrain->getWaterPositionMapsIndices().empty() == false) {
802 xml+= "<selectbox-parent-option image=\"resources/engine/images/terrain_water.png\" text=\"" + GUIParser::escapeQuotes("Water") + "\" value=\"" + GUIParser::escapeQuotes("terrain.waters") + "\">\n";
803 auto i = 0;
804 for (auto waterIdx: terrain->getWaterPositionMapsIndices()) {
805 xml+= "<selectbox-option image=\"resources/engine/images/terrain_water.png\" text=\"" + GUIParser::escapeQuotes("Water " + to_string(i)) + "\" value=\"" + GUIParser::escapeQuotes("terrain.waters." + to_string(waterIdx)) + "\" />\n";
806 i++;
807 }
808 xml+= "</selectbox-parent-option>\n";
809 } else {
810 xml+= "<selectbox-option image=\"resources/engine/images/terrain_water.png\" text=\"" + GUIParser::escapeQuotes("Water") + "\" value=\"" + GUIParser::escapeQuotes("terrain.waters") + "\" />\n";
811 }
812 if (terrain != nullptr && terrain->getBrushes().empty() == false) {
813 xml+= "<selectbox-parent-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escapeQuotes("Foliage") + "\" value=\"" + GUIParser::escapeQuotes("terrain.foliage") + "\">\n";
814 auto i = 0;
815 for (auto brush: terrain->getBrushes()) {
816 if (brush->getPrototypes().empty() == false) {
817 xml+= "<selectbox-parent-option image=\"resources/engine/images/foliage.png\" text=\"" + GUIParser::escapeQuotes("Foliage Brush " + to_string(i)) + "\" value=\"" + GUIParser::escapeQuotes("terrain.foliage." + to_string(i)) + "\" >\n";
818 auto j = 0;
819 for (auto brushPrototype: brush->getPrototypes()) {
820 xml+= "<selectbox-option image=\"resources/engine/images/mesh.png\" text=\"" + GUIParser::escapeQuotes("Prototype " + to_string(j)) + "\" value=\"" + GUIParser::escapeQuotes("terrain.foliagebrushes." + to_string(i) + "." + to_string(j)) + "\" />\n";
821 j++;
822 }
823 xml+= "</selectbox-parent-option>\n";
824 } else {
825 xml+= "<selectbox-option image=\"resources/engine/images/foliage.png\" text=\"" + GUIParser::escapeQuotes("Foliage Brush " + to_string(i)) + "\" value=\"" + GUIParser::escapeQuotes("terrain.foliage." + to_string(i)) + "\" />\n";
826 }
827 i++;
828 }
829 xml+= "</selectbox-parent-option>\n";
830 } else {
831 xml+= "<selectbox-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escapeQuotes("Foliage") + "\" value=\"" + GUIParser::escapeQuotes("terrain.foliage") + "\" />\n";
832 }
833 auto foliagePrototypeIndices = terrain != nullptr?terrain->getFoliagePrototypeIndices():vector<int>();
834 if (foliagePrototypeIndices.empty() == false) {
835 xml+= "<selectbox-parent-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escapeQuotes("Prototypes") + "\" value=\"" + GUIParser::escapeQuotes("terrain.foliageprototypes") + "\">\n";
836 auto i = 0;
837 for (auto prototypeIdx: foliagePrototypeIndices) {
838 auto foliagePrototype = terrain->getFoliagePrototype(prototypeIdx);
839 xml+= "<selectbox-option image=\"resources/engine/images/mesh.png\" text=\"" + GUIParser::escapeQuotes(Tools::removeFileEnding(Tools::getFileName(foliagePrototype->getFileName()))) + "\" value=\"" + GUIParser::escapeQuotes("terrain.foliageprototypes." + to_string(prototypeIdx)) + "\" />\n";
840 i++;
841 }
842 xml+= "</selectbox-parent-option>\n";
843 }
844 xml+= "</selectbox-parent-option>\n";
846}
847
850}
851
853 auto prototype = view->getPrototype();
854 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
855 if (terrain == nullptr) return;
856
857 //
858 try {
859 view->reset();
860 auto width = Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("terrain_size_x"))->getController()->getValue().getString());
861 auto depth = Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("terrain_size_z"))->getController()->getValue().getString());
862 if (width < 1.0f || width > 4000.0f) throw ExceptionBase("Width must be within 1 .. 4000");
863 if (depth < 1.0f || depth > 4000.0f) throw ExceptionBase("Depth must be within 1 .. 4000");
864 terrain->getHeightVector().clear();
865 for (auto idx: terrain->getWaterPositionMapsIndices()) terrain->removeWaterPositionMap(idx);
866 BoundingBox terrainBoundingBox;
867 vector<Model*> terrainModels;
868 Terrain2::createTerrainModels(width, depth, 0.0f, terrain->getHeightVector(), terrainBoundingBox, terrainModels);
869 Terrain2::createFoliageMaps(terrainBoundingBox, terrain->getFoliageMaps());
870 Terrain2::createFoliageMaps(terrainBoundingBox, newFoliageMaps);
871 terrain->setWidth(terrainBoundingBox.getDimensions().getX());
872 terrain->setDepth(terrainBoundingBox.getDimensions().getZ());
874 } catch (Exception& exception) {
875 showErrorPopUp("Warning", (string(exception.what())));
876 }
877
878 //
879 class ReloadOutlinerAction: public Action {
880 public:
881 void performAction() override {
882 terrainEditorTabController->view->getEditorView()->reloadTabOutliner("terrain");
883 }
884 ReloadOutlinerAction(TerrainEditorTabController* terrainEditorTabController): terrainEditorTabController(terrainEditorTabController) {
885 }
886 private:
887 TerrainEditorTabController* terrainEditorTabController;
888 };
889 Engine::getInstance()->enqueueAction(new ReloadOutlinerAction(this));
890}
891
893 if (currentTerrainBrushOperation != Terrain2::BRUSHOPERATION_NONE) {
895 if (view->getEditorView()->getScreenController()->getOutlinerSelection() == "terrain.brush") {
897 }
898 } else
899 if (currentFoliageBrushOperation != Terrain2::BRUSHOPERATION_NONE) {
900 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
901 auto foliageBrushIdx = -1;
902 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == true) {
903 foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
904 } else {
905 auto foliageBrushPrototypeIdx = -1;
906 if (checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
907 }
908 auto prototype = view->getPrototype();
909 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
910 if (terrain == nullptr) return;
911 auto brush = terrain->getBrush(foliageBrushIdx);
912 if (brush == nullptr) return;
913 brush->setSize(scale);
914 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == true) updateFoliageBrushDetails();
916 }
917}
918
920 if (currentTerrainBrushOperation != Terrain2::BRUSHOPERATION_NONE) {
921 currentTerrainBrushStrength = densityStrength;
922 if (view->getEditorView()->getScreenController()->getOutlinerSelection() == "terrain.brush") {
924 }
925 } else
926 if (currentFoliageBrushOperation != Terrain2::BRUSHOPERATION_NONE) {
927 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
928 auto foliageBrushIdx = -1;
929 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == true) {
930 foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
931 } else {
932 auto foliageBrushPrototypeIdx = -1;
933 if (checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
934 }
935 auto prototype = view->getPrototype();
936 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
937 if (terrain == nullptr) return;
938 auto brush = terrain->getBrush(foliageBrushIdx);
939 if (brush == nullptr) return;
940 brush->setDensity(densityStrength);
941 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == true) updateFoliageBrushDetails();
943 }
944}
945
947 auto prototype = view->getPrototype();
948 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
949 if (terrain == nullptr) return;
950
951 //
953 "<template id=\"details_terrain\" src=\"resources/engine/gui/template_details_terrain.xml\" />\n"
954 );
955
956 //
957 try {
958 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_terrain"))->getActiveConditions().add("open");
959 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("terrain_size_x"))->getController()->setValue(MutableString(terrain->getWidth()));
960 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("terrain_size_z"))->getController()->setValue(MutableString(terrain->getDepth()));
961 } catch (Exception& exception) {
962 Console::println(string("TerrainEditorTabController::setTerrainDetails(): An error occurred: ") + exception.what());;
963 showErrorPopUp("Warning", (string(exception.what())));
964 }
965}
966
969 "<template id=\"details_terrainbrush\" src=\"resources/engine/gui/template_details_terrainbrush.xml\" />\n"
970 );
971
972 //
973 try {
974 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_terrainbrush"))->getActiveConditions().add("open");
975 required_dynamic_cast<GUITextureNode*>(screenNode->getNodeById("terrainbrush_texture"))->setTexture(currentTerrainBrushTexture);
976 } catch (Exception& exception) {
977 Console::println(string("TerrainEditorTabController::setTerrainBrushDetails(): An error occurred: ") + exception.what());;
978 showErrorPopUp("Warning", (string(exception.what())));
979 }
980
981 //
983}
984
986 try {
987 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("terrainbrush_size"))->getController()->setValue(MutableString(currentTerrainBrushScale));
988 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("terrainbrush_strength"))->getController()->setValue(MutableString(currentTerrainBrushStrength));
989 } catch (Exception& exception) {
990 Console::println(string("TerrainEditorTabController::updateTerrainBrushDetails(): An error occurred: ") + exception.what());;
991 showErrorPopUp("Warning", (string(exception.what())));
992 }
993}
994
996 try {
997 currentTerrainBrushScale = Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("terrainbrush_size"))->getController()->getValue().getString()); // TODO: a.drewke, size != scale
998 currentTerrainBrushStrength = Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("terrainbrush_strength"))->getController()->getValue().getString());
999 } catch (Exception& exception) {
1000 Console::println(string("TerrainEditorTabController::setTerrainBrushDetails(): An error occurred: ") + exception.what());;
1001 showErrorPopUp("Warning", (string(exception.what())));
1002 }
1003 // TODO: a.drewke, maybe improve me
1005}
1006
1009 "<template id=\"details_foliagebrush\" src=\"resources/engine/gui/template_details_foliagebrush.xml\" />\n"
1010 );
1011
1012 //
1013 try {
1014 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_foliagebrush"))->getActiveConditions().add("open");
1015 } catch (Exception& exception) {
1016 Console::println(string("TerrainEditorTabController::setFoliageBrushDetails(): An error occurred: ") + exception.what());;
1017 showErrorPopUp("Warning", (string(exception.what())));
1018 }
1019
1020 //
1022}
1023
1025 //
1026 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
1027 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == false) return;
1028 auto foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
1029 auto prototype = view->getPrototype();
1030 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
1031 if (terrain == nullptr) return;
1032 auto brush = terrain->getBrush(foliageBrushIdx);
1033 if (brush == nullptr) return;
1034
1035 //
1036 try {
1037 required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("foliagebrush_texture"))->setSource(brush->getFileName());
1038 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_size"))->getController()->setValue(MutableString(brush->getSize()));
1039 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_density"))->getController()->setValue(MutableString(brush->getDensity()));
1040 } catch (Exception& exception) {
1041 Console::println(string("TerrainEditorTabController::updateFoliageBrushDetails(): An error occurred: ") + exception.what());
1042 showErrorPopUp("Warning", (string(exception.what())));
1043 }
1044}
1045
1047 //
1048 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
1049 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == false) return;
1050 auto foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
1051 auto prototype = view->getPrototype();
1052 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
1053 if (terrain == nullptr) return;
1054 auto brush = terrain->getBrush(foliageBrushIdx);
1055 if (brush == nullptr) return;
1056
1057 //
1058 try {
1059 brush->setSize(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_size"))->getController()->getValue().getString()));
1060 brush->setDensity(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_density"))->getController()->getValue().getString()));
1061 } catch (Exception& exception) {
1062 Console::println(string("TerrainEditorTabController::applyFoliageBrushDetails(): An error occurred: ") + exception.what());;
1063 showErrorPopUp("Warning", (string(exception.what())));
1064 }
1065}
1066
1069 "<template id=\"details_foliagebrush_prototype\" src=\"resources/engine/gui/template_details_foliagebrush_prototype.xml\" />\n"
1070 );
1071
1072 auto prototype = view->getPrototype();
1073 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
1074 if (terrain == nullptr) return;
1075
1076 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
1077 auto foliageBrushIdx = -1;
1078 auto foliageBrushPrototypeIdx = -1;
1079 if (checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
1080 auto brush = terrain->getBrush(foliageBrushIdx);
1081 if (brush == nullptr) return;
1082 auto brushPrototype = brush->getPrototype(foliageBrushPrototypeIdx);
1083 if (brushPrototype == nullptr) return;
1084
1085 //
1086 try {
1087 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_foliagebrush_prototype"))->getActiveConditions().add("open");
1088
1089 required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("foliagebrush_prototype_file"))->setSource(brushPrototype->getFileName());
1090 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_object_count"))->getController()->setValue(MutableString(brushPrototype->getCount()));
1091 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_normalalign"))->getController()->setValue(MutableString(brushPrototype->isNormalAlign() == true?"1":""));
1092 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_x_min"))->getController()->setValue(MutableString(brushPrototype->getRotationXMin()));
1093 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_x_max"))->getController()->setValue(MutableString(brushPrototype->getRotationXMax()));
1094 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_y_min"))->getController()->setValue(MutableString(brushPrototype->getRotationYMin()));
1095 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_y_max"))->getController()->setValue(MutableString(brushPrototype->getRotationYMax()));
1096 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_z_min"))->getController()->setValue(MutableString(brushPrototype->getRotationZMin()));
1097 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_z_max"))->getController()->setValue(MutableString(brushPrototype->getRotationZMax()));
1098 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_scalerange_min"))->getController()->setValue(MutableString(brushPrototype->getScaleMin()));
1099 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_scalerange_max"))->getController()->setValue(MutableString(brushPrototype->getScaleMax()));
1100 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_heightrange_min"))->getController()->setValue(MutableString(brushPrototype->getHeightMin()));
1101 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_heightrange_max"))->getController()->setValue(MutableString(brushPrototype->getHeightMax()));
1102 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_sloperange_min"))->getController()->setValue(MutableString(brushPrototype->getSlopeMin()));
1103 required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_sloperange_max"))->getController()->setValue(MutableString(brushPrototype->getSlopeMax()));
1104 } catch (Exception& exception) {
1105 Console::println(string("TerrainEditorTabController::setFoliageBrushPrototypeDetails(): An error occurred: ") + exception.what());;
1106 showErrorPopUp("Warning", (string(exception.what())));
1107 }
1108}
1109
1111 auto prototype = view->getPrototype();
1112 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
1113 if (terrain == nullptr) return;
1114
1115 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
1116 auto foliageBrushIdx = -1;
1117 auto foliageBrushPrototypeIdx = -1;
1118 if (checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
1119 auto brush = terrain->getBrush(foliageBrushIdx);
1120 if (brush == nullptr) return;
1121 auto brushPrototype = brush->getPrototype(foliageBrushPrototypeIdx);
1122 if (brushPrototype == nullptr) return;
1123
1124 try {
1125 brushPrototype->setCount(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_object_count"))->getController()->getValue().getString()));
1126 brushPrototype->setNormalAlign(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_normalalign"))->getController()->getValue().getString() == "1");
1127 brushPrototype->setRotationXMin(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_x_min"))->getController()->getValue().getString()));
1128 brushPrototype->setRotationXMax(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_x_max"))->getController()->getValue().getString()));
1129 brushPrototype->setRotationYMin(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_y_min"))->getController()->getValue().getString()));
1130 brushPrototype->setRotationYMax(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_y_max"))->getController()->getValue().getString()));
1131 brushPrototype->setRotationZMin(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_z_min"))->getController()->getValue().getString()));
1132 brushPrototype->setRotationZMax(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_rotationrange_z_max"))->getController()->getValue().getString()));
1133 brushPrototype->setScaleMin(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_scalerange_min"))->getController()->getValue().getString()));
1134 brushPrototype->setScaleMax(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_scalerange_max"))->getController()->getValue().getString()));
1135 brushPrototype->setHeightMin(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_heightrange_min"))->getController()->getValue().getString()));
1136 brushPrototype->setHeightMax(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_heightrange_max"))->getController()->getValue().getString()));
1137 brushPrototype->setSlopeMin(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_sloperange_min"))->getController()->getValue().getString()));
1138 brushPrototype->setSlopeMax(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("foliagebrush_prototype_sloperange_max"))->getController()->getValue().getString()));
1139 } catch (Exception& exception) {
1140 Console::println(string("TerrainEditorTabController::applyFoliageBrushPrototypeDetails(): An error occurred: ") + exception.what());;
1141 showErrorPopUp("Warning", (string(exception.what())));
1142 }
1143}
1144
1145bool TerrainEditorTabController::checkOutlinerFoliageBrushPrototype(const string& outlinerNode, int& foliageBrushIdx, int& foliageBrushPrototypeIdx) {
1146 if (StringTools::startsWith(outlinerNode, "terrain.foliagebrushes.") == false) return false;
1147 auto brushIdxBeginIdx = string("terrain.foliagebrushes.").size();
1148 auto brushIdxEndIdx = outlinerNode.find('.', brushIdxBeginIdx + 1);
1149 auto prototypeBeginIdx = brushIdxEndIdx + 1;
1150 auto prototypeEndIdx = outlinerNode.size();
1151 foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, brushIdxBeginIdx, brushIdxEndIdx));
1152 foliageBrushPrototypeIdx = Integer::parse(StringTools::substring(outlinerNode, prototypeBeginIdx, prototypeEndIdx));
1153 return true;
1154}
1155
1156void TerrainEditorTabController::updateDetails(const string& outlinerNode) {
1157 view->getEditorView()->setDetailsContent(string());
1158 if (outlinerNode == "terrain") {
1161 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
1163 required_dynamic_cast<GUIElementNode*>(view->getEditorView()->getScreenController()->getScreenNode()->getNodeById(view->getTabId() + "_tab_viewport"))->getActiveConditions().set("terrain");
1164 } else
1165 if (outlinerNode == "terrain.brush") {
1168 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
1169 view->unsetBrush();
1170 required_dynamic_cast<GUIElementNode*>(view->getEditorView()->getScreenController()->getScreenNode()->getNodeById(view->getTabId() + "_tab_viewport"))->getActiveConditions().set("terrain");
1171 } else
1172 if (outlinerNode == "terrain.waters" || StringTools::startsWith(outlinerNode, "terrain.waters.") == true) {
1174 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
1175 view->unsetBrush();
1176 required_dynamic_cast<GUIElementNode*>(view->getEditorView()->getScreenController()->getScreenNode()->getNodeById(view->getTabId() + "_tab_viewport"))->getActiveConditions().set("water");
1177 } else
1178 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == true) {
1180 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_NONE;
1183 required_dynamic_cast<GUIElementNode*>(view->getEditorView()->getScreenController()->getScreenNode()->getNodeById(view->getTabId() + "_tab_viewport"))->getActiveConditions().set("foliage");
1184 } else
1185 if (StringTools::startsWith(outlinerNode, "terrain.foliagebrushes.") == true) {
1187 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_NONE;
1190 required_dynamic_cast<GUIElementNode*>(view->getEditorView()->getScreenController()->getScreenNode()->getNodeById(view->getTabId() + "_tab_viewport"))->getActiveConditions().set("foliage");
1191 } else {
1192 view->unsetBrush();
1193 currentTerrainBrushOperation = Terrain2::BRUSHOPERATION_NONE;
1194 currentFoliageBrushOperation = Terrain2::BRUSHOPERATION_NONE;
1195 required_dynamic_cast<GUIElementNode*>(view->getEditorView()->getScreenController()->getScreenNode()->getNodeById(view->getTabId() + "_tab_viewport"))->getActiveConditions().removeAll();
1197 }
1198}
1199
1201 auto prototype = view->getPrototype();
1202 if (prototype == nullptr) return;
1203
1204 //
1205 try {
1206 auto width = prototype->getTerrain()->getWidth();
1207 auto depth = prototype->getTerrain()->getDepth();
1208 BoundingBox terrainBoundingBox;
1209 vector<Model*> terrainModels;
1210 Terrain2::createTerrainModels(width, depth, 0.0f, prototype->getTerrain()->getHeightVector(), terrainBoundingBox, terrainModels);
1211 view->unsetWater();
1212 view->setTerrain(terrainBoundingBox, terrainModels);
1213 auto waterPositionMapsIndices = prototype->getTerrain()->getWaterPositionMapsIndices();
1214 for (auto waterPositionMapIdx: waterPositionMapsIndices) {
1215 vector<Model*> waterModels;
1216 Terrain2::createWaterModels(
1217 terrainBoundingBox,
1218 prototype->getTerrain()->getWaterPositionMap(waterPositionMapIdx),
1219 prototype->getTerrain()->getWaterPositionMapHeight(waterPositionMapIdx),
1220 waterPositionMapIdx,
1221 waterModels
1222 );
1223 view->addWater(
1224 waterPositionMapIdx,
1225 waterModels,
1226 Terrain2::computeWaterReflectionEnvironmentMappingPosition(
1227 prototype->getTerrain()->getWaterPositionMap(waterPositionMapIdx),
1228 prototype->getTerrain()->getWaterPositionMapHeight(waterPositionMapIdx)
1229 )
1230 );
1231 }
1232 view->addFoliage();
1233 Terrain2::createFoliageMaps(terrainBoundingBox, newFoliageMaps);
1234 prototype->getTerrain()->setWidth(terrainBoundingBox.getDimensions().getX());
1235 prototype->getTerrain()->setDepth(terrainBoundingBox.getDimensions().getZ());
1236 } catch (Exception& exception) {
1237 showErrorPopUp("Warning", (string(exception.what())));
1238 }
1239}
1240
1241void TerrainEditorTabController::applyTerrainBrush(BoundingBox& terrainBoundingBox, vector<Model*>& terrainModels, const Vector3& brushCenterPosition, int64_t deltaTime) {
1242 auto prototype = view->getPrototype();
1243 if (prototype == nullptr) return;
1244 if (terrainModels.empty() == true) return;
1245
1246 // apply brush first
1247 Terrain2::applyBrushToTerrainModels(
1248 terrainBoundingBox,
1249 terrainModels,
1250 prototype->getTerrain()->getHeightVector(),
1251 brushCenterPosition,
1254 currentTerrainBrushStrength * static_cast<float>(deltaTime) / 200.0f, // if strength = 1.0f it will e.g. add to level 5 meters/second
1257 );
1258
1259 //
1260 Terrain2::FoliageBrush foliageBrush = {
1261 foliageBrush.brushTexture = Terrain2::BRUSHOPERATION_RAMP?rampTerrainBrushTexture:currentTerrainBrushTexture,
1263 foliageBrush.brushDensity = 1.0f
1264 };
1265
1266 // and update foliage
1267 Terrain2::updateFoliageTerrainBrush(
1268 terrainBoundingBox,
1269 prototype->getTerrain()->getHeightVector(),
1270 brushCenterPosition,
1272 prototype->getTerrain()->getFoliageMaps(),
1274 );
1275
1276 //
1279}
1280
1281bool TerrainEditorTabController::determineCurrentBrushHeight(BoundingBox& terrainBoundingBox, vector<Model*> terrainModels, const Vector3& brushCenterPosition) {
1282 auto prototype = view->getPrototype();
1283 if (prototype == nullptr) return false;
1284 if (currentTerrainBrushOperation != Terrain2::BRUSHOPERATION_FLATTEN &&
1285 currentTerrainBrushOperation != Terrain2::BRUSHOPERATION_WATER_ADD &&
1286 currentTerrainBrushOperation != Terrain2::BRUSHOPERATION_RAMP) {
1287 return true;
1288 }
1289 if (haveCurrentTerrainBrushHeight == true) return true;
1290 if (terrainModels.empty() == true) return false;
1291 auto terrainModel = terrainModels[0];
1292 if (terrainModel == nullptr) return false;
1293 haveCurrentTerrainBrushHeight = Terrain2::getTerrainModelsHeight(
1294 terrainBoundingBox,
1295 terrainModels,
1296 prototype->getTerrain()->getHeightVector(),
1297 brushCenterPosition,
1299 );
1301}
1302
1303bool TerrainEditorTabController::determineRampHeight(BoundingBox& terrainBoundingBox, vector<Model*> terrainModels, const Vector3& position, float& height) {
1304 auto prototype = view->getPrototype();
1305 if (prototype == nullptr) return false;
1306 if (currentTerrainBrushOperation != Terrain2::BRUSHOPERATION_RAMP) {
1307 return false;
1308 }
1309 if (terrainModels.empty() == true) return false;
1310 auto terrainModel = terrainModels[0];
1311 if (terrainModel == nullptr) return false;
1312 return Terrain2::getTerrainModelsHeight(
1313 terrainBoundingBox,
1314 terrainModels,
1315 prototype->getTerrain()->getHeightVector(),
1316 position,
1317 height
1318 );
1319}
1320
1323}
1324
1325void TerrainEditorTabController::applyRampTerrainBrush(BoundingBox& terrainBoundingBox, vector<Model*>& terrainModels, const Vector3& position, float rotation, const Vector2& scale, float minHeight, float maxHeight) {
1326 auto prototype = view->getPrototype();
1327 if (prototype == nullptr) return;
1328 if (terrainModels.empty() == true) return;
1329
1330 // apply brush first
1331 Terrain2::applyRampBrushToTerrainModels(
1332 terrainBoundingBox,
1333 terrainModels,
1334 prototype->getTerrain()->getHeightVector(),
1335 position,
1337 rotation,
1338 scale,
1339 minHeight,
1340 maxHeight
1341 );
1342
1343 // and update foliage
1344 Terrain2::updateFoliageTerrainRampBrush(
1345 terrainBoundingBox,
1346 prototype->getTerrain()->getHeightVector(),
1347 position,
1349 rotation,
1350 scale,
1351 prototype->getTerrain()->getFoliageMaps(),
1353 );
1354
1355 //
1358}
1359
1360void TerrainEditorTabController::createWater(BoundingBox& terrainBoundingBox, const Vector3& brushCenterPosition, vector<Model*>& waterModels, Vector3& waterReflectionEnvironmentMappingPosition) {
1361 auto prototype = view->getPrototype();
1362 if (prototype == nullptr) return;
1363 auto waterPositionMapIdx = prototype->getTerrain()->allocateWaterPositionMapIdx();
1364 prototype->getTerrain()->setWaterPositionMapHeight(waterPositionMapIdx, currentTerrainBrushHeight);
1365 if (Terrain2::computeWaterPositionMap(
1366 terrainBoundingBox,
1367 prototype->getTerrain()->getHeightVector(),
1368 brushCenterPosition,
1369 prototype->getTerrain()->getWaterPositionMapHeight(waterPositionMapIdx),
1370 prototype->getTerrain()->getWaterPositionMap(waterPositionMapIdx)) == true) {
1371 //
1372 Terrain2::createWaterModels(
1373 terrainBoundingBox,
1374 prototype->getTerrain()->getWaterPositionMap(waterPositionMapIdx),
1375 prototype->getTerrain()->getWaterPositionMapHeight(waterPositionMapIdx),
1376 waterPositionMapIdx,
1377 waterModels
1378 );
1379 waterReflectionEnvironmentMappingPosition = Terrain2::computeWaterReflectionEnvironmentMappingPosition(
1380 prototype->getTerrain()->getWaterPositionMap(waterPositionMapIdx),
1381 prototype->getTerrain()->getWaterPositionMapHeight(waterPositionMapIdx)
1382 );
1383 view->addWater(
1384 waterPositionMapIdx,
1385 waterModels,
1386 waterReflectionEnvironmentMappingPosition
1387 );
1388 }
1389 view->getEditorView()->reloadTabOutliner("terrain.waters." + to_string(waterPositionMapIdx));
1390}
1391
1392void TerrainEditorTabController::deleteWater(int waterPositionMapIdx) {
1393 auto prototype = view->getPrototype();
1394 if (prototype == nullptr) return;
1395 prototype->getTerrain()->removeWaterPositionMap(waterPositionMapIdx);
1396 view->removeWater(waterPositionMapIdx);
1397 view->getEditorView()->reloadTabOutliner("terrain.waters");
1398}
1399
1401 auto prototype = view->getPrototype();
1402 if (prototype == nullptr) return;
1403
1404 //
1405 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
1406 auto foliageBrushIdx = -1;
1407 auto foliageBrushPrototypeIdx = -1;
1408 if (checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
1409 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
1410 if (terrain == nullptr) return;
1411 auto brush = terrain->getBrush(foliageBrushIdx);
1412 if (brush == nullptr) return;
1413
1414 // texture
1415 auto foliageBrushTexture = TextureReader::read(Tools::getPathName(brush->getFileName()), Tools::getFileName(brush->getFileName()), false, false);
1416 if (foliageBrushTexture == nullptr) return;
1417
1418 //
1419 view->setBrush(foliageBrushTexture, brush->getSize(), brush->getDensity());
1420}
1421
1423 auto prototype = view->getPrototype();
1424 if (prototype == nullptr) return;
1425
1426 //
1427 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
1428 auto foliageBrushIdx = -1;
1429 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == true) {
1430 foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
1431 } else {
1432 auto foliageBrushPrototypeIdx = -1;
1433 if (checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
1434 }
1435
1436 //
1437 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
1438 if (terrain == nullptr) return;
1439 auto brush = terrain->getBrush(foliageBrushIdx);
1440 if (brush == nullptr) return;
1441
1442 //
1443 if (foliageBrush.brushTexture != nullptr) foliageBrush.brushTexture->releaseReference();
1444
1445 //
1446 foliageBrush.brushTexture = TextureReader::read(Tools::getPathName(brush->getFileName()), Tools::getFileName(brush->getFileName()), false, false);
1447 foliageBrush.brushScale = brush->getSize();
1448 foliageBrush.brushDensity = brush->getDensity();
1449 foliageBrush.brushTexture->acquireReference();
1450
1451 //
1452 foliageBrushPrototypes.clear();
1453 for (auto foliageBrushPrototype: brush->getPrototypes()) {
1454 Prototype* foliagePrototype = nullptr;
1455 if (foliageBrushPrototype->getFileName().empty() == false) {
1456 try {
1457 foliagePrototype = PrototypeReader::read(
1458 PrototypeReader::getResourcePathName(Tools::getPathName(foliageBrushPrototype->getFileName()), foliageBrushPrototype->getFileName()),
1459 Tools::getFileName(foliageBrushPrototype->getFileName())
1460 );
1461 } catch (Exception& exception) {
1462 Console::println("TerrainEditorTabController::updateFoliageBrush(): failed to load prototype: " + foliageBrushPrototype->getFileName());
1463 }
1464 }
1465 if (foliagePrototype == nullptr) continue;
1466 foliageBrushPrototypes.push_back(
1467 {
1468 .prototypeId = terrain->getFoliagePrototypeIndex(foliagePrototype),
1469 .count = foliageBrushPrototype->getCount(),
1470 .normalAlign = foliageBrushPrototype->isNormalAlign(),
1471 .rotationXMin = foliageBrushPrototype->getRotationXMin(),
1472 .rotationXMax = foliageBrushPrototype->getRotationXMax(),
1473 .rotationYMin = foliageBrushPrototype->getRotationYMin(),
1474 .rotationYMax = foliageBrushPrototype->getRotationYMax(),
1475 .rotationZMin = foliageBrushPrototype->getRotationZMin(),
1476 .rotationZMax = foliageBrushPrototype->getRotationZMax(),
1477 .scaleMin = foliageBrushPrototype->getScaleMin(),
1478 .scaleMax = foliageBrushPrototype->getScaleMax(),
1479 .heightMin = foliageBrushPrototype->getHeightMin(),
1480 .heightMax = foliageBrushPrototype->getHeightMax(),
1481 .slopeMin = foliageBrushPrototype->getSlopeMin(),
1482 .slopeMax = foliageBrushPrototype->getSlopeMax()
1483 }
1484 );
1485 }
1486
1487 //
1488 view->setBrush(foliageBrush.brushTexture, brush->getSize(), brush->getDensity());
1489}
1490
1491void TerrainEditorTabController::applyFoliageBrush(BoundingBox& terrainBoundingBox, const Vector3& brushCenterPosition, int64_t deltaTime) {
1492 auto prototype = view->getPrototype();
1493 if (prototype == nullptr) return;
1494
1495 //
1496 auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
1497 auto foliageBrushIdx = -1;
1498 if (StringTools::startsWith(outlinerNode, "terrain.foliage.") == true) {
1499 foliageBrushIdx = Integer::parse(StringTools::substring(outlinerNode, string("terrain.foliage.").size(), outlinerNode.size()));
1500 } else {
1501 auto foliageBrushPrototypeIdx = -1;
1502 if (checkOutlinerFoliageBrushPrototype(outlinerNode, foliageBrushIdx, foliageBrushPrototypeIdx) == false) return;
1503 }
1504 auto terrain = prototype != nullptr?prototype->getTerrain():nullptr;
1505 if (terrain == nullptr) return;
1506 auto brush = terrain->getBrush(foliageBrushIdx);
1507 if (brush == nullptr) return;
1508
1509 // check if having brush prototypes (ids)
1510 if (currentFoliageBrushOperation == Terrain2::BRUSHOPERATION_ADD) {
1511 auto haveBrushPrototypeIds = false;
1512 for (auto& foliageBrushPrototype: foliageBrushPrototypes) {
1513 if (foliageBrushPrototype.prototypeId != -1) haveBrushPrototypeIds = true;
1514 }
1515 if (haveBrushPrototypeIds == false) return;
1516 }
1517
1518 //
1520 case Terrain2::BRUSHOPERATION_ADD:
1521 //
1522 Terrain2::applyFoliageDeleteBrush(
1523 terrainBoundingBox,
1524 brushCenterPosition,
1527 Terrain2::BRUSHOPERATION_DELETE,
1528 prototype->getTerrain()->getFoliageMaps(),
1530 );
1531 //
1532 Terrain2::applyFoliageBrush(
1533 terrainBoundingBox,
1534 prototype->getTerrain()->getHeightVector(),
1535 brushCenterPosition,
1539 prototype->getTerrain()->getFoliageMaps(),
1541 );
1542 break;
1543 case Terrain2::BRUSHOPERATION_DELETE:
1544 //
1545 Terrain2::applyFoliageDeleteBrush(
1546 terrainBoundingBox,
1547 brushCenterPosition,
1551 prototype->getTerrain()->getFoliageMaps(),
1553 );
1554 break;
1555 }
1556
1557 //
1560
1561 //
1563 Terrain2::emptyFoliageMaps(newFoliageMaps);
1564}
1565
1567 if (required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById(view->getTabId() + "_tab_terrain_add"))->getController()->getValue().equals("1") == true) {
1568 return Terrain2::BRUSHOPERATION_ADD;
1569 } else
1570 if (required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById(view->getTabId() + "_tab_terrain_substract"))->getController()->getValue().equals("1") == true) {
1571 return Terrain2::BRUSHOPERATION_SUBTRACT;
1572 } else
1573 if (required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById(view->getTabId() + "_tab_terrain_flatten"))->getController()->getValue().equals("1") == true) {
1574 return Terrain2::BRUSHOPERATION_FLATTEN;
1575 } else
1576 if (required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById(view->getTabId() + "_tab_terrain_smooth"))->getController()->getValue().equals("1") == true) {
1577 return Terrain2::BRUSHOPERATION_SMOOTH;
1578 } else
1579 if (required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById(view->getTabId() + "_tab_terrain_ramp"))->getController()->getValue().equals("1") == true) {
1580 return Terrain2::BRUSHOPERATION_RAMP;
1581 } else
1582 if (required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById(view->getTabId() + "_tab_terrain_delete"))->getController()->getValue().equals("1") == true) {
1583 return Terrain2::BRUSHOPERATION_DELETE;
1584 } else {
1585 return Terrain2::BRUSHOPERATION_NONE;
1586 }
1587}
1588
1590 if (required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById(view->getTabId() + "_tab_water_water"))->getController()->getValue().equals("1") == true) {
1591 return Terrain2::BRUSHOPERATION_WATER_ADD;
1592 } else
1593 if (required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById(view->getTabId() + "_tab_water_delete"))->getController()->getValue().equals("1") == true) {
1594 return Terrain2::BRUSHOPERATION_WATER_DELETE;
1595 } else {
1596 return Terrain2::BRUSHOPERATION_NONE;
1597 }
1598}
1599
1601 if (required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById(view->getTabId() + "_tab_foliage_add"))->getController()->getValue().equals("1") == true) {
1602 return Terrain2::BRUSHOPERATION_ADD;
1603 } else
1604 if (required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById(view->getTabId() + "_tab_foliage_delete"))->getController()->getValue().equals("1") == true) {
1605 return Terrain2::BRUSHOPERATION_DELETE;
1606 } else {
1607 return Terrain2::BRUSHOPERATION_NONE;
1608 }
1609}
Engine main class.
Definition: Engine.h:122
Axis aligned bounding box used for frustum, this is not directly connectable with physics engine.
Definition: BoundingBox.h:25
const Vector3 & getDimensions() const
Definition: BoundingBox.h:127
void setFileName(const string &fileName)
Set texture file name.
void removeWaterPositionMap(int idx)
Remove water position map at given water position map index.
PrototypeTerrainBrush * getBrush(int idx)
Get prototype terrain brush.
Prototype definition.
Definition: Prototype.h:49
PrototypeTerrain * getTerrain()
Definition: Prototype.h:561
GUI parser.
Definition: GUIParser.h:39
GUI module class.
Definition: GUI.h:66
GUI node controller base class.
const string & getId()
Definition: GUINode.h:329
GUI parent node base class thats supporting child nodes.
Definition: GUIParentNode.h:43
GUI screen node that represents a screen that can be rendered via GUI system.
Definition: GUIScreenNode.h:57
GUINode * getNodeById(const string &nodeId)
Get GUI node by id.
2D vector 2 class
Definition: Vector2.h:19
3D vector 3 class
Definition: Vector3.h:22
float getX() const
Definition: Vector3.h:103
float getZ() const
Definition: Vector3.h:136
File system singleton class.
Definition: FileSystem.h:14
void addMenuItem(const string &text, const string &id, Action *action=nullptr)
Add menu item.
void setOutlinerSelection(const string &newSelectionValue)
Set outliner selection.
void show(const string &cwd, const string &captionText, const vector< string > &extensions, const string &fileName, bool enableFilter, Action *applyAction, Action *cancelAction=nullptr, const string &settingsFileName=".filedialog.properties", const string &settingsPathName=string())
Shows the file dialog pop up.
void show(const string &caption, const string &message)
Shows the pop up.
Pop ups controller accessor class.
Definition: PopUps.h:19
FileDialogScreenController * getFileDialogScreenController()
Definition: PopUps.h:42
ContextMenuScreenController * getContextMenuScreenController()
Definition: PopUps.h:70
InfoDialogScreenController * getInfoDialogScreenController()
Definition: PopUps.h:49
void updateInfoText(const MutableString &text)
Update info text line.
void applyFoliageBrushPrototypeDetails()
Apply foliage brush prototype details.
void applyTerrainBrush(BoundingBox &terrainBoundingBox, vector< Model * > &terrainModels, const Vector3 &brushCenterPosition, int64_t deltaTime)
Apply current brush to terrain at given brush center position.
bool determineCurrentBrushHeight(BoundingBox &terrainBoundingBox, vector< Model * > terrainModels, const Vector3 &brushCenterPosition)
Determine current brush flatten height.
void setBrushDensityStrength(float densityStrength)
Set brush density/strength.
void onContextMenuRequested(GUIElementNode *node, int mouseX, int mouseY) override
On mouse over.
bool determineRampHeight(BoundingBox &terrainBoundingBox, vector< Model * > terrainModels, const Vector3 &position, float &height)
Determine ramp height.
void onValueChanged(GUIElementNode *node) override
On value changed.
bool checkOutlinerFoliageBrushPrototype(const string &outlinerNode, int &foliageBrushIdx, int &foliageBrushPrototypeIdx)
Check if outliner selection is foliage brush prototype.
void onActionPerformed(GUIActionListenerType type, GUIElementNode *node) override
vector< unordered_map< int, vector< Transformations > > > newFoliageMaps
void showErrorPopUp(const string &caption, const string &message)
Shows the error pop up.
void applyRampTerrainBrush(BoundingBox &terrainBoundingBox, vector< Model * > &terrainModels, const Vector3 &position, float rotation, const Vector2 &scale, float minHeight, float maxHeight)
Apply current brush to terrain at given brush center position.
void createWater(BoundingBox &terrainBoundingBox, const Vector3 &brushCenterPosition, vector< Model * > &waterModels, Vector3 &waterReflectionEnvironmentMappingPosition)
Create water using a auto fill like algorithm.
void applyFoliageBrush(BoundingBox &terrainBoundingBox, const Vector3 &brushCenterPosition, int64_t deltaTime)
Apply current brush to foliage at given brush center position.
void onValueChanged(GUIElementNode *node, BaseProperties *baseProperties)
On value changed.
void onFocus(GUIElementNode *node, BaseProperties *baseProperties)
On focus.
void onUnfocus(GUIElementNode *node, BaseProperties *baseProperties)
On unfocus.
void updateDetails(BaseProperties *baseProperties, const string &outlinerNode)
Update details panel.
void onActionPerformed(GUIActionListenerType type, GUIElementNode *node, BaseProperties *baseProperties)
On action performed.
void onContextMenuRequested(GUIElementNode *node, int mouseX, int mouseY, BaseProperties *baseProperties)
On context menu requested.
void createBasePropertiesXML(BaseProperties *baseProperties, string &xml)
Create base properties XML for outliner.
void saveFile(const string &pathName, const string &fileName)
Saving prototype as tmodel prototype.
void recreateFoliage(const unordered_set< int > &partitionIdxSet)
Recreate foliage using render groups at given partition indices that has been transformed to temporar...
void addWater(int waterIdx, vector< Model * > waterModels, const Vector3 &waterReflectionEnvironmentMappingPosition)
Add water.
void updateTemporaryFoliage(const unordered_set< int > &partitionIdxSet)
Update temporary foliage.
void addFoliage()
Add foliage using render groups at given partition indices.
void addTemporaryFoliage(const vector< unordered_map< int, vector< Transformations > > > &newFoliageMaps)
Add temporary foliage.
void recreateTemporaryFoliage(const unordered_set< int > &partitionIdxSet)
Recreate temporary foliage at given partition indices.
void setBrush(Texture *texture, float scale, float densityStrength)
Set brush.
void setTerrain(BoundingBox &terrainBoundingBox, vector< Model * > terrainModels)
Set terrain models.
void setOutlinerAddDropDownContent(const string &xml)
Set outliner add drop down content.
Definition: EditorView.cpp:214
void setOutlinerContent(const string &xml)
Set outliner content.
Definition: EditorView.cpp:210
void setDetailsContent(const string &xml)
Set details content.
Definition: EditorView.cpp:218
EditorScreenController * getScreenController()
Definition: EditorView.h:57
void reloadTabOutliner(const string &newSelectionValue=string())
Reload tab outliner.
Definition: EditorView.cpp:222
Console class.
Definition: Console.h:26
Exception base class.
Definition: ExceptionBase.h:20
Float class.
Definition: Float.h:23
Integer class.
Definition: Integer.h:26
Mutable string class.
Definition: MutableString.h:16
void releaseReference()
releases a reference, thus decrementing the counter and delete it if reference counter is zero
Definition: Reference.cpp:20
String tools class.
Definition: StringTools.h:20
Terrain 2 utility.
Definition: Terrain2.h:33
An attribute is a name-value pair.
Definition: tinyxml.h:734
Always the top level node.
Definition: tinyxml.h:1317
The element is a container class.
Definition: tinyxml.h:886
std::exception Exception
Exception base class.
Definition: Exception.h:19
Tab controller, which connects UI with logic.
Definition: TabController.h:23
Action Interface.
Definition: Action.h:12