TDME2  1.9.200
ModelEditorTabController.cpp
Go to the documentation of this file.
2 
3 #include <memory>
4 #include <string>
5 #include <unordered_map>
6 #include <vector>
7 
8 #include <tdme/tdme.h>
15 #include <tdme/engine/model/Node.h>
23 #include <tdme/engine/Engine.h>
28 #include <tdme/gui/nodes/GUINode.h>
33 #include <tdme/gui/GUI.h>
34 #include <tdme/gui/GUIParser.h>
35 #include <tdme/math/Vector3.h>
54 #include <tdme/utilities/Action.h>
55 #include <tdme/utilities/Console.h>
58 #include <tdme/utilities/Float.h>
59 #include <tdme/utilities/Integer.h>
62 
63 using std::make_unique;
64 using std::string;
65 using std::unique_ptr;
66 using std::unordered_map;
67 using std::vector;
68 
70 
122 
123 ModelEditorTabController::ModelEditorTabController(ModelEditorTabView* view)
124 {
125  this->view = view;
126  this->popUps = view->getPopUps();
127  this->basePropertiesSubController = make_unique<BasePropertiesSubController>(view->getEditorView(), "prototype");
128  this->prototypePhysicsSubController = make_unique<PrototypePhysicsSubController>(view->getEditorView(), view, true);
129  this->prototypeSoundsSubController = make_unique<PrototypeSoundsSubController>(view->getEditorView(), view);
130  this->prototypeDisplaySubController = make_unique<PrototypeDisplaySubController>(view->getEditorView(), view, this->prototypePhysicsSubController->getView());
131  this->prototypeScriptSubController = make_unique<PrototypeScriptSubController>(view->getEditorView());
132 }
133 
135 }
136 
138 {
139  this->screenNode = screenNode;
145 }
146 
148 {
149 }
150 
152 {
153  switch (command) {
154  case COMMAND_SAVE:
155  {
156  auto fileName = view->getPrototype() != nullptr?view->getPrototype()->getFileName():"";
157  try {
158  if (fileName.empty() == true) throw ExceptionBase("Could not save file. No filename known");
159  view->saveFile(
160  Tools::getPathName(fileName),
161  Tools::getFileName(fileName)
162  );
163  } catch (Exception& exception) {
164  showInfoPopUp("Warning", string(exception.what()));
165  }
166  }
167  break;
168  case COMMAND_SAVEAS:
169  {
170  class OnModelSave: public virtual Action
171  {
172  public:
173  void performAction() override {
174  try {
175  modelEditorTabController->view->saveFile(
176  modelEditorTabController->popUps->getFileDialogScreenController()->getPathName(),
177  modelEditorTabController->popUps->getFileDialogScreenController()->getFileName()
178  );
179  } catch (Exception& exception) {
180  modelEditorTabController->showInfoPopUp("Warning", string(exception.what()));
181  }
182  modelEditorTabController->popUps->getFileDialogScreenController()->close();
183  }
184 
185  /**
186  * Public constructor
187  * @param modelEditorTabController model editor tab controller
188  */
189  OnModelSave(ModelEditorTabController* modelEditorTabController): modelEditorTabController(modelEditorTabController) {
190  }
191 
192  private:
193  ModelEditorTabController* modelEditorTabController;
194  };
195 
196  auto fileName = view->getPrototype() != nullptr?view->getPrototype()->getFileName():"";
197  if (fileName.length() == 0) {
198  fileName = view->getFileName();
199  if (StringTools::endsWith(StringTools::toLowerCase(fileName), ".tmodel") == false) {
200  fileName = Tools::removeFileExtension(fileName) + ".tmodel";
201  }
202  }
203  vector<string> extensions = {
204  "tmodel"
205  };
207  Tools::getPathName(fileName),
208  "Save to: ",
209  extensions,
210  Tools::getFileName(fileName),
211  false,
212  new OnModelSave(this)
213  );
214  }
215  break;
216  default:
217  showInfoPopUp("Warning", "This command is not supported yet");
218  break;
219  }
220 }
221 
222 void ModelEditorTabController::onDrop(const string& payload, int mouseX, int mouseY) {
223  if (prototypeSoundsSubController->onDrop(payload, mouseX, mouseY, view->getPrototype()) == true) return;
224  if (prototypePhysicsSubController->onDrop(payload, mouseX, mouseY, view->getPrototype()) == true) return;
225  if (prototypeScriptSubController->onDrop(payload, mouseX, mouseY, view->getPrototype()) == true) return;
226  if (StringTools::startsWith(payload, "file:") == false) {
227  showInfoPopUp("Warning", "Unknown payload in drop");
228  } else {
229  auto fileName = StringTools::substring(payload, string("file:").size());
230  if (view->getEditorView()->getScreenController()->isDropOnNode(mouseX, mouseY, "specularmaterial_diffuse_texture") == true) {
231  if (Tools::hasFileExtension(fileName, TextureReader::getTextureExtensions()) == false) {
232  showInfoPopUp("Warning", "You can not drop this file here. Allowed file extensions are " + Tools::enumerateFileExtensions(TextureReader::getTextureExtensions()));
233  } else {
234  setMaterialDiffuseTexture(fileName);
235  }
236  } else
237  if (view->getEditorView()->getScreenController()->isDropOnNode(mouseX, mouseY, "specularmaterial_transparency_texture") == true) {
238  if (Tools::hasFileExtension(fileName, TextureReader::getTextureExtensions()) == false) {
239  showInfoPopUp("Warning", "You can not drop this file here. Allowed file extensions are " + Tools::enumerateFileExtensions(TextureReader::getTextureExtensions()));
240  } else {
242  }
243  } else
244  if (view->getEditorView()->getScreenController()->isDropOnNode(mouseX, mouseY, "specularmaterial_normal_texture") == true) {
245  if (Tools::hasFileExtension(fileName, TextureReader::getTextureExtensions()) == false) {
246  showInfoPopUp("Warning", "You can not drop this file here. Allowed file extensions are " + Tools::enumerateFileExtensions(TextureReader::getTextureExtensions()));
247  } else {
248  setMaterialNormalTexture(fileName);
249  }
250  } else
251  if (view->getEditorView()->getScreenController()->isDropOnNode(mouseX, mouseY, "specularmaterial_specular_texture") == true) {
252  if (Tools::hasFileExtension(fileName, TextureReader::getTextureExtensions()) == false) {
253  showInfoPopUp("Warning", "You can not drop this file here. Allowed file extensions are " + Tools::enumerateFileExtensions(TextureReader::getTextureExtensions()));
254  } else {
255  setMaterialSpecularTexture(fileName);
256  }
257  } else
258  if (view->getEditorView()->getScreenController()->isDropOnNode(mouseX, mouseY, "pbrmaterial_basecolor_texture") == true) {
259  if (Tools::hasFileExtension(fileName, TextureReader::getTextureExtensions()) == false) {
260  showInfoPopUp("Warning", "You can not drop this file here. Allowed file extensions are " + Tools::enumerateFileExtensions(TextureReader::getTextureExtensions()));
261  } else {
263  }
264  } else
265  if (view->getEditorView()->getScreenController()->isDropOnNode(mouseX, mouseY, "pbrmaterial_metallic_roughness_texture") == true) {
266  if (Tools::hasFileExtension(fileName, TextureReader::getTextureExtensions()) == false) {
267  showInfoPopUp("Warning", "You can not drop this file here. Allowed file extensions are " + Tools::enumerateFileExtensions(TextureReader::getTextureExtensions()));
268  } else {
270  }
271  } else
272  if (view->getEditorView()->getScreenController()->isDropOnNode(mouseX, mouseY, "pbrmaterial_normal_texture") == true) {
273  if (Tools::hasFileExtension(fileName, TextureReader::getTextureExtensions()) == false) {
274  showInfoPopUp("Warning", "You can not drop this file here. Allowed file extensions are " + Tools::enumerateFileExtensions(TextureReader::getTextureExtensions()));
275  } else {
276  setMaterialPBRNormalTexture(fileName);
277  }
278  } else
279  if (view->getEditorView()->getScreenController()->isDropOnNode(mouseX, mouseY, "pbrmaterial_emissive_texture") == true) {
280  if (Tools::hasFileExtension(fileName, TextureReader::getTextureExtensions()) == false) {
281  showInfoPopUp("Warning", "You can not drop this file here. Allowed file extensions are " + Tools::enumerateFileExtensions(TextureReader::getTextureExtensions()));
282  } else {
284  }
285  } else
286  if (view->getEditorView()->getScreenController()->isDropOnNode(mouseX, mouseY, "animationpreview_attachment1_model") == true) {
287  if (Tools::hasFileExtension(fileName, ModelReader::getModelExtensions()) == false) {
288  showInfoPopUp("Warning", "You can not drop this file here. Allowed file extensions are " + Tools::enumerateFileExtensions(ModelReader::getModelExtensions()));
289  } else {
291  }
292  } else {
293  showInfoPopUp("Warning", "You can not drop a file here");
294  }
295  }
296 }
297 
298 void ModelEditorTabController::createOutlinerModelNodesXML(const string& prefix, const unordered_map<string, Node*>& subNodes, string& xml) {
299  for (const auto& [nodeId, node]: subNodes) {
300  string image;
301  if (node->isJoint() == true) {
302  image = "bone.png";
303  } else
304  if (node->isEmpty() == true) {
305  image = "empty.png";
306  } else {
307  image = "mesh.png";
308  }
309  if (node->getSubNodes().empty() == false) {
310  xml+= "<selectbox-parent-option image=\"resources/engine/images/" + image + "\" text=\"" + GUIParser::escape(node->getId()) + "\" value=\"" + GUIParser::escape(prefix + ".nodes." + node->getId()) + "\">\n";
311  createOutlinerModelNodesXML(prefix, node->getSubNodes(), xml);
312  xml+= "</selectbox-parent-option>\n";
313  } else {
314  xml+= " <selectbox-option image=\"resources/engine/images/" + image + "\" text=\"" + GUIParser::escape(node->getId()) + "\" value=\"" + GUIParser::escape(prefix + ".nodes." + node->getId()) + "\" />\n";
315  }
316  }
317 }
318 
320  string xml;
321  xml+= "<selectbox-parent-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escape("Prototype") + "\" value=\"" + GUIParser::escape("prototype") + "\">\n";
322  auto prototype = view->getPrototype();
323  if (prototype != nullptr) {
324  basePropertiesSubController->createBasePropertiesXML(prototype, xml);
325  prototypeScriptSubController->createScriptXML(prototype, xml);
326  prototypeDisplaySubController->createDisplayPropertiesXML(prototype, xml);
327  prototypePhysicsSubController->createOutlinerPhysicsXML(prototype, xml);
328  prototypeSoundsSubController->createOutlinerSoundsXML(prototype, xml);
329  for (auto lodLevel = 1; lodLevel < 5; lodLevel++) {
330  Model* model = nullptr;
331  switch (lodLevel) {
332  case 1:
333  model = prototype->getModel();
334  break;
335  case 2:
336  model = prototype->getLODLevel2() != nullptr?prototype->getLODLevel2()->getModel():nullptr;
337  if (prototype->getLODLevel2() == nullptr) continue;
338  break;
339  case 3:
340  model = prototype->getLODLevel3() != nullptr?prototype->getLODLevel3()->getModel():nullptr;
341  if (prototype->getLODLevel3() == nullptr) continue;
342  break;
343  case 4:
344  model = nullptr;
345  if (prototype->getImposterLOD() == nullptr) continue;
346  break;
347  }
348  auto modelPrefix = lodLevel == 1?"model":"lod" + to_string(lodLevel) + ".model";
349  // TODO: clean up "model != nullpt" stuff here
350  if (model != nullptr) {
351  xml+= "<selectbox-parent-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escape(lodLevel != 1?"LOD " + to_string(lodLevel) + " Model":"Model") + "\" value=\"" + GUIParser::escape(modelPrefix) + "\">\n";
352  } else {
353  xml+= "<selectbox-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escape(lodLevel != 1?"LOD " + to_string(lodLevel) + " Model":"Model") + "\" value=\"" + GUIParser::escape(modelPrefix) + "\" />\n";
354  }
355  if (model != nullptr) {
356  xml+= "<selectbox-parent-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escape("Materials") + "\" value=\"" + GUIParser::escape(modelPrefix + ".materials") + "\">\n";
357  for (const auto& materialId: model->getMaterialIds()) {
358  xml+= " <selectbox-option image=\"resources/engine/images/material.png\" text=\"" + GUIParser::escape(materialId) + "\" value=\"" + GUIParser::escape(modelPrefix + ".materials." + materialId) + "\" />\n";
359  }
360  xml+= "</selectbox-parent-option>\n";
361  }
362  if (model != nullptr && model->getSubNodes().empty() == false) {
363  xml+= "<selectbox-parent-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escape("Nodes") + "\" value=\"" + GUIParser::escape(modelPrefix + ".nodes") + "\">\n";
364  createOutlinerModelNodesXML(modelPrefix, model->getSubNodes(), xml);
365  xml+= "</selectbox-parent-option>\n";
366  }
367  if (model != nullptr &&
368  (model->getAnimationSetups().size() > 1 || model->getAnimationSetup(Model::ANIMATIONSETUP_DEFAULT) == nullptr)) {
369  xml+= "<selectbox-parent-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escape("Animations") + "\" value=\"" + GUIParser::escape(modelPrefix + ".animations") + "\">\n";
370  for (const auto& animationSetupId: model->getAnimationSetupIds()) {
371  if (animationSetupId == Model::ANIMATIONSETUP_DEFAULT) continue;
372  xml+= " <selectbox-option image=\"resources/engine/images/animation.png\" text=\"" + GUIParser::escape(animationSetupId) + "\" id=\"" + GUIParser::escape(modelPrefix + ".animations." + animationSetupId) + "\" value=\"" + GUIParser::escape(modelPrefix + ".animations." + animationSetupId) + "\" />\n";
373  }
374  xml+= "</selectbox-parent-option>\n";
375  }
376  if (model != nullptr) xml+= "</selectbox-parent-option>\n";
377  }
378  }
379  xml+= "</selectbox-parent-option>\n";
381 }
382 
385  string("<dropdown-option text=\"Property\" value=\"property\" />\n") +
386  string("<dropdown-option text=\"BV\" value=\"boundingvolume\" />\n") +
387  string("<dropdown-option text=\"Sound\" value=\"sound\" />\n") +
388  string("<dropdown-option text=\"Animation\" value=\"animation\" />\n") +
389  string("<dropdown-option text=\"LOD\" value=\"lod\" />\n") +
390  string("<dropdown-option text=\"LOD None\" value=\"lod_none\" />\n")
391  );
392 }
393 
395  view->getEditorView()->setDetailsContent(string());
396 }
397 
399  auto prototype = view->getPrototype();
400  if (prototype == nullptr) return nullptr;
401  switch (level) {
402  case 2:
403  {
404  auto prototypeLodLevel = prototype->getLODLevel2();
405  if (prototypeLodLevel == nullptr) {
406  auto newPrototypeLodLevel = make_unique<PrototypeLODLevel>(
407  LODObject::LODLEVELTYPE_NONE,
408  "",
409  nullptr,
410  75.0f
411  );
412  prototype->setLODLevel2(newPrototypeLodLevel.get());
413  prototypeLodLevel = newPrototypeLodLevel.release();
414  }
415  return prototypeLodLevel;
416  }
417  case 3:
418  {
419  auto prototypeLodLevel = prototype->getLODLevel3();
420  if (prototypeLodLevel == nullptr) {
421  auto newPrototypeLodLevel = make_unique<PrototypeLODLevel>(
422  LODObject::LODLEVELTYPE_NONE,
423  "",
424  nullptr,
425  150.0f
426  );
427  prototype->setLODLevel3(newPrototypeLodLevel.get());
428  prototypeLodLevel = newPrototypeLodLevel.release();
429  }
430  return prototypeLodLevel;
431  }
432  }
433  return nullptr;
434 }
435 
437  Model* model = nullptr;
438  switch (level) {
439  case 1: model = view->getPrototype()->getModel(); break;
440  case 2: model = view->getPrototype()->getLODLevel2() != nullptr?view->getPrototype()->getLODLevel2()->getModel():nullptr; break;
441  case 3: model = view->getPrototype()->getLODLevel3() != nullptr?view->getPrototype()->getLODLevel3()->getModel():nullptr; break;
442  default: model = nullptr;
443  }
444  return model;
445 }
446 
448  auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
449  string outlinerNodeModel;
450  Model* model = nullptr;
451  getOutlinerNodeLOD(outlinerNode, outlinerNodeModel, &model);
452  return model;
453 }
454 
456  string materialId;
457  auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
458  string outlinerNodeModel;
459  Model* model = nullptr;
460  getOutlinerNodeLOD(outlinerNode, outlinerNodeModel, &model);
461  if (model == nullptr) return nullptr;
462  if (StringTools::startsWith(outlinerNodeModel, "model.materials.") == true) {
463  materialId = StringTools::substring(outlinerNodeModel, string("model.materials.").size(), outlinerNode.size());
464  } else {
465  return nullptr;
466  }
467  auto materialIt = model->getMaterials().find(materialId);
468  return materialIt != model->getMaterials().end()?materialIt->second:nullptr;
469 }
470 
472  string animationId;
473  auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
474  string outlinerNodeModel;
475  Model* model = nullptr;
476  getOutlinerNodeLOD(outlinerNode, outlinerNodeModel, &model);
477  if (model == nullptr) return nullptr;
478  if (StringTools::startsWith(outlinerNodeModel, "model.animations.") == true) {
479  animationId = StringTools::substring(outlinerNodeModel, string("model.animations.").size(), outlinerNode.size());
480  } else {
481  return nullptr;
482  }
483  return model->getAnimationSetup(animationId);
484 }
485 
486 void ModelEditorTabController::setStatistics(int statsOpaqueFaces, int statsTransparentFaces, int statsMaterialCount)
487 {
488 }
489 
491 {
492 }
493 
495  view->computeNormals();
496 }
497 
499  view->optimizeModel();
500 }
501 
503 {
504  view->reloadFile();
505 }
506 
508  class OnModelLoad: public virtual Action
509  {
510 
511  public:
512  void performAction() override {
513  modelEditorTabController->view->loadModel(
514  modelEditorTabController->popUps->getFileDialogScreenController()->getPathName(),
515  modelEditorTabController->popUps->getFileDialogScreenController()->getFileName()
516  );
517  modelEditorTabController->popUps->getFileDialogScreenController()->close();
518  }
519 
520  /**
521  * Public constructor
522  * @param modelEditorTabController model editor tab controller
523  */
524  OnModelLoad(ModelEditorTabController* modelEditorTabController): modelEditorTabController(modelEditorTabController) {
525  }
526 
527  private:
528  ModelEditorTabController* modelEditorTabController;
529  };
530 
532  string(),
533  "Load model from: ",
534  ModelReader::getModelExtensions(),
535  view->getFileName(),
536  true,
537  new OnModelLoad(this)
538  );
539 }
540 
542 {
543  class OnModelReimport: public virtual Action
544  {
545 
546  public:
547  void performAction() override {
548  modelEditorTabController->view->reimportModel(
549  modelEditorTabController->popUps->getFileDialogScreenController()->getPathName(),
550  modelEditorTabController->popUps->getFileDialogScreenController()->getFileName()
551  );
552  modelEditorTabController->popUps->getFileDialogScreenController()->close();
553  }
554 
555  /**
556  * Public constructor
557  * @param modelEditorTabController model editor tab controller
558  */
559  OnModelReimport(ModelEditorTabController* modelEditorTabController): modelEditorTabController(modelEditorTabController) {
560  }
561 
562  private:
563  ModelEditorTabController* modelEditorTabController;
564  };
565 
567  string(),
568  "Reimport model from: ",
569  ModelReader::getModelExtensions(),
570  view->getFileName(),
571  true,
572  new OnModelReimport(this)
573  );
574 }
575 
576 void ModelEditorTabController::saveFile(const string& pathName, const string& fileName)
577 {
578  view->saveFile(pathName, fileName);
579 }
580 
581 void ModelEditorTabController::loadFile(const string& pathName, const string& fileName)
582 {
583  view->loadModel(pathName, fileName);
584 }
585 
587  class OnLODLoad: public virtual Action
588  {
589 
590  public:
591  void performAction() override {
592  PrototypeLODLevel* prototypeLODLevel = nullptr;
593  switch (lodLevel) {
594  case 2: prototypeLODLevel = prototype->getLODLevel2(); break;
595  case 3: prototypeLODLevel = prototype->getLODLevel3(); break;
596  default: break;
597  }
598  if (prototypeLODLevel == nullptr) return;
599 
600  modelEditorTabController->view->setLODLevel(1);
601 
602  try {
603  // set model in LOD level
604  prototypeLODLevel->setModel(
605  ModelReader::read(
606  modelEditorTabController->popUps->getFileDialogScreenController()->getPathName(),
607  modelEditorTabController->popUps->getFileDialogScreenController()->getFileName()
608  )
609  );
610  } catch (Exception& exception) {
611  Console::println("OnLODLoad::performAction(): An error occurred: " + string(exception.what()));
612  modelEditorTabController->showInfoPopUp("Warning", string(exception.what()));
613  }
614 
615  modelEditorTabController->view->setLODLevel(lodLevel);
616  modelEditorTabController->view->getEditorView()->reloadTabOutliner("lod" + to_string(lodLevel) + ".model");
617  modelEditorTabController->popUps->getFileDialogScreenController()->close();
618  }
619 
620  /**
621  * Public constructor
622  * @param modelEditorTabController model editor tab controller
623  * @param prototype prototype
624  * @param lodLevel LOD level
625  */
626  OnLODLoad(ModelEditorTabController* modelEditorTabController, Prototype* prototype, int lodLevel): modelEditorTabController(modelEditorTabController), prototype(prototype), lodLevel(lodLevel) {
627  }
628 
629  private:
630  ModelEditorTabController* modelEditorTabController;
631  Prototype* prototype;
632  int lodLevel;
633  };
634 
636  string(),
637  "Load LOD " + to_string(lodLevel) + " model from: ",
638  ModelReader::getModelExtensions(),
639  view->getFileName(),
640  true,
641  new OnLODLoad(this, view->getPrototype(), lodLevel)
642  );
643 }
644 
646  required_dynamic_cast<GUITextNode*>(screenNode->getNodeById(view->getTabId() + "_tab_text_info"))->setText(text);
647 }
648 
649 void ModelEditorTabController::showInfoPopUp(const string& caption, const string& message)
650 {
651  popUps->getInfoDialogScreenController()->show(caption, message);
652 }
653 
656  "<template id=\"details_material_base\" src=\"resources/engine/gui/template_details_material.xml\" />\n"
657  );
658 
659  try {
660  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_material_base"))->getActiveConditions().add("open");
661  } catch (Exception& exception) {
662  Console::println("ModelEditorTabController::setMaterialBaseDetails(): An error occurred: " + string(exception.what()));
663  showInfoPopUp("Warning", string(exception.what()));
664  }
665 
666  //
668 }
669 
671  auto model = getSelectedModel();
672  if (model == nullptr) return;
673 
674  try {
675  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("material_specular_embedtextures_enabled"))->getController()->setValue(MutableString(model->hasEmbeddedSpecularTextures() == true?"1":""));
676  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("material_pbr_embedtextures_enabled"))->getController()->setValue(MutableString(model->hasEmbeddedPBRTextures() == true?"1":""));
677  auto shaderModel = model->getShaderModel();
678  if (shaderModel == ShaderModel::SPECULAR) {
679  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("material_lightningmodel"))->getController()->setValue(MutableString("specular"));
680  } else
681  if (shaderModel == ShaderModel::PBR) {
682  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("material_lightningmodel"))->getController()->setValue(MutableString("pbr"));
683  } else
684  if (shaderModel == ShaderModel::SPECULARPBR) {
685  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("material_lightningmodel"))->getController()->setValue(MutableString("pbrspecular"));
686  }
687  } catch (Exception& exception) {
688  Console::println("ModelEditorTabController::updateMaterialBaseDetails(): An error occurred: " + string(exception.what()));
689  showInfoPopUp("Warning", string(exception.what()));
690  }
691 }
692 
694  auto model = getSelectedModel();
695  if (model == nullptr) return;
696 
697  //
698  try {
699  model->setEmbedSpecularTextures(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("material_specular_embedtextures_enabled"))->getController()->getValue().getString() == "1");
700  model->setEmbedPBRTextures(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("material_pbr_embedtextures_enabled"))->getController()->getValue().getString() == "1");
701  auto shaderModel = required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("material_lightningmodel"))->getController()->getValue().getString();
702  if (shaderModel == "specular") {
703  model->setShaderModel(ShaderModel::SPECULAR);
704  } else
705  if (shaderModel == "pbr") {
706  model->setShaderModel(ShaderModel::PBR);
707  } else
708  if (shaderModel == "specularpbr") {
709  model->setShaderModel(ShaderModel::SPECULARPBR);
710  }
711  } catch (Exception& exception) {
712  Console::println("ModelEditorTabController::applyMaterialBaseDetails(): An error occurred: " + string(exception.what()));
713  showInfoPopUp("Warning", string(exception.what()));
714  }
715 
716  //
718 }
719 
721  auto material = getSelectedMaterial();
722  if (material == nullptr) return;
723  auto model = getSelectedModel();
724  if (model == nullptr) return;
725 
726  auto specularMaterialProperties = material->getSpecularMaterialProperties();
727  auto pbrMaterialProperties = material->getPBRMaterialProperties();
728 
730  string("<template id=\"details_material_spec\" src=\"resources/engine/gui/template_details_material_specular.xml\" />\n") +
731  string(model->getShaderModel() != ShaderModel::SPECULAR?"<template id=\"details_material_pbr\" src=\"resources/engine/gui/template_details_material_pbr.xml\" />\n":"")
732  );
733 
734  try {
735  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_material_spec"))->getActiveConditions().add("open");
736  if (model->getShaderModel() != ShaderModel::SPECULAR) {
737  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_material_pbr"))->getActiveConditions().add("open");
738  }
739  } catch (Exception& exception) {
740  Console::println("ModelEditorTabController::setMaterialDetails(): An error occurred: " + string(exception.what()));
741  showInfoPopUp("Warning", string(exception.what()));
742  }
743 
744  //
746 }
747 
749  auto material = getSelectedMaterial();
750  if (material == nullptr) return;
751  auto model = getSelectedModel();
752  if (model == nullptr) return;
753 
754  auto specularMaterialProperties = material->getSpecularMaterialProperties();
755  auto pbrMaterialProperties = material->getPBRMaterialProperties();
756 
757  try {
758  {
759  auto diffuseTextureFileName =
760  specularMaterialProperties->getDiffuseTextureFileName().empty() == true?
761  string():
762  (
763  PrototypeReader::getResourcePathName(
764  view->getEditorView()->getScreenController()->getProjectPath() + "/resources",
765  specularMaterialProperties->getDiffuseTexturePathName() + "/" + specularMaterialProperties->getDiffuseTextureFileName()
766  ) +
767  "/" +
768  specularMaterialProperties->getDiffuseTextureFileName()
769  );
770  auto diffuseTransparencyTextureFileName =
771  specularMaterialProperties->getDiffuseTransparencyTextureFileName().empty() == true?
772  string():
773  (
774  PrototypeReader::getResourcePathName(
775  view->getEditorView()->getScreenController()->getProjectPath() + "/resources",
776  specularMaterialProperties->getDiffuseTransparencyTexturePathName() + "/" + specularMaterialProperties->getDiffuseTransparencyTextureFileName()
777  ) +
778  "/" +
779  specularMaterialProperties->getDiffuseTransparencyTextureFileName()
780  );
781  auto normalTextureFileName =
782  specularMaterialProperties->getNormalTextureFileName().empty() == true?
783  string():
784  (
785  PrototypeReader::getResourcePathName(
786  view->getEditorView()->getScreenController()->getProjectPath() + "/resources",
787  specularMaterialProperties->getNormalTexturePathName() + "/" + specularMaterialProperties->getNormalTextureFileName()
788  ) +
789  "/" +
790  specularMaterialProperties->getNormalTextureFileName()
791  );
792  auto specularTextureFileName =
793  specularMaterialProperties->getSpecularTextureFileName().empty() == true?
794  string():
795  (
796  PrototypeReader::getResourcePathName(
797  view->getEditorView()->getScreenController()->getProjectPath() + "/resources",
798  specularMaterialProperties->getSpecularTexturePathName() + "/" + specularMaterialProperties->getSpecularTextureFileName()
799  ) +
800  "/" +
801  specularMaterialProperties->getSpecularTextureFileName()
802  );
803  //
804  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_diffuse_texture"))->setTexture(specularMaterialProperties->getDiffuseTexture());
805  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_diffuse_texture"))->setTooltip(diffuseTextureFileName);
806  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_transparency_texture"))->setSource(diffuseTransparencyTextureFileName);
807  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_transparency_texture"))->setTooltip(diffuseTransparencyTextureFileName);
808  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_normal_texture"))->setTexture(specularMaterialProperties->getNormalTexture());
809  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_normal_texture"))->setTooltip(normalTextureFileName);
810  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_specular_texture"))->setTexture(specularMaterialProperties->getSpecularTexture());
811  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_specular_texture"))->setTooltip(specularTextureFileName);
812  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("specularmaterial_shininess"))->getController()->setValue(specularMaterialProperties->getShininess());
813  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("specularmaterial_reflection"))->getController()->setValue(specularMaterialProperties->getReflection());
814  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("specularmaterial_maskedtransparency"))->getController()->setValue(MutableString(specularMaterialProperties->hasDiffuseTextureMaskedTransparency() == true?"1":""));
815  }
816 
817  if (model->getShaderModel() != ShaderModel::SPECULAR && pbrMaterialProperties != nullptr) {
818  auto baseColorTextureFileName =
819  pbrMaterialProperties->getBaseColorTextureFileName().empty() == true?
820  string():
821  (
822  PrototypeReader::getResourcePathName(
823  view->getEditorView()->getScreenController()->getProjectPath() + "/resources",
824  pbrMaterialProperties->getBaseColorTexturePathName() + "/" + pbrMaterialProperties->getBaseColorTextureFileName()
825  ) +
826  "/" +
827  pbrMaterialProperties->getBaseColorTextureFileName()
828  );
829  auto metallicRoughnessTextureFileName =
830  pbrMaterialProperties->getMetallicRoughnessTextureFileName().empty() == true?
831  string():
832  (
833  PrototypeReader::getResourcePathName(
834  view->getEditorView()->getScreenController()->getProjectPath() + "/resources",
835  pbrMaterialProperties->getMetallicRoughnessTexturePathName() + "/" + pbrMaterialProperties->getMetallicRoughnessTextureFileName()
836  ) +
837  "/" +
838  pbrMaterialProperties->getMetallicRoughnessTextureFileName()
839  );
840  auto normalTextureFileName =
841  pbrMaterialProperties->getNormalTextureFileName().empty() == true?
842  string():
843  (
844  PrototypeReader::getResourcePathName(
845  view->getEditorView()->getScreenController()->getProjectPath() + "/resources",
846  pbrMaterialProperties->getNormalTexturePathName() + "/" + pbrMaterialProperties->getNormalTextureFileName()
847  ) +
848  "/" +
849  pbrMaterialProperties->getNormalTextureFileName()
850  );
851  auto emissiveTextureFileName =
852  pbrMaterialProperties->getEmissiveTextureFileName().empty() == true?
853  string():
854  (
855  PrototypeReader::getResourcePathName(
856  view->getEditorView()->getScreenController()->getProjectPath() + "/resources",
857  pbrMaterialProperties->getEmissiveTexturePathName() + "/" + pbrMaterialProperties->getEmissiveTextureFileName()
858  ) +
859  "/" +
860  pbrMaterialProperties->getEmissiveTextureFileName()
861  );
862  //
863  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("pbrmaterial_basecolor_texture"))->setTexture(pbrMaterialProperties->getBaseColorTexture());
864  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("pbrmaterial_basecolor_texture"))->setTooltip(baseColorTextureFileName);
865  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("pbrmaterial_metallic_roughness_texture"))->setTexture(pbrMaterialProperties->getMetallicRoughnessTexture());
866  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("pbrmaterial_metallic_roughness_texture"))->setTooltip(metallicRoughnessTextureFileName);
867  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("pbrmaterial_normal_texture"))->setTexture(pbrMaterialProperties->getNormalTexture());
868  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("pbrmaterial_normal_texture"))->setTooltip(normalTextureFileName);
869  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("pbrmaterial_emissive_texture"))->setTexture(pbrMaterialProperties->getEmissiveTexture());
870  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("pbrmaterial_emissive_texture"))->setTooltip(emissiveTextureFileName);
871  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("pbrmaterial_metallic_factor"))->getController()->setValue(pbrMaterialProperties->getMetallicFactor());
872  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("pbrmaterial_roughness_factor"))->getController()->setValue(pbrMaterialProperties->getRoughnessFactor());
873  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("pbrmaterial_normal_scale"))->getController()->setValue(pbrMaterialProperties->getNormalScale());
874  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("pbrmaterial_exposure"))->getController()->setValue(pbrMaterialProperties->getExposure());
875  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("pbrmaterial_maskedtransparency"))->getController()->setValue(MutableString(pbrMaterialProperties->hasBaseColorTextureMaskedTransparency() == true?"1":""));
876  }
877  } catch (Exception& exception) {
878  Console::println("ModelEditorTabController::updateMaterialDetails(): An error occurred: " + string(exception.what()));
879  showInfoPopUp("Warning", string(exception.what()));
880  }
881 
882  //
884 }
885 
887  auto material = getSelectedMaterial();
888  if (material == nullptr) return;
889 
890  auto specularMaterialProperties = material->getSpecularMaterialProperties();
891  auto pbrMaterialProperties = material->getPBRMaterialProperties();
892 
893  try {
894  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_ambient"))->setEffectColorMul(Color4(specularMaterialProperties->getAmbientColor()));
895  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_diffuse"))->setEffectColorMul(Color4(specularMaterialProperties->getDiffuseColor()));
896  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_emission"))->setEffectColorMul(Color4(specularMaterialProperties->getEmissionColor()));
897  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("specularmaterial_specular"))->setEffectColorMul(Color4(specularMaterialProperties->getSpecularColor()));
898 
899  if (pbrMaterialProperties != nullptr) {
900  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("pbrmaterial_basecolor"))->setEffectColorMul(Color4(pbrMaterialProperties->getBaseColorFactor()));
901  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("pbrmaterial_emissivefactor"))->setEffectColorMul(Color4(pbrMaterialProperties->getEmissiveFactor()));
902  }
903  } catch (Exception& exception) {
904  Console::println("ModelEditorTabController::updateMaterialColorDetails(): An error occurred: " + string(exception.what()));
905  showInfoPopUp("Warning", string(exception.what()));
906  }
907 }
908 
910  auto material = getSelectedMaterial();
911  if (material == nullptr) return;
912 
913  auto specularMaterialProperties = material->getSpecularMaterialProperties();
914 
915  try {
916  specularMaterialProperties->setShininess(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("specularmaterial_shininess"))->getController()->getValue().getString()));
917  specularMaterialProperties->setReflection(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("specularmaterial_reflection"))->getController()->getValue().getString()));
918  specularMaterialProperties->setDiffuseTextureMaskedTransparency(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("specularmaterial_maskedtransparency"))->getController()->getValue().getString() == "1");
919  } catch (Exception& exception) {
920  Console::println("ModelEditorTabController::applySpecularMaterialDetails(): An error occurred: " + string(exception.what()));
921  showInfoPopUp("Warning", string(exception.what()));
922  }
923 }
924 
926  auto material = getSelectedMaterial();
927  if (material == nullptr) return;
928 
929  try {
930  if (material->getPBRMaterialProperties() == nullptr) {
932  string outlinerNodeModel;
933  Model* model = nullptr;
935  material->setPBRMaterialProperties(make_unique<PBRMaterialProperties>().release());
937  }
938  } catch (Exception& exception) {
939  Console::println("ModelEditorTabController::applyPBRMaterialDetails(): An error occurred: " + string(exception.what()));
940  showInfoPopUp("Warning", string(exception.what()));
941  }
942 
943  auto pbrMaterialProperties = material->getPBRMaterialProperties();
944  if (pbrMaterialProperties == nullptr) return;
945 
946  try {
947  pbrMaterialProperties->setMetallicFactor(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("pbrmaterial_metallic_factor"))->getController()->getValue().getString()));
948  pbrMaterialProperties->setRoughnessFactor(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("pbrmaterial_roughness_factor"))->getController()->getValue().getString()));
949  pbrMaterialProperties->setNormalScale(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("pbrmaterial_normal_scale"))->getController()->getValue().getString()));
950  pbrMaterialProperties->setExposure(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("pbrmaterial_exposure"))->getController()->getValue().getString()));
951  pbrMaterialProperties->setBaseColorTextureMaskedTransparency(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("pbrmaterial_maskedtransparency"))->getController()->getValue().getString() == "1");
952  } catch (Exception& exception) {
953  Console::println("ModelEditorTabController::applyPBRMaterialDetails(): An error occurred: " + string(exception.what()));
954  showInfoPopUp("Warning", string(exception.what()));
955  }
956 }
957 
959  auto model = getSelectedModel();
960  auto animationSetup = getSelectedAnimationSetup();
961  auto defaultAnimation = animationSetup != nullptr && animationSetup->getId() == Model::ANIMATIONSETUP_DEFAULT;
962 
963  if (animationSetup == nullptr) return;
964 
965  auto defaultAnimationSetup = model->getAnimationSetup(Model::ANIMATIONSETUP_DEFAULT);
966 
968  string("<template id=\"details_animation\" src=\"resources/engine/gui/template_details_animation.xml\" max-frames=\"") +
969  to_string(defaultAnimationSetup != nullptr?defaultAnimationSetup->getEndFrame():0) +
970  string("\" />\n")
971  );
972 
973  //
974  {
975  string animationsXML;
976  animationsXML =
977  animationsXML +
978  "<dropdown-option text=\"<None>\" value=\"\" " + (animationSetup->getOverlayFromNodeId().empty() == true?"selected=\"true\" ":"") + " />\n";
979  for (const auto& nodeId: model->getNodeIds()) {
980  animationsXML+=
981  "<dropdown-option text=\"" +
982  GUIParser::escape(nodeId) +
983  "\" value=\"" +
984  GUIParser::escape(nodeId) +
985  "\" " +
986  (animationSetup->getOverlayFromNodeId() == nodeId?"selected=\"true\" ":"") +
987  " />\n";
988  }
989  try {
990  required_dynamic_cast<GUIParentNode*>(screenNode->getInnerNodeById("animation_overlaybone_scrollarea"))->replaceSubNodes(animationsXML, true);
991  } catch (Exception& exception) {
992  Console::println("ModelEditorTabController::setAnimationDetails(): An error occurred: " + string(exception.what()));
993  }
994  }
995 
996  //
997  try {
998  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_animation"))->getActiveConditions().add("open");
999  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_startframe"))->getController()->setValue(animationSetup->getStartFrame());
1000  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_startframe"))->getController()->setDisabled(defaultAnimation == true);
1001  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_endframe"))->getController()->setValue(animationSetup->getEndFrame());
1002  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_endframe"))->getController()->setDisabled(defaultAnimation == true);
1003  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_speed"))->getController()->setValue(animationSetup->getSpeed());
1004  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_speed"))->getController()->setDisabled(defaultAnimation == true);
1005  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_loop"))->getController()->setValue(MutableString(animationSetup->isLoop() == true?"1":""));
1006  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_loop"))->getController()->setDisabled(defaultAnimation == true);
1007  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_overlaybone"))->getController()->setValue(animationSetup->getOverlayFromNodeId());
1008  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_overlaybone"))->getController()->setDisabled(defaultAnimation == true);
1009  } catch (Exception& exception) {
1010  Console::println("ModelEditorTabController::setAnimationDetails(): An error occurred: " + string(exception.what()));
1011  showInfoPopUp("Warning", string(exception.what()));
1012  }
1013 }
1014 
1016  //
1017  view->playAnimation(Model::ANIMATIONSETUP_DEFAULT);
1018 
1019  auto model = getSelectedModel();
1020  auto animationSetup = getSelectedAnimationSetup();
1021  auto defaultAnimation = animationSetup != nullptr && animationSetup->getId() == Model::ANIMATIONSETUP_DEFAULT;
1022 
1023  if (animationSetup == nullptr) return;
1024 
1025  try {
1026  auto startFrame = Integer::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_startframe"))->getController()->getValue().getString());
1027  auto endFrame = Integer::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_endframe"))->getController()->getValue().getString());
1028  auto speed = Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_speed"))->getController()->getValue().getString());
1029  auto loop = required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_loop"))->getController()->getValue().getString() == "1";
1030  auto overlayFromNodeId = required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animation_overlaybone"))->getController()->getValue().getString();
1031 
1032  animationSetup->setStartFrame(startFrame < endFrame?startFrame:endFrame);
1033  animationSetup->setEndFrame(endFrame > startFrame?endFrame:startFrame);
1034  animationSetup->setSpeed(speed);
1035  animationSetup->setLoop(loop);
1036  animationSetup->setOverlayFromNodeId(overlayFromNodeId);
1037 
1038  view->playAnimation(animationSetup->getId());
1039  } catch (Exception& exception) {
1040  Console::println("ModelEditorTabController::setAnimationDetails(): An error occurred: " + string(exception.what()));
1041  showInfoPopUp("Warning", string(exception.what()));
1042  }
1043 }
1044 
1046  auto model = getSelectedModel();
1047  auto defaultAnimationSetup = model->getAnimationSetup(Model::ANIMATIONSETUP_DEFAULT);
1048 
1050  string("<template id=\"details_animationpreview\" src=\"resources/engine/gui/template_details_animationpreview.xml\" />\n")
1051  );
1052 
1053  {
1054  string animationsXML;
1055  animationsXML = animationsXML + "<dropdown-option text=\"<No animation>\" value=\"\" selected=\"true\" />";
1056  for (const auto& animationSetupId: model->getAnimationSetupIds()) {
1057  auto animationSetup = model->getAnimationSetup(animationSetupId);
1058  if (animationSetup == nullptr || animationSetup->isOverlayAnimationSetup() == true) continue;
1059  animationsXML =
1060  animationsXML + "<dropdown-option text=\"" +
1061  GUIParser::escape(animationSetup->getId()) +
1062  "\" value=\"" +
1063  GUIParser::escape(animationSetup->getId()) +
1064  "\" " +
1065  " />\n";
1066  }
1067  try {
1068  required_dynamic_cast<GUIParentNode*>(screenNode->getInnerNodeById("animationpreview_base_scrollarea"))->replaceSubNodes(animationsXML, true);
1069  } catch (Exception& exception) {
1070  Console::println("ModelEditorTabController::setAnimationPreviewDetails(): An error occurred: " + string(exception.what()));
1071  }
1072  }
1073 
1074  {
1075  string overlayAnimationsXML;
1076  overlayAnimationsXML = overlayAnimationsXML + "<dropdown-option text=\"<No animation>\" value=\"\" selected=\"true\" />";
1077  for (const auto& animationSetupId: model->getAnimationSetupIds()) {
1078  auto animationSetup = model->getAnimationSetup(animationSetupId);
1079  if (animationSetup == nullptr || animationSetup->isOverlayAnimationSetup() == false) continue;
1080  overlayAnimationsXML =
1081  overlayAnimationsXML + "<dropdown-option text=\"" +
1082  GUIParser::escape(animationSetup->getId()) +
1083  "\" value=\"" +
1084  GUIParser::escape(animationSetup->getId()) +
1085  "\" " +
1086  " />\n";
1087  }
1088  try {
1089  required_dynamic_cast<GUIParentNode*>(screenNode->getInnerNodeById("animationpreview_overlay1_scrollarea"))->replaceSubNodes(overlayAnimationsXML, true);
1090  } catch (Exception& exception) {
1091  Console::println("ModelEditorTabController::setAnimationPreviewDetails(): An error occurred: " + string(exception.what()));
1092  }
1093  try {
1094  required_dynamic_cast<GUIParentNode*>(screenNode->getInnerNodeById("animationpreview_overlay2_scrollarea"))->replaceSubNodes(overlayAnimationsXML, true);
1095  } catch (Exception& exception) {
1096  Console::println("ModelEditorTabController::setAnimationPreviewDetails(): An error occurred: " + string(exception.what()));
1097  }
1098  try {
1099  required_dynamic_cast<GUIParentNode*>(screenNode->getInnerNodeById("animationpreview_overlay3_scrollarea"))->replaceSubNodes(overlayAnimationsXML, true);
1100  } catch (Exception& exception) {
1101  Console::println("ModelEditorTabController::setAnimationPreviewDetails(): An error occurred: " + string(exception.what()));
1102  }
1103  }
1104 
1105  {
1106  string bonesXML;
1107  bonesXML = bonesXML + "<dropdown-option text=\"<No bone>\" value=\"\" selected=\"true\" />";
1108  for (const auto& nodeId: model->getNodeIds()) {
1109  bonesXML =
1110  bonesXML + "<dropdown-option text=\"" +
1111  GUIParser::escape(nodeId) +
1112  "\" value=\"" +
1113  GUIParser::escape(nodeId) +
1114  "\" " +
1115  " />\n";
1116  }
1117  try {
1118  required_dynamic_cast<GUIParentNode*>(screenNode->getInnerNodeById("animationpreview_attachment1_bone_scrollarea"))->replaceSubNodes(bonesXML, true);
1119  } catch (Exception& exception) {
1120  Console::println("ModelEditorTabController::setAnimationPreviewDetails(): An error occurred: " + string(exception.what()));
1121  }
1122  }
1123 
1124  try {
1125  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_animationpreview"))->getActiveConditions().add("open");
1126  } catch (Exception& exception) {
1127  Console::println("ModelEditorTabController::setAnimationPreviewDetails(): An error occurred: " + string(exception.what()));
1128  showInfoPopUp("Warning", string(exception.what()));
1129  }
1130 }
1131 
1133  attachment1ModelFileName = fileName;
1135  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animationpreview_attachment1_bone"))->getController()->getValue().getString(),
1137  );
1138  try {
1139  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("animationpreview_attachment1_model"))->setSource(attachment1ModelFileName);
1140  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("animationpreview_attachment1_model"))->setTooltip(attachment1ModelFileName);
1141  } catch (Exception& exception) {
1142  Console::println("ModelEditorTabController::setPreviewAnimationsAttachment1Model(): An error occurred: " + string(exception.what()));
1143  showInfoPopUp("Warning", string(exception.what()));
1144  }
1145 }
1146 
1148  class OnPreviewAnimationsAttachment1ModelLoad: public virtual Action
1149  {
1150 
1151  public:
1152  void performAction() override {
1153  modelEditorTabController->setPreviewAnimationsAttachment1Model(modelEditorTabController->popUps->getFileDialogScreenController()->getPathName() + "/" + modelEditorTabController->popUps->getFileDialogScreenController()->getFileName());
1154  modelEditorTabController->popUps->getFileDialogScreenController()->close();
1155  }
1156 
1157  /**
1158  * Public constructor
1159  * @param modelEditorTabController model editor tab controller
1160  */
1161  OnPreviewAnimationsAttachment1ModelLoad(ModelEditorTabController* modelEditorTabController): modelEditorTabController(modelEditorTabController) {
1162  }
1163 
1164  private:
1165  ModelEditorTabController* modelEditorTabController;
1166  };
1167 
1169  string(),
1170  "Load animation preview attachment 1 model from: ",
1171  ModelReader::getModelExtensions(),
1172  string(),
1173  true,
1174  new OnPreviewAnimationsAttachment1ModelLoad(this)
1175  );
1176 }
1177 
1179  attachment1ModelFileName.clear();
1180  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("animationpreview_attachment1_model"))->setSource(attachment1ModelFileName);
1181  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("animationpreview_attachment1_model"))->setTooltip(attachment1ModelFileName);
1183 }
1184 
1186  if (attachment1ModelFileName.empty() == true) {
1187  showInfoPopUp("Browse To", "Nothing to browse to");
1188  return;
1189  }
1191 }
1192 
1194  try {
1195  view->setAttachment1NodeId(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animationpreview_attachment1_bone"))->getController()->getValue().getString());
1197  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animationpreview_base"))->getController()->getValue().getString(),
1198  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animationpreview_overlay1"))->getController()->getValue().getString(),
1199  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animationpreview_overlay2"))->getController()->getValue().getString(),
1200  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("animationpreview_overlay3"))->getController()->getValue().getString()
1201  );
1202  } catch (Exception& exception) {
1203  Console::println("ModelEditorTabController::applyAnimationPreviewDetails(): An error occurred: " + string(exception.what()));
1204  showInfoPopUp("Warning", string(exception.what()));
1205  }
1206 }
1207 
1208 void ModelEditorTabController::updateDetails(const string& outlinerNode) {
1209  view->getEditorView()->setDetailsContent(string());
1210  string outlinerNodeModel;
1211  Model* model = nullptr;
1212  getOutlinerNodeLOD(outlinerNode, outlinerNodeModel, &model);
1213  if (outlinerNodeModel == "model.materials") {
1215  } else
1216  if (StringTools::startsWith(outlinerNodeModel, "model.materials.") == true) {
1218  } else
1219  if (outlinerNodeModel == "model.animations") {
1221  } else
1222  if (StringTools::startsWith(outlinerNodeModel, "model.animations.") == true) {
1223  auto animationSetup = getSelectedAnimationSetup();
1224  view->playAnimation(animationSetup == nullptr?Model::ANIMATIONSETUP_DEFAULT:animationSetup->getId());
1226  } else {
1227  basePropertiesSubController->updateDetails(view->getPrototype(), outlinerNode, view->getPrototype());
1228  prototypeDisplaySubController->updateDetails(view->getPrototype(), outlinerNode);
1229  prototypePhysicsSubController->updateDetails(view->getPrototype(), outlinerNode);
1230  // TODO: model is here always NULLPTR, you cant have selected a LOD and at the same time sounds currently
1231  prototypeSoundsSubController->updateDetails(view->getPrototype(), view->getPrototype()->getModel(), outlinerNode);
1232  prototypeScriptSubController->updateDetails(view->getPrototype(), outlinerNode);
1233  }
1234 }
1235 
1237  auto material = getSelectedMaterial();
1238  if (material == nullptr) return;
1239  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1240  if (specularMaterialProperties == nullptr) {
1241  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1242  }
1243  view->reloadPrototype();
1244  specularMaterialProperties->setDiffuseTexture(
1245  Tools::getPathName(fileName),
1246  Tools::getFileName(fileName),
1247  specularMaterialProperties->getDiffuseTransparencyTexturePathName(),
1248  specularMaterialProperties->getDiffuseTransparencyTextureFileName()
1249  );
1251 }
1252 
1254  auto material = getSelectedMaterial();
1255  if (material == nullptr) return;
1256  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1257  if (specularMaterialProperties == nullptr) {
1258  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1259  material->setSpecularMaterialProperties(specularMaterialProperties);
1260  }
1261 
1262  class OnLoadTexture: public virtual Action
1263  {
1264  public:
1265  void performAction() override {
1266  modelEditorTabController->setMaterialDiffuseTexture(
1267  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() + "/" + modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
1268  );
1269  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
1270  }
1271 
1272  /**
1273  * Public constructor
1274  * @param modelEditorTabController model editor tab controller
1275  * @param specularMaterialProperties specular material properties
1276  */
1277  OnLoadTexture(ModelEditorTabController* modelEditorTabController, SpecularMaterialProperties* specularMaterialProperties)
1278  : modelEditorTabController(modelEditorTabController)
1279  , specularMaterialProperties(specularMaterialProperties) {
1280  }
1281 
1282 
1283  private:
1284  ModelEditorTabController* modelEditorTabController;
1285  SpecularMaterialProperties* specularMaterialProperties;
1286  };
1287 
1288  auto extensions = TextureReader::getTextureExtensions();
1290  specularMaterialProperties->getDiffuseTextureFileName().empty() == false?specularMaterialProperties->getDiffuseTexturePathName():string(),
1291  "Load specular diffuse texture from: ",
1292  extensions,
1293  specularMaterialProperties->getDiffuseTextureFileName(),
1294  true,
1295  new OnLoadTexture(this, specularMaterialProperties)
1296  );
1297 }
1298 
1300  auto material = getSelectedMaterial();
1301  if (material == nullptr) return;
1302  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1303  if (specularMaterialProperties == nullptr) {
1304  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1305  }
1306  view->reloadPrototype();
1307  specularMaterialProperties->setDiffuseTexture(
1308  string(),
1309  string(),
1310  specularMaterialProperties->getDiffuseTransparencyTexturePathName(),
1311  specularMaterialProperties->getDiffuseTransparencyTextureFileName()
1312  );
1314 }
1315 
1317  auto model = getSelectedModel();
1318  if (model == nullptr) {
1319  showInfoPopUp("Browse To", "Nothing to browse to");
1320  return;
1321  }
1322  if (model->hasEmbeddedSpecularTextures() == true) {
1323  showInfoPopUp("Browse To", "This model has embedded specular material textures");
1324  return;
1325  }
1326  auto material = getSelectedMaterial();
1327  if (material == nullptr) {
1328  showInfoPopUp("Browse To", "Nothing to browse to");
1329  return;
1330  }
1331  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1332  if (specularMaterialProperties == nullptr || specularMaterialProperties->getDiffuseTextureFileName().empty() == true) {
1333  showInfoPopUp("Browse To", "Nothing to browse to");
1334  return;
1335  }
1336  view->getEditorView()->getScreenController()->browseTo(specularMaterialProperties->getDiffuseTexturePathName() + "/" + specularMaterialProperties->getDiffuseTextureFileName());
1337 }
1338 
1340  auto material = getSelectedMaterial();
1341  if (material == nullptr) return;
1342  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1343  if (specularMaterialProperties == nullptr) {
1344  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1345  }
1346  view->reloadPrototype();
1347  specularMaterialProperties->setDiffuseTexture(
1348  specularMaterialProperties->getDiffuseTexturePathName(),
1349  specularMaterialProperties->getDiffuseTextureFileName(),
1350  Tools::getPathName(fileName),
1351  Tools::getFileName(fileName)
1352  );
1354 }
1355 
1357  auto material = getSelectedMaterial();
1358  if (material == nullptr) return;
1359  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1360  if (specularMaterialProperties == nullptr) {
1361  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1362  }
1363 
1364  class OnLoadTexture: public virtual Action
1365  {
1366  public:
1367  void performAction() override {
1368  modelEditorTabController->setMaterialDiffuseTransparencyTexture(
1369  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() + "/" + modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
1370  );
1371  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
1372  }
1373 
1374  /**
1375  * Public constructor
1376  * @param modelEditorTabController model editor tab controller
1377  * @param specularMaterialProperties specular material properties
1378  */
1379  OnLoadTexture(ModelEditorTabController* modelEditorTabController, SpecularMaterialProperties* specularMaterialProperties)
1380  : modelEditorTabController(modelEditorTabController)
1381  , specularMaterialProperties(specularMaterialProperties) {
1382  }
1383 
1384  private:
1385  ModelEditorTabController* modelEditorTabController;
1386  SpecularMaterialProperties* specularMaterialProperties;
1387  };
1388 
1389  auto extensions = TextureReader::getTextureExtensions();
1391  specularMaterialProperties->getDiffuseTransparencyTextureFileName().empty() == false?specularMaterialProperties->getDiffuseTransparencyTexturePathName():string(),
1392  "Load specular diffuse transparency texture from: ",
1393  extensions,
1394  specularMaterialProperties->getDiffuseTransparencyTextureFileName(),
1395  true,
1396  new OnLoadTexture(this, specularMaterialProperties)
1397  );
1398 }
1399 
1401  auto material = getSelectedMaterial();
1402  if (material == nullptr) return;
1403  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1404  if (specularMaterialProperties == nullptr) {
1405  specularMaterialProperties = new SpecularMaterialProperties();
1406  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1407  }
1408  view->reloadPrototype();
1409  specularMaterialProperties->setDiffuseTexture(
1410  specularMaterialProperties->getDiffuseTexturePathName(),
1411  specularMaterialProperties->getDiffuseTextureFileName(),
1412  string(),
1413  string()
1414  );
1416 }
1417 
1419  auto model = getSelectedModel();
1420  if (model == nullptr) {
1421  showInfoPopUp("Browse To", "Nothing to browse to");
1422  return;
1423  }
1424  if (model->hasEmbeddedSpecularTextures() == true) {
1425  showInfoPopUp("Browse To", "This model has embedded specular material textures");
1426  return;
1427  }
1428  auto material = getSelectedMaterial();
1429  if (material == nullptr) {
1430  showInfoPopUp("Browse To", "Nothing to browse to");
1431  return;
1432  }
1433  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1434  if (specularMaterialProperties == nullptr) {
1435  showInfoPopUp("Browse To", "Nothing to browse to");
1436  return;
1437  }
1438  if (specularMaterialProperties->getDiffuseTransparencyTextureFileName().empty() == false) {
1439  view->getEditorView()->getScreenController()->browseTo(specularMaterialProperties->getDiffuseTransparencyTexturePathName() + "/" + specularMaterialProperties->getDiffuseTransparencyTextureFileName());
1440  } else
1441  if (specularMaterialProperties->getDiffuseTextureFileName().empty() == false) {
1442  view->getEditorView()->getScreenController()->browseTo(specularMaterialProperties->getDiffuseTexturePathName() + "/" + specularMaterialProperties->getDiffuseTextureFileName());
1443  } else {
1444  showInfoPopUp("Browse To", "Nothing to browse to");
1445  }
1446 }
1447 
1449  auto material = getSelectedMaterial();
1450  if (material == nullptr) return;
1451  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1452  if (specularMaterialProperties == nullptr) {
1453  specularMaterialProperties = new SpecularMaterialProperties();
1454  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1455  }
1456  view->reloadPrototype();
1457  specularMaterialProperties->setNormalTexture(
1458  Tools::getPathName(fileName),
1459  Tools::getFileName(fileName)
1460  );
1462 }
1463 
1465  auto material = getSelectedMaterial();
1466  if (material == nullptr) return;
1467  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1468  if (specularMaterialProperties == nullptr) {
1469  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1470  }
1471 
1472  class OnLoadTexture: public virtual Action
1473  {
1474  public:
1475  void performAction() override {
1476  modelEditorTabController->setMaterialNormalTexture(
1477  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() + "/" + modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
1478  );
1479  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
1480  }
1481 
1482  /**
1483  * Public constructor
1484  * @param modelEditorTabController model editor tab controller
1485  * @param specularMaterialProperties specular material properties
1486  */
1487  OnLoadTexture(ModelEditorTabController* modelEditorTabController, SpecularMaterialProperties* specularMaterialProperties)
1488  : modelEditorTabController(modelEditorTabController)
1489  , specularMaterialProperties(specularMaterialProperties) {
1490  }
1491 
1492 
1493  private:
1494  ModelEditorTabController* modelEditorTabController;
1495  SpecularMaterialProperties* specularMaterialProperties;
1496  };
1497 
1498  auto extensions = TextureReader::getTextureExtensions();
1500  specularMaterialProperties->getNormalTextureFileName().empty() == false?specularMaterialProperties->getNormalTexturePathName():string(),
1501  "Load specular normal texture from: ",
1502  extensions,
1503  specularMaterialProperties->getNormalTextureFileName(),
1504  true,
1505  new OnLoadTexture(this, specularMaterialProperties)
1506  );
1507 }
1508 
1510  auto material = getSelectedMaterial();
1511  if (material == nullptr) return;
1512  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1513  if (specularMaterialProperties == nullptr) {
1514  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1515  }
1516  view->reloadPrototype();
1517  specularMaterialProperties->setNormalTexture(
1518  string(),
1519  string()
1520  );
1522 }
1523 
1525  auto model = getSelectedModel();
1526  if (model == nullptr) {
1527  showInfoPopUp("Browse To", "Nothing to browse to");
1528  return;
1529  }
1530  if (model->hasEmbeddedSpecularTextures() == true) {
1531  showInfoPopUp("Browse To", "This model has embedded specular material textures");
1532  return;
1533  }
1534  auto material = getSelectedMaterial();
1535  if (material == nullptr) {
1536  showInfoPopUp("Browse To", "Nothing to browse to");
1537  return;
1538  }
1539  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1540  if (specularMaterialProperties == nullptr || specularMaterialProperties->getNormalTextureFileName().empty() == true) {
1541  showInfoPopUp("Browse To", "Nothing to browse to");
1542  return;
1543  }
1544  view->getEditorView()->getScreenController()->browseTo(specularMaterialProperties->getNormalTexturePathName() + "/" + specularMaterialProperties->getNormalTextureFileName());
1545 }
1546 
1548  auto material = getSelectedMaterial();
1549  if (material == nullptr) return;
1550  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1551  if (specularMaterialProperties == nullptr) {
1552  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1553  }
1554  //
1555  view->reloadPrototype();
1556  specularMaterialProperties->setSpecularTexture(
1557  Tools::getPathName(fileName),
1558  Tools::getFileName(fileName)
1559  );
1561 }
1562 
1564  auto material = getSelectedMaterial();
1565  if (material == nullptr) return;
1566  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1567  if (specularMaterialProperties == nullptr) {
1568  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1569  }
1570 
1571  class OnLoadTexture: public virtual Action
1572  {
1573  public:
1574  void performAction() override {
1575  modelEditorTabController->setMaterialSpecularTexture(
1576  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() + "/" + modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
1577  );
1578  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
1579  }
1580 
1581  /**
1582  * Public constructor
1583  * @param modelEditorTabController model editor tab controller
1584  * @param specularMaterialProperties specular material properties
1585  */
1586  OnLoadTexture(ModelEditorTabController* modelEditorTabController, SpecularMaterialProperties* specularMaterialProperties)
1587  : modelEditorTabController(modelEditorTabController)
1588  , specularMaterialProperties(specularMaterialProperties) {
1589  }
1590 
1591 
1592  private:
1593  ModelEditorTabController* modelEditorTabController;
1594  SpecularMaterialProperties* specularMaterialProperties;
1595  };
1596 
1597  auto extensions = TextureReader::getTextureExtensions();
1599  specularMaterialProperties->getSpecularTextureFileName().empty() == false?specularMaterialProperties->getSpecularTexturePathName():string(),
1600  "Load specular specular texture from: ",
1601  extensions,
1602  specularMaterialProperties->getSpecularTextureFileName(),
1603  true,
1604  new OnLoadTexture(this, specularMaterialProperties)
1605  );
1606 }
1607 
1609  auto material = getSelectedMaterial();
1610  if (material == nullptr) return;
1611  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1612  if (specularMaterialProperties == nullptr) {
1613  material->setSpecularMaterialProperties(specularMaterialProperties = (make_unique<SpecularMaterialProperties>()).release());
1614  }
1615  view->reloadPrototype();
1616  specularMaterialProperties->setSpecularTexture(
1617  string(),
1618  string()
1619  );
1621 }
1622 
1624  auto model = getSelectedModel();
1625  if (model == nullptr) {
1626  showInfoPopUp("Browse To", "Nothing to browse to");
1627  return;
1628  }
1629  if (model->hasEmbeddedSpecularTextures() == true) {
1630  showInfoPopUp("Browse To", "This model has embedded specular material textures");
1631  return;
1632  }
1633  auto material = getSelectedMaterial();
1634  if (material == nullptr) {
1635  showInfoPopUp("Browse To", "Nothing to browse to");
1636  return;
1637  }
1638  auto specularMaterialProperties = material->getSpecularMaterialProperties();
1639  if (specularMaterialProperties == nullptr || specularMaterialProperties->getSpecularTextureFileName().empty() == true) {
1640  showInfoPopUp("Browse To", "Nothing to browse to");
1641  return;
1642  }
1643  view->getEditorView()->getScreenController()->browseTo(specularMaterialProperties->getSpecularTexturePathName() + "/" + specularMaterialProperties->getSpecularTextureFileName());
1644 }
1645 
1647  auto material = getSelectedMaterial();
1648  if (material == nullptr) return;
1649  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1650  if (pbrMaterialProperties == nullptr) return;
1651  //
1652  view->reloadPrototype();
1653  pbrMaterialProperties->setBaseColorTexture(
1654  Tools::getPathName(fileName),
1655  Tools::getFileName(fileName)
1656  );
1658 }
1659 
1661  auto material = getSelectedMaterial();
1662  if (material == nullptr) return;
1663  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1664  if (pbrMaterialProperties == nullptr) return;
1665 
1666  class OnLoadTexture: public virtual Action
1667  {
1668  public:
1669  void performAction() override {
1670  modelEditorTabController->setMaterialPBRBaseColorTexture(
1671  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() + "/" + modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
1672  );
1673  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
1674  }
1675 
1676  /**
1677  * Public constructor
1678  * @param modelEditorTabController model editor tab controller
1679  * @param specularMaterialProperties specular material properties
1680  */
1681  OnLoadTexture(ModelEditorTabController* modelEditorTabController, PBRMaterialProperties* pbrMaterialProperties)
1682  : modelEditorTabController(modelEditorTabController)
1683  , pbrMaterialProperties(pbrMaterialProperties) {
1684  }
1685 
1686 
1687  private:
1688  ModelEditorTabController* modelEditorTabController;
1689  PBRMaterialProperties* pbrMaterialProperties;
1690  };
1691 
1692  auto extensions = TextureReader::getTextureExtensions();
1694  pbrMaterialProperties->getBaseColorTextureFileName().empty() == false?pbrMaterialProperties->getBaseColorTexturePathName():string(),
1695  "Load PBR base color texture from: ",
1696  extensions,
1697  pbrMaterialProperties->getBaseColorTextureFileName(),
1698  true,
1699  new OnLoadTexture(this, pbrMaterialProperties)
1700  );
1701 }
1702 
1704  auto material = getSelectedMaterial();
1705  if (material == nullptr) return;
1706  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1707  if (pbrMaterialProperties == nullptr) return;
1708  view->reloadPrototype();
1709  pbrMaterialProperties->setBaseColorTexture(
1710  string(),
1711  string()
1712  );
1714 }
1715 
1717  auto model = getSelectedModel();
1718  if (model == nullptr) {
1719  showInfoPopUp("Browse To", "Nothing to browse to");
1720  return;
1721  }
1722  if (model->hasEmbeddedPBRTextures() == true) {
1723  showInfoPopUp("Browse To", "This model has embedded PBR material textures");
1724  return;
1725  }
1726  auto material = getSelectedMaterial();
1727  if (material == nullptr) {
1728  showInfoPopUp("Browse To", "Nothing to browse to");
1729  return;
1730  }
1731  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1732  if (pbrMaterialProperties == nullptr || pbrMaterialProperties->getBaseColorTextureFileName().empty() == true) {
1733  showInfoPopUp("Browse To", "Nothing to browse to");
1734  return;
1735  }
1736  view->getEditorView()->getScreenController()->browseTo(pbrMaterialProperties->getBaseColorTexturePathName() + "/" + pbrMaterialProperties->getBaseColorTextureFileName());
1737 }
1738 
1740  auto material = getSelectedMaterial();
1741  if (material == nullptr) return;
1742  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1743  if (pbrMaterialProperties == nullptr) return;
1744  //
1745  view->reloadPrototype();
1746  pbrMaterialProperties->setMetallicRoughnessTexture(
1747  Tools::getPathName(fileName),
1748  Tools::getFileName(fileName)
1749  );
1751 }
1752 
1754  auto material = getSelectedMaterial();
1755  if (material == nullptr) return;
1756  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1757  if (pbrMaterialProperties == nullptr) return;
1758 
1759  class OnLoadTexture: public virtual Action
1760  {
1761  public:
1762  void performAction() override {
1763  modelEditorTabController->setMaterialPBRMetallicRoughnessTexture(
1764  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() + "/" + modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
1765  );
1766  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
1767  }
1768 
1769  /**
1770  * Public constructor
1771  * @param modelEditorTabController model editor tab controller
1772  * @param specularMaterialProperties specular material properties
1773  */
1774  OnLoadTexture(ModelEditorTabController* modelEditorTabController, PBRMaterialProperties* pbrMaterialProperties)
1775  : modelEditorTabController(modelEditorTabController)
1776  , pbrMaterialProperties(pbrMaterialProperties) {
1777  }
1778 
1779 
1780  private:
1781  ModelEditorTabController* modelEditorTabController;
1782  PBRMaterialProperties* pbrMaterialProperties;
1783  };
1784 
1785  auto extensions = TextureReader::getTextureExtensions();
1787  pbrMaterialProperties->getMetallicRoughnessTextureFileName().empty() == false?pbrMaterialProperties->getMetallicRoughnessTexturePathName():string(),
1788  "Load PBR metallic/roughness texture from: ",
1789  extensions,
1790  pbrMaterialProperties->getMetallicRoughnessTextureFileName(),
1791  true,
1792  new OnLoadTexture(this, pbrMaterialProperties)
1793  );
1794 }
1795 
1797  auto material = getSelectedMaterial();
1798  if (material == nullptr) return;
1799  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1800  if (pbrMaterialProperties == nullptr) return;
1801  view->reloadPrototype();
1802  pbrMaterialProperties->setMetallicRoughnessTexture(
1803  string(),
1804  string()
1805  );
1807 }
1808 
1810  auto model = getSelectedModel();
1811  if (model == nullptr) {
1812  showInfoPopUp("Browse To", "Nothing to browse to");
1813  return;
1814  }
1815  if (model->hasEmbeddedPBRTextures() == true) {
1816  showInfoPopUp("Browse To", "This model has embedded PBR material textures");
1817  return;
1818  }
1819  auto material = getSelectedMaterial();
1820  if (material == nullptr) {
1821  showInfoPopUp("Browse To", "Nothing to browse to");
1822  return;
1823  }
1824  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1825  if (pbrMaterialProperties == nullptr || pbrMaterialProperties->getMetallicRoughnessTextureFileName().empty() == true) {
1826  showInfoPopUp("Browse To", "Nothing to browse to");
1827  return;
1828  }
1829  view->getEditorView()->getScreenController()->browseTo(pbrMaterialProperties->getMetallicRoughnessTexturePathName() + "/" + pbrMaterialProperties->getMetallicRoughnessTextureFileName());
1830 }
1831 
1833  auto material = getSelectedMaterial();
1834  if (material == nullptr) return;
1835  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1836  if (pbrMaterialProperties == nullptr) return;
1837  //
1838  view->reloadPrototype();
1839  pbrMaterialProperties->setNormalTexture(
1840  Tools::getPathName(fileName),
1841  Tools::getFileName(fileName)
1842  );
1844 }
1845 
1847  auto material = getSelectedMaterial();
1848  if (material == nullptr) return;
1849  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1850  if (pbrMaterialProperties == nullptr) return;
1851 
1852  class OnLoadTexture: public virtual Action
1853  {
1854  public:
1855  void performAction() override {
1856  modelEditorTabController->setMaterialPBRNormalTexture(
1857  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() + "/" + modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
1858  );
1859  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
1860  }
1861 
1862  /**
1863  * Public constructor
1864  * @param modelEditorTabController model editor tab controller
1865  * @param specularMaterialProperties specular material properties
1866  */
1867  OnLoadTexture(ModelEditorTabController* modelEditorTabController, PBRMaterialProperties* pbrMaterialProperties)
1868  : modelEditorTabController(modelEditorTabController)
1869  , pbrMaterialProperties(pbrMaterialProperties) {
1870  }
1871 
1872 
1873  private:
1874  ModelEditorTabController* modelEditorTabController;
1875  PBRMaterialProperties* pbrMaterialProperties;
1876  };
1877 
1878  auto extensions = TextureReader::getTextureExtensions();
1880  pbrMaterialProperties->getNormalTextureFileName().empty() == false?pbrMaterialProperties->getNormalTexturePathName():string(),
1881  "Load PBR normal texture from: ",
1882  extensions,
1883  pbrMaterialProperties->getNormalTextureFileName(),
1884  true,
1885  new OnLoadTexture(this, pbrMaterialProperties)
1886  );
1887 }
1888 
1890  auto material = getSelectedMaterial();
1891  if (material == nullptr) return;
1892  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1893  if (pbrMaterialProperties == nullptr) return;
1894  view->reloadPrototype();
1895  pbrMaterialProperties->setNormalTexture(
1896  string(),
1897  string()
1898  );
1900 }
1901 
1903  auto model = getSelectedModel();
1904  if (model == nullptr) {
1905  showInfoPopUp("Browse To", "Nothing to browse to");
1906  return;
1907  }
1908  if (model->hasEmbeddedPBRTextures() == true) {
1909  showInfoPopUp("Browse To", "This model has embedded PBR material textures");
1910  return;
1911  }
1912  auto material = getSelectedMaterial();
1913  if (material == nullptr) {
1914  showInfoPopUp("Browse To", "Nothing to browse to");
1915  return;
1916  }
1917  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1918  if (pbrMaterialProperties == nullptr || pbrMaterialProperties->getNormalTextureFileName().empty() == true) {
1919  showInfoPopUp("Browse To", "Nothing to browse to");
1920  return;
1921  }
1922  view->getEditorView()->getScreenController()->browseTo(pbrMaterialProperties->getNormalTexturePathName() + "/" + pbrMaterialProperties->getNormalTextureFileName());
1923 }
1924 
1926  auto material = getSelectedMaterial();
1927  if (material == nullptr) return;
1928  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1929  if (pbrMaterialProperties == nullptr) return;
1930  //
1931  view->reloadPrototype();
1932  pbrMaterialProperties->setEmissiveTexture(
1933  Tools::getPathName(fileName),
1934  Tools::getFileName(fileName)
1935  );
1937 }
1938 
1940  auto material = getSelectedMaterial();
1941  if (material == nullptr) return;
1942  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1943  if (pbrMaterialProperties == nullptr) return;
1944 
1945  class OnLoadTexture: public virtual Action
1946  {
1947  public:
1948  void performAction() override {
1949  modelEditorTabController->setMaterialPBREmissiveTexture(
1950  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() + "/" + modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
1951  );
1952  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
1953  }
1954 
1955  /**
1956  * Public constructor
1957  * @param modelEditorTabController model editor tab controller
1958  * @param specularMaterialProperties specular material properties
1959  */
1960  OnLoadTexture(ModelEditorTabController* modelEditorTabController, PBRMaterialProperties* pbrMaterialProperties)
1961  : modelEditorTabController(modelEditorTabController)
1962  , pbrMaterialProperties(pbrMaterialProperties) {
1963  }
1964 
1965 
1966  private:
1967  ModelEditorTabController* modelEditorTabController;
1968  PBRMaterialProperties* pbrMaterialProperties;
1969  };
1970 
1971  auto extensions = TextureReader::getTextureExtensions();
1973  pbrMaterialProperties->getEmissiveTextureFileName().empty() == false?pbrMaterialProperties->getEmissiveTexturePathName():string(),
1974  "Load PBR emissive texture from: ",
1975  extensions,
1976  pbrMaterialProperties->getEmissiveTextureFileName(),
1977  true,
1978  new OnLoadTexture(this, pbrMaterialProperties)
1979  );
1980 }
1981 
1983  auto material = getSelectedMaterial();
1984  if (material == nullptr) return;
1985  auto pbrMaterialProperties = material->getPBRMaterialProperties();
1986  if (pbrMaterialProperties == nullptr) return;
1987  view->reloadPrototype();
1988  pbrMaterialProperties->setEmissiveTexture(
1989  string(),
1990  string()
1991  );
1993 }
1994 
1996  auto model = getSelectedModel();
1997  if (model == nullptr) {
1998  showInfoPopUp("Browse To", "Nothing to browse to");
1999  return;
2000  }
2001  if (model->hasEmbeddedPBRTextures() == true) {
2002  showInfoPopUp("Browse To", "This model has embedded PBR material textures");
2003  return;
2004  }
2005  auto material = getSelectedMaterial();
2006  if (material == nullptr) {
2007  showInfoPopUp("Browse To", "Nothing to browse to");
2008  return;
2009  }
2010  auto pbrMaterialProperties = material->getPBRMaterialProperties();
2011  if (pbrMaterialProperties == nullptr || pbrMaterialProperties->getEmissiveTextureFileName().empty() == true) {
2012  showInfoPopUp("Browse To", "Nothing to browse to");
2013  return;
2014  }
2015  view->getEditorView()->getScreenController()->browseTo(pbrMaterialProperties->getEmissiveTexturePathName() + "/" + pbrMaterialProperties->getEmissiveTextureFileName());
2016 }
2017 
2018 void ModelEditorTabController::startRenameAnimation(int lodLevel, const string& animationId) {
2019  auto prototype = view->getPrototype();
2020  if (prototype == nullptr) return;
2021 
2022  auto selectBoxOptionParentNode = dynamic_cast<GUIParentNode*>(view->getEditorView()->getScreenController()->getScreenNode()->getNodeById((lodLevel == 1?"model":"lod" + to_string(lodLevel) + ".model") + ".animations." + animationId));
2023  if (selectBoxOptionParentNode == nullptr) return;
2024 
2025  renameAnimationId = animationId;
2026  renameAnimationLOD = lodLevel;
2027  selectBoxOptionParentNode->replaceSubNodes(
2028  "<template id=\"tdme.animations.rename_input\" hint=\"Animation name\" text=\"" + GUIParser::escape(animationId) + "\"src=\"resources/engine/gui/template_outliner_rename.xml\" />\n",
2029  true
2030  );
2031  Engine::getInstance()->getGUI()->setFoccussedNode(dynamic_cast<GUIElementNode*>(view->getEditorView()->getScreenController()->getScreenNode()->getNodeById("tdme.animations.rename_input")));
2032  view->getEditorView()->getScreenController()->getScreenNode()->forwardChange(required_dynamic_cast<GUIElementNode*>(view->getEditorView()->getScreenController()->getScreenNode()->getNodeById("selectbox_outliner")));
2033 }
2034 
2037  if (model == nullptr) {
2038  renameAnimationLOD = -1;
2039  renameAnimationId.clear();
2040  return;
2041  }
2042 
2043  auto animationSetup = model->getAnimationSetup(renameAnimationId);
2044  renameAnimationId.clear();
2045  if (animationSetup != nullptr) {
2046  view->playAnimation(Model::ANIMATIONSETUP_DEFAULT);
2047  try {
2048  if (model->renameAnimationSetup(
2049  animationSetup->getId(),
2050  required_dynamic_cast<GUIElementNode*>(view->getEditorView()->getScreenController()->getScreenNode()->getNodeById("tdme.animations.rename_input"))->getController()->getValue().getString()
2051  ) == false) {
2052  //
2053  throw ExceptionBase("Could not rename animation");
2054  }
2055  } catch (Exception& exception) {
2056  Console::println("ModelEditorTabController::renameAnimation(): An error occurred: " + string(exception.what()));
2057  showInfoPopUp("Warning", string(exception.what()));
2058  }
2059  }
2060 
2061  view->getEditorView()->reloadTabOutliner((renameAnimationLOD == 1?"model":"lod" + to_string(renameAnimationLOD) + ".model") + ".animations" + (animationSetup != nullptr?"." + animationSetup->getId():""));
2062  renameAnimationLOD = -1;
2063 }
2064 
2066  Model* model = getSelectedModel();
2067  if (model == nullptr) return;
2068 
2069  //
2070  auto defaultAnimationSetup = model->getAnimationSetup(Model::ANIMATIONSETUP_DEFAULT);
2071 
2072  auto animationSetupCreated = false;
2073  auto animationSetupName = string() + "New animation";
2074  if (model->getAnimationSetup(animationSetupName) == nullptr &&
2075  model->addAnimationSetup(animationSetupName, defaultAnimationSetup != nullptr?defaultAnimationSetup->getStartFrame():0, defaultAnimationSetup != nullptr?defaultAnimationSetup->getEndFrame():0, false, 1.0f) != nullptr) {
2076  animationSetupCreated = true;
2077  } else {
2078  //
2079  for (auto i = 1; i < 10001; i++) {
2080  animationSetupName = string() + "New animation " + to_string(i);
2081  if (model->getAnimationSetup(animationSetupName) == nullptr &&
2082  model->addAnimationSetup(animationSetupName, defaultAnimationSetup != nullptr?defaultAnimationSetup->getStartFrame():0, defaultAnimationSetup != nullptr?defaultAnimationSetup->getEndFrame():0, false, 1.0f) != nullptr) {
2083  animationSetupCreated = true;
2084  //
2085  break;
2086  }
2087  }
2088  }
2089  try {
2090  if (animationSetupCreated == false) {
2091  throw ExceptionBase("Could not create animation");
2092  }
2093  } catch (Exception& exception) {
2094  Console::println("ModelEditorTabController::createAnimationSetup(): An error occurred: " + string(exception.what()));
2095  showInfoPopUp("Warning", string(exception.what()));
2096  }
2097 
2098  if (animationSetupCreated == true) {
2099  view->getEditorView()->reloadTabOutliner(string() + "model.animations." + animationSetupName);
2100  startRenameAnimation(lodLevel, animationSetupName);
2101  }
2102 }
2103 
2105  class OnLoadLODModel: public virtual Action
2106  {
2107  public:
2108  void performAction() override {
2109  auto lodLevelIdx = -1;
2110  PrototypeLODLevel* lodLevel = nullptr;
2111  if (modelEditorTabController->view->getPrototype()->getLODLevel2() == nullptr) {
2112  lodLevel = modelEditorTabController->getLODLevel(2);
2113  lodLevelIdx = 2;
2114  } else
2115  if (modelEditorTabController->view->getPrototype()->getLODLevel3() == nullptr) {
2116  lodLevel = modelEditorTabController->getLODLevel(3);
2117  lodLevelIdx = 3;
2118  }
2119  if (lodLevel == nullptr) return;
2120 
2121  lodLevel->setFileName(
2122  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() +
2123  "/" +
2124  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
2125  );
2126  lodLevel->setType(LODObject::LODLEVELTYPE_MODEL);
2127  try {
2128  lodLevel->setModel(
2129  lodLevel->getType() == LODObject::LODLEVELTYPE_MODEL?
2130  ModelReader::read(
2131  Tools::getPathName(lodLevel->getFileName()),
2132  Tools::getFileName(lodLevel->getFileName())
2133  ):
2134  nullptr
2135  );
2136  } catch (Exception& exception) {
2137  Console::println("OnLoadLODModel::performAction(): An error occurred: " + string(exception.what()));
2138  modelEditorTabController->showInfoPopUp("Warning", string(exception.what()));
2139  }
2140  modelEditorTabController->view->getEditorView()->reloadTabOutliner("lod" + to_string(lodLevelIdx) + ".model");
2141  modelEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
2142  }
2143 
2144  /**
2145  * Public constructor
2146  * @param modelEditorTabController model editor tab controller
2147  */
2148  OnLoadLODModel(ModelEditorTabController* modelEditorTabController)
2149  : modelEditorTabController(modelEditorTabController) {
2150  //
2151  }
2152 
2153  private:
2154  ModelEditorTabController* modelEditorTabController;
2155  };
2156 
2157  PrototypeLODLevel* lodLevel = nullptr;
2158  if (view->getPrototype()->getLODLevel2() != nullptr && view->getPrototype()->getLODLevel3() != nullptr) {
2159  Console::println("ModelEditorTabController::createLOD(): LOD level 2 and LOD level 3 is already in use");
2160  showInfoPopUp("Warning", "LOD level 2 and LOD level 3 is already in use");
2161  return;
2162  }
2163 
2165  string(),
2166  "Load LOD model from: ",
2167  ModelReader::getModelExtensions(),
2168  string(),
2169  true,
2170  new OnLoadLODModel(this)
2171  );
2172 }
2173 
2175  PrototypeLODLevel* lodLevel = nullptr;
2176  if (view->getPrototype()->getLODLevel2() == nullptr) {
2177  lodLevel = getLODLevel(2);
2178  } else
2179  if (view->getPrototype()->getLODLevel3() == nullptr) {
2180  lodLevel = getLODLevel(3);
2181  }
2182  if (lodLevel == nullptr) return;
2183 
2184  lodLevel->setType(LODObject::LODLEVELTYPE_IGNORE);
2187 }
2188 
2190  auto prototype = view->getPrototype();
2191  if (prototype == nullptr) return;
2192 
2193  PrototypeLODLevel* prototypeLODLevel = nullptr;
2194  switch (lodLevel) {
2195  case 2: prototypeLODLevel = prototype->getLODLevel2(); break;
2196  case 3: prototypeLODLevel = prototype->getLODLevel3(); break;
2197  }
2198  if (prototypeLODLevel == nullptr) return;
2199 
2201  string("<template id=\"details_lod\" src=\"resources/engine/gui/template_details_lod.xml\" />\n")
2202  );
2203 
2204  try {
2205  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_lod"))->getActiveConditions().add("open");
2206  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("lod_min_distance"))->getController()->setValue(prototypeLODLevel->getMinDistance());
2207  } catch (Exception& exception) {
2208  Console::println("ModelEditorTabController::setLODDetails(): An error occurred: " + string(exception.what()));
2209  showInfoPopUp("Warning", string(exception.what()));
2210  }
2211 
2212  //
2213  updateLODColorDetails(lodLevel);
2214 }
2215 
2217  auto prototype = view->getPrototype();
2218  if (prototype == nullptr) return;
2219 
2220  PrototypeLODLevel* prototypeLODLevel = nullptr;
2221  switch (lodLevel) {
2222  case 2: prototypeLODLevel = prototype->getLODLevel2(); break;
2223  case 3: prototypeLODLevel = prototype->getLODLevel3(); break;
2224  }
2225  if (prototypeLODLevel == nullptr) return;
2226 
2227  try {
2228  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("lod_color_add"))->setEffectColorMul(Color4(prototypeLODLevel->getColorAdd()));
2229  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("lod_color_mul"))->setEffectColorMul(Color4(prototypeLODLevel->getColorMul()));
2230  } catch (Exception& exception) {
2231  Console::println("ModelEditorTabController::updateLODColorDetails(): An error occurred: " + string(exception.what()));
2232  showInfoPopUp("Warning", string(exception.what()));
2233  }
2234 }
2235 
2237  auto prototype = view->getPrototype();
2238  if (prototype == nullptr) return;
2239 
2240  PrototypeLODLevel* prototypeLODLevel = nullptr;
2241  switch (lodLevel) {
2242  case 2: prototypeLODLevel = prototype->getLODLevel2(); break;
2243  case 3: prototypeLODLevel = prototype->getLODLevel3(); break;
2244  }
2245  if (prototypeLODLevel == nullptr) return;
2246 
2247  try {
2248  prototypeLODLevel->setMinDistance(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("lod_min_distance"))->getController()->getValue().getString()));
2249  } catch (Exception& exception) {
2250  Console::println("ModelEditorTabController::applyLODDetails(): An error occurred: " + string(exception.what()));
2251  showInfoPopUp("Warning", string(exception.what()));
2252  }
2253 }
2254 
2255 bool ModelEditorTabController::getOutlinerNodeLOD(const string& outlinerNode, string& modelOutlinerNode, Model** model, int* lodLevel) {
2256  if (StringTools::startsWith(outlinerNode, "model.") == true) {
2257  if (model != nullptr) *model = view->getPrototype()->getModel();
2258  if (lodLevel != nullptr) *lodLevel = 1;
2259  modelOutlinerNode = outlinerNode;
2260  } else
2261  if (outlinerNode == "lod2.model") {
2262  if (model != nullptr) *model = view->getPrototype()->getLODLevel2() != nullptr?view->getPrototype()->getLODLevel2()->getModel():nullptr;
2263  if (lodLevel != nullptr) *lodLevel = 2;
2264  modelOutlinerNode = outlinerNode;
2265  } else
2266  if (StringTools::startsWith(outlinerNode, "lod2.model.") == true) {
2267  if (model != nullptr) *model = view->getPrototype()->getLODLevel2() != nullptr?view->getPrototype()->getLODLevel2()->getModel():nullptr;
2268  if (lodLevel != nullptr) *lodLevel = 2;
2269  modelOutlinerNode = StringTools::substring(outlinerNode, string("lod2.").size(), outlinerNode.size());
2270  } else
2271  if (outlinerNode == "lod3.model") {
2272  if (model != nullptr) *model = view->getPrototype()->getLODLevel3() != nullptr?view->getPrototype()->getLODLevel3()->getModel():nullptr;
2273  if (lodLevel != nullptr) *lodLevel = 3;
2274  modelOutlinerNode = outlinerNode;
2275  } else
2276  if (StringTools::startsWith(outlinerNode, "lod3.model.") == true) {
2277  if (model != nullptr) *model = view->getPrototype()->getLODLevel3() != nullptr?view->getPrototype()->getLODLevel3()->getModel():nullptr;
2278  if (lodLevel != nullptr) *lodLevel = 3;
2279  modelOutlinerNode = StringTools::substring(outlinerNode, string("lod3.").size(), outlinerNode.size());
2280  } else
2281  if (outlinerNode == "lod4.model") {
2282  if (model != nullptr) *model = nullptr;
2283  if (lodLevel != nullptr) *lodLevel = 4;
2284  modelOutlinerNode = outlinerNode;
2285  } else
2286  if (StringTools::startsWith(outlinerNode, "lod4.model.") == true) {
2287  if (model != nullptr) *model = nullptr;
2288  if (lodLevel != nullptr) *lodLevel = 4;
2289  modelOutlinerNode = StringTools::substring(outlinerNode, string("lod4.").size(), outlinerNode.size());
2290  } else {
2291  if (model != nullptr) *model = view->getPrototype()->getModel();
2292  if (lodLevel != nullptr) *lodLevel = 1;
2293  modelOutlinerNode = outlinerNode;
2294  }
2295  return model != nullptr;
2296 }
2297 
2299 {
2300  if (basePropertiesSubController->onChange(node, view->getPrototype(), view->getPrototype()) == true) return;
2301  if (prototypeDisplaySubController->onChange(node, view->getPrototype()) == true) return;
2302  if (prototypePhysicsSubController->onChange(node, view->getPrototype()) == true) return;
2303  if (prototypeScriptSubController->onChange(node, view->getPrototype()) == true) return;
2304  //
2305  auto model = getSelectedModel();
2306  if (model != nullptr) {
2307  if (prototypeSoundsSubController->onChange(node, view->getPrototype(), model) == true) return;
2308  }
2309  //
2310  if (node->getId() == "dropdown_outliner_add") {
2311  auto addOutlinerType = node->getController()->getValue().getString();
2312  if (addOutlinerType == "animation") {
2313  auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
2314  string modelOutlinerNode;
2315  int lodLevel = -1;
2316  getOutlinerNodeLOD(outlinerNode, modelOutlinerNode, nullptr, &lodLevel);
2317  createAnimationSetup(lodLevel);
2318  } else
2319  if (addOutlinerType == "lod") {
2320  createLOD();
2321  } else
2322  if (addOutlinerType == "lod_none") {
2323  createLODNone();
2324  }
2325  } else
2326  if (node->getId() == "selectbox_outliner") {
2327  auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
2328  auto haveDetails = false;
2329  if (outlinerNode == "lod2.model" ||
2330  StringTools::startsWith(outlinerNode, "lod2.model.") == true) {
2331  if (view->getLODLevel() != 2) view->setLODLevel(2);
2332  if (outlinerNode == "lod2.model") {
2333  haveDetails = true;
2334  setLODDetails(2);
2335  }
2336  } else
2337  if (outlinerNode == "lod3.model" ||
2338  StringTools::startsWith(outlinerNode, "lod3.model.") == true) {
2339  if (view->getLODLevel() != 3) view->setLODLevel(3);
2340  if (outlinerNode == "lod3.model") {
2341  haveDetails = true;
2342  setLODDetails(3);
2343  }
2344  } else
2345  if (outlinerNode == "lod4.model" ||
2346  StringTools::startsWith(outlinerNode, "lod4.model.") == true) {
2347  if (view->getLODLevel() != 3) view->setLODLevel(4);
2348  if (outlinerNode == "lod4.model") {
2349  haveDetails = true;
2350  setLODDetails(4);
2351  }
2352  } else {
2353  if (view->getLODLevel() != 1) view->setLODLevel(1);
2354  }
2355  //
2356  if (haveDetails == false) updateDetails(outlinerNode);
2357  } else {
2358  //
2359  for (const auto& applyAnimationNode: applyAnimationNodes) {
2360  if (node->getId() == applyAnimationNode) {
2362  break;
2363  }
2364  }
2365  for (const auto& applyMaterialBaseNode: applyMaterialBaseNodes) {
2366  if (node->getId() == applyMaterialBaseNode) {
2368  break;
2369  }
2370  }
2371  for (const auto& applySpecularMaterialNode: applySpecularMaterialNodes) {
2372  if (node->getId() == applySpecularMaterialNode) {
2374  break;
2375  }
2376  }
2377  for (const auto& applyPBRMaterialNode: applyPBRMaterialNodes) {
2378  if (node->getId() == applyPBRMaterialNode) {
2380  break;
2381  }
2382  }
2383  for (const auto& applyAnimationPreviewNode: applyAnimationPreviewNodes) {
2384  if (node->getId() == applyAnimationPreviewNode) {
2386  break;
2387  }
2388  }
2389  {
2390  auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
2391  for (const auto& applyLODNode: applyLODNodes) {
2392  if (node->getId() == applyLODNode) {
2393  auto lodLevel = -1;
2394  if (outlinerNode == "lod2.model") {
2395  lodLevel = 2;
2396  } else
2397  if (outlinerNode == "lod3.model") {
2398  lodLevel = 3;
2399  }
2400  if (lodLevel != -1) applyLODDetails(lodLevel);
2401  break;
2402  }
2403  }
2404  }
2405  }
2406 }
2407 
2409  if (basePropertiesSubController->onFocus(node, view->getPrototype()) == true) return;
2410  if (prototypeSoundsSubController->onFocus(node, view->getPrototype()) == true) return;
2411 }
2412 
2414  if (basePropertiesSubController->onUnfocus(node, view->getPrototype()) == true) return;
2415  if (prototypeSoundsSubController->onUnfocus(node, view->getPrototype()) == true) return;
2416  //
2417  if (node->getId() == "tdme.animations.rename_input") {
2418  renameAnimation();
2419  }
2420 }
2421 
2423  basePropertiesSubController->onContextMenuRequest(node, mouseX, mouseY, view->getPrototype());
2424  prototypePhysicsSubController->onContextMenuRequest(node, mouseX, mouseY, view->getPrototype());
2425  prototypeSoundsSubController->onContextMenuRequest(node, mouseX, mouseY, view->getPrototype());
2426  if (node->getId() == "selectbox_outliner") {
2427  auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
2428  string modelOutlinerNode;
2429  int lodLevel = -1;
2430  getOutlinerNodeLOD(outlinerNode, modelOutlinerNode, nullptr, &lodLevel);
2431  if (outlinerNode == "model") {
2432  // clear
2434 
2435  // reload
2436  class OnModelReloadAction: public virtual Action
2437  {
2438  public:
2439  void performAction() override {
2440  modelEditorTabController->onModelReload();
2441  }
2442  OnModelReloadAction(ModelEditorTabController* modelEditorTabController): modelEditorTabController(modelEditorTabController) {
2443  }
2444  private:
2445  ModelEditorTabController* modelEditorTabController;
2446  };
2447  popUps->getContextMenuScreenController()->addMenuItem("Reload", "contextmenu_reload", new OnModelReloadAction(this));
2448 
2449  // load
2450  class OnModelLoadAction: public virtual Action
2451  {
2452  public:
2453  void performAction() override {
2454  modelEditorTabController->onModelLoad();
2455  }
2456  OnModelLoadAction(ModelEditorTabController* modelEditorTabController): modelEditorTabController(modelEditorTabController) {
2457  }
2458  private:
2459  ModelEditorTabController* modelEditorTabController;
2460  };
2461  popUps->getContextMenuScreenController()->addMenuItem("Load", "contextmenu_load", new OnModelLoadAction(this));
2462 
2463  // reimport
2464  class OnModelReimportAction: public virtual Action
2465  {
2466  public:
2467  void performAction() override {
2468  modelEditorTabController->onModelReimport();
2469  }
2470  OnModelReimportAction(ModelEditorTabController* modelEditorTabController): modelEditorTabController(modelEditorTabController) {
2471  }
2472  private:
2473  ModelEditorTabController* modelEditorTabController;
2474  };
2475  popUps->getContextMenuScreenController()->addMenuItem("Reimport", "contextmenu_reimport", new OnModelReimportAction(this));
2476 
2477  // generate billboard lod
2478  class EnqueueOnModelGenerateBillboardLodAction: public virtual Action {
2479  public:
2480  void performAction() override {
2481  auto prototype = modelEditorTabController->getView()->getPrototype();
2482  if (prototype == nullptr) return;
2483  auto model = prototype->getModel();
2484  auto fileName = prototype->getModelFileName();
2485  try {
2486  if (prototype->getLODLevel2() != nullptr && prototype->getLODLevel3() != nullptr) {
2487  throw ExceptionBase("All 3 LOD levels are in use");
2488  }
2489  if (fileName.empty() == true) throw ExceptionBase("Could not save file. No filename known");
2490  auto billboardModelPathName = Tools::getPathName(fileName);
2491  auto billboardModelFileName = Tools::removeFileExtension(Tools::getFileName(fileName)) + ".lod" + to_string(prototype->getLODLevel2() == nullptr?2:3) + ".tm";
2492  auto billboardLODModel = GenerateBillboardLOD::generate(
2493  model,
2494  billboardModelPathName,
2495  billboardModelFileName
2496  );
2497  if (prototype->getLODLevel2() == nullptr) {
2498  prototype->setLODLevel2(
2499  make_unique<PrototypeLODLevel>(
2500  LODObject::LODLEVELTYPE_MODEL,
2501  billboardModelPathName + "/" + billboardModelFileName,
2502  billboardLODModel,
2503  75.0f
2504  ).release()
2505  );
2506  } else
2507  if (prototype->getLODLevel2() == nullptr) {
2508  prototype->setLODLevel3(
2509  make_unique<PrototypeLODLevel>(
2510  LODObject::LODLEVELTYPE_MODEL,
2511  billboardModelPathName + "/" + billboardModelFileName,
2512  billboardLODModel,
2513  150.0f
2514  ).release()
2515  );
2516  }
2517  modelEditorTabController->getView()->reloadPrototype();
2518  } catch (Exception& exception) {
2519  modelEditorTabController->showInfoPopUp("Warning", string(exception.what()));
2520  }
2521  }
2522  EnqueueOnModelGenerateBillboardLodAction(ModelEditorTabController* modelEditorTabController): modelEditorTabController(modelEditorTabController) {
2523  }
2524  private:
2525  ModelEditorTabController* modelEditorTabController;
2526  };
2527 
2528  popUps->getContextMenuScreenController()->addMenuItem("Generate billboard LOD", "contextmenu_generatebillboardlod", new EnqueueOnModelGenerateBillboardLodAction(this));
2529 
2530  // generate imposter lod
2531  class EnqueueOnModelGenerateImposterLodAction: public virtual Action {
2532  public:
2533  void performAction() override {
2534  auto prototype = modelEditorTabController->getView()->getPrototype();
2535  if (prototype == nullptr) return;
2536  auto model = prototype->getModel();
2537  auto fileName = prototype->getModelFileName();
2538  try {
2539  if (fileName.empty() == true) throw ExceptionBase("Could not save file. No filename known");
2540  auto imposterModelPathName = Tools::getPathName(fileName);
2541  auto imposterModelFileName = Tools::removeFileExtension(Tools::getFileName(fileName)) + ".lod" + to_string(prototype->getLODLevel2() == nullptr?2:3) + ".tm";
2542  vector<Model*> imposterLODModels;
2543  vector<string> imposterLODFileNames;
2544  GenerateImposterLOD::generate(
2545  model,
2546  imposterModelPathName,
2547  imposterModelFileName,
2548  24,
2549  imposterLODFileNames,
2550  imposterLODModels
2551  );
2552  prototype->setImposterLOD(
2553  make_unique<PrototypeImposterLOD>(
2554  imposterLODFileNames,
2555  imposterLODModels,
2556  75.0f
2557  ).release()
2558  );
2559  modelEditorTabController->getView()->reloadPrototype();
2560  } catch (Exception& exception) {
2561  modelEditorTabController->showInfoPopUp("Warning", string(exception.what()));
2562  }
2563  }
2564  EnqueueOnModelGenerateImposterLodAction(ModelEditorTabController* modelEditorTabController): modelEditorTabController(modelEditorTabController) {
2565  }
2566  private:
2567  ModelEditorTabController* modelEditorTabController;
2568  };
2569 
2570  popUps->getContextMenuScreenController()->addMenuItem("Generate imposter LOD", "contextmenu_generateimposterlod", new EnqueueOnModelGenerateImposterLodAction(this));
2571 
2572  //
2573  popUps->getContextMenuScreenController()->show(mouseX, mouseY);
2574  } else
2575  if (outlinerNode == "lod2.model") {
2576  // clear
2578 
2579  // load
2580  class OnLODLoadAction: public virtual Action
2581  {
2582  public:
2583  void performAction() override {
2584  modelEditorTabController->onLODLoad(lodLevel);
2585  }
2586  OnLODLoadAction(ModelEditorTabController* modelEditorTabController, int lodLevel): modelEditorTabController(modelEditorTabController), lodLevel(lodLevel) {
2587  }
2588  private:
2589  ModelEditorTabController* modelEditorTabController;
2590  int lodLevel;
2591  };
2592  popUps->getContextMenuScreenController()->addMenuItem("Load", "contextmenu_load", new OnLODLoadAction(this, 2));
2593 
2594  // delete
2595  class OnLODDeleteAction: public virtual Action
2596  {
2597  public:
2598  void performAction() override {
2599  if (prototype == nullptr) return;
2600  modelEditorTabController->view->setLODLevel(1);
2601  prototype->removeLODLevel(lodLevel);
2602  modelEditorTabController->view->getEditorView()->reloadTabOutliner("model");
2603  }
2604  OnLODDeleteAction(ModelEditorTabController* modelEditorTabController, Prototype* prototype, int lodLevel): modelEditorTabController(modelEditorTabController), prototype(prototype), lodLevel(lodLevel) {
2605  }
2606  private:
2607  ModelEditorTabController* modelEditorTabController;
2608  Prototype* prototype;
2609  int lodLevel;
2610  };
2611  popUps->getContextMenuScreenController()->addMenuItem("Delete", "contextmenu_delete", new OnLODDeleteAction(this, view->getPrototype(), 2));
2612 
2613  //
2614  popUps->getContextMenuScreenController()->show(mouseX, mouseY);
2615  } else
2616  if (outlinerNode == "lod3.model") {
2617  // clear
2619 
2620  // load
2621  class OnLODLoadAction: public virtual Action
2622  {
2623  public:
2624  void performAction() override {
2625  modelEditorTabController->onLODLoad(lodLevel);
2626  }
2627  OnLODLoadAction(ModelEditorTabController* modelEditorTabController, int lodLevel): modelEditorTabController(modelEditorTabController), lodLevel(lodLevel) {
2628  }
2629  private:
2630  ModelEditorTabController* modelEditorTabController;
2631  int lodLevel;
2632  };
2633  popUps->getContextMenuScreenController()->addMenuItem("Load", "contextmenu_load", new OnLODLoadAction(this, 3));
2634 
2635  // delete
2636  class OnLODDeleteAction: public virtual Action
2637  {
2638  public:
2639  void performAction() override {
2640  if (prototype == nullptr) return;
2641  modelEditorTabController->view->setLODLevel(2);
2642  prototype->removeLODLevel(lodLevel);
2643  modelEditorTabController->view->getEditorView()->reloadTabOutliner("lod2.model");
2644  }
2645  OnLODDeleteAction(ModelEditorTabController* modelEditorTabController, Prototype* prototype, int lodLevel): modelEditorTabController(modelEditorTabController), prototype(prototype), lodLevel(lodLevel) {
2646  }
2647  private:
2648  ModelEditorTabController* modelEditorTabController;
2649  Prototype* prototype;
2650  int lodLevel;
2651  };
2652  popUps->getContextMenuScreenController()->addMenuItem("Delete", "contextmenu_delete", new OnLODDeleteAction(this, view->getPrototype(), 3));
2653 
2654  //
2655  popUps->getContextMenuScreenController()->show(mouseX, mouseY);
2656  } else
2657  if (outlinerNode == "lod4.model") {
2658  // clear
2660 
2661  // delete
2662  class OnLOD4DeleteAction: public virtual Action
2663  {
2664  public:
2665  void performAction() override {
2666  if (prototype == nullptr) return;
2667  modelEditorTabController->view->setLODLevel(1);
2668  prototype->setImposterLOD(nullptr);
2669  modelEditorTabController->view->getEditorView()->reloadTabOutliner("model");
2670  }
2671  OnLOD4DeleteAction(ModelEditorTabController* modelEditorTabController, Prototype* prototype): modelEditorTabController(modelEditorTabController), prototype(prototype) {
2672  }
2673  private:
2674  ModelEditorTabController* modelEditorTabController;
2675  Prototype* prototype;
2676  };
2677  popUps->getContextMenuScreenController()->addMenuItem("Delete", "contextmenu_delete", new OnLOD4DeleteAction(this, view->getPrototype()));
2678 
2679  //
2680  popUps->getContextMenuScreenController()->show(mouseX, mouseY);
2681  } else
2682  if (modelOutlinerNode == "model.animations") {
2683  // clear
2685  // add
2686  class OnAddAnimationAction: public virtual Action
2687  {
2688  public:
2689  void performAction() override {
2690  auto outlinerNode = modelEditorTabController->view->getEditorView()->getScreenController()->getOutlinerSelection();
2691  string modelOutlinerNode;
2692  int lodLevel = -1;
2693  modelEditorTabController->getOutlinerNodeLOD(outlinerNode, modelOutlinerNode, nullptr, &lodLevel);
2694  if (modelOutlinerNode == "model.animations") modelEditorTabController->createAnimationSetup(lodLevel);
2695  }
2696  OnAddAnimationAction(ModelEditorTabController* modelEditorTabController, Prototype* prototype): modelEditorTabController(modelEditorTabController), prototype(prototype) {
2697  }
2698  private:
2699  ModelEditorTabController* modelEditorTabController;
2700  Prototype* prototype;
2701  };
2702  popUps->getContextMenuScreenController()->addMenuItem("Add Animation", "contextmenu_add", new OnAddAnimationAction(this, view->getPrototype()));
2703 
2704  //
2705  popUps->getContextMenuScreenController()->show(mouseX, mouseY);
2706  } else
2707  if (StringTools::startsWith(modelOutlinerNode, "model.animations.") == true) {
2708  // clear
2710  // rename
2711  class OnRenameAction: public virtual Action
2712  {
2713  public:
2714  void performAction() override {
2715  auto outlinerNode = modelEditorTabController->view->getEditorView()->getScreenController()->getOutlinerSelection();
2716  string modelOutlinerNode;
2717  int lodLevel = -1;
2718  modelEditorTabController->getOutlinerNodeLOD(outlinerNode, modelOutlinerNode, nullptr, &lodLevel);
2719  if (StringTools::startsWith(modelOutlinerNode, "model.animations.") == true) {
2720  modelEditorTabController->startRenameAnimation(
2721  lodLevel,
2722  StringTools::substring(modelOutlinerNode, string("model.animations.").size(), modelOutlinerNode.size())
2723  );
2724  }
2725  }
2726  OnRenameAction(ModelEditorTabController* modelEditorTabController, Prototype* prototype): modelEditorTabController(modelEditorTabController), prototype(prototype) {
2727  }
2728  private:
2729  ModelEditorTabController* modelEditorTabController;
2730  Prototype* prototype;
2731  };
2732  popUps->getContextMenuScreenController()->addMenuItem("Rename", "contextmenu_rename", new OnRenameAction(this, view->getPrototype()));
2733 
2734  // separator
2736 
2737  // delete
2738  class OnDeleteAction: public virtual Action
2739  {
2740  public:
2741  void performAction() override {
2742  auto outlinerNode = modelEditorTabController->view->getEditorView()->getScreenController()->getOutlinerSelection();
2743  string modelOutlinerNode;
2744  int lodLevel = -1;
2745  modelEditorTabController->getOutlinerNodeLOD(outlinerNode, modelOutlinerNode, nullptr, &lodLevel);
2746  if (StringTools::startsWith(modelOutlinerNode, "model.animations.") == true) {
2747  modelEditorTabController->view->playAnimation(Model::ANIMATIONSETUP_DEFAULT);
2748  auto animationId = StringTools::substring(modelOutlinerNode, string("model.animations.").size(), modelOutlinerNode.size());
2749  Model* model = modelEditorTabController->getLODLevelModel(lodLevel);
2750  model->removeAnimationSetup(animationId);
2751  modelEditorTabController->view->getEditorView()->reloadTabOutliner((lodLevel == 1?"model":"lod" + to_string(lodLevel) + ".model") + ".animations");
2752  }
2753  }
2754  OnDeleteAction(ModelEditorTabController* modelEditorTabController, Prototype* prototype): modelEditorTabController(modelEditorTabController), prototype(prototype) {
2755  }
2756  private:
2757  ModelEditorTabController* modelEditorTabController;
2758  Prototype* prototype;
2759  };
2760  popUps->getContextMenuScreenController()->addMenuItem("Delete", "contextmenu_delete", new OnDeleteAction(this, view->getPrototype()));
2761 
2762  //
2763  popUps->getContextMenuScreenController()->show(mouseX, mouseY);
2764  }
2765  }
2766 }
2767 
2768 void ModelEditorTabController::onTooltipShowRequest(GUINode* node, int mouseX, int mouseY) {
2769  int tooltipLeft, tooltipTop;
2770  if (view->getEditorView()->getCurrentTabTooltipPosition(screenNode, mouseX, mouseY, tooltipLeft, tooltipTop) == false) return;
2771  //
2772  popUps->getTooltipScreenController()->show(tooltipLeft, tooltipTop, node->getToolTip());
2773 }
2774 
2777 }
2778 
2780 {
2781  auto prototype = view->getPrototype();
2782  //
2783  if (basePropertiesSubController->onAction(type, node, prototype) == true) return;
2784  if (prototypeDisplaySubController->onAction(type, node, prototype) == true) return;
2785  if (prototypePhysicsSubController->onAction(type, node, prototype) == true) return;
2786  if (prototypeSoundsSubController->onAction(type, node, prototype) == true) return;
2787  if (prototypeScriptSubController->onAction(type, node, prototype) == true) return;
2788  //
2789  if (type == GUIActionListenerType::PERFORMED) {
2790  if (node->getId().compare("specularmaterial_diffuse_texture_open") == 0) {
2792  } else
2793  if (node->getId().compare("specularmaterial_diffuse_texture_remove") == 0) {
2795  } else
2796  if (node->getId().compare("specularmaterial_diffuse_texture_browseto") == 0) {
2798  } else
2799  if (node->getId().compare("specularmaterial_transparency_texture_open") == 0) {
2801  } else
2802  if (node->getId().compare("specularmaterial_transparency_texture_remove") == 0) {
2804  } else
2805  if (node->getId().compare("specularmaterial_transparency_texture_browseto") == 0) {
2807  } else
2808  if (node->getId().compare("specularmaterial_normal_texture_open") == 0) {
2810  } else
2811  if (node->getId().compare("specularmaterial_normal_texture_remove") == 0) {
2813  } else
2814  if (node->getId().compare("specularmaterial_normal_texture_browseto") == 0) {
2816  } else
2817  if (node->getId().compare("specularmaterial_specular_texture_open") == 0) {
2819  } else
2820  if (node->getId().compare("specularmaterial_specular_texture_remove") == 0) {
2822  } else
2823  if (node->getId().compare("specularmaterial_specular_texture_browseto") == 0) {
2825  } else
2826  if (node->getId().compare("pbrmaterial_basecolor_texture_open") == 0) {
2828  } else
2829  if (node->getId().compare("pbrmaterial_basecolor_texture_remove") == 0) {
2831  } else
2832  if (node->getId().compare("pbrmaterial_basecolor_texture_browseto") == 0) {
2834  } else
2835  if (node->getId().compare("pbrmaterial_metallic_roughness_texture_open") == 0) {
2837  } else
2838  if (node->getId().compare("pbrmaterial_metallic_roughness_texture_remove") == 0) {
2840  } else
2841  if (node->getId().compare("pbrmaterial_metallic_roughness_texture_browseto") == 0) {
2843  } else
2844  if (node->getId().compare("pbrmaterial_normal_texture_open") == 0) {
2846  } else
2847  if (node->getId().compare("pbrmaterial_normal_texture_remove") == 0) {
2849  } else
2850  if (node->getId().compare("pbrmaterial_normal_texture_browseto") == 0) {
2852  } else
2853  if (node->getId().compare("pbrmaterial_emissive_texture_open") == 0) {
2855  } else
2856  if (node->getId().compare("pbrmaterial_emissive_texture_remove") == 0) {
2858  } else
2859  if (node->getId().compare("pbrmaterial_emissive_texture_browseto") == 0) {
2861  } else
2862  if (node->getId().compare("animationpreview_attachment1_model_open") == 0) {
2864  } else
2865  if (node->getId().compare("animationpreview_attachment1_model_remove") == 0) {
2867  } else
2868  if (node->getId().compare("animationpreview_attachment1_model_browseto") == 0) {
2870  } else
2871  if (node->getId().compare("specularmaterial_ambient_edit") == 0) {
2872  auto material = getSelectedMaterial();
2873  auto specularMaterialProperties = material != nullptr?material->getSpecularMaterialProperties():nullptr;
2874  if (specularMaterialProperties != nullptr) {
2875  class OnColorChangeAction: public virtual Action
2876  {
2877  public:
2878  void performAction() override {
2879  material->getSpecularMaterialProperties()->setAmbientColor(Color4(modelEditorTabController->popUps->getColorPickerScreenController()->getColor()));
2880  modelEditorTabController->updateMaterialColorDetails();
2881  }
2882  OnColorChangeAction(ModelEditorTabController* modelEditorTabController, Material* material): modelEditorTabController(modelEditorTabController), material(material) {
2883  }
2884  private:
2885  ModelEditorTabController* modelEditorTabController;
2886  Material* material;
2887  };
2888  popUps->getColorPickerScreenController()->show(specularMaterialProperties->getAmbientColor(), new OnColorChangeAction(this, material));
2889  }
2890  } else
2891  if (node->getId().compare("specularmaterial_diffuse_edit") == 0) {
2892  auto material = getSelectedMaterial();
2893  auto specularMaterialProperties = material != nullptr?material->getSpecularMaterialProperties():nullptr;
2894  if (specularMaterialProperties != nullptr) {
2895  class OnColorChangeAction: public virtual Action
2896  {
2897  public:
2898  void performAction() override {
2899  material->getSpecularMaterialProperties()->setDiffuseColor(Color4(modelEditorTabController->popUps->getColorPickerScreenController()->getColor()));
2900  modelEditorTabController->updateMaterialColorDetails();
2901  }
2902  OnColorChangeAction(ModelEditorTabController* modelEditorTabController, Material* material): modelEditorTabController(modelEditorTabController), material(material) {
2903  }
2904  private:
2905  ModelEditorTabController* modelEditorTabController;
2906  Material* material;
2907  };
2908  popUps->getColorPickerScreenController()->show(specularMaterialProperties->getDiffuseColor(), new OnColorChangeAction(this, material));
2909  }
2910  } else
2911  if (node->getId().compare("specularmaterial_emission_edit") == 0) {
2912  auto material = getSelectedMaterial();
2913  auto specularMaterialProperties = material != nullptr?material->getSpecularMaterialProperties():nullptr;
2914  if (specularMaterialProperties != nullptr) {
2915  class OnColorChangeAction: public virtual Action
2916  {
2917  public:
2918  void performAction() override {
2919  material->getSpecularMaterialProperties()->setEmissionColor(Color4(modelEditorTabController->popUps->getColorPickerScreenController()->getColor()));
2920  modelEditorTabController->updateMaterialColorDetails();
2921  }
2922  OnColorChangeAction(ModelEditorTabController* modelEditorTabController, Material* material): modelEditorTabController(modelEditorTabController), material(material) {
2923  }
2924  private:
2925  ModelEditorTabController* modelEditorTabController;
2926  Material* material;
2927  };
2928  popUps->getColorPickerScreenController()->show(specularMaterialProperties->getEmissionColor(), new OnColorChangeAction(this, material));
2929  }
2930  } else
2931  if (node->getId().compare("specularmaterial_specular_edit") == 0) {
2932  auto material = getSelectedMaterial();
2933  auto specularMaterialProperties = material != nullptr?material->getSpecularMaterialProperties():nullptr;
2934  if (specularMaterialProperties != nullptr) {
2935  class OnColorChangeAction: public virtual Action
2936  {
2937  public:
2938  void performAction() override {
2939  material->getSpecularMaterialProperties()->setSpecularColor(Color4(modelEditorTabController->popUps->getColorPickerScreenController()->getColor()));
2940  modelEditorTabController->updateMaterialColorDetails();
2941  }
2942  OnColorChangeAction(ModelEditorTabController* modelEditorTabController, Material* material): modelEditorTabController(modelEditorTabController), material(material) {
2943  }
2944  private:
2945  ModelEditorTabController* modelEditorTabController;
2946  Material* material;
2947  };
2948  popUps->getColorPickerScreenController()->show(specularMaterialProperties->getSpecularColor(), new OnColorChangeAction(this, material));
2949  }
2950  } else
2951  if (node->getId().compare("pbrmaterial_basecolor_edit") == 0) {
2952  auto material = getSelectedMaterial();
2953  auto pbrMaterialProperties = material != nullptr?material->getPBRMaterialProperties():nullptr;
2954  if (pbrMaterialProperties != nullptr) {
2955  class OnColorChangeAction: public virtual Action
2956  {
2957  public:
2958  void performAction() override {
2959  material->getPBRMaterialProperties()->setBaseColorFactor(Color4(modelEditorTabController->popUps->getColorPickerScreenController()->getColor()));
2960  modelEditorTabController->updateMaterialColorDetails();
2961  }
2962  OnColorChangeAction(ModelEditorTabController* modelEditorTabController, Material* material): modelEditorTabController(modelEditorTabController), material(material) {
2963  }
2964  private:
2965  ModelEditorTabController* modelEditorTabController;
2966  Material* material;
2967  };
2968  popUps->getColorPickerScreenController()->show(pbrMaterialProperties->getBaseColorFactor(), new OnColorChangeAction(this, material));
2969  }
2970  } else
2971  if (node->getId().compare("pbrmaterial_emissivefactor_edit") == 0) {
2972  auto material = getSelectedMaterial();
2973  auto pbrMaterialProperties = material != nullptr?material->getPBRMaterialProperties():nullptr;
2974  if (pbrMaterialProperties != nullptr) {
2975  class OnColorChangeAction: public virtual Action
2976  {
2977  public:
2978  void performAction() override {
2979  material->getPBRMaterialProperties()->setEmissiveFactor(Color4(modelEditorTabController->popUps->getColorPickerScreenController()->getColor()));
2980  modelEditorTabController->updateMaterialColorDetails();
2981  }
2982  OnColorChangeAction(ModelEditorTabController* modelEditorTabController, Material* material): modelEditorTabController(modelEditorTabController), material(material) {
2983  }
2984  private:
2985  ModelEditorTabController* modelEditorTabController;
2986  Material* material;
2987  };
2988  popUps->getColorPickerScreenController()->show(pbrMaterialProperties->getEmissiveFactor(), new OnColorChangeAction(this, material));
2989  }
2990  } else
2991  if (node->getId().compare("lod_color_add_edit") == 0) {
2992  auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
2993  string modelOutlinerNode;
2994  int lodLevel = -1;
2995  getOutlinerNodeLOD(outlinerNode, modelOutlinerNode, nullptr, &lodLevel);
2996  PrototypeLODLevel* prototypeLODLevel = nullptr;
2997  switch (lodLevel) {
2998  case 2: prototypeLODLevel = prototype->getLODLevel2(); break;
2999  case 3: prototypeLODLevel = prototype->getLODLevel3(); break;
3000  default: break;
3001  }
3002  if (prototypeLODLevel == nullptr) return;
3003  class OnColorChangeAction: public virtual Action
3004  {
3005  public:
3006  void performAction() override {
3007  prototypeLODLevel->setColorAdd(Color4(modelEditorTabController->popUps->getColorPickerScreenController()->getColor()));
3008  modelEditorTabController->updateLODColorDetails(lodLevel);
3009  modelEditorTabController->view->updateLODLevel();
3010  }
3011  OnColorChangeAction(ModelEditorTabController* modelEditorTabController, int lodLevel, PrototypeLODLevel* prototypeLODLevel): modelEditorTabController(modelEditorTabController), lodLevel(lodLevel), prototypeLODLevel(prototypeLODLevel) {
3012  }
3013  private:
3014  ModelEditorTabController* modelEditorTabController;
3015  int lodLevel;
3016  PrototypeLODLevel* prototypeLODLevel;
3017  };
3018  popUps->getColorPickerScreenController()->show(prototypeLODLevel->getColorAdd(), new OnColorChangeAction(this, lodLevel, prototypeLODLevel));
3019  } else
3020  if (node->getId().compare("lod_color_mul_edit") == 0) {
3021  auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
3022  string modelOutlinerNode;
3023  int lodLevel = -1;
3024  getOutlinerNodeLOD(outlinerNode, modelOutlinerNode, nullptr, &lodLevel);
3025  PrototypeLODLevel* prototypeLODLevel = nullptr;
3026  switch (lodLevel) {
3027  case 2: prototypeLODLevel = prototype->getLODLevel2(); break;
3028  case 3: prototypeLODLevel = prototype->getLODLevel3(); break;
3029  default: break;
3030  }
3031  if (prototypeLODLevel == nullptr) return;
3032  class OnColorChangeAction: public virtual Action
3033  {
3034  public:
3035  void performAction() override {
3036  prototypeLODLevel->setColorMul(Color4(modelEditorTabController->popUps->getColorPickerScreenController()->getColor()));
3037  modelEditorTabController->updateLODColorDetails(lodLevel);
3038  modelEditorTabController->view->updateLODLevel();
3039  }
3040  OnColorChangeAction(ModelEditorTabController* modelEditorTabController, int lodLevel, PrototypeLODLevel* prototypeLODLevel): modelEditorTabController(modelEditorTabController), lodLevel(lodLevel), prototypeLODLevel(prototypeLODLevel) {
3041  }
3042  private:
3043  ModelEditorTabController* modelEditorTabController;
3044  int lodLevel;
3045  PrototypeLODLevel* prototypeLODLevel;
3046  };
3047  popUps->getColorPickerScreenController()->show(prototypeLODLevel->getColorMul(), new OnColorChangeAction(this, lodLevel, prototypeLODLevel));
3048  } else
3049  if (node->getId() == "tdme.animations.rename_input") {
3050  renameAnimation();
3051  }
3052  }
3053 }
Color 4 definition class.
Definition: Color4.h:18
Engine main class.
Definition: Engine.h:131
Represents a material.
Definition: Material.h:23
Representation of a 3D model.
Definition: Model.h:35
const vector< string > getMaterialIds()
Definition: Model.cpp:80
unordered_map< string, Node * > & getSubNodes()
Returns object's sub nodes.
Definition: Model.h:220
unordered_map< string, Material * > & getMaterials()
Returns all object materials.
Definition: Model.h:185
AnimationSetup * getAnimationSetup(const string &id)
Definition: Model.h:274
bool removeAnimationSetup(const string &id)
Remove animation setup.
Definition: Model.cpp:135
AnimationSetup * addAnimationSetup(const string &id, int32_t startFrame, int32_t endFrame, bool loop, float speed=1.0f)
Adds an base animation setup.
Definition: Model.cpp:101
const vector< string > getAnimationSetupIds()
Definition: Model.cpp:94
const unordered_map< string, AnimationSetup * > & getAnimationSetups()
Definition: Model.h:262
bool renameAnimationSetup(const string &id, const string &newId)
Rename animation set up.
Definition: Model.cpp:125
Model node.
Definition: Node.h:32
Represents specular material properties.
Represents specular material properties.
Base property model class.
Definition: BaseProperty.h:15
Prototype LOD level definition.
void setFileName(const string &fileName)
Set file name.
void setColorAdd(const Color4 &colorAdd)
Set color add.
void setType(LODObject::LODLevelType type)
Set type.
void setColorMul(const Color4 &colorMul)
Set color mul.
LODObject::LODLevelType getType() const
void setMinDistance(float minDistance)
Set min distance.
Prototype definition.
Definition: Prototype.h:55
PrototypeLODLevel * getLODLevel3()
Definition: Prototype.h:341
PrototypeLODLevel * getLODLevel2()
Definition: Prototype.h:328
GUI parser.
Definition: GUIParser.h:40
GUI node controller base class.
virtual const MutableString & getValue()=0
GUI node base class.
Definition: GUINode.h:64
const string & getToolTip()
Definition: GUINode.h:346
GUINodeController * getController()
Definition: GUINode.h:661
const string & getId()
Definition: GUINode.h:339
GUI parent node base class thats supporting child nodes.
Definition: GUIParentNode.h:42
GUI screen node that represents a screen that can be rendered via GUI system.
Definition: GUIScreenNode.h:72
void forwardChange(GUIElementNode *node)
Forward change event.
GUINode * getInnerNodeById(const string &nodeId)
Get inner GUI node by id.
GUINode * getNodeById(const string &nodeId)
Get GUI node by id.
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Definition: Vector3.h:20
void show(const Color4 &color, Action *onColorChangeAction)
Shows the pop up.
void show(int mouseX, int mouseY)
Shows the pop up.
void addMenuItem(const string &text, const string &id, Action *action=nullptr)
Add menu item.
bool isDropOnNode(int dropX, int dropY, const string &nodeId)
Is drop on node.
void browseTo(const string &fileName)
Browse to file name.
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.
void show(int mouseX, int mouseY, const string &tooltip)
Show tooltip.
Generate billboard LOD utility class.
Generate imposter LOD utility class.
Pop ups controller accessor class.
Definition: PopUps.h:29
ColorPickerScreenController * getColorPickerScreenController()
Definition: PopUps.h:89
FileDialogScreenController * getFileDialogScreenController()
Definition: PopUps.h:61
TooltipScreenController * getTooltipScreenController()
Definition: PopUps.h:131
ContextMenuScreenController * getContextMenuScreenController()
Definition: PopUps.h:96
InfoDialogScreenController * getInfoDialogScreenController()
Definition: PopUps.h:75
void onMaterialClearPBRBaseColorTexture()
On material clear PBR base color texture.
void saveFile(const string &pathName, const string &fileName)
Save file.
void onContextMenuRequest(GUIElementNode *node, int mouseX, int mouseY) override
On context menu request.
void onDrop(const string &payload, int mouseX, int mouseY) override
On drop.
void setMaterialSpecularTexture(const string &fileName)
Set material specular texture.
unique_ptr< PrototypeSoundsSubController > prototypeSoundsSubController
void updateInfoText(const MutableString &text)
Update info text line.
void setOutlinerAddDropDownContent()
Set outliner add drop down content.
void setMaterialDiffuseTexture(const string &fileName)
Set material diffuse texture.
void onMaterialBrowseToDiffuseTexture()
On material browse to diffuse texture.
void onMaterialLoadPBRNormalTexture()
On material load PBR normal texture.
void onPreviewAnimationsAttachment1ModelBrowseTo()
On preview animations attachment 1 model browse to.
void onMaterialClearPBREmissiveTexture()
On material load PBR emissive texture.
void onMaterialClearPBRMetallicRoughnessTexture()
On material clear PBR metallic roughness texture.
void onMaterialClearSpecularTexture()
On material clear specular texture.
void onMaterialBrowseToDiffuseTransparencyTexture()
On material browse to diffuse transparency texture.
void setMaterialPBRNormalTexture(const string &fileName)
Set material PBR normal texture.
void onCommand(TabControllerCommand command) override
On command.
void onPreviewAnimationsAttachment1ModelLoad()
On preview animations attachment 1 model load.
void setStatistics(int statsOpaqueFaces, int statsTransparentFaces, int statsMaterialCount)
Set up model statistics.
void onMaterialClearPBRNormalTexture()
On material load PBR normal texture.
void startRenameAnimation(int lodLevel, const string &animationId)
Start rename animation.
void onMaterialLoadPBREmissiveTexture()
On material load PBR emissive texture.
void onMaterialLoadPBRMetallicRoughnessTexture()
On material load PBR metallic roughness texture.
void onMaterialLoadPBRBaseColorTexture()
On material load PBR base color texture.
void updateDetails(const string &outlinerNode)
Update details panel.
void setPreviewAnimationsAttachment1Model(const string &fileName)
Set preview animations attachment 1 model.
void onMaterialLoadDiffuseTransparencyTexture()
On material load diffuse transparency texture.
void createOutlinerModelNodesXML(const string &prefix, const unordered_map< string, Node * > &subNodes, string &xml)
Create outliner model nodes xml.
void onMaterialBrowseToPBRBaseColorTexture()
On material browse to PBR base color texture.
void onPreviewAnimationsAttachment1ModelClear()
On preview animations attachment 1 model clear.
unique_ptr< PrototypeScriptSubController > prototypeScriptSubController
void onMaterialBrowseToPBRMetallicRoughnessTexture()
On material browse to PBR metallic roughness texture.
void onMaterialBrowseToPBRNormalTexture()
On material browse to PBR normal texture.
void setMaterialPBRMetallicRoughnessTexture(const string &fileName)
Set material PBR metallic roughness texture.
unique_ptr< PrototypePhysicsSubController > prototypePhysicsSubController
void setMaterialPBREmissiveTexture(const string &fileName)
Set material PBR emissive texture.
unique_ptr< PrototypeDisplaySubController > prototypeDisplaySubController
void loadFile(const string &pathName, const string &fileName)
Load file.
void showInfoPopUp(const string &caption, const string &message)
Show the information pop up / modal.
void onAction(GUIActionListenerType type, GUIElementNode *node) override
void onMaterialBrowseToNormalTexture()
On material browse to normal texture.
void onMaterialBrowseToSpecularTexture()
On material browse to specular texture.
void setMaterialNormalTexture(const string &fileName)
Set material normal texture.
void setMaterialPBRBaseColorTexture(const string &fileName)
Set material PBR base color texture.
unique_ptr< BasePropertiesSubController > basePropertiesSubController
bool getOutlinerNodeLOD(const string &outlinerNode, string &modelOutlinerNode, Model **model=nullptr, int *lodLevel=nullptr)
Get outliner node within model or LOD models.
void onTooltipShowRequest(GUINode *node, int mouseX, int mouseY) override
On tooltip show request.
void setMaterialDiffuseTransparencyTexture(const string &fileName)
Set material diffuse transparency texture.
void onMaterialBrowseToPBREmissiveTexture()
On material browse to PBR emissive texture.
void onMaterialClearDiffuseTransparencyTexture()
On material clear diffuse transparency texture.
void saveFile(const string &pathName, const string &fileName)
Saving prototype as tmodel prototype.
void addAttachment1(const string &nodeId, const string &attachmentModelFile)
Add attachment 1.
void setLODLevel(int lodLevel)
Set LOD level to display.
void playAnimation(const string &baseAnimationId, const string &overlay1AnimationId=string(), const string &overlay2AnimationId=string(), const string &overlay3AnimationId=string())
Play animation.
void setAttachment1NodeId(const string &nodeId)
Set attachment 1 node id.
void setOutlinerAddDropDownContent(const string &xml)
Set outliner add drop down content.
Definition: EditorView.cpp:400
void setOutlinerContent(const string &xml)
Set outliner content.
Definition: EditorView.cpp:396
EditorScreenController * getScreenController()
Definition: EditorView.h:69
void setDetailsContent(const string &xml)
Set details content.
Definition: EditorView.cpp:404
bool getCurrentTabTooltipPosition(GUIScreenNode *screenNode, int mouseX, int mouseY, int &tooltipLeft, int &tooltipTop)
Determine current tab tooltip position.
Definition: EditorView.cpp:439
void reloadTabOutliner(const string &newSelectionValue=string())
Reload tab outliner.
Definition: EditorView.cpp:408
Console class.
Definition: Console.h:29
Exception base class.
Definition: ExceptionBase.h:19
Float class.
Definition: Float.h:27
Integer class.
Definition: Integer.h:25
Mutable utf8 aware string class.
Definition: MutableString.h:23
const string & getString() const
String tools class.
Definition: StringTools.h:22
std::exception Exception
Exception base class.
Definition: Exception.h:18
Tab controller, which connects UI with logic.
Definition: TabController.h:34
Action Interface.
Definition: Action.h:11