SceneSelection.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. //
  2. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  3. // LICENSE: Atomic Game Engine Editor and Tools EULA
  4. // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
  5. // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
  6. //
  7. #include <Atomic/IO/Log.h>
  8. #include <Atomic/Core/CoreEvents.h>
  9. #include <Atomic/Graphics/Graphics.h>
  10. #include <Atomic/Graphics/Drawable.h>
  11. #include <Atomic/Graphics/DebugRenderer.h>
  12. #include <Atomic/Atomic3D/Terrain.h>
  13. #include <Atomic/Scene/SceneEvents.h>
  14. #include <Atomic/Scene/Node.h>
  15. #include <Atomic/Scene/Scene.h>
  16. #include <Atomic/Scene/PrefabComponent.h>
  17. #include "SceneEditor3D.h"
  18. #include "SceneEditor3DEvents.h"
  19. #include "SceneSelection.h"
  20. #include "SceneEditHistory.h"
  21. namespace AtomicEditor
  22. {
  23. SceneSelection::SceneSelection(Context* context, SceneEditor3D *sceneEditor) : Object(context)
  24. {
  25. sceneEditor3D_ = sceneEditor;
  26. scene_ = sceneEditor3D_->GetScene();
  27. SubscribeToEvent(E_POSTRENDERUPDATE, HANDLER(SceneSelection, HandlePostRenderUpdate));
  28. SubscribeToEvent(scene_, E_NODEREMOVED, HANDLER(SceneSelection, HandleNodeRemoved));
  29. SubscribeToEvent(scene_, E_SCENEEDITPREFABSAVE, HANDLER(SceneSelection, HandleSceneEditPrefabSave));
  30. SubscribeToEvent(scene_, E_SCENEEDITPREFABREVERT, HANDLER(SceneSelection, HandleSceneEditPrefabRevert));
  31. SubscribeToEvent(scene_, E_SCENEEDITPREFABBREAK, HANDLER(SceneSelection, HandleSceneEditPrefabBreak));
  32. }
  33. SceneSelection::~SceneSelection()
  34. {
  35. }
  36. Node* SceneSelection::GetSelectedNode(unsigned index) const
  37. {
  38. if (index > nodes_.Size())
  39. return 0;
  40. return nodes_[index];
  41. }
  42. bool SceneSelection::Contains(Node* node)
  43. {
  44. SharedPtr<Node> _node(node);
  45. return nodes_.Contains(_node);
  46. }
  47. void SceneSelection::AddNode(Node* node, bool clear)
  48. {
  49. if (clear)
  50. Clear();
  51. SharedPtr<Node> _node(node);
  52. if (!nodes_.Contains(_node))
  53. {
  54. nodes_.Push(_node);
  55. VariantMap eventData;
  56. eventData[SceneNodeSelected::P_SCENE] = scene_;
  57. eventData[SceneNodeSelected::P_NODE] = node;
  58. eventData[SceneNodeSelected::P_SELECTED] = true;
  59. scene_->SendEvent(E_SCENENODESELECTED, eventData);
  60. }
  61. }
  62. void SceneSelection::RemoveNode(Node* node, bool quiet)
  63. {
  64. SharedPtr<Node> _node(node);
  65. if(!nodes_.Contains(_node))
  66. return;
  67. nodes_.Remove(_node);
  68. VariantMap eventData;
  69. eventData[SceneNodeSelected::P_SCENE] = scene_;
  70. eventData[SceneNodeSelected::P_NODE] = node;
  71. eventData[SceneNodeSelected::P_SELECTED] = false;
  72. eventData[SceneNodeSelected::P_QUIET] = quiet;
  73. scene_->SendEvent(E_SCENENODESELECTED, eventData);
  74. }
  75. void SceneSelection::Clear()
  76. {
  77. Vector<SharedPtr<Node>> nodes = nodes_;
  78. for (unsigned i = 0; i < nodes.Size(); i++)
  79. {
  80. RemoveNode(nodes[i]);
  81. }
  82. }
  83. void SceneSelection::Paste()
  84. {
  85. if (!clipBoardNodes_.Size())
  86. return;
  87. Vector<SharedPtr<Node>> newClipBoardNodes;
  88. Node* parent = scene_;
  89. if (nodes_.Size() >= 1)
  90. parent = nodes_[0]->GetParent();
  91. if (!parent)
  92. parent = scene_;
  93. Clear();
  94. VariantMap eventData;
  95. eventData[SceneEditAddRemoveNodes::P_END] = false;
  96. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  97. for (unsigned i = 0; i < clipBoardNodes_.Size(); i++)
  98. {
  99. // Nodes must have a parent to clone, so first parent
  100. Node* clipNode = clipBoardNodes_[i];
  101. Matrix3x4 transform = clipNode->GetWorldTransform();
  102. parent->AddChild(clipNode);
  103. clipNode->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
  104. // clone
  105. newClipBoardNodes.Push(SharedPtr<Node>(clipNode->Clone()));
  106. // remove from parent
  107. newClipBoardNodes.Back()->Remove();
  108. newClipBoardNodes.Back()->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
  109. // generate scene edit event
  110. VariantMap nodeAddedEventData;
  111. nodeAddedEventData[SceneEditNodeAdded::P_NODE] = clipNode;
  112. nodeAddedEventData[SceneEditNodeAdded::P_PARENT] = parent;
  113. nodeAddedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
  114. scene_->SendEvent(E_SCENEEDITNODEADDED, nodeAddedEventData);
  115. }
  116. eventData[SceneEditAddRemoveNodes::P_END] = true;
  117. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  118. for (unsigned i = 0; i < clipBoardNodes_.Size(); i++)
  119. {
  120. AddNode(clipBoardNodes_[i], false);
  121. }
  122. clipBoardNodes_ = newClipBoardNodes;
  123. }
  124. void SceneSelection::Cut()
  125. {
  126. Copy();
  127. Delete();
  128. }
  129. void SceneSelection::Copy()
  130. {
  131. clipBoardNodes_.Clear();
  132. for (unsigned i = 0; i < nodes_.Size(); i++)
  133. {
  134. Node* node = nodes_[i];
  135. if (!node->GetParent())
  136. {
  137. clipBoardNodes_.Clear();
  138. LOGERROR("SceneSelection::Copy - unable to copy node to clipboard (no parent)");
  139. return;
  140. }
  141. for (unsigned j = 0; j < nodes_.Size(); j++)
  142. {
  143. if ( i == j )
  144. continue;
  145. PODVector<Node*> children;
  146. nodes_[j]->GetChildren(children, true);
  147. if (children.Contains(node))
  148. {
  149. node = 0;
  150. break;
  151. }
  152. }
  153. if (node)
  154. {
  155. Matrix3x4 transform = node->GetWorldTransform();
  156. SharedPtr<Node> clipNode(node->Clone());
  157. clipNode->Remove();
  158. clipNode->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
  159. clipBoardNodes_.Push(clipNode);
  160. }
  161. }
  162. }
  163. void SceneSelection::Delete()
  164. {
  165. Vector<SharedPtr<Node>> nodes = nodes_;
  166. Clear();
  167. VariantMap eventData;
  168. eventData[SceneEditAddRemoveNodes::P_END] = false;
  169. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  170. for (unsigned i = 0; i < nodes.Size(); i++)
  171. {
  172. // generate scene edit event
  173. VariantMap nodeRemovedEventData;
  174. nodeRemovedEventData[SceneEditNodeAdded::P_NODE] = nodes[i];
  175. nodeRemovedEventData[SceneEditNodeAdded::P_PARENT] = nodes[i]->GetParent();
  176. nodeRemovedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
  177. scene_->SendEvent(E_SCENEEDITNODEREMOVED, nodeRemovedEventData);
  178. nodes[i]->Remove();
  179. }
  180. eventData[SceneEditAddRemoveNodes::P_END] = true;
  181. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  182. }
  183. void SceneSelection::GetBounds(BoundingBox& bbox)
  184. {
  185. bbox.Clear();
  186. if (!nodes_.Size())
  187. return;
  188. // Get all the drawables, which define the bounding box of the selection
  189. PODVector<Drawable*> drawables;
  190. for (unsigned i = 0; i < nodes_.Size(); i++)
  191. {
  192. Node* node = nodes_[i];
  193. node->GetDerivedComponents<Drawable>(drawables, true, false);
  194. }
  195. if (!drawables.Size())
  196. return;
  197. // Calculate the combined bounding box of all drawables
  198. for (unsigned i = 0; i < drawables.Size(); i++ )
  199. {
  200. Drawable* drawable = drawables[i];
  201. bbox.Merge(drawable->GetWorldBoundingBox());
  202. }
  203. }
  204. void SceneSelection::DrawNodeDebug(Node* node, DebugRenderer* debug, bool drawNode)
  205. {
  206. if (drawNode)
  207. debug->AddNode(node, 1.0, false);
  208. // Exception for the scene to avoid bringing the editor to its knees: drawing either the whole hierarchy or the subsystem-
  209. // components can have a large performance hit. Also do not draw terrain child nodes due to their large amount
  210. // (TerrainPatch component itself draws nothing as debug geometry)
  211. if (node != scene_ && !node->GetComponent<Terrain>())
  212. {
  213. const Vector<SharedPtr<Component> >& components = node->GetComponents();
  214. for (unsigned j = 0; j < components.Size(); ++j)
  215. components[j]->DrawDebugGeometry(debug, false);
  216. // To avoid cluttering the view, do not draw the node axes for child nodes
  217. for (unsigned k = 0; k < node->GetNumChildren(); ++k)
  218. DrawNodeDebug(node->GetChild(k), debug, false);
  219. }
  220. }
  221. void SceneSelection::HandleNodeRemoved(StringHash eventType, VariantMap& eventData)
  222. {
  223. Node* node = (Node*) (eventData[NodeRemoved::P_NODE].GetPtr());
  224. RemoveNode(node, true);
  225. }
  226. void SceneSelection::HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
  227. {
  228. if (!nodes_.Size())
  229. return;
  230. // Visualize the currently selected nodes
  231. DebugRenderer* debugRenderer = sceneEditor3D_->GetSceneView3D()->GetDebugRenderer();
  232. for (unsigned i = 0; i < nodes_.Size(); i++)
  233. {
  234. DrawNodeDebug(nodes_[i], debugRenderer);
  235. }
  236. }
  237. void SceneSelection::HandleSceneEditPrefabSave(StringHash eventType, VariantMap& eventData)
  238. {
  239. Node* node = static_cast<Node*> ( eventData[SceneEditPrefabSave::P_NODE].GetPtr());
  240. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  241. if (!prefab)
  242. {
  243. LOGERRORF("Prefab Save: Unable to get prefab component for node: %s", node->GetName().CString());
  244. return;
  245. }
  246. prefab->SavePrefab();
  247. AddNode(node, true);
  248. }
  249. void SceneSelection::HandleSceneEditPrefabRevert(StringHash eventType, VariantMap& eventData)
  250. {
  251. Node* node = static_cast<Node*> ( eventData[SceneEditPrefabRevert::P_NODE].GetPtr());
  252. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  253. if (!prefab)
  254. {
  255. LOGERRORF("Prefab Revert: Unable to get prefab component for node: %s", node->GetName().CString());
  256. return;
  257. }
  258. prefab->UndoPrefab();
  259. AddNode(node, true);
  260. }
  261. void SceneSelection::HandleSceneEditPrefabBreak(StringHash eventType, VariantMap& eventData)
  262. {
  263. Node* node = static_cast<Node*> ( eventData[SceneEditPrefabBreak::P_NODE].GetPtr());
  264. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  265. if (!prefab)
  266. {
  267. LOGERRORF("Prefab Break: Unable to get prefab component for node: %s", node->GetName().CString());
  268. return;
  269. }
  270. Clear();
  271. prefab->BreakPrefab();
  272. PODVector<Node*> nodes;
  273. node->GetChildren(nodes, true);
  274. nodes.Insert(0, node);
  275. SceneEditHistory* editHistory = sceneEditor3D_->GetEditHistory();
  276. for (unsigned i = 0; i < nodes.Size(); i++)
  277. {
  278. editHistory->RemoveNode(nodes[i]);
  279. }
  280. AddNode(node, true);
  281. scene_->SendEvent(E_SCENEEDITSCENEMODIFIED);
  282. }
  283. }