SceneSelection.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  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/Graphics/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), hasCopied_(false)
  39. {
  40. sceneEditor3D_ = sceneEditor;
  41. scene_ = sceneEditor3D_->GetScene();
  42. SubscribeToEvent(E_POSTRENDERUPDATE, ATOMIC_HANDLER(SceneSelection, HandlePostRenderUpdate));
  43. SubscribeToEvent(scene_, E_NODEREMOVED, ATOMIC_HANDLER(SceneSelection, HandleNodeRemoved));
  44. SubscribeToEvent(scene_, E_SCENEEDITPREFABSAVE, ATOMIC_HANDLER(SceneSelection, HandleSceneEditPrefabSave));
  45. SubscribeToEvent(scene_, E_SCENEEDITPREFABREVERT, ATOMIC_HANDLER(SceneSelection, HandleSceneEditPrefabRevert));
  46. SubscribeToEvent(scene_, E_SCENEEDITPREFABBREAK, ATOMIC_HANDLER(SceneSelection, HandleSceneEditPrefabBreak));
  47. SubscribeToEvent(scene_, E_SCENEEDITPREFABCOPY, ATOMIC_HANDLER(SceneSelection, HandleSceneEditPrefabCopy));
  48. SubscribeToEvent(scene_, E_SCENEEDITPREFABPASTE, ATOMIC_HANDLER(SceneSelection, HandleSceneEditPrefabPaste));
  49. SubscribeToEvent(scene_, E_SCENEEDITCOMPONENTCOPY, ATOMIC_HANDLER(SceneSelection, HandleSceneEditComponentCopy));
  50. SubscribeToEvent(scene_, E_SCENEEDITCOMPONENTPASTE, ATOMIC_HANDLER(SceneSelection, HandleSceneEditComponentPaste));
  51. }
  52. SceneSelection::~SceneSelection()
  53. {
  54. }
  55. Node* SceneSelection::GetSelectedNode(unsigned index) const
  56. {
  57. if (index >= nodes_.Size())
  58. return 0;
  59. return nodes_[index];
  60. }
  61. bool SceneSelection::Contains(Node* node)
  62. {
  63. SharedPtr<Node> _node(node);
  64. return nodes_.Contains(_node);
  65. }
  66. void SceneSelection::AddNode(Node* node, bool clear)
  67. {
  68. if (clear)
  69. Clear();
  70. SharedPtr<Node> _node(node);
  71. if (!nodes_.Contains(_node))
  72. {
  73. nodes_.Push(_node);
  74. VariantMap eventData;
  75. eventData[SceneNodeSelected::P_SCENE] = scene_;
  76. eventData[SceneNodeSelected::P_NODE] = node;
  77. eventData[SceneNodeSelected::P_SELECTED] = true;
  78. scene_->SendEvent(E_SCENENODESELECTED, eventData);
  79. }
  80. }
  81. void SceneSelection::RemoveNode(Node* node, bool quiet)
  82. {
  83. SharedPtr<Node> _node(node);
  84. if(!nodes_.Contains(_node))
  85. return;
  86. nodes_.Remove(_node);
  87. VariantMap eventData;
  88. eventData[SceneNodeSelected::P_SCENE] = scene_;
  89. eventData[SceneNodeSelected::P_NODE] = node;
  90. eventData[SceneNodeSelected::P_SELECTED] = false;
  91. eventData[SceneNodeSelected::P_QUIET] = quiet;
  92. scene_->SendEvent(E_SCENENODESELECTED, eventData);
  93. }
  94. void SceneSelection::Clear()
  95. {
  96. Vector<SharedPtr<Node>> nodes = nodes_;
  97. for (unsigned i = 0; i < nodes.Size(); i++)
  98. {
  99. RemoveNode(nodes[i]);
  100. }
  101. }
  102. void SceneSelection::Paste()
  103. {
  104. if (!clipBoardNodes_.Size())
  105. return;
  106. Vector<SharedPtr<Node>> newClipBoardNodes;
  107. Node* parent = scene_;
  108. if (nodes_.Size() >= 1)
  109. parent = nodes_[0]->GetParent();
  110. if (!parent)
  111. parent = scene_;
  112. Clear();
  113. VariantMap eventData;
  114. eventData[SceneEditAddRemoveNodes::P_END] = false;
  115. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  116. for (unsigned i = 0; i < clipBoardNodes_.Size(); i++)
  117. {
  118. // Nodes must have a parent to clone, so first parent
  119. Node* clipNode = clipBoardNodes_[i];
  120. Matrix3x4 transform = clipNode->GetWorldTransform();
  121. parent->AddChild(clipNode);
  122. clipNode->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
  123. // clone
  124. newClipBoardNodes.Push(SharedPtr<Node>(clipNode->Clone()));
  125. // remove from parent
  126. newClipBoardNodes.Back()->Remove();
  127. newClipBoardNodes.Back()->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
  128. // generate scene edit event
  129. VariantMap nodeAddedEventData;
  130. nodeAddedEventData[SceneEditNodeAdded::P_NODE] = clipNode;
  131. nodeAddedEventData[SceneEditNodeAdded::P_PARENT] = parent;
  132. nodeAddedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
  133. scene_->SendEvent(E_SCENEEDITNODEADDED, nodeAddedEventData);
  134. }
  135. eventData[SceneEditAddRemoveNodes::P_END] = true;
  136. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  137. for (unsigned i = 0; i < clipBoardNodes_.Size(); i++)
  138. {
  139. AddNode(clipBoardNodes_[i], false);
  140. }
  141. clipBoardNodes_ = newClipBoardNodes;
  142. }
  143. void SceneSelection::Cut()
  144. {
  145. Copy();
  146. Delete();
  147. }
  148. void SceneSelection::Copy()
  149. {
  150. clipBoardNodes_.Clear();
  151. for (unsigned i = 0; i < nodes_.Size(); i++)
  152. {
  153. Node* node = nodes_[i];
  154. if (!node->GetParent())
  155. {
  156. clipBoardNodes_.Clear();
  157. ATOMIC_LOGERROR("SceneSelection::Copy - unable to copy node to clipboard (no parent)");
  158. return;
  159. }
  160. for (unsigned j = 0; j < nodes_.Size(); j++)
  161. {
  162. if ( i == j )
  163. continue;
  164. PODVector<Node*> children;
  165. nodes_[j]->GetChildren(children, true);
  166. if (children.Contains(node))
  167. {
  168. node = 0;
  169. break;
  170. }
  171. }
  172. if (node)
  173. {
  174. Matrix3x4 transform = node->GetWorldTransform();
  175. SharedPtr<Node> clipNode(node->Clone());
  176. clipNode->Remove();
  177. clipNode->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
  178. clipBoardNodes_.Push(clipNode);
  179. }
  180. }
  181. }
  182. void SceneSelection::Delete()
  183. {
  184. Vector<SharedPtr<Node>> nodes = nodes_;
  185. Clear();
  186. VariantMap eventData;
  187. eventData[SceneEditAddRemoveNodes::P_END] = false;
  188. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  189. for (unsigned i = 0; i < nodes.Size(); i++)
  190. {
  191. // generate scene edit event
  192. VariantMap nodeRemovedEventData;
  193. nodeRemovedEventData[SceneEditNodeAdded::P_NODE] = nodes[i];
  194. nodeRemovedEventData[SceneEditNodeAdded::P_PARENT] = nodes[i]->GetParent();
  195. nodeRemovedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
  196. scene_->SendEvent(E_SCENEEDITNODEREMOVED, nodeRemovedEventData);
  197. nodes[i]->Remove();
  198. }
  199. eventData[SceneEditAddRemoveNodes::P_END] = true;
  200. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  201. }
  202. void SceneSelection::GetBounds(BoundingBox& bbox)
  203. {
  204. bbox.Clear();
  205. if (!nodes_.Size())
  206. return;
  207. // Get all the drawables, which define the bounding box of the selection
  208. PODVector<Drawable*> drawables;
  209. for (unsigned i = 0; i < nodes_.Size(); i++)
  210. {
  211. Node* node = nodes_[i];
  212. node->GetDerivedComponents<Drawable>(drawables, true, false);
  213. }
  214. if (!drawables.Size())
  215. return;
  216. // Calculate the combined bounding box of all drawables
  217. for (unsigned i = 0; i < drawables.Size(); i++ )
  218. {
  219. Drawable* drawable = drawables[i];
  220. bbox.Merge(drawable->GetWorldBoundingBox());
  221. }
  222. }
  223. void SceneSelection::DrawNodeDebug(Node* node, DebugRenderer* debug, bool drawNode)
  224. {
  225. if (drawNode)
  226. debug->AddNode(node, 1.0, false);
  227. // Exception for the scene to avoid bringing the editor to its knees: drawing either the whole hierarchy or the subsystem-
  228. // components can have a large performance hit. Also do not draw terrain child nodes due to their large amount
  229. // (TerrainPatch component itself draws nothing as debug geometry)
  230. if (node != scene_ && !node->GetComponent<Terrain>())
  231. {
  232. const Vector<SharedPtr<Component> >& components = node->GetComponents();
  233. for (unsigned j = 0; j < components.Size(); ++j)
  234. components[j]->DrawDebugGeometry(debug, false);
  235. // To avoid cluttering the view, do not draw the node axes for child nodes
  236. for (unsigned k = 0; k < node->GetNumChildren(); ++k)
  237. DrawNodeDebug(node->GetChild(k), debug, false);
  238. }
  239. }
  240. void SceneSelection::HandleNodeRemoved(StringHash eventType, VariantMap& eventData)
  241. {
  242. Node* node = (Node*) (eventData[NodeRemoved::P_NODE].GetPtr());
  243. RemoveNode(node, true);
  244. }
  245. void SceneSelection::HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
  246. {
  247. if (!nodes_.Size())
  248. return;
  249. // Visualize the currently selected nodes
  250. DebugRenderer* debugRenderer = sceneEditor3D_->GetSceneView3D()->GetDebugRenderer();
  251. for (unsigned i = 0; i < nodes_.Size(); i++)
  252. {
  253. DrawNodeDebug(nodes_[i], debugRenderer);
  254. }
  255. }
  256. void SceneSelection::HandleSceneEditPrefabSave(StringHash eventType, VariantMap& eventData)
  257. {
  258. Node* node = static_cast<Node*> ( eventData[SceneEditPrefabSave::P_NODE].GetPtr());
  259. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  260. if (!prefab)
  261. {
  262. ATOMIC_LOGERRORF("Prefab Save: Unable to get prefab component for node: %s", node->GetName().CString());
  263. return;
  264. }
  265. prefab->SavePrefab();
  266. AddNode(node, true);
  267. }
  268. void SceneSelection::HandleSceneEditPrefabRevert(StringHash eventType, VariantMap& eventData)
  269. {
  270. Node* node = static_cast<Node*> ( eventData[SceneEditPrefabRevert::P_NODE].GetPtr());
  271. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  272. if (!prefab)
  273. {
  274. ATOMIC_LOGERRORF("Prefab Revert: Unable to get prefab component for node: %s", node->GetName().CString());
  275. return;
  276. }
  277. prefab->UndoPrefab();
  278. AddNode(node, true);
  279. }
  280. void SceneSelection::HandleSceneEditPrefabBreak(StringHash eventType, VariantMap& eventData)
  281. {
  282. Node* node = static_cast<Node*> ( eventData[SceneEditPrefabBreak::P_NODE].GetPtr());
  283. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  284. if (!prefab)
  285. {
  286. ATOMIC_LOGERRORF("Prefab Break: Unable to get prefab component for node: %s", node->GetName().CString());
  287. return;
  288. }
  289. Clear();
  290. prefab->BreakPrefab();
  291. PODVector<Node*> nodes;
  292. node->GetChildren(nodes, true);
  293. nodes.Insert(0, node);
  294. SceneEditHistory* editHistory = sceneEditor3D_->GetEditHistory();
  295. for (unsigned i = 0; i < nodes.Size(); i++)
  296. {
  297. editHistory->RemoveNode(nodes[i]);
  298. }
  299. AddNode(node, true);
  300. scene_->SendEvent(E_SCENEEDITSCENEMODIFIED);
  301. }
  302. void SceneSelection::HandleSceneEditPrefabCopy(StringHash eventType, VariantMap & eventData)
  303. {
  304. Node* node = static_cast<Node*> (eventData[SceneEditPrefabCopy::P_NODE].GetPtr());
  305. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  306. if (!prefab)
  307. {
  308. ATOMIC_LOGERRORF("Prefab Copy: Unable to get prefab component for node: %s", node->GetName().CString());
  309. return;
  310. }
  311. nodePosition_ = node->GetAttribute("Position").GetVector3();
  312. nodeRotation_ = node->GetAttribute("Rotation").GetQuaternion();
  313. nodeScale_ = node->GetAttribute("Scale").GetVector3();
  314. }
  315. void SceneSelection::HandleSceneEditPrefabPaste(StringHash eventType, VariantMap & eventData)
  316. {
  317. Node* node = static_cast<Node*> (eventData[SceneEditPrefabPaste::P_NODE].GetPtr());
  318. PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
  319. if (!prefab)
  320. {
  321. ATOMIC_LOGERRORF("Prefab Paste: Unable to get prefab component for node: %s", node->GetName().CString());
  322. return;
  323. }
  324. node->SetPosition(nodePosition_);
  325. node->SetRotation(nodeRotation_);
  326. node->SetScale(nodeScale_);
  327. }
  328. void SceneSelection::HandleSceneEditComponentCopy(StringHash eventType, VariantMap & eventData)
  329. {
  330. Component* component = static_cast<Component*> (eventData[SceneEditComponentCopy::P_COMPONENT].GetPtr());
  331. copiedComponent_ = component;
  332. if (!component)
  333. {
  334. ATOMIC_LOGERRORF("Component Copy: Unable to copy component from node: %s", component->GetAttribute("type").ToString().CString());
  335. return;
  336. }
  337. componentAttributeNames_.Clear();
  338. componentAttributeValues_.Clear();
  339. for (unsigned i = 0; i < component->GetAttributes()->Size(); i++)
  340. {
  341. String attributeName = component->GetAttributes()->At(i).name_;
  342. Variant attributeValue = component->GetAttribute(attributeName);
  343. componentAttributeNames_.Push(attributeName);
  344. componentAttributeValues_.Push(attributeValue);
  345. }
  346. hasCopied_ = true;
  347. }
  348. void SceneSelection::HandleSceneEditComponentPaste(StringHash eventType, VariantMap & eventData)
  349. {
  350. Component* component = static_cast<Component*> (eventData[SceneEditComponentCopy::P_COMPONENT].GetPtr());
  351. if (!component)
  352. {
  353. ATOMIC_LOGERRORF("Component Paste: Unable to paste component to node: %s", component->GetAttribute("type").ToString().CString());
  354. return;
  355. }
  356. if (!hasCopied_)
  357. {
  358. ATOMIC_LOGERROR("Component Paste: Unable to paste, no information has been copied.");
  359. return;
  360. }
  361. if (copiedComponent_->GetType() != component->GetType())
  362. {
  363. ATOMIC_LOGERROR("Component Paste: Unable to paste, component type differ.");
  364. return;
  365. }
  366. for (unsigned i = 0; i < componentAttributeNames_.Size(); i++)
  367. {
  368. String attrName = componentAttributeNames_[i];
  369. Variant attrValue = componentAttributeValues_[i];
  370. component->SetAttribute(attrName, attrValue);
  371. }
  372. }
  373. }