SceneEditor3D.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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/Scene/SceneEvents.h>
  25. #include <Atomic/Scene/Scene.h>
  26. #include <Atomic/Graphics/Camera.h>
  27. #include <Atomic/Graphics/DebugRenderer.h>
  28. #include <Atomic/Graphics/Viewport.h>
  29. #include <Atomic/Graphics/Octree.h>
  30. #include <Atomic/IO/FileSystem.h>
  31. #include <Atomic/Resource/ResourceCache.h>
  32. #include <Atomic/Physics/PhysicsWorld.h>
  33. #include <Atomic/Input/Input.h>
  34. #include <Atomic/UI/UI.h>
  35. #include <ToolCore/ToolSystem.h>
  36. #include <ToolCore/Project/Project.h>
  37. #include <ToolCore/Project/ProjectEvents.h>
  38. #include <ToolCore/Project/ProjectUserPrefs.h>
  39. #include <ToolCore/Assets/AssetDatabase.h>
  40. #include <ToolCore/Assets/Asset.h>
  41. #include <ToolCore/Assets/SceneImporter.h>
  42. #include "../../EditorMode/AEEditorEvents.h"
  43. #include "SceneEditor3D.h"
  44. #include "SceneSelection.h"
  45. #include "SceneEditHistory.h"
  46. #include "SceneEditor3DEvents.h"
  47. using namespace ToolCore;
  48. namespace AtomicEditor
  49. {
  50. Vector<WeakPtr<SceneEditor3D>> SceneEditor3D::sceneEditors_;
  51. SceneEditor3D::SceneEditor3D(Context* context, const String &fullpath, UITabContainer *container) :
  52. ResourceEditor(context, fullpath, container),
  53. cubemapRenderCount_(0)
  54. {
  55. // store a local reference to user project prefs
  56. ToolSystem* tsystem = GetSubsystem<ToolSystem>();
  57. Project* project = tsystem->GetProject();
  58. userPrefs_ = project->GetUserPrefs();
  59. ResourceCache* cache = GetSubsystem<ResourceCache>();
  60. scene_ = new Scene(context_);
  61. SharedPtr<File> xmlFile = cache->GetFile(fullpath);
  62. if (GetExtension(fullpath) == ".scene")
  63. scene_->LoadXML(*xmlFile);
  64. else
  65. scene_->Load(*xmlFile);
  66. scene_->SetUpdateEnabled(false);
  67. selection_ = new SceneSelection(context, this);
  68. sceneView_ = new SceneView3D(context_, this);
  69. editHistory_ = new SceneEditHistory(context, this);
  70. AssetDatabase* assetDB = GetSubsystem<AssetDatabase>();
  71. Asset* sceneAsset = assetDB->GetAssetByPath(fullpath);
  72. if (sceneAsset)
  73. {
  74. sceneImporter_ = static_cast<SceneImporter*>(sceneAsset->GetImporter());
  75. sceneView_->GetCameraNode()->SetWorldPosition(sceneImporter_->GetSceneCamPosition());
  76. sceneView_->SetPitch(sceneImporter_->GetSceneCamRotation().PitchAngle());
  77. sceneView_->SetYaw(sceneImporter_->GetSceneCamRotation().YawAngle());
  78. }
  79. else
  80. {
  81. ATOMIC_LOGERRORF("SceneEditor3D::SceneEditor3D - Unable to get scene asset");
  82. }
  83. sceneView_->SetGravity(UI_GRAVITY_ALL);
  84. rootContentWidget_->AddChild(sceneView_);
  85. gizmo3D_ = new Gizmo3D(context_);
  86. gizmo3D_->SetView(sceneView_);
  87. gizmo3D_->Show();
  88. UpdateGizmoSnapSettings();
  89. SubscribeToEvent(E_UPDATE, ATOMIC_HANDLER(SceneEditor3D, HandleUpdate));
  90. SubscribeToEvent(E_GIZMOEDITMODECHANGED, ATOMIC_HANDLER(SceneEditor3D, HandleGizmoEditModeChanged));
  91. SubscribeToEvent(E_GIZMOAXISMODECHANGED, ATOMIC_HANDLER(SceneEditor3D, HandleGizmoAxisModeChanged));
  92. // FIXME: Set the size at the end of setup, so all children are updated accordingly
  93. // future size changes will be handled automatically
  94. IntRect rect = container_->GetContentRoot()->GetRect();
  95. rootContentWidget_->SetSize(rect.Width(), rect.Height());
  96. SubscribeToEvent(E_PROJECTUSERPREFSAVED, ATOMIC_HANDLER(SceneEditor3D, HandleUserPrefSaved));
  97. SubscribeToEvent(scene_, E_SCENEEDITNODECREATED, ATOMIC_HANDLER(SceneEditor3D, HandleSceneEditNodeCreated));
  98. SubscribeToEvent(E_EDITORPLAYERSTARTED, ATOMIC_HANDLER(SceneEditor3D, HandlePlayStarted));
  99. SubscribeToEvent(E_EDITORPLAYERSTOPPED, ATOMIC_HANDLER(SceneEditor3D, HandlePlayStopped));
  100. SubscribeToEvent(scene_, E_SCENEEDITSCENEMODIFIED, ATOMIC_HANDLER(SceneEditor3D, HandleSceneEditSceneModified));
  101. SubscribeToEvent(scene_, E_CUBEMAPRENDERBEGIN, ATOMIC_HANDLER(SceneEditor3D, HandleCubemapRenderBegin));
  102. SubscribeToEvent(scene_, E_CUBEMAPRENDEREND, ATOMIC_HANDLER(SceneEditor3D, HandleCubemapRenderEnd));
  103. RegisterSceneEditor();
  104. }
  105. SceneEditor3D::~SceneEditor3D()
  106. {
  107. }
  108. bool SceneEditor3D::OnEvent(const TBWidgetEvent &ev)
  109. {
  110. if (ev.type == EVENT_TYPE_KEY_UP)
  111. {
  112. if (ev.special_key == TB_KEY_DELETE || ev.special_key == TB_KEY_BACKSPACE)
  113. {
  114. selection_->Delete();
  115. }
  116. }
  117. if (ev.type == EVENT_TYPE_SHORTCUT)
  118. {
  119. if (ev.ref_id == TBIDC("copy"))
  120. {
  121. selection_->Copy();
  122. return true;
  123. }
  124. else if (ev.ref_id == TBIDC("paste"))
  125. {
  126. selection_->Paste();
  127. return true;
  128. }
  129. else if (ev.ref_id == TBIDC("close"))
  130. {
  131. RequestClose();
  132. return true;
  133. }
  134. else if (ev.ref_id == TBIDC("undo"))
  135. {
  136. Undo();
  137. return true;
  138. }
  139. else if (ev.ref_id == TBIDC("redo"))
  140. {
  141. Redo();
  142. return true;
  143. }
  144. }
  145. if (ev.type == EVENT_TYPE_CLICK)
  146. {
  147. SetFocus();
  148. if (ev.target)
  149. {
  150. if (ev.target->GetID() == TBIDC("3d_translate"))
  151. {
  152. gizmo3D_->SetEditMode(EDIT_MOVE);
  153. return false;
  154. }
  155. else if (ev.target->GetID() == TBIDC("3d_rotate"))
  156. {
  157. gizmo3D_->SetEditMode(EDIT_ROTATE);
  158. return false;
  159. }
  160. else if (ev.target->GetID() == TBIDC("3d_scale"))
  161. {
  162. gizmo3D_->SetEditMode(EDIT_SCALE);
  163. return false;
  164. }
  165. }
  166. }
  167. return false;
  168. }
  169. void SceneEditor3D::SetFocus()
  170. {
  171. sceneView_->SetFocus();
  172. }
  173. void SceneEditor3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
  174. {
  175. if (!cubemapRenderCount_)
  176. gizmo3D_->Update();
  177. }
  178. void SceneEditor3D::HandlePlayStarted(StringHash eventType, VariantMap& eventData)
  179. {
  180. }
  181. void SceneEditor3D::HandlePlayStopped(StringHash eventType, VariantMap& eventData)
  182. {
  183. }
  184. void SceneEditor3D::HandleGizmoEditModeChanged(StringHash eventType, VariantMap& eventData)
  185. {
  186. EditMode mode = (EditMode) (eventData[GizmoEditModeChanged::P_MODE].GetInt());
  187. gizmo3D_->SetEditMode(mode);
  188. }
  189. void SceneEditor3D::HandleGizmoAxisModeChanged(StringHash eventType, VariantMap& eventData)
  190. {
  191. AxisMode mode = (AxisMode) (eventData[GizmoAxisModeChanged::P_MODE].GetInt());
  192. gizmo3D_->SetAxisMode(mode);
  193. }
  194. void SceneEditor3D::Close(bool navigateToAvailableResource)
  195. {
  196. VariantMap data;
  197. data["Scene"] = scene_;
  198. SendEvent("EditorSceneClosed", data);
  199. selection_ = 0;
  200. editHistory_ = 0;
  201. if (sceneImporter_.NotNull())
  202. {
  203. sceneImporter_->SetSceneCamPosition(sceneView_->GetCameraNode()->GetWorldPosition());
  204. sceneImporter_->SetSceneCamRotation(sceneView_->GetCameraNode()->GetWorldRotation());
  205. sceneImporter_->GetAsset()->Save();
  206. sceneImporter_ = nullptr;
  207. }
  208. ResourceEditor::Close(navigateToAvailableResource);
  209. }
  210. bool SceneEditor3D::Save()
  211. {
  212. File file(context_);
  213. if (file.Open(fullpath_, FILE_WRITE))
  214. {
  215. scene_->SaveXML(file);
  216. file.Close();
  217. }
  218. SetModified(false);
  219. return true;
  220. }
  221. void SceneEditor3D::RegisterNode(Node * node)
  222. {
  223. VariantMap eventData;
  224. eventData[SceneEditAddRemoveNodes::P_END] = false;
  225. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  226. // generate scene edit event
  227. VariantMap nodeAddedEventData;
  228. nodeAddedEventData[SceneEditNodeAdded::P_NODE] = node;
  229. nodeAddedEventData[SceneEditNodeAdded::P_PARENT] = node->GetParent();
  230. nodeAddedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
  231. scene_->SendEvent(E_SCENEEDITNODEADDED, nodeAddedEventData);
  232. eventData[SceneEditAddRemoveNodes::P_END] = true;
  233. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  234. }
  235. void SceneEditor3D::RegisterNodes(const PODVector<Node*>& nodes)
  236. {
  237. VariantMap eventData;
  238. eventData[SceneEditAddRemoveNodes::P_END] = false;
  239. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  240. // generate scene edit event
  241. for (unsigned i = 0; i < nodes.Size(); i++)
  242. {
  243. Node* node = nodes[i];
  244. VariantMap nodeAddedEventData;
  245. nodeAddedEventData[SceneEditNodeAdded::P_NODE] = node;
  246. nodeAddedEventData[SceneEditNodeAdded::P_PARENT] = node->GetParent();
  247. nodeAddedEventData[SceneEditNodeAdded::P_SCENE] = scene_;
  248. scene_->SendEvent(E_SCENEEDITNODEADDED, nodeAddedEventData);
  249. }
  250. eventData[SceneEditAddRemoveNodes::P_END] = true;
  251. scene_->SendEvent(E_SCENEEDITADDREMOVENODES, eventData);
  252. }
  253. void SceneEditor3D::Undo()
  254. {
  255. editHistory_->Undo();
  256. }
  257. void SceneEditor3D::Redo()
  258. {
  259. editHistory_->Redo();
  260. }
  261. void SceneEditor3D::Cut()
  262. {
  263. selection_->Cut();
  264. }
  265. void SceneEditor3D::Copy()
  266. {
  267. selection_->Copy();
  268. }
  269. void SceneEditor3D::Paste()
  270. {
  271. selection_->Paste();
  272. }
  273. void SceneEditor3D::HandleSceneEditNodeCreated(StringHash eventType, VariantMap& eventData)
  274. {
  275. PODVector<Node*> nodes;
  276. nodes.Push(static_cast<Node*>(eventData[SceneEditNodeCreated::P_NODE].GetPtr()));
  277. RegisterNodes(nodes);
  278. selection_->AddNode(nodes[0], true);
  279. }
  280. void SceneEditor3D::HandleSceneEditSceneModified(StringHash eventType, VariantMap& eventData)
  281. {
  282. SetModified(true);
  283. }
  284. void SceneEditor3D::HandleUserPrefSaved(StringHash eventType, VariantMap& eventData)
  285. {
  286. UpdateGizmoSnapSettings();
  287. }
  288. void SceneEditor3D::UpdateGizmoSnapSettings()
  289. {
  290. gizmo3D_->SetSnapTranslationX(userPrefs_->GetSnapTranslationX());
  291. gizmo3D_->SetSnapTranslationY(userPrefs_->GetSnapTranslationY());
  292. gizmo3D_->SetSnapTranslationZ(userPrefs_->GetSnapTranslationZ());
  293. gizmo3D_->SetSnapRotation(userPrefs_->GetSnapRotation());
  294. gizmo3D_->SetSnapScale(userPrefs_->GetSnapScale());
  295. }
  296. void SceneEditor3D::InvokeShortcut(const String& shortcut)
  297. {
  298. if (shortcut == "frameselected")
  299. {
  300. sceneView_->FrameSelection();
  301. return;
  302. }
  303. ResourceEditor::InvokeShortcut(shortcut);
  304. }
  305. void SceneEditor3D::ReparentNode(Node* node, Node* newParent)
  306. {
  307. // can't parent to self
  308. if (node == newParent)
  309. return;
  310. // already parented
  311. Node* oldParent = node->GetParent();
  312. if (oldParent == newParent)
  313. return;
  314. // must be in same scene
  315. if (node->GetScene() != newParent->GetScene())
  316. {
  317. return;
  318. }
  319. // check if dropping on child of ourselves
  320. Node* parent = newParent;
  321. while (parent)
  322. {
  323. if (parent == node)
  324. {
  325. return;
  326. }
  327. parent = parent->GetParent();
  328. }
  329. selection_->AddNode(node, true);
  330. Matrix3x4 transform = node->GetWorldTransform();
  331. newParent->AddChild(node);
  332. node->SetWorldTransform(transform.Translation(), transform.Rotation(), transform.Scale());
  333. scene_->SendEvent(E_SCENEEDITEND);
  334. PODVector<Node*> nodes;
  335. node->GetChildren(nodes, true);
  336. nodes.Insert(0, node);
  337. VariantMap evData;
  338. for (unsigned i = 0; i < nodes.Size(); i++)
  339. {
  340. evData[SceneEditNodeReparent::P_NODE] = nodes[i];
  341. evData[SceneEditNodeReparent::P_ADDED] = false;
  342. scene_->SendEvent(E_SCENEEDITNODEREPARENT, evData);
  343. }
  344. evData[SceneEditNodeReparent::P_NODE] = node;
  345. evData[SceneEditNodeReparent::P_ADDED] = true;
  346. scene_->SendEvent(E_SCENEEDITNODEREPARENT, evData);
  347. selection_->AddNode(node, true);
  348. }
  349. void SceneEditor3D::RegisterSceneEditor()
  350. {
  351. // prune released scene editors
  352. for (Vector<WeakPtr<SceneEditor3D> >::Iterator i = sceneEditors_.Begin(); i != sceneEditors_.End();)
  353. {
  354. if (*i)
  355. {
  356. ++i;
  357. }
  358. else
  359. {
  360. i = sceneEditors_.Erase(i);
  361. }
  362. }
  363. sceneEditors_.Push(WeakPtr<SceneEditor3D>(this));
  364. }
  365. SceneEditor3D* SceneEditor3D::GetSceneEditor(Scene* scene)
  366. {
  367. for (Vector<WeakPtr<SceneEditor3D> >::Iterator i = sceneEditors_.Begin(); i != sceneEditors_.End();)
  368. {
  369. if (*i && scene == (*i)->GetScene())
  370. return *i;
  371. i++;
  372. }
  373. return NULL;
  374. }
  375. void SceneEditor3D::HandleCubemapRenderBegin(StringHash eventType, VariantMap& eventData)
  376. {
  377. cubemapRenderCount_++;
  378. if (cubemapRenderCount_ == 1)
  379. {
  380. // first time
  381. sceneView_->GetDebugRenderer()->SetEnabled(false);
  382. gizmo3D_->Hide();
  383. }
  384. }
  385. void SceneEditor3D::HandleCubemapRenderEnd(StringHash eventType, VariantMap& eventData)
  386. {
  387. cubemapRenderCount_--;
  388. if (cubemapRenderCount_ == 0)
  389. {
  390. // last one
  391. sceneView_->GetDebugRenderer()->SetEnabled(true);
  392. gizmo3D_->Show();
  393. }
  394. }
  395. }