TDME2  1.9.200
DecalEditorTabController.cpp
Go to the documentation of this file.
2 
3 #include <memory>
4 #include <string>
5 
6 #include <tdme/tdme.h>
8 #include <tdme/engine/Texture.h>
17 #include <tdme/gui/nodes/GUINode.h>
21 #include <tdme/gui/GUI.h>
22 #include <tdme/gui/GUIParser.h>
37 #include <tdme/utilities/Action.h>
38 #include <tdme/utilities/Base64.h>
39 #include <tdme/utilities/Console.h>
42 #include <tdme/utilities/Integer.h>
45 
46 using std::make_unique;
47 using std::string;
48 using std::unique_ptr;
49 
51 
86 
87 DecalEditorTabController::DecalEditorTabController(DecalEditorTabView* view)
88 {
89  this->view = view;
90  this->popUps = view->getPopUps();
91  this->basePropertiesSubController = make_unique<BasePropertiesSubController>(view->getEditorView(), "prototype");
92  this->prototypePhysicsSubController = make_unique<PrototypePhysicsSubController>(view->getEditorView(), view, false);
93  this->prototypeDisplaySubController = make_unique<PrototypeDisplaySubController>(view->getEditorView(), view, this->prototypePhysicsSubController->getView());
94  this->prototypeScriptSubController = make_unique<PrototypeScriptSubController>(view->getEditorView());
95 }
96 
98 }
99 
101 {
102  this->screenNode = screenNode;
107 }
108 
110 {
111 }
112 
114 {
115  switch (command) {
116  case COMMAND_SAVE:
117  {
118  auto fileName = view->getPrototype() != nullptr?view->getPrototype()->getFileName():"";
119  try {
120  if (fileName.empty() == true) throw ExceptionBase("Could not save file. No filename known");
121  view->saveFile(
122  Tools::getPathName(fileName),
123  Tools::getFileName(fileName)
124  );
125  } catch (Exception& exception) {
126  showInfoPopUp("Warning", string(exception.what()));
127  }
128  }
129  break;
130  case COMMAND_SAVEAS:
131  {
132  class OnDecalSave: public virtual Action
133  {
134  public:
135  void performAction() override {
136  try {
137  decalEditorTabController->view->saveFile(
138  decalEditorTabController->popUps->getFileDialogScreenController()->getPathName(),
139  decalEditorTabController->popUps->getFileDialogScreenController()->getFileName()
140  );
141  } catch (Exception& exception) {
142  decalEditorTabController->showInfoPopUp("Warning", string(exception.what()));
143  }
144  decalEditorTabController->popUps->getFileDialogScreenController()->close();
145  }
146  OnDecalSave(DecalEditorTabController* decalEditorTabController): decalEditorTabController(decalEditorTabController) {
147  }
148  private:
149  DecalEditorTabController* decalEditorTabController;
150  };
151 
152  auto fileName = view->getPrototype() != nullptr?view->getPrototype()->getFileName():"";
153  vector<string> extensions = {
154  "tdecal"
155  };
157  fileName.empty() == false?Tools::getPathName(fileName):string(),
158  "Save to: ",
159  extensions,
160  Tools::getFileName(fileName),
161  false,
162  new OnDecalSave(this)
163  );
164  }
165  break;
166  default:
167  showInfoPopUp("Warning", "This command is not supported yet");
168  break;
169  }
170 }
171 
172 void DecalEditorTabController::onDrop(const string& payload, int mouseX, int mouseY) {
173  if (prototypePhysicsSubController->onDrop(payload, mouseX, mouseY, view->getPrototype()) == true) return;
174  if (prototypeScriptSubController->onDrop(payload, mouseX, mouseY, view->getPrototype()) == true) return;
175  if (StringTools::startsWith(payload, "file:") == false) {
176  showInfoPopUp("Warning", "Unknown payload in drop");
177  } else {
178  auto fileName = StringTools::substring(payload, string("file:").size());
179  if (view->getEditorView()->getScreenController()->isDropOnNode(mouseX, mouseY, "decal_texture") == true) {
180  if (Tools::hasFileExtension(fileName, TextureReader::getTextureExtensions()) == false) {
181  showInfoPopUp("Warning", "You can not drop this file here. Allowed file extensions are " + Tools::enumerateFileExtensions(TextureReader::getTextureExtensions()));
182  } else {
183  setDecalTexture(fileName);
184  }
185  } else {
186  showInfoPopUp("Warning", "You can not drop a file here");
187  }
188  }
189 }
190 
192 {
193  if (basePropertiesSubController->onChange(node, view->getPrototype(), view->getPrototype()) == true) return;
194  if (prototypeDisplaySubController->onChange(node, view->getPrototype()) == true) return;
195  if (prototypePhysicsSubController->onChange(node, view->getPrototype()) == true) return;
196  if (prototypeScriptSubController->onChange(node, view->getPrototype()) == true) return;
197  //
198  for (const auto& applyDecalNode: applyDecalNodes) {
199  if (node->getId() == applyDecalNode) {
201  return;
202  }
203  }
204  //
205  if (node->getId() == "selectbox_outliner") {
206  auto outlinerNode = view->getEditorView()->getScreenController()->getOutlinerSelection();
207  updateDetails(outlinerNode);
208  }
209 }
210 
212  if (basePropertiesSubController->onFocus(node, view->getPrototype()) == true) return;
213 }
214 
216  if (basePropertiesSubController->onUnfocus(node, view->getPrototype()) == true) return;
217 }
218 
220  basePropertiesSubController->onContextMenuRequest(node, mouseX, mouseY, view->getPrototype());
221  prototypePhysicsSubController->onContextMenuRequest(node, mouseX, mouseY, view->getPrototype());
222 }
223 
224 void DecalEditorTabController::onTooltipShowRequest(GUINode* node, int mouseX, int mouseY) {
225  int tooltipLeft, tooltipTop;
226  if (view->getEditorView()->getCurrentTabTooltipPosition(screenNode, mouseX, mouseY, tooltipLeft, tooltipTop) == false) return;
227  //
228  popUps->getTooltipScreenController()->show(tooltipLeft, tooltipTop, node->getToolTip());
229 }
230 
233 }
234 
236 {
237  if (basePropertiesSubController->onAction(type, node, view->getPrototype()) == true) return;
238  if (prototypeDisplaySubController->onAction(type, node, view->getPrototype()) == true) return;
239  if (prototypePhysicsSubController->onAction(type, node, view->getPrototype()) == true) return;
240  if (prototypeScriptSubController->onAction(type, node, view->getPrototype()) == true) return;
241  //
242  if (type == GUIActionListenerType::PERFORMED) {
243  if (node->getId() == "decal_texture_open") {
244  //
245  class OnDecalTextureFileOpenAction: public virtual Action
246  {
247  public:
248  void performAction() override {
249  decalEditorTabController->setDecalTexture(
250  decalEditorTabController->view->getPopUps()->getFileDialogScreenController()->getPathName() +
251  "/" +
252  decalEditorTabController->view->getPopUps()->getFileDialogScreenController()->getFileName()
253  );
254  decalEditorTabController->view->getPopUps()->getFileDialogScreenController()->close();
255  }
256 
257  /**
258  * Public constructor
259  * @param decalEditorTabController decal editor tab controller
260  */
261  OnDecalTextureFileOpenAction(DecalEditorTabController* decalEditorTabController): decalEditorTabController(decalEditorTabController) {
262  }
263 
264  private:
265  DecalEditorTabController* decalEditorTabController;
266  };
267 
268  auto prototype = view->getPrototype();
269  if (prototype == nullptr) return;
270  auto decal = prototype->getDecal();
271  if (decal == nullptr) return;
272  vector<string> extensions = TextureReader::getTextureExtensions();
274  decal->getTextureFileName().empty() == false?Tools::getPathName(decal->getTextureFileName()):string(),
275  "Load decal texture from: ",
276  extensions,
277  Tools::getFileName(decal->getTextureFileName()),
278  true,
279  new OnDecalTextureFileOpenAction(this)
280  );
281  } else
282  if (node->getId() == "decal_texture_remove") {
283  auto prototype = view->getPrototype();
284  if (prototype == nullptr) return;
285  auto decal = prototype->getDecal();
286  if (decal == nullptr) return;
287  decal->setTextureFileName(string());
288  prototype->setThumbnail(string());
289  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("decal_texture"))->setSource(prototype->getDecal()->getTextureFileName());
290  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("decal_texture"))->setTooltip(prototype->getDecal()->getTextureFileName());
291  } else
292  if (node->getId() == "decal_texture_browseto") {
293  auto prototype = view->getPrototype();
294  if (prototype == nullptr) return;
295  auto decal = prototype->getDecal();
296  if (decal != nullptr && decal->getTextureFileName().empty() == false) {
297  view->getEditorView()->getScreenController()->browseTo(decal->getTextureFileName());
298  } else {
299  showInfoPopUp("Browse To", "Nothig to browse to");
300  }
301  }
302  }
303 }
304 
305 void DecalEditorTabController::setDecalTexture(const string& fileName) {
306  //
307  auto prototype = view->getPrototype();
308  if (prototype == nullptr) return;
309  //
310  auto decal = prototype != nullptr?prototype->getDecal():nullptr;
311  if (decal == nullptr) return;
312  //
313  try {
314  decal->setTextureFileName(fileName);
315  //
316  if (decal->getTexture() == nullptr) {
317  showInfoPopUp("Warning", "Unsupported file format or corrupt file");
318  } else {
319  // thumbnail
320  auto decalTextureThumbnail = TextureReader::scale(decal->getTexture(), 128, 128);
321  vector<uint8_t> pngData;
322  string base64PNGData;
323  PNGTextureWriter::write(decalTextureThumbnail, pngData, false, false);
324  Base64::encode(pngData, base64PNGData);
325  prototype->setThumbnail(base64PNGData);
326  decalTextureThumbnail->releaseReference();
327  // adjust oriented bounding box
328  auto physicsSubView = prototypePhysicsSubController->getView();
329  physicsSubView->applyBoundingVolumeObb(
330  prototype,
331  0,
332  Vector3(),
333  OrientedBoundingBox::AABB_AXIS_X,
334  OrientedBoundingBox::AABB_AXIS_Y,
335  OrientedBoundingBox::AABB_AXIS_Z,
336  Vector3(
337  0.5f * (static_cast<float>(decal->getTexture()->getWidth()) / static_cast<float>(decal->getTexture()->getHeight())),
338  0.5f,
339  0.5f
340  )
341  );
342  physicsSubView->updateGizmo(prototype);
343  }
344  } catch (Exception& exception) {
345  Console::println("OnDecalTextureFileOpenAction::performAction(): An error occurred: " + string(exception.what()));
346  showInfoPopUp("Warning", string(exception.what()));
347  }
348  //
349  setDecalDetails();
350 }
351 
353  string xml;
354  xml+= "<selectbox-parent-option image=\"resources/engine/images/folder.png\" text=\"" + GUIParser::escape("Prototype") + "\" value=\"" + GUIParser::escape("prototype") + "\">\n";
355  auto prototype = view->getPrototype();
356  if (prototype != nullptr) {
357  xml+= "<selectbox-option text=\"" + GUIParser::escape("Decal") + "\" value=\"" + GUIParser::escape("decal") + "\" />\n";
358  basePropertiesSubController->createBasePropertiesXML(prototype, xml);
359  prototypeScriptSubController->createScriptXML(prototype, xml);
360  prototypePhysicsSubController->createOutlinerPhysicsXML(prototype, xml);
361  }
362  xml+= "</selectbox-parent-option>\n";
364 }
365 
368  string("<dropdown-option text=\"Property\" value=\"property\" />\n") +
369  string("<dropdown-option text=\"BV\" value=\"boundingvolume\" />\n")
370  );
371 }
372 
375  "<template id=\"details_decal\" src=\"resources/engine/gui/template_details_decal.xml\" />\n"
376  );
377 
378  auto prototype = view->getPrototype();
379  if (prototype == nullptr) return;
380  auto decal = prototype->getDecal();
381  if (decal == nullptr) return;
382 
383  //
384  try {
385  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("details_decal"))->getActiveConditions().add("open");
386  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("decal_texture"))->setSource(decal->getTextureFileName());
387  required_dynamic_cast<GUIImageNode*>(screenNode->getNodeById("decal_texture"))->setTooltip(decal->getTextureFileName());
388  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("decal_texture_horizontal_sprites"))->getController()->setValue(MutableString(decal->getTextureHorizontalSprites()));
389  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("decal_texture_vertical_sprites"))->getController()->setValue(MutableString(decal->getTextureVerticalSprites()));
390  required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("decal_texture_fps"))->getController()->setValue(MutableString(decal->getTextureSpritesFPS()));
391  } catch (Exception& exception) {
392  Console::println("DecalEditorTabController::setDecalDetails(): An error occurred: " + string(exception.what()));
393  showInfoPopUp("Warning", string(exception.what()));
394  }
395 }
396 
397 void DecalEditorTabController::updateDetails(const string& outlinerNode) {
398  if (outlinerNode == "decal") {
399  setDecalDetails();
400  } else {
401  view->getEditorView()->setDetailsContent(string());
402  basePropertiesSubController->updateDetails(view->getPrototype(), outlinerNode);
403  prototypeDisplaySubController->updateDetails(view->getPrototype(), outlinerNode);
404  prototypePhysicsSubController->updateDetails(view->getPrototype(), outlinerNode);
405  prototypePhysicsSubController->getView()->setDisplayBoundingVolume(true);
406  prototypeScriptSubController->updateDetails(view->getPrototype(), outlinerNode);
407  }
408 }
409 
411  auto prototype = view->getPrototype();
412  if (prototype == nullptr) return;
413  auto decal = prototype->getDecal();
414  if (decal == nullptr) return;
415  //
416  decal->setTextureHorizontalSprites(Math::max(1, Integer::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("decal_texture_horizontal_sprites"))->getController()->getValue().getString())));
417  decal->setTextureVerticalSprites(Math::max(1, Integer::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("decal_texture_vertical_sprites"))->getController()->getValue().getString())));
418  decal->setTextureSpritesFPS(Float::parse(required_dynamic_cast<GUIElementNode*>(screenNode->getNodeById("decal_texture_fps"))->getController()->getValue().getString()));
419 }
420 
422  required_dynamic_cast<GUITextNode*>(screenNode->getNodeById(view->getTabId() + "_tab_text_info"))->setText(text);
423 }
424 
425 void DecalEditorTabController::showInfoPopUp(const string& caption, const string& message)
426 {
427  popUps->getInfoDialogScreenController()->show(caption, message);
428 }
Texture entity.
Definition: Texture.h:24
Oriented bounding box physics primitive.
void setTextureHorizontalSprites(int textureHorizontalSprites)
Set texture horizontal number of sprites.
void setTextureFileName(const string &textureFileName, const string &transparencyTextureFileName=string())
Set texture file name with optional transparency texture.
Prototype definition.
Definition: Prototype.h:55
GUI parser.
Definition: GUIParser.h:40
GUI node controller base class.
GUI node base class.
Definition: GUINode.h:64
const string & getToolTip()
Definition: GUINode.h:346
const string & getId()
Definition: GUINode.h:339
GUI screen node that represents a screen that can be rendered via GUI system.
Definition: GUIScreenNode.h:72
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
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.
Pop ups controller accessor class.
Definition: PopUps.h:29
FileDialogScreenController * getFileDialogScreenController()
Definition: PopUps.h:61
TooltipScreenController * getTooltipScreenController()
Definition: PopUps.h:131
InfoDialogScreenController * getInfoDialogScreenController()
Definition: PopUps.h:75
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 updateInfoText(const MutableString &text)
Update info text line.
void setOutlinerAddDropDownContent()
Set outliner add drop down content.
void onCommand(TabControllerCommand command) override
On command.
void updateDetails(const string &outlinerNode)
Update details panel.
unique_ptr< PrototypeScriptSubController > prototypeScriptSubController
void setDecalTexture(const string &fileName)
Set decal texture.
unique_ptr< PrototypePhysicsSubController > prototypePhysicsSubController
unique_ptr< PrototypeDisplaySubController > prototypeDisplaySubController
void showInfoPopUp(const string &caption, const string &message)
Show the information pop up / modal.
void onAction(GUIActionListenerType type, GUIElementNode *node) override
unique_ptr< BasePropertiesSubController > basePropertiesSubController
void onTooltipShowRequest(GUINode *node, int mouseX, int mouseY) override
On tooltip show request.
void saveFile(const string &pathName, const string &fileName)
Saving prototype as tempty prototype.
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
Base64 encoding/decoding class.
Definition: Base64.h:16
Console class.
Definition: Console.h:29
Exception base class.
Definition: ExceptionBase.h:19
Integer class.
Definition: Integer.h:25
Mutable utf8 aware string class.
Definition: MutableString.h:23
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