Gizmo3D.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. // Portions Copyright (c) 2008-2015 the Urho3D project.
  2. //
  3. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  4. // LICENSE: Atomic Game Engine Editor and Tools EULA
  5. // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
  6. // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
  7. //
  8. #include <Atomic/Atomic3D/Model.h>
  9. #include <Atomic/Graphics/Material.h>
  10. #include <Atomic/Graphics/Octree.h>
  11. #include <Atomic/Resource/ResourceCache.h>
  12. #include <Atomic/Input/Input.h>
  13. #include "SceneEditor3DEvents.h"
  14. #include "Gizmo3D.h"
  15. namespace AtomicEditor
  16. {
  17. Gizmo3D::Gizmo3D(Context* context) : Object(context),
  18. dragging_(false)
  19. {
  20. ResourceCache* cache = GetSubsystem<ResourceCache>();
  21. gizmoNode_ = new Node(context_);
  22. gizmo_ = gizmoNode_->CreateComponent<StaticModel>();
  23. gizmo_->SetModel(cache->GetResource<Model>("AtomicEditor/Models/Axes.mdl"));
  24. gizmo_->SetEnabled(false);
  25. gizmo_->SetViewMask(0x80000000); // Editor raycasts use viewmask 0x7fffffff
  26. gizmo_->SetOccludee(false);
  27. axisMode_ = AXIS_LOCAL;
  28. gizmoAxisX_.lastSelected_ = false;
  29. gizmoAxisY_.lastSelected_ = false;
  30. gizmoAxisZ_.lastSelected_ = false;
  31. editMode_ = EDIT_MOVE;
  32. lastEditMode_ = EDIT_SELECT;
  33. gizmo_->SetMaterial(0, cache->GetResource<Material>("AtomicEditor/Materials/RedUnlit.xml"));
  34. gizmo_->SetMaterial(1, cache->GetResource<Material>("AtomicEditor/Materials/GreenUnlit.xml"));
  35. gizmo_->SetMaterial(2, cache->GetResource<Material>("AtomicEditor/Materials/BlueUnlit.xml"));
  36. }
  37. Gizmo3D::~Gizmo3D()
  38. {
  39. }
  40. void Gizmo3D::SetView(SceneView3D* view3D)
  41. {
  42. view3D_ = view3D;
  43. scene_ = view3D->GetScene();
  44. camera_ = view3D->GetCameraNode()->GetComponent<Camera>();
  45. assert(camera_.NotNull());
  46. }
  47. void Gizmo3D::Position()
  48. {
  49. Vector3 center(0, 0, 0);
  50. bool containsScene = false;
  51. for (unsigned i = 0; i < editNodes_->Size(); ++i)
  52. {
  53. // Scene's transform should not be edited, so hide gizmo if it is included
  54. if (editNodes_->At(i) == scene_)
  55. {
  56. containsScene = true;
  57. break;
  58. }
  59. center += editNodes_->At(i)->GetWorldPosition();
  60. }
  61. if (editNodes_->Empty() || containsScene)
  62. {
  63. Hide();
  64. return;
  65. }
  66. center /= editNodes_->Size();
  67. gizmoNode_->SetPosition(center);
  68. if (axisMode_ == AXIS_WORLD || editNodes_->Size() > 1)
  69. gizmoNode_->SetRotation(Quaternion());
  70. else
  71. gizmoNode_->SetRotation(editNodes_->At(0)->GetWorldRotation());
  72. ResourceCache* cache = GetSubsystem<ResourceCache>();
  73. if (editMode_ != lastEditMode_)
  74. {
  75. switch (editMode_)
  76. {
  77. case EDIT_MOVE:
  78. gizmo_->SetModel(cache->GetResource<Model>("AtomicEditor/Models/Axes.mdl"));
  79. break;
  80. case EDIT_ROTATE:
  81. gizmo_->SetModel(cache->GetResource<Model>("AtomicEditor/Models/RotateAxes.mdl"));
  82. break;
  83. case EDIT_SCALE:
  84. gizmo_->SetModel(cache->GetResource<Model>("AtomicEditor/Models/ScaleAxes.mdl"));
  85. break;
  86. default:
  87. break;
  88. }
  89. lastEditMode_ = editMode_;
  90. }
  91. bool orbiting = false;
  92. if ((editMode_ != EDIT_SELECT && !orbiting) && !gizmo_->IsEnabled())
  93. Show();
  94. else if ((editMode_ == EDIT_SELECT || orbiting) && gizmo_->IsEnabled())
  95. Hide();
  96. if (gizmo_->IsEnabled())
  97. {
  98. float scale = 0.1f / camera_->GetZoom();
  99. if (camera_->IsOrthographic())
  100. scale *= camera_->GetOrthoSize();
  101. else
  102. scale *= (camera_->GetView() * gizmoNode_->GetPosition()).z_;
  103. gizmoNode_->SetScale(Vector3(scale, scale, scale));
  104. }
  105. }
  106. void Gizmo3D::Update(Vector<Node *> &editNodes)
  107. {
  108. editNodes_ = &editNodes;
  109. Use();
  110. Position();
  111. }
  112. void Gizmo3D::CalculateGizmoAxes()
  113. {
  114. gizmoAxisX_.axisRay_ = Ray(gizmoNode_->GetPosition(), gizmoNode_->GetRotation() * Vector3(1, 0, 0));
  115. gizmoAxisY_.axisRay_ = Ray(gizmoNode_->GetPosition(), gizmoNode_->GetRotation() * Vector3(0, 1, 0));
  116. gizmoAxisZ_.axisRay_ = Ray(gizmoNode_->GetPosition(), gizmoNode_->GetRotation() * Vector3(0, 0, 1));
  117. }
  118. void Gizmo3D::Use()
  119. {
  120. if (gizmo_.Null() || !gizmo_->IsEnabled() || editMode_ == EDIT_SELECT)
  121. {
  122. //StoreGizmoEditActions();
  123. //previousGizmoDrag = false;
  124. return;
  125. }
  126. ResourceCache* cache = GetSubsystem<ResourceCache>();
  127. Input* input = GetSubsystem<Input>();
  128. Ray cameraRay = view3D_->GetCameraRay();
  129. float scale = gizmoNode_->GetScale().x_;
  130. // Recalculate axes only when not left-dragging
  131. bool drag = input->GetMouseButtonDown(MOUSEB_LEFT);// && (Abs(input->GetMouseMoveX()) > 3 || Abs(input->GetMouseMoveY()) > 3);
  132. if (!drag)
  133. {
  134. if (dragging_)
  135. {
  136. VariantMap eventData;
  137. eventData[SceneEditSerializable::P_SERIALIZABLE] = editNodes_->At(0);
  138. eventData[SceneEditSerializable::P_OPERATION] = 1;
  139. scene_->SendEvent(E_SCENEEDITSERIALIZABLE, eventData);
  140. dragging_ = false;
  141. }
  142. CalculateGizmoAxes();
  143. }
  144. gizmoAxisX_.Update(cameraRay, scale, drag, camera_->GetNode());
  145. gizmoAxisY_.Update(cameraRay, scale, drag, camera_->GetNode());
  146. gizmoAxisZ_.Update(cameraRay, scale, drag, camera_->GetNode());
  147. if (!editNodes_->Size() || editNodes_->At(0) == scene_)
  148. {
  149. gizmoAxisX_.selected_ = gizmoAxisY_.selected_ = gizmoAxisZ_.selected_ = false;
  150. // this just forces an update
  151. gizmoAxisX_.lastSelected_ = gizmoAxisY_.lastSelected_ = gizmoAxisZ_.lastSelected_ = true;
  152. }
  153. if (gizmoAxisX_.selected_ != gizmoAxisX_.lastSelected_)
  154. {
  155. gizmo_->SetMaterial(0, cache->GetResource<Material>(
  156. gizmoAxisX_.selected_ ?
  157. "AtomicEditor/Materials/BrightRedUnlit.xml" : "AtomicEditor/Materials/RedUnlit.xml"));
  158. gizmoAxisX_.lastSelected_ = gizmoAxisX_.selected_;
  159. }
  160. if (gizmoAxisY_.selected_ != gizmoAxisY_.lastSelected_)
  161. {
  162. gizmo_->SetMaterial(1, cache->GetResource<Material>(
  163. gizmoAxisY_.selected_ ?
  164. "AtomicEditor/Materials/BrightGreenUnlit.xml" : "AtomicEditor/Materials/GreenUnlit.xml"));
  165. gizmoAxisY_.lastSelected_ = gizmoAxisY_.selected_;
  166. }
  167. if (gizmoAxisZ_.selected_ != gizmoAxisZ_.lastSelected_)
  168. {
  169. gizmo_->SetMaterial(2, cache->GetResource<Material>(
  170. gizmoAxisZ_.selected_ ?
  171. "AtomicEditor/Materials/BrightBlueUnlit.xml" : "AtomicEditor/Materials/BlueUnlit.xml"));
  172. gizmoAxisZ_.lastSelected_ = gizmoAxisZ_.selected_;
  173. }
  174. if (drag && Selected())
  175. Drag();
  176. }
  177. bool Gizmo3D::MoveEditNodes(Vector3 adjust)
  178. {
  179. bool moved = false;
  180. if (adjust.Length() > M_EPSILON)
  181. {
  182. for (unsigned i = 0; i < editNodes_->Size(); ++i)
  183. {
  184. /*
  185. if (moveSnap)
  186. {
  187. float moveStepScaled = moveStep * snapScale;
  188. adjust.x = Floor(adjust.x / moveStepScaled + 0.5) * moveStepScaled;
  189. adjust.y = Floor(adjust.y / moveStepScaled + 0.5) * moveStepScaled;
  190. adjust.z = Floor(adjust.z / moveStepScaled + 0.5) * moveStepScaled;
  191. }
  192. */
  193. Node* node = editNodes_->At(i);
  194. Vector3 nodeAdjust = adjust;
  195. if (axisMode_ == AXIS_LOCAL && editNodes_->Size() == 1)
  196. nodeAdjust = node->GetWorldRotation() * nodeAdjust;
  197. Vector3 worldPos = node->GetWorldPosition();
  198. Vector3 oldPos = node->GetPosition();
  199. worldPos += nodeAdjust;
  200. if (!node->GetParent())
  201. node->SetPosition(worldPos);
  202. else
  203. node->SetPosition(node->GetParent()->WorldToLocal(worldPos));
  204. if (node->GetPosition() != oldPos)
  205. moved = true;
  206. }
  207. }
  208. return moved;
  209. }
  210. bool Gizmo3D::RotateEditNodes(Vector3 adjust)
  211. {
  212. bool moved = false;
  213. /*
  214. if (rotateSnap)
  215. {
  216. float rotateStepScaled = rotateStep * snapScale;
  217. adjust.x = Floor(adjust.x / rotateStepScaled + 0.5) * rotateStepScaled;
  218. adjust.y = Floor(adjust.y / rotateStepScaled + 0.5) * rotateStepScaled;
  219. adjust.z = Floor(adjust.z / rotateStepScaled + 0.5) * rotateStepScaled;
  220. }
  221. */
  222. if (adjust.Length() > M_EPSILON)
  223. {
  224. moved = true;
  225. for (unsigned i = 0; i < editNodes_->Size(); ++i)
  226. {
  227. Node* node = editNodes_->At(i);
  228. Quaternion rotQuat(adjust.x_, adjust.y_, adjust.z_);
  229. if (axisMode_ == AXIS_LOCAL && editNodes_->Size() == 1)
  230. node->SetRotation(node->GetRotation() * rotQuat);
  231. else
  232. {
  233. Vector3 offset = node->GetWorldPosition() - gizmoAxisX_.axisRay_.origin_;
  234. if (node->GetParent() && node->GetParent()->GetWorldRotation() != Quaternion(1, 0, 0, 0))
  235. rotQuat = node->GetParent()->GetWorldRotation().Inverse() * rotQuat * node->GetParent()->GetWorldRotation();
  236. node->SetRotation(rotQuat * node->GetRotation());
  237. Vector3 newPosition = gizmoAxisX_.axisRay_.origin_ + rotQuat * offset;
  238. if (node->GetParent())
  239. newPosition = node->GetParent()->WorldToLocal(newPosition);
  240. node->SetPosition(newPosition);
  241. }
  242. }
  243. }
  244. return moved;
  245. }
  246. bool Gizmo3D::ScaleEditNodes(Vector3 adjust)
  247. {
  248. bool moved = false;
  249. if (adjust.Length() > M_EPSILON)
  250. {
  251. for (unsigned i = 0; i < editNodes_->Size(); ++i)
  252. {
  253. Node* node = editNodes_->At(i);
  254. Vector3 scale = node->GetScale();
  255. Vector3 oldScale = scale;
  256. if (true)//!scaleSnap)
  257. scale += adjust;
  258. else
  259. {
  260. /*
  261. float scaleStepScaled = scaleStep * snapScale;
  262. if (adjust.x != 0)
  263. {
  264. scale.x += adjust.x * scaleStepScaled;
  265. scale.x = Floor(scale.x / scaleStepScaled + 0.5) * scaleStepScaled;
  266. }
  267. if (adjust.y != 0)
  268. {
  269. scale.y += adjust.y * scaleStepScaled;
  270. scale.y = Floor(scale.y / scaleStepScaled + 0.5) * scaleStepScaled;
  271. }
  272. if (adjust.z != 0)
  273. {
  274. scale.z += adjust.z * scaleStepScaled;
  275. scale.z = Floor(scale.z / scaleStepScaled + 0.5) * scaleStepScaled;
  276. }
  277. */
  278. }
  279. if (scale != oldScale)
  280. moved = true;
  281. node->SetScale(scale);
  282. }
  283. }
  284. return moved;
  285. }
  286. void Gizmo3D::Moved()
  287. {
  288. gizmoAxisX_.Moved();
  289. gizmoAxisY_.Moved();
  290. gizmoAxisZ_.Moved();
  291. SendEvent(E_GIZMOMOVED);
  292. }
  293. void Gizmo3D::Drag()
  294. {
  295. bool moved = false;
  296. dragging_ = true;
  297. float scale = gizmoNode_->GetScale().x_;
  298. if (editMode_ == EDIT_MOVE)
  299. {
  300. Vector3 adjust(0, 0, 0);
  301. if (gizmoAxisX_.selected_)
  302. adjust += Vector3(1, 0, 0) * (gizmoAxisX_.t_ - gizmoAxisX_.lastT_);
  303. if (gizmoAxisY_.selected_)
  304. adjust += Vector3(0, 1, 0) * (gizmoAxisY_.t_ - gizmoAxisY_.lastT_);
  305. if (gizmoAxisZ_.selected_)
  306. adjust += Vector3(0, 0, 1) * (gizmoAxisZ_.t_ - gizmoAxisZ_.lastT_);
  307. moved = MoveEditNodes(adjust);
  308. }
  309. else if (editMode_ == EDIT_ROTATE)
  310. {
  311. const float rotSensitivity = 50.0;
  312. Vector3 adjust(0, 0, 0);
  313. if (gizmoAxisX_.selected_)
  314. adjust.x_ = (gizmoAxisX_.d_ - gizmoAxisX_.lastD_) * rotSensitivity / scale;
  315. if (gizmoAxisY_.selected_)
  316. adjust.y_ = -(gizmoAxisY_.d_ - gizmoAxisY_.lastD_) * rotSensitivity / scale;
  317. if (gizmoAxisZ_.selected_)
  318. adjust.z_ = (gizmoAxisZ_.d_ - gizmoAxisZ_.lastD_) * rotSensitivity / scale;
  319. moved = RotateEditNodes(adjust);
  320. }
  321. else if (editMode_ == EDIT_SCALE)
  322. {
  323. Vector3 adjust(0, 0, 0);
  324. if (gizmoAxisX_.selected_)
  325. adjust += Vector3(1, 0, 0) * (gizmoAxisX_.t_ - gizmoAxisX_.lastT_);
  326. if (gizmoAxisY_.selected_)
  327. adjust += Vector3(0, 1, 0) * (gizmoAxisY_.t_ - gizmoAxisY_.lastT_);
  328. if (gizmoAxisZ_.selected_)
  329. adjust += Vector3(0, 0, 1) * (gizmoAxisZ_.t_ - gizmoAxisZ_.lastT_);
  330. // Special handling for uniform scale: use the unmodified X-axis movement only
  331. if (editMode_ == EDIT_SCALE && gizmoAxisX_.selected_ && gizmoAxisY_.selected_ && gizmoAxisZ_.selected_)
  332. {
  333. float x = gizmoAxisX_.t_ - gizmoAxisX_.lastT_;
  334. adjust = Vector3(x, x, x);
  335. }
  336. moved = ScaleEditNodes(adjust);
  337. }
  338. if (moved)
  339. {
  340. Moved();
  341. //UpdateNodeAttributes();
  342. //needGizmoUndo = true;
  343. }
  344. }
  345. void Gizmo3D::SetAxisMode(AxisMode mode)
  346. {
  347. axisMode_ = mode;
  348. }
  349. void Gizmo3D::SetEditMode(EditMode mode)
  350. {
  351. editMode_ = mode;
  352. }
  353. void Gizmo3D::Hide()
  354. {
  355. gizmoAxisX_.selected_ = gizmoAxisY_.selected_ = gizmoAxisZ_.selected_ = false;
  356. gizmo_->SetEnabled(false);
  357. }
  358. void Gizmo3D::Show()
  359. {
  360. if (scene_.Null())
  361. return;
  362. gizmo_->SetEnabled(true);
  363. Octree* octree = scene_->GetComponent<Octree>();
  364. if (!octree)
  365. return;
  366. octree->AddManualDrawable(gizmo_);
  367. }
  368. }