SceneSelection.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. //
  2. // Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include <Atomic/IO/Log.h>
  23. #include <Atomic/Core/CoreEvents.h>
  24. #include <Atomic/Graphics/Graphics.h>
  25. #include <Atomic/Graphics/Drawable.h>
  26. #include <Atomic/Graphics/DebugRenderer.h>
  27. #include <Atomic/Atomic3D/Terrain.h>
  28. #include <Atomic/Scene/SceneEvents.h>
  29. #include <Atomic/Scene/Node.h>
  30. #include <Atomic/Scene/Scene.h>
  31. #include <Atomic/Scene/PrefabComponent.h>
  32. #include "SceneEditor3D.h"
  33. #include "SceneEditor3DEvents.h"
  34. #include "SceneSelection.h"
  35. #include "SceneEditHistory.h"
  36. namespace AtomicEditor
  37. {
  38. SceneSelection::SceneSelection(Context* context, SceneEditor3D *sceneEditor) : Object(context)
  39. {
  40. sceneEditor3D_ = sceneEditor;
  41. scene_ = sceneEditor3D_->GetScene();
  42. SubscribeToEvent(E_POSTRENDERUPDATE, HANDLER(SceneSelection, HandlePostRenderUpdate));
  43. SubscribeToEvent(scene_, E_NODEREMOVED, HANDLER(SceneSelection, HandleNodeRemoved));
  44. SubscribeToEvent(scene_, E_SCENEEDITPREFABSAVE, HANDLER(SceneSelection, HandleSceneEditPrefabSave));
  45. SubscribeToEvent(scene_, E_SCENEEDITPREFABREVERT, HANDLER(SceneSelection, HandleSceneEditPrefabRevert));
  46. SubscribeToEvent(scene_, E_SCENEEDITPREFABBREAK, HANDLER(SceneSelection, HandleSceneEditPrefabBreak));
  47. }
  48. SceneSelection::~SceneSelection()
  49. {
  50. }
  51. Node* SceneSelection::GetSelectedNode(unsigned index) const
  52. {
  53. if (index > nodes_.Size())
  54. return 0;
  55. return nodes_[index];
  56. }
  57. bool SceneSelection::Contains(Node* node)
  58. {
  59. SharedPtr<Node> _node(node);
  60. return nodes_.Contains(_node);
  61. }
  62. void SceneSelection::AddNode(Node* node, bool clear)
  63. {
  64. if (clear)
  65. Clear();
  66. SharedPtr<Node> _node(node);
  67. if (!nodes_.Contains(_node))
  68. {
  69. nodes_.Push(_node);
  70. VariantMap eventData;
  71. eventData[SceneNodeSelected::P_SCENE] = scene_;
  72. eventData[SceneNodeSelected::P_NODE] = node;
  73. eventData[SceneNodeSelected::P_SELECTED] = true;
  74. scene_->SendEvent(E_SCENENODESELECTED, eventData);
  75. }
  76. }
  77. void SceneSelection::RemoveNode(Node* node, bool quiet)
  78. {
  79. SharedPtr<Node> _node(node);
  80. if(!nodes_.Contains(_node))
  81. return;
  82. nodes_.Remove(_node);
  83. VariantMap eventData;
  84. eventData[SceneNodeSelected::P_SCENE] = scene_;
  85. eventData[SceneNodeSelected::P_NODE] = node;
  86. eventData[SceneNodeSelected::P_SELECTED] = false;
  87. eventData[SceneNodeSelected::P_QUIET] = quiet;
  88. scene_->SendEvent(E_SCENENODESELECTED, eventData);
  89. }
  90. void SceneSelection::Clear()
  91. {
  92. Vector<SharedPtr<Node>> nodes = nodes_;
  93. for (unsigned i = 0; i < nodes.Size(); i++)
  94. {
  95. RemoveNode(nodes[i]);
  96. }
  97. }
  98. void SceneSelection::Paste()
  99. {
  100. if (!clipBoardNodes_.Size())
  101. return;
  102. Vector<SharedPtr<Node>> newClipBoardNodes;
  103. Node* parent = scene_;
  104. if (nodes_.Size() >= 1)
  105. parent = nodes_[0]->GetParent();
  106. if (!parent)
  107. parent = scene_;
  108. Clear();
  109. VariantMap eventData;
  110. eventData[SceneEditAddRemoveNodes::P_END] = false;
  111. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  112. for (unsigned i = 0; i < clipBoardNodes_.Size(); i++)
  113. {
  114. // Nodes must have a parent to clone, so first parent
  115. Node* clipNode = clipBoardNodes_[i];
  116. Matrix3x4 transform = clipNode->GetWorldTransform();
  117. parent->AddChild(clipNode);
  118. clipNode->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
  119. // clone
  120. newClipBoardNodes.Push(SharedPtr<Node>(clipNode->Clone()));
  121. // remove from parent
  122. newClipBoardNodes.Back()->Remove();
  123. newClipBoardNodes.Back()->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
  124. // generate scene edit event
  125. VariantMap nodeAddedEventData;
  126. nodeAddedEventData[SceneEditNodeAdded::P_NODE] = clipNode;
  127. nodeAddedEventData[SceneEditNodeAdded::P_PARENT] = parent;
  128. nodeAddedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
  129. scene_->SendEvent(E_SCENEEDITNODEADDED, nodeAddedEventData);
  130. }
  131. eventData[SceneEditAddRemoveNodes::P_END] = true;
  132. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  133. for (unsigned i = 0; i < clipBoardNodes_.Size(); i++)
  134. {
  135. AddNode(clipBoardNodes_[i], false);
  136. }
  137. clipBoardNodes_ = newClipBoardNodes;
  138. }
  139. void SceneSelection::Cut()
  140. {
  141. Copy();
  142. Delete();
  143. }
  144. void SceneSelection::Copy()
  145. {
  146. clipBoardNodes_.Clear();
  147. for (unsigned i = 0; i < nodes_.Size(); i++)
  148. {
  149. Node* node = nodes_[i];
  150. if (!node->GetParent())
  151. {
  152. clipBoardNodes_.Clear();
  153. LOGERROR("SceneSelection::Copy - unable to copy node to clipboard (no parent)");
  154. return;
  155. }
  156. for (unsigned j = 0; j < nodes_.Size(); j++)
  157. {
  158. if ( i == j )
  159. continue;
  160. PODVector<Node*> children;
  161. nodes_[j]->GetChildren(children, true);
  162. if (children.Contains(node))
  163. {
  164. node = 0;
  165. break;
  166. }
  167. }
  168. if (node)
  169. {
  170. Matrix3x4 transform = node->GetWorldTransform();
  171. SharedPtr<Node> clipNode(node->Clone());
  172. clipNode->Remove();
  173. clipNode->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
  174. clipBoardNodes_.Push(clipNode);
  175. }
  176. }
  177. }
  178. void SceneSelection::Delete()
  179. {
  180. Vector<SharedPtr<Node>> nodes = nodes_;
  181. Clear();
  182. VariantMap eventData;
  183. eventData[SceneEditAddRemoveNodes::P_END] = false;
  184. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  185. for (unsigned i = 0; i < nodes.Size(); i++)
  186. {
  187. // generate scene edit event
  188. VariantMap nodeRemovedEventData;
  189. nodeRemovedEventData[SceneEditNodeAdded::P_NODE] = nodes[i];
  190. nodeRemovedEventData[SceneEditNodeAdded::P_PARENT] = nodes[i]->GetParent();
  191. nodeRemovedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
  192. scene_->SendEvent(E_SCENEEDITNODEREMOVED, nodeRemovedEventData);
  193. nodes[i]->Remove();
  194. }
  195. eventData[SceneEditAddRemoveNodes::P_END] = true;
  196. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  197. }
  198. void SceneSelection::GetBounds(BoundingBox& bbox)
  199. {
  200. bbox.Clear();
  201. if (!nodes_.Size())
  202. return;
  203. // Get all the drawables, which define the bounding box of the selection
  204. PODVector<Drawable*> drawables;
  205. for (unsigned i = 0; i < nodes_.Size(); i++)
  206. {
  207. Node* node = nodes_[i];
  208. node->GetDerivedComponents<Drawable>(drawables, true, false);
  209. }
  210. if (!drawables.Size())
  211. return;
  212. // Calculate the combined bounding box of all drawables
  213. for (unsigned i = 0; i < drawables.Size(); i++ )
  214. {
  215. Drawable* drawable = drawables[i];
  216. bbox.Merge(drawable->GetWorldBoundingBox());
  217. }
  218. }
  219. void SceneSelection::DrawNodeDebug(Node* node, DebugRenderer* debug, bool drawNode)
  220. {
  221. if (drawNode)
  222. debug->AddNode(node, 1.0, false);
  223. // Exception for the scene to avoid bringing the editor to its knees: drawing either the whole hierarchy or the subsystem-
  224. // components can have a large performance hit. Also do not draw terrain child nodes due to their large amount
  225. // (TerrainPatch component itself draws nothing as debug geometry)
  226. if (node != scene_ && !node->GetComponent<Terrain>())
  227. {
  228. const Vector<SharedPtr<Component> >& components = node->GetComponents();
  229. for (unsigned j = 0; j < components.Size(); ++j)
  230. components[j]->DrawDebugGeometry(debug, false);
  231. // To avoid cluttering the view, do not draw the node axes for child nodes
  232. for (unsigned k = 0; k < node->GetNumChildren(); ++k)
  233. DrawNodeDebug(node->GetChild(k), debug, false);
  234. }
  235. }
  236. void SceneSelection::HandleNodeRemoved(StringHash eventType, VariantMap& eventData)
  237. {
  238. Node* node = (Node*) (eventData[NodeRemoved::P_NODE].GetPtr());
  239. RemoveNode(node, true);
  240. }
  241. void SceneSelection::HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
  242. {
  243. if (!nodes_.Size())
  244. return;
  245. // Visualize the currently selected nodes
  246. DebugRenderer* debugRenderer = sceneEditor3D_->GetSceneView3D()->GetDebugRenderer();
  247. for (unsigned i = 0; i < nodes_.Size(); i++)
  248. {
  249. DrawNodeDebug(nodes_[i], debugRenderer);
  250. }
  251. }
  252. void SceneSelection::HandleSceneEditPrefabSave(StringHash eventType, VariantMap& eventData)
  253. {
  254. Node* node = static_cast<Node*> ( eventData[SceneEditPrefabSave::P_NODE].GetPtr());
  255. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  256. if (!prefab)
  257. {
  258. LOGERRORF("Prefab Save: Unable to get prefab component for node: %s", node->GetName().CString());
  259. return;
  260. }
  261. prefab->SavePrefab();
  262. AddNode(node, true);
  263. }
  264. void SceneSelection::HandleSceneEditPrefabRevert(StringHash eventType, VariantMap& eventData)
  265. {
  266. Node* node = static_cast<Node*> ( eventData[SceneEditPrefabRevert::P_NODE].GetPtr());
  267. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  268. if (!prefab)
  269. {
  270. LOGERRORF("Prefab Revert: Unable to get prefab component for node: %s", node->GetName().CString());
  271. return;
  272. }
  273. prefab->UndoPrefab();
  274. AddNode(node, true);
  275. }
  276. void SceneSelection::HandleSceneEditPrefabBreak(StringHash eventType, VariantMap& eventData)
  277. {
  278. Node* node = static_cast<Node*> ( eventData[SceneEditPrefabBreak::P_NODE].GetPtr());
  279. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  280. if (!prefab)
  281. {
  282. LOGERRORF("Prefab Break: Unable to get prefab component for node: %s", node->GetName().CString());
  283. return;
  284. }
  285. Clear();
  286. prefab->BreakPrefab();
  287. PODVector<Node*> nodes;
  288. node->GetChildren(nodes, true);
  289. nodes.Insert(0, node);
  290. SceneEditHistory* editHistory = sceneEditor3D_->GetEditHistory();
  291. for (unsigned i = 0; i < nodes.Size(); i++)
  292. {
  293. editHistory->RemoveNode(nodes[i]);
  294. }
  295. AddNode(node, true);
  296. scene_->SendEvent(E_SCENEEDITSCENEMODIFIED);
  297. }
  298. }