TransformGizmo.cpp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505
  1. /*
  2. Copyright (C) 2013 by Ivan Safrin
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. THE SOFTWARE.
  18. */
  19. #include "polycode/ide/TransformGizmo.h"
  20. #include <cmath>
  21. extern UIGlobalMenu *globalMenu;
  22. TransformGrips::TransformGrips(Core *core, ResourcePool *pool) : UIElement(core) {
  23. mainRect = new UIRect(core, pool, 1.0, 1.0);
  24. mainRect->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
  25. mainRect->color.setColor(0.0, 0.5, 1.0, 0.2);
  26. grips.push_back(mainRect);
  27. transformTL = new UIImage(core, pool, "spriteEditor/transform_corner.png", 8, 8);
  28. grips.push_back(transformTL);
  29. transformT = new UIImage(core, pool, "spriteEditor/transform_corner.png", 8, 8);
  30. grips.push_back(transformT);
  31. transformTR = new UIImage(core, pool, "spriteEditor/transform_corner.png", 8, 8);
  32. grips.push_back(transformTR);
  33. transformL = new UIImage(core, pool, "spriteEditor/transform_corner.png", 8, 8);
  34. grips.push_back(transformL);
  35. transformR = new UIImage(core, pool, "spriteEditor/transform_corner.png", 8, 8);
  36. grips.push_back(transformR);
  37. transformBL = new UIImage(core, pool, "spriteEditor/transform_corner.png", 8, 8);
  38. grips.push_back(transformBL);
  39. transformB = new UIImage(core, pool, "spriteEditor/transform_corner.png", 8, 8);
  40. grips.push_back(transformB);
  41. transformBR = new UIImage(core, pool, "spriteEditor/transform_corner.png", 8, 8);
  42. grips.push_back(transformBR);
  43. transformOffset = new UIImage(core, pool, "spriteEditor/transform_offset.png", 12, 12);
  44. grips.push_back(transformOffset);
  45. for(int i=0; i < grips.size(); i++) {
  46. addChild(grips[i]);
  47. if(grips[i] != mainRect) {
  48. grips[i]->setAnchorPoint(Vector3());
  49. }
  50. grips[i]->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
  51. grips[i]->addEventListener(this, InputEvent::EVENT_MOUSEUP);
  52. grips[i]->addEventListener(this, InputEvent::EVENT_MOUSEUP_OUTSIDE);
  53. grips[i]->blockMouseInput = true;
  54. }
  55. core->getInput()->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);
  56. transforming = false;
  57. movingTransform = NULL;
  58. }
  59. Polycode::Rectangle TransformGrips::getGripRectangle() {
  60. return gripRectangle;
  61. }
  62. void TransformGrips::handleEvent(Event *event) {
  63. if(event->getDispatcher() == core->getInput()) {
  64. if(transforming) {
  65. Vector2 newMouse = core->getInput()->getMousePosition();
  66. if(movingTransform == mainRect) {
  67. gripRectangle.x += newMouse.x - mouseBase.x;
  68. gripRectangle.y += newMouse.y - mouseBase.y;
  69. } else if(movingTransform == transformTL) {
  70. gripRectangle.x += newMouse.x - mouseBase.x;
  71. gripRectangle.y += newMouse.y - mouseBase.y;
  72. gripRectangle.w -= newMouse.x - mouseBase.x;
  73. gripRectangle.h -= newMouse.y - mouseBase.y;
  74. } else if(movingTransform == transformTR) {
  75. gripRectangle.y += newMouse.y - mouseBase.y;
  76. gripRectangle.w += newMouse.x - mouseBase.x;
  77. gripRectangle.h -= newMouse.y - mouseBase.y;
  78. } else if(movingTransform == transformT) {
  79. gripRectangle.y += newMouse.y - mouseBase.y;
  80. gripRectangle.h -= newMouse.y - mouseBase.y;
  81. } else if(movingTransform == transformL) {
  82. gripRectangle.x += newMouse.x - mouseBase.x;
  83. gripRectangle.w -= newMouse.x - mouseBase.x;
  84. } else if(movingTransform == transformR) {
  85. gripRectangle.w += newMouse.x - mouseBase.x;
  86. } else if(movingTransform == transformBL) {
  87. gripRectangle.x += newMouse.x - mouseBase.x;
  88. gripRectangle.w -= newMouse.x - mouseBase.x;
  89. gripRectangle.h += newMouse.y - mouseBase.y;
  90. } else if(movingTransform == transformBR) {
  91. gripRectangle.w += newMouse.x - mouseBase.x;
  92. gripRectangle.h += newMouse.y - mouseBase.y;
  93. } else if(movingTransform == transformB) {
  94. gripRectangle.h += newMouse.y - mouseBase.y;
  95. } else if(movingTransform == transformOffset) {
  96. anchorPoint.x += (newMouse.x - mouseBase.x) / gripRectangle.w;
  97. anchorPoint.y += (newMouse.y - mouseBase.y) / gripRectangle.h;
  98. }
  99. mouseBase = newMouse;
  100. dispatchEvent(new Event(), Event::CHANGE_EVENT);
  101. }
  102. } else {
  103. if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
  104. movingTransform = (UIImage*) event->getDispatcher();
  105. transforming = true;
  106. mouseBase = core->getInput()->getMousePosition();
  107. } else {
  108. transforming = false;
  109. }
  110. }
  111. }
  112. Vector2 TransformGrips::getAnchorPoint() {
  113. return anchorPoint;
  114. }
  115. TransformGrips::~TransformGrips() {
  116. core->getInput()->removeAllHandlersForListener(this);
  117. }
  118. void TransformGrips::setGripRectangle(Polycode::Rectangle rectangle, Vector2 offset) {
  119. mainRect->setPosition(rectangle.x, rectangle.y);
  120. mainRect->Resize(rectangle.w, rectangle.h);
  121. transformTL->setPosition(rectangle.x, rectangle.y);
  122. transformT->setPosition(rectangle.x + (rectangle.w * 0.5), rectangle.y);
  123. transformTR->setPosition(rectangle.x + (rectangle.w), rectangle.y);
  124. transformL->setPosition(rectangle.x, rectangle.y +(rectangle.h * 0.5));
  125. transformR->setPosition(rectangle.x + (rectangle.w), rectangle.y+(rectangle.h * 0.5));
  126. transformBL->setPosition(rectangle.x, rectangle.y+rectangle.h);
  127. transformB->setPosition(rectangle.x + (rectangle.w * 0.5), rectangle.y+rectangle.h);
  128. transformBR->setPosition(rectangle.x+rectangle.w, rectangle.y+rectangle.h);
  129. transformOffset->setPosition(rectangle.x + (rectangle.w * 0.5) + (offset.x * rectangle.w), rectangle.y + (rectangle.h * 0.5) + (offset.y * rectangle.h));
  130. gripRectangle = rectangle;
  131. anchorPoint = offset;
  132. }
  133. TrasnformGizmoEvent::TrasnformGizmoEvent(int mode) : Event() {
  134. this->mode = mode;
  135. this->eventCode = eventCode;
  136. eventType = "TrasnformGizmoEvent";
  137. }
  138. TransformGizmoMenu::TransformGizmoMenu(Core *core, ResourcePool *pool, TransformGizmo *gizmo) : UIElement(core) {
  139. processInputEvents = true;
  140. this->gizmo = gizmo;
  141. transformSelector = new UIIconSelector(core, pool);
  142. addChild(transformSelector);
  143. transformSelector->addIcon("entityEditor/move_gizmo.png");
  144. transformSelector->addIcon("entityEditor/scale_gizmo.png");
  145. transformSelector->addIcon("entityEditor/rotate_gizmo.png");
  146. transformSelector->setPosition(4, 3.0);
  147. transformSelector->addEventListener(this, UIEvent::SELECT_EVENT);
  148. orientationCombo = new UIComboBox(core, pool, globalMenu, 100);
  149. orientationCombo->addComboItem("Global");
  150. orientationCombo->addComboItem("Local");
  151. orientationCombo->setSelectedIndex(0);
  152. addChild(orientationCombo);
  153. orientationCombo->setPosition(100, 2);
  154. orientationCombo->addEventListener(this, UIEvent::CHANGE_EVENT);
  155. centerSelector = new UIIconSelector(core, pool);
  156. addChild(centerSelector);
  157. centerSelector->addIcon("entityEditor/median_center.png");
  158. centerSelector->addIcon("entityEditor/individual_centers.png");
  159. centerSelector->setPosition(210, 3.0);
  160. centerSelector->addEventListener(this, UIEvent::SELECT_EVENT);
  161. }
  162. void TransformGizmoMenu::handleEvent(Event *event) {
  163. if(event->getDispatcher() == transformSelector) {
  164. switch(transformSelector->getSelectedIndex()) {
  165. case 0:
  166. gizmo->setTransformMode(TransformGizmo::TRANSFORM_MOVE);
  167. break;
  168. case 1:
  169. gizmo->setTransformMode(TransformGizmo::TRANSFORM_SCALE);
  170. break;
  171. case 2:
  172. gizmo->setTransformMode(TransformGizmo::TRANSFORM_ROTATE);
  173. break;
  174. }
  175. } else if(event->getDispatcher() == orientationCombo) {
  176. gizmo->setTransformOrientation(orientationCombo->getSelectedIndex());
  177. } else if(event->getDispatcher() == centerSelector) {
  178. if(centerSelector->getSelectedIndex() == 0) {
  179. gizmo->setCenterMode(TransformGizmo::CENTER_MODE_MEDIAN);
  180. } else {
  181. gizmo->setCenterMode(TransformGizmo::CENTER_MODE_INDIVIDUAL);
  182. }
  183. }
  184. }
  185. TransformGizmoMenu::~TransformGizmoMenu() {
  186. }
  187. void TransformGizmo::setCenterMode(int centerMode) {
  188. this->centerMode = centerMode;
  189. }
  190. void TransformGizmo::toggleOrientation() {
  191. if(startingOrientation == -1)
  192. startingOrientation = orientation;
  193. if(orientation == ORIENTATION_GLOBAL)
  194. orientation = ORIENTATION_LOCAL;
  195. else if(orientation == ORIENTATION_LOCAL)
  196. orientation = ORIENTATION_GLOBAL;
  197. }
  198. TransformGizmo::TransformGizmo(Core *core, ResourcePool *pool, Scene *targetScene, Camera *targetCamera) : core(core) {
  199. processInputEvents = true;
  200. orientation = ORIENTATION_GLOBAL;
  201. startingOrientation = -1;
  202. centerMode = CENTER_MODE_MEDIAN;
  203. enableGizmo = true;
  204. firstMove = true;
  205. snapEnabled = false;
  206. snapSize = 1.0;
  207. this->targetScene = targetScene;
  208. this->targetCamera = targetCamera;
  209. ScenePrimitive *centerCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 0.3, 0.3, 16);
  210. centerCircle->setColor(0.7, 0.7, 0.7, 1.0);
  211. centerCircle->depthTest = false;
  212. centerCircle->billboardMode = true;
  213. addChild(centerCircle);
  214. centerCircle->setLineWidth(core->getRenderer()->getBackingResolutionScaleX());
  215. centerCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
  216. trasnformDecorators = new Entity();
  217. addChild(trasnformDecorators);
  218. scaleDecorators = new Entity();
  219. addChild(scaleDecorators);
  220. transformAndScaleLines = new Entity();
  221. addChild(transformAndScaleLines);
  222. rotateDectorators = new Entity();
  223. addChild(rotateDectorators);
  224. yLine = new SceneMesh();
  225. MeshGeometry yLineGeometry;
  226. yLineGeometry.meshType = MeshGeometry::LINE_MESH;
  227. yLineGeometry.addVertex(0.0, 0.0, 0.0);
  228. yLineGeometry.addVertex(0.0, 0.75, 0.0);
  229. yLine->getMesh()->addSubmesh(yLineGeometry);
  230. yLine->setMaterial(pool->getMaterial("UnlitUntextured"));
  231. yLine->depthTest = false;
  232. yLine->color.setColorHexFromString(TRANSGIZMO_Y_COLOR);
  233. yLine->setLocalBoundingBox(yLine->getMesh()->calculateBBox());
  234. yLine->setLineWidth(core->getRenderer()->getBackingResolutionScaleX() * 2.0);
  235. transformAndScaleLines->addChild(yLine);
  236. yLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
  237. yLine->setForceMaterial(true);
  238. xLine = new SceneMesh();
  239. MeshGeometry xLineGeometry;
  240. xLineGeometry.meshType = MeshGeometry::LINE_MESH;
  241. xLineGeometry.addVertex(0.0, 0.0, 0.0);
  242. xLineGeometry.addVertex(0.75, 0.0, 0.0);
  243. xLine->getMesh()->addSubmesh(xLineGeometry);
  244. xLine->setMaterial(pool->getMaterial("UnlitUntextured"));
  245. xLine->depthTest = false;
  246. xLine->color.setColorHexFromString(TRANSGIZMO_X_COLOR);
  247. xLine->setLocalBoundingBox(xLine->getMesh()->calculateBBox());
  248. xLine->setLineWidth(core->getRenderer()->getBackingResolutionScaleX() * 2.0);
  249. transformAndScaleLines->addChild(xLine);
  250. xLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
  251. xLine->setForceMaterial(true);
  252. zLine = new SceneMesh();
  253. MeshGeometry zLineGeometry;
  254. zLineGeometry.meshType = MeshGeometry::LINE_MESH;
  255. zLineGeometry.addVertex(0.0, 0.0, 0.0);
  256. zLineGeometry.addVertex(0.00, 0.0, 0.75);
  257. zLine->getMesh()->addSubmesh(zLineGeometry);
  258. zLine->depthTest = false;
  259. zLine->color.setColorHexFromString(TRANSGIZMO_Z_COLOR);
  260. zLine->setLocalBoundingBox(zLine->getMesh()->calculateBBox());
  261. zLine->setLineWidth(core->getRenderer()->getBackingResolutionScaleX() * 2.0);
  262. transformAndScaleLines->addChild(zLine);
  263. zLine->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
  264. zLine->setForceMaterial(true);
  265. zLine->setMaterial(pool->getMaterial("UnlitUntextured"));
  266. // MOVE
  267. yArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
  268. yArrow->color.setColorHexFromString(TRANSGIZMO_Y_COLOR);
  269. yArrow->setPosition(0.0, 0.75, 0.0);
  270. yArrow->depthTest = false;
  271. trasnformDecorators->addChild(yArrow);
  272. yArrow->setForceMaterial(true);
  273. yArrow->setMaterial(pool->getMaterial("UnlitUntextured"));
  274. xArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
  275. xArrow->color.setColorHexFromString(TRANSGIZMO_X_COLOR);
  276. xArrow->setPosition(0.75, 0.0, 0.0);
  277. xArrow->Roll(-90);
  278. xArrow->depthTest = false;
  279. trasnformDecorators->addChild(xArrow);
  280. xArrow->setForceMaterial(true);
  281. xArrow->setMaterial(pool->getMaterial("UnlitUntextured"));
  282. zArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
  283. zArrow->color.setColorHexFromString(TRANSGIZMO_Z_COLOR);
  284. zArrow->setPosition(0.0, 0.0, 0.75);
  285. zArrow->Pitch(90);
  286. zArrow->depthTest = false;
  287. trasnformDecorators->addChild(zArrow);
  288. zArrow->setForceMaterial(true);
  289. zArrow->setMaterial(pool->getMaterial("UnlitUntextured"));
  290. // SCALE
  291. yBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.08, 0.08, 0.08);
  292. yBox->color.setColorHexFromString(TRANSGIZMO_Y_COLOR);
  293. yBox->setPosition(0.0, 0.75, 0.0);
  294. yBox->depthTest = false;
  295. scaleDecorators->addChild(yBox);
  296. yBox->setForceMaterial(true);
  297. yBox->setMaterial(pool->getMaterial("UnlitUntextured"));
  298. xBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.08, 0.08, 0.08);
  299. xBox->color.setColorHexFromString(TRANSGIZMO_X_COLOR);
  300. xBox->setPosition(0.75, 0.0, 0.0);
  301. xBox->Roll(-90);
  302. xBox->depthTest = false;
  303. scaleDecorators->addChild(xBox);
  304. xBox->setForceMaterial(true);
  305. xBox->setMaterial(pool->getMaterial("UnlitUntextured"));
  306. zBox = new ScenePrimitive(ScenePrimitive::TYPE_BOX, 0.08, 0.08, 0.08);
  307. zBox->color.setColorHexFromString(TRANSGIZMO_Z_COLOR);
  308. zBox->setPosition(0.0, 0.0, 0.75);
  309. zBox->Pitch(90);
  310. zBox->depthTest = false;
  311. scaleDecorators->addChild(zBox);
  312. zBox->setForceMaterial(true);
  313. zBox->setMaterial(pool->getMaterial("UnlitUntextured"));
  314. // ROTATE
  315. bgCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 2.6, 2.6, 32);
  316. bgCircle->setColor(0.0, 0.0, 0.0, 1.0);
  317. bgCircle->depthTest = false;
  318. // bgCircle->billboardMode = true;
  319. //rotateDectorators->addChild(bgCircle);
  320. bgCircle->setLineWidth(core->getRenderer()->getBackingResolutionScaleX());
  321. bgCircle->setForceMaterial(true);
  322. bgCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
  323. bgCircle->setMaterial(pool->getMaterial("UnlitUntextured"));
  324. outerCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 3.0, 3.0, 32);
  325. outerCircle->setColor(1.0, 1.0, 1.0, 1.0);
  326. outerCircle->depthTest = false;
  327. outerCircle->billboardMode = true;
  328. rotateDectorators->addChild(outerCircle);
  329. outerCircle->setLineWidth(core->getRenderer()->getBackingResolutionScaleX() * 2.0);
  330. outerCircle->setForceMaterial(true);
  331. outerCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
  332. outerCircle->setMaterial(pool->getMaterial("UnlitUntextured"));
  333. pitchCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 1.55, 1.55, 64);
  334. pitchCircle->color.setColorHexFromString(TRANSGIZMO_X_COLOR);
  335. pitchCircle->depthTest = false;
  336. pitchCircle->Yaw(90);
  337. rotateDectorators->addChild(pitchCircle);
  338. pitchCircle->setMaterial(pool->getMaterial("OneSidedLine"));
  339. pitchCircle->setLineWidth(core->getRenderer()->getBackingResolutionScaleX() * 2.0);
  340. pitchCircle->setForceMaterial(true);
  341. pitchCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
  342. yawCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 1.65, 1.65, 64);
  343. yawCircle->color.setColorHexFromString(TRANSGIZMO_Y_COLOR);
  344. yawCircle->depthTest = false;
  345. yawCircle->Pitch(90);
  346. rotateDectorators->addChild(yawCircle);
  347. yawCircle->setMaterial(pool->getMaterial("OneSidedLine"));
  348. yawCircle->setLineWidth(core->getRenderer()->getBackingResolutionScaleX()* 2.0);
  349. yawCircle->setForceMaterial(true);
  350. yawCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
  351. rollCircle = new ScenePrimitive(ScenePrimitive::TYPE_LINE_CIRCLE, 1.6, 1.6, 64);
  352. rollCircle->color.setColorHexFromString(TRANSGIZMO_Z_COLOR);
  353. rollCircle->depthTest = false;
  354. rotateDectorators->addChild(rollCircle);
  355. rollCircle->setMaterial(pool->getMaterial("OneSidedLine"));
  356. rollCircle->setLineWidth(core->getRenderer()->getBackingResolutionScaleX()* 2.0);
  357. rollCircle->setForceMaterial(true);
  358. rollCircle->setBlendingMode(Renderer::BLEND_MODE_NORMAL);
  359. rotateDectorators->processInputEvents = true;
  360. //pitchGrip = new ScenePrimitive(ScenePrimitive::TYPE_TORUS, 1.55 * 0.5, 0.05, 16, 3);
  361. pitchGrip = new ScenePrimitive(ScenePrimitive::TYPE_UNCAPPED_CYLINDER, 0.15, 1.55 * 0.5, 16);
  362. pitchGrip->color.setColorHexFromString(TRANSGIZMO_X_COLOR);
  363. pitchGrip->depthTest = false;
  364. pitchGrip->Pitch(90);
  365. pitchGrip->Yaw(90);
  366. rotateDectorators->addChild(pitchGrip);
  367. pitchGrip->processInputEvents = true;
  368. pitchGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
  369. pitchGrip->useGeometryHitDetection = true;
  370. pitchGrip->blockMouseInput = true;
  371. rollGrip = new ScenePrimitive(ScenePrimitive::TYPE_UNCAPPED_CYLINDER, 0.15, 1.6 * 0.5, 16);
  372. rollGrip->color.setColorHexFromString(TRANSGIZMO_Z_COLOR);
  373. rollGrip->depthTest = false;
  374. rollGrip->Pitch(90);
  375. rotateDectorators->addChild(rollGrip);
  376. rollGrip->processInputEvents = true;
  377. rollGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
  378. rollGrip->useGeometryHitDetection = true;
  379. rollGrip->blockMouseInput = true;
  380. yawGrip= new ScenePrimitive(ScenePrimitive::TYPE_UNCAPPED_CYLINDER, 0.15, 1.65 * 0.5, 16);
  381. yawGrip->color.setColorHexFromString(TRANSGIZMO_Y_COLOR);
  382. yawGrip->depthTest = false;
  383. yawGrip->Yaw(90);
  384. rotateDectorators->addChild(yawGrip);
  385. yawGrip->processInputEvents = true;
  386. yawGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
  387. yawGrip->useGeometryHitDetection = true;
  388. yawGrip->blockMouseInput = true;
  389. viewportRotateGripBase = new Entity();
  390. viewportRotateGripBase->processInputEvents = true;
  391. rotateDectorators->addChild(viewportRotateGripBase);
  392. viewportRotateGrip = new ScenePrimitive(ScenePrimitive::TYPE_TORUS, 3.0 * 0.5, 0.08, 16, 3);
  393. viewportRotateGrip->Pitch(90);
  394. viewportRotateGrip->setColor(0.0, 1.0, 0.0, 0.2);
  395. viewportRotateGrip->depthTest = false;
  396. viewportRotateGripBase->addChild(viewportRotateGrip);
  397. viewportRotateGrip->processInputEvents = true;
  398. viewportRotateGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
  399. viewportRotateGrip->useGeometryHitDetection = true;
  400. viewportRotateGrip->blockMouseInput = true;
  401. pitchGrip->visible = false;
  402. yawGrip->visible = false;
  403. rollGrip->visible = false;
  404. viewportRotateGrip->visible = false;
  405. xTransformGrip = new Entity();
  406. xTransformGrip->setLocalBoundingBox(1.3, 0.1, 0.1);
  407. xTransformGrip->depthTest = false;
  408. xTransformGrip->setColor(1.0, 0.0, 0.0, 1.0);
  409. addChild(xTransformGrip);
  410. xTransformGrip->setAnchorPoint(Vector3(-1.0, 0.0, 0.0));
  411. xTransformGrip->processInputEvents = true;
  412. xTransformGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
  413. yTransformGrip = new Entity();
  414. yTransformGrip->setLocalBoundingBox(0.1, 1.3, 0.1);
  415. addChild(yTransformGrip);
  416. yTransformGrip->setAnchorPoint(Vector3(0.0, -1.0, 0.0));
  417. yTransformGrip->processInputEvents = true;
  418. yTransformGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
  419. zTransformGrip = new Entity();
  420. zTransformGrip->setLocalBoundingBox(0.1, 0.1, 1.3);
  421. addChild(zTransformGrip);
  422. zTransformGrip->setAnchorPoint(Vector3(0.0, 0.0, -1.0));
  423. zTransformGrip->processInputEvents = true;
  424. zTransformGrip->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
  425. transforming = false;
  426. mode = TRANSFORM_MOVE;
  427. visible = false;
  428. enabled = false;
  429. coreInput = core->getInput();
  430. coreInput->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);
  431. coreInput->addEventListener(this, InputEvent::EVENT_MOUSEUP);
  432. coreInput->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
  433. coreInput->addEventListener(this, InputEvent::EVENT_KEYDOWN);
  434. gizmoMode = GIZMO_MODE_3D;
  435. setTransformMode(TRANSFORM_MOVE);
  436. }
  437. void TransformGizmo::enableSnap(bool val) {
  438. snapEnabled = val;
  439. }
  440. void TransformGizmo::setSnapSize(Number snapSize) {
  441. this->snapSize = snapSize;
  442. }
  443. void TransformGizmo::setTransformOrientation(int orientation) {
  444. this->orientation = orientation;
  445. }
  446. void TransformGizmo::setTransformPlaneFromView() {
  447. switch(gizmoMode) {
  448. case GIZMO_MODE_2D_X:
  449. setTransformPlane(1.0, 0.0, 0.0, true);
  450. transformConstraint = Vector3(0.0, 1.0, 1.0);
  451. break;
  452. case GIZMO_MODE_2D_Y:
  453. setTransformPlane(0.0, 1.0, 0.0, true);
  454. transformConstraint = Vector3(1.0, 0.0, 1.0);
  455. break;
  456. case GIZMO_MODE_2D_Z:
  457. setTransformPlane(0.0, 0.0, 1.0, true);
  458. transformConstraint = Vector3(1.0, 1.0, 0.0);
  459. break;
  460. default:
  461. Vector3 camVec = targetCamera->getConcatenatedMatrix().getPosition() - getConcatenatedMatrix().getPosition();
  462. camVec.Normalize();
  463. setTransformPlane(camVec.x, camVec.y, camVec.z, true);
  464. break;
  465. }
  466. }
  467. void TransformGizmo::setTransformPlane(Number x, Number y, Number z, bool forceGlobal) {
  468. planeMatrix = getConcatenatedMatrix();
  469. Vector3 localPlane = Vector3(x,y,z);
  470. localTransformPlane = localPlane;
  471. Number planeDistance = 0;
  472. if(forceGlobal) {
  473. transformPlane = localPlane;
  474. transformPlaneDistance = planeDistance;
  475. planeMatrix.identity();
  476. return;
  477. }
  478. transformPlane = planeMatrix.rotateVector(localPlane);
  479. Vector3 planePoint = planeMatrix.getPosition();
  480. transformPlaneDistance = planePoint.dot(transformPlane);
  481. Ray gizmoRay;
  482. gizmoRay.origin = 0.0;
  483. gizmoRay.direction = transformPlane * -1;
  484. gizmoPoint = gizmoRay.planeIntersectPoint(transformPlane, transformPlaneDistance);
  485. gizmoPoint = planeMatrix.Inverse() * gizmoPoint;
  486. }
  487. void TransformGizmo::setTransformPlane(bool useX, bool useY, bool useZ) {
  488. Vector3 xDir = getAnchorAdjustedMatrix().rotateVector(Vector3(1.0, 0.0, 0.0));
  489. Vector3 yDir = getAnchorAdjustedMatrix().rotateVector(Vector3(0.0, 1.0, 0.0));
  490. Vector3 zDir = getAnchorAdjustedMatrix().rotateVector(Vector3(0.0, 0.0, 1.0));
  491. Number xDot = abs(targetCamera->getRotationQuat().applyTo(Vector3(0.0, 0.0, -1.0)).dot(xDir));
  492. Number yDot = abs(targetCamera->getRotationQuat().applyTo(Vector3(0.0, 0.0, -1.0)).dot(yDir));
  493. Number zDot = abs(targetCamera->getRotationQuat().applyTo(Vector3(0.0, 0.0, -1.0)).dot(zDir));
  494. if(useX && !useY && !useZ) {
  495. if(yDot > zDot)
  496. setTransformPlane(0.0, 1.0, 0.0);
  497. else
  498. setTransformPlane(0.0, 0.0, 1.0);
  499. } else if(!useX && useY && !useZ) {
  500. if(xDot > zDot)
  501. setTransformPlane(1.0, 0.0, 0.0);
  502. else
  503. setTransformPlane(0.0, 0.0, 1.0);
  504. } else if(!useX && !useY && useZ) {
  505. if(xDot > yDot)
  506. setTransformPlane(1.0, 0.0, 0.0);
  507. else
  508. setTransformPlane(0.0, 1.0, 0.0);
  509. } else if(!useX) {
  510. setTransformPlane(1.0, 0.0, 0.0);
  511. } else if(!useY) {
  512. setTransformPlane(0.0, 1.0, 0.0);
  513. } else if(!useZ) {
  514. setTransformPlane(0.0, 0.0, 1.0);
  515. }
  516. }
  517. Vector3 TransformGizmo::getTransformPlanePosition() {
  518. Ray ray = targetScene->projectRayFromCameraAndViewportCoordinate(targetCamera, coreInput->getMousePosition());
  519. // hack to fix NaN's in the plane intersect math (sorry)
  520. ray.direction += Vector3(0.00001, 0.00001, 0.00001);
  521. Vector3 ret = ray.planeIntersectPoint(transformPlane, transformPlaneDistance);
  522. return ret;
  523. }
  524. Vector3 TransformGizmo::getPositionAlongAxis() {
  525. Ray ray = Ray(position, rotationQuat.applyTo(transformConstraint));
  526. Ray ray2 = targetScene->projectRayFromCameraAndViewportCoordinate(targetCamera, coreInput->getMousePosition());
  527. Vector3 ret;
  528. ray.closestPointsBetween(ray2, &ret, NULL);
  529. return ret;
  530. }
  531. bool TransformGizmo::isConstrainedToSingleAxis() {
  532. if(transformConstraint.x == 1.0) {
  533. if(transformConstraint.y == 0.0 && transformConstraint.z == 0.0)
  534. return true;
  535. }
  536. if(transformConstraint.y == 1.0) {
  537. if(transformConstraint.x == 0.0 && transformConstraint.z == 0.0)
  538. return true;
  539. }
  540. if(transformConstraint.z == 1.0) {
  541. if(transformConstraint.x == 0.0 && transformConstraint.y == 0.0)
  542. return true;
  543. }
  544. return false;
  545. }
  546. void TransformGizmo::setTransformMode(int newMode) {
  547. transformMode = newMode;
  548. trasnformDecorators->visible = false;
  549. scaleDecorators->visible = false;
  550. transformAndScaleLines->visible = false;
  551. rotateDectorators->visible = false;
  552. xTransformGrip->enabled = false;
  553. yTransformGrip->enabled = false;
  554. zTransformGrip->enabled = false;
  555. pitchGrip->enabled = false;
  556. rollGrip->enabled = false;
  557. yawGrip->enabled = false;
  558. viewportRotateGrip->enabled = false;
  559. xTransformGrip->enabled = false;
  560. yTransformGrip->enabled = false;
  561. zTransformGrip->enabled = false;
  562. mode = newMode;
  563. switch (mode) {
  564. case TRANSFORM_MOVE:
  565. trasnformDecorators->visible = true;
  566. transformAndScaleLines->visible = true;
  567. switch(gizmoMode) {
  568. case GIZMO_MODE_3D:
  569. xTransformGrip->enabled = true;
  570. yTransformGrip->enabled = true;
  571. zTransformGrip->enabled = true;
  572. xArrow->visible = true;
  573. yArrow->visible = true;
  574. zArrow->visible = true;
  575. xLine->visible = true;
  576. yLine->visible = true;
  577. zLine->visible = true;
  578. break;
  579. case GIZMO_MODE_2D_X:
  580. xTransformGrip->enabled = false;
  581. yTransformGrip->enabled = true;
  582. zTransformGrip->enabled = true;
  583. xArrow->visible = false;
  584. yArrow->visible = true;
  585. zArrow->visible = true;
  586. xLine->visible = false;
  587. yLine->visible = true;
  588. zLine->visible = true;
  589. break;
  590. case GIZMO_MODE_2D_Y:
  591. xTransformGrip->enabled = true;
  592. yTransformGrip->enabled = false;
  593. zTransformGrip->enabled = true;
  594. xArrow->visible = true;
  595. yArrow->visible = false;
  596. zArrow->visible = true;
  597. xLine->visible = true;
  598. yLine->visible = false;
  599. zLine->visible = true;
  600. break;
  601. case GIZMO_MODE_2D_Z:
  602. xTransformGrip->enabled = true;
  603. yTransformGrip->enabled = true;
  604. zTransformGrip->enabled = false;
  605. xArrow->visible = true;
  606. yArrow->visible = true;
  607. zArrow->visible = false;
  608. xLine->visible = true;
  609. yLine->visible = true;
  610. zLine->visible = false;
  611. break;
  612. }
  613. break;
  614. case TRANSFORM_SCALE:
  615. scaleDecorators->visible = true;
  616. transformAndScaleLines->visible = true;
  617. switch(gizmoMode) {
  618. case GIZMO_MODE_3D:
  619. xTransformGrip->enabled = true;
  620. yTransformGrip->enabled = true;
  621. zTransformGrip->enabled = true;
  622. xBox->visible = true;
  623. yBox->visible = true;
  624. zBox->visible = true;
  625. xLine->visible = true;
  626. yLine->visible = true;
  627. zLine->visible = true;
  628. break;
  629. case GIZMO_MODE_2D_X:
  630. xTransformGrip->enabled = false;
  631. yTransformGrip->enabled = true;
  632. zTransformGrip->enabled = true;
  633. xBox->visible = false;
  634. yBox->visible = true;
  635. zBox->visible = true;
  636. xLine->visible = false;
  637. yLine->visible = true;
  638. zLine->visible = true;
  639. break;
  640. case GIZMO_MODE_2D_Y:
  641. xTransformGrip->enabled = true;
  642. yTransformGrip->enabled = false;
  643. zTransformGrip->enabled = true;
  644. xBox->visible = true;
  645. yBox->visible = false;
  646. zBox->visible = true;
  647. xLine->visible = true;
  648. yLine->visible = false;
  649. zLine->visible = true;
  650. break;
  651. case GIZMO_MODE_2D_Z:
  652. xTransformGrip->enabled = true;
  653. yTransformGrip->enabled = true;
  654. zTransformGrip->enabled = false;
  655. xBox->visible = true;
  656. yBox->visible = true;
  657. zBox->visible = false;
  658. xLine->visible = true;
  659. yLine->visible = true;
  660. zLine->visible = false;
  661. break;
  662. }
  663. break;
  664. case TRANSFORM_ROTATE:
  665. rotateDectorators->visible = true;
  666. switch(gizmoMode) {
  667. case GIZMO_MODE_3D:
  668. rollGrip->enabled = true;
  669. rollCircle->visible = true;
  670. pitchGrip->enabled = true;
  671. pitchCircle->visible = true;
  672. yawGrip->enabled = true;
  673. yawCircle->visible = true;
  674. viewportRotateGrip->enabled = false;
  675. outerCircle->visible = false;
  676. outerCircle->setColor(1.0, 1.0, 1.0, 1.0);
  677. break;
  678. case GIZMO_MODE_2D_X:
  679. rollGrip->enabled = false;
  680. rollCircle->visible = false;
  681. pitchGrip->enabled = false;
  682. pitchCircle->visible = false;
  683. yawGrip->enabled = false;
  684. yawCircle->visible = false;
  685. viewportRotateGrip->enabled = true;
  686. outerCircle->visible = true;
  687. outerCircle->setColor(1.0, 0.0, 0.0, 1.0);
  688. viewportRotateGrip->setYaw(90);
  689. viewportRotateGrip->setPitch(90);
  690. break;
  691. case GIZMO_MODE_2D_Y:
  692. rollGrip->enabled = false;
  693. rollCircle->visible = false;
  694. pitchGrip->enabled = false;
  695. pitchCircle->visible = false;
  696. yawGrip->enabled = false;
  697. yawCircle->visible = false;
  698. viewportRotateGrip->enabled = true;
  699. outerCircle->visible = true;
  700. outerCircle->setColor(0.0, 1.0, 0.0, 1.0);
  701. viewportRotateGrip->setPitch(0);
  702. viewportRotateGrip->setYaw(0);
  703. break;
  704. case GIZMO_MODE_2D_Z:
  705. rollGrip->enabled = false;
  706. rollCircle->visible = false;
  707. pitchGrip->enabled = false;
  708. pitchCircle->visible = false;
  709. yawGrip->enabled = false;
  710. yawCircle->visible = false;
  711. viewportRotateGrip->enabled = true;
  712. outerCircle->visible = true;
  713. outerCircle->setColor(0.0, 0.0, 1.0, 1.0);
  714. viewportRotateGrip->setPitch(90);
  715. viewportRotateGrip->setYaw(0);
  716. break;
  717. }
  718. break;
  719. default:
  720. assert(false); // invalid mode
  721. break;
  722. }
  723. }
  724. void TransformGizmo::setTransformSelection(std::vector<Entity*> selectedEntities) {
  725. entityPositions.clear();
  726. this->selectedEntities = selectedEntities;
  727. if(selectedEntities.size() > 0) {
  728. visible = true;
  729. enabled = true;
  730. Vector3 centerPoint;
  731. for(int i=0; i < selectedEntities.size(); i++) {
  732. centerPoint += selectedEntities[i]->getConcatenatedMatrix().getPosition();
  733. entityPositions.push_back(selectedEntities[i]->getPosition());
  734. }
  735. centerPoint = centerPoint / selectedEntities.size();
  736. setPosition(centerPoint);
  737. } else {
  738. visible = false;
  739. enabled = false;
  740. }
  741. }
  742. void TransformGizmo::resetTransform() {
  743. if(firstMove) return;
  744. for(int i=0; i < selectedEntities.size(); i++) {
  745. selectedEntities[i]->setPosition(oldPosition[i]);
  746. entityPositions[i] = oldPosition[i];
  747. selectedEntities[i]->setScale(oldScale[i]);
  748. selectedEntities[i]->setRotationByQuaternion(oldRotation[i]);
  749. }
  750. if(isConstrainedToSingleAxis())
  751. startingPoint = getPositionAlongAxis();
  752. else
  753. startingPoint = getTransformPlanePosition();
  754. }
  755. void TransformGizmo::transformSelectedEntities(const Vector3 &move, const Vector3 &scale, Number rotate) {
  756. if(firstMove) {
  757. firstMove = false;
  758. dispatchEvent(new TrasnformGizmoEvent(mode), Event::SELECT_EVENT);
  759. oldPosition.clear();
  760. oldScale.clear();
  761. oldRotation.clear();
  762. for(int i=0; i < selectedEntities.size(); i++) {
  763. oldPosition.push_back(selectedEntities[i]->getPosition());
  764. oldScale.push_back(selectedEntities[i]->getScale());
  765. oldRotation.push_back(selectedEntities[i]->getRotationQuat());
  766. }
  767. }
  768. Vector3 globalCenter = getConcatenatedMatrix().getPosition();
  769. for(int i=0; i < selectedEntities.size(); i++) {
  770. if((orientation == ORIENTATION_GLOBAL && mode != TRANSFORM_SCALE_VIEW)) {//|| (ORIENTATION_LOCAL && mode == TRANSFORM_MOVE_VIEW)) {
  771. entityPositions[i] += move;
  772. Quaternion q;
  773. Quaternion currentRotation = selectedEntities[i]->getRotationQuat();
  774. Vector3 axisVector = transformConstraint;
  775. axisVector = currentRotation.Inverse().applyTo(axisVector);
  776. axisVector.Normalize();
  777. q.fromAngleAxis(rotate, axisVector);
  778. Vector3 newScale = selectedEntities[i]->getRotationQuat().applyTo(scale);
  779. newScale.x = fabs(newScale.x);
  780. newScale.y = fabs(newScale.y);
  781. newScale.z = fabs(newScale.z);
  782. if(scale.x < 0 || scale.y < 0 || scale.z < 0) {
  783. newScale = newScale * -1.0;
  784. }
  785. if(centerMode == CENTER_MODE_MEDIAN) {
  786. Vector3 globalPosition = selectedEntities[i]->getConcatenatedMatrix().getPosition();
  787. Quaternion tQ;
  788. tQ.fromAngleAxis(rotate, transformConstraint);
  789. Vector3 trans = globalCenter + tQ.applyTo(globalPosition-globalCenter) - globalPosition;
  790. globalPosition += trans;
  791. selectedEntities[i]->setPosition(globalPosition - selectedEntities[i]->getParentEntity()->getConcatenatedMatrix().getPosition());
  792. selectedEntities[i]->setRotationByQuaternion(currentRotation * q);
  793. if(move.length() == 0.0) {
  794. entityPositions[i] = selectedEntities[i]->getPosition();
  795. }
  796. selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+newScale));
  797. if(newScale.length() > 0.0) {
  798. Vector3 scalePosition;
  799. scalePosition.x = globalPosition.x + ((globalPosition.x - globalCenter.x) * newScale.x);
  800. scalePosition.y = globalPosition.y + ((globalPosition.y - globalCenter.y) * newScale.y);
  801. scalePosition.z = globalPosition.z + ((globalPosition.z - globalCenter.z) * newScale.z);
  802. scalePosition = selectedEntities[i]->getParentEntity()->getConcatenatedMatrix().Inverse().transpose() * scalePosition;
  803. selectedEntities[i]->setPosition(scalePosition);
  804. if(move.length() == 0.0) {
  805. entityPositions[i] = selectedEntities[i]->getPosition();
  806. }
  807. }
  808. } else {
  809. selectedEntities[i]->setRotationByQuaternion(currentRotation * q);
  810. if(mode == TRANSFORM_SCALE_VIEW)
  811. selectedEntities[i]->setScale(oldScale[i] * scale);
  812. else
  813. selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+newScale));
  814. }
  815. } else {
  816. entityPositions[i] += getRotationQuat().applyTo(move);
  817. Quaternion q;
  818. Quaternion currentRotation = selectedEntities[i]->getRotationQuat();
  819. Vector3 axisVector = transformConstraint;
  820. // always global in the 2d view
  821. if(gizmoMode != GIZMO_MODE_3D) {
  822. axisVector = currentRotation.Inverse().applyTo(axisVector);
  823. }
  824. axisVector.Normalize();
  825. q.fromAngleAxis(rotate, axisVector);
  826. if(centerMode == CENTER_MODE_MEDIAN) {
  827. Vector3 globalPosition = selectedEntities[i]->getConcatenatedMatrix().getPosition();
  828. Quaternion tQ;
  829. tQ.fromAngleAxis(rotate, getRotationQuat().applyTo(axisVector));
  830. Vector3 trans = globalCenter + tQ.applyTo(globalPosition-globalCenter) - globalPosition;
  831. globalPosition += trans;
  832. selectedEntities[i]->setPosition(globalPosition - selectedEntities[i]->getParentEntity()->getConcatenatedMatrix().getPosition());
  833. selectedEntities[i]->setRotationByQuaternion(currentRotation * q);
  834. if(move.length() == 0.0) {
  835. entityPositions[i] = selectedEntities[i]->getPosition();
  836. }
  837. if(mode == TRANSFORM_SCALE_VIEW)
  838. selectedEntities[i]->setScale(oldScale[i] * scale);
  839. else
  840. selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+scale));
  841. if(scale.length() > 0.0) {
  842. Vector3 scalePosition;
  843. scalePosition.x = globalPosition.x + ((globalPosition.x - globalCenter.x) * scale.x);
  844. scalePosition.y = globalPosition.y + ((globalPosition.y - globalCenter.y) * scale.y);
  845. scalePosition.z = globalPosition.z + ((globalPosition.z - globalCenter.z) * scale.z);
  846. scalePosition = selectedEntities[i]->getParentEntity()->getConcatenatedMatrix().Inverse().transpose() * scalePosition;
  847. selectedEntities[i]->setPosition(scalePosition);
  848. if(move.length() == 0.0) {
  849. entityPositions[i] = selectedEntities[i]->getPosition();
  850. }
  851. }
  852. } else {
  853. selectedEntities[i]->setRotationByQuaternion(currentRotation * q);
  854. if(mode == TRANSFORM_SCALE_VIEW)
  855. selectedEntities[i]->setScale(oldScale[i] * scale);
  856. else
  857. selectedEntities[i]->setScale(selectedEntities[i]->getScale() * (Vector3(1.0, 1.0, 1.0)+scale));
  858. }
  859. }
  860. // snap if moving and snap is on
  861. if(scale.length() == 0.0 && rotate == 0.0) {
  862. if(snapEnabled) {
  863. Vector3 snappedPositon = entityPositions[i];
  864. snappedPositon.x = round(((Number)snappedPositon.x)/(snapSize)) * snapSize;
  865. snappedPositon.y = round(((Number)snappedPositon.y)/(snapSize)) * snapSize;
  866. snappedPositon.z = round(((Number)snappedPositon.z)/(snapSize)) * snapSize;
  867. selectedEntities[i]->setPosition(snappedPositon);
  868. } else {
  869. selectedEntities[i]->setPosition(entityPositions[i]);
  870. }
  871. }
  872. }
  873. }
  874. Number TransformGizmo::getTransformPlaneAngle() {
  875. Ray gizmoRay;
  876. gizmoRay.origin = getConcatenatedMatrix().getPosition();
  877. gizmoRay.direction = localTransformPlane * -1;
  878. Vector3 gizmoIntersect = gizmoRay.planeIntersectPoint(transformPlane, transformPlaneDistance);
  879. gizmoIntersect = planeMatrix.Inverse() * gizmoIntersect;
  880. Ray ray = targetScene->projectRayFromCameraAndViewportCoordinate(targetCamera, coreInput->getMousePosition());
  881. Vector3 mouseIntersect = ray.planeIntersectPoint(transformPlane, transformPlaneDistance);
  882. mouseIntersect = planeMatrix.Inverse() * mouseIntersect;
  883. Vector2 planePosition;
  884. if(localTransformPlane.x > 0) {
  885. planePosition.x = mouseIntersect.z - gizmoIntersect.z;
  886. planePosition.y = mouseIntersect.y - gizmoIntersect.y;
  887. } else if(localTransformPlane.y > 0.0) {
  888. planePosition.x = mouseIntersect.x - gizmoIntersect.x;
  889. planePosition.y = mouseIntersect.z - gizmoIntersect.z;
  890. } else if(localTransformPlane.z > 0.0) {
  891. planePosition.x = mouseIntersect.x - gizmoIntersect.x;
  892. planePosition.y = mouseIntersect.y - gizmoIntersect.y;
  893. }
  894. planePosition.Normalize();
  895. return atan2(planePosition.x, planePosition.y);
  896. }
  897. Vector2 TransformGizmo::getCorrectedMousePosition() {
  898. Vector2 localMouse = core->getInput()->getMousePosition();
  899. localMouse.x -= targetScene->sceneMouseRect.x;
  900. localMouse.y -= targetScene->sceneMouseRect.y;
  901. return localMouse;
  902. }
  903. Number TransformGizmo::get2dAngle() {
  904. Polycode::Rectangle view = targetScene->sceneMouseRect;
  905. Polycode::Rectangle camView = targetCamera->getViewport();
  906. Vector2 origin = getScreenPosition(targetCamera->getProjectionMatrix(), targetCamera->getConcatenatedMatrix().Inverse(), camView);
  907. origin.y = core->getYRes() - origin.y;
  908. Vector2 localStart = mouseStart2d - origin;
  909. Vector2 localMouse = core->getInput()->getMousePosition();
  910. localMouse.x -= view.x;
  911. localMouse.y -= view.y;
  912. localMouse -= origin;
  913. Number ang = atan2(localStart.crossProduct(localMouse), localStart.dot(localMouse));
  914. Number dot = targetCamera->getRotationQuat().applyTo(Vector3(0,0,-1)).dot(rotationQuat.applyTo(transformConstraint));
  915. if(dot < 0.0)
  916. ang *= -1.0;
  917. else {
  918. if(gizmoMode == GIZMO_MODE_2D_X || gizmoMode == GIZMO_MODE_2D_Y)
  919. ang *= -1.0;
  920. }
  921. return ang;
  922. }
  923. void TransformGizmo::setGizmoMode(int newMode) {
  924. gizmoMode = newMode;
  925. setTransformMode(transformMode);
  926. }
  927. void TransformGizmo::handleEvent(Event *event) {
  928. if(!enableGizmo) {
  929. return;
  930. }
  931. if(!coreInput->getKeyState(KEY_LALT) && !coreInput->getKeyState(KEY_RALT)) {
  932. if(event->getDispatcher() == pitchGrip) {
  933. if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
  934. if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
  935. transforming = true;
  936. transformConstraint = Vector3(1.0, 0.0, 0.0);
  937. setTransformPlane(1.0, 0.0, 0.0);
  938. mouseStart2d = getCorrectedMousePosition();
  939. startingAngle = get2dAngle();
  940. }
  941. }
  942. } else if(event->getDispatcher() == yawGrip) {
  943. if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
  944. if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
  945. transforming = true;
  946. transformConstraint = Vector3(0.0, 1.0, 0.0);
  947. setTransformPlane(0.0, 1.0, 0.0);
  948. mouseStart2d = getCorrectedMousePosition();
  949. startingAngle = get2dAngle();
  950. }
  951. }
  952. } else if(event->getDispatcher() == rollGrip) {
  953. if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
  954. if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
  955. transforming = true;
  956. transformConstraint = Vector3(0.0, 0.0, 1.0);
  957. setTransformPlane(0.0, 0.0, -1.0);
  958. mouseStart2d = getCorrectedMousePosition();
  959. startingAngle = get2dAngle();
  960. }
  961. }
  962. } else if(event->getDispatcher() == viewportRotateGrip) {
  963. if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
  964. if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
  965. if(gizmoMode != GIZMO_MODE_3D) {
  966. transforming = true;
  967. setTransformPlaneFromView();
  968. transformConstraint = transformPlane;
  969. mouseStart2d = getCorrectedMousePosition();
  970. startingAngle = get2dAngle();
  971. }
  972. }
  973. }
  974. }
  975. if(event->getDispatcher() == xTransformGrip) {
  976. if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
  977. if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
  978. transforming = true;
  979. transformConstraint = Vector3(1.0, 0.0, 0.0);
  980. setTransformPlane(true, false, false);
  981. startingPoint = getTransformPlanePosition();
  982. }
  983. }
  984. } else if(event->getDispatcher() == yTransformGrip) {
  985. if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
  986. if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
  987. transforming = true;
  988. transformConstraint = Vector3(0.0, 1.0, 0.0);
  989. setTransformPlane(false, true, false);
  990. startingPoint = getTransformPlanePosition();
  991. }
  992. }
  993. } else if(event->getDispatcher() == zTransformGrip) {
  994. if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN) {
  995. if(((InputEvent*)event)->getMouseButton() != CoreInput::MOUSE_BUTTON3) {
  996. transforming = true;
  997. transformConstraint = Vector3(0.0, 0.0, 1.0);
  998. setTransformPlane(false, false, true);
  999. startingPoint = getTransformPlanePosition();
  1000. }
  1001. }
  1002. }
  1003. }
  1004. if(event->getDispatcher() == coreInput) {
  1005. if (!coreInput->getKeyState(KEY_LCTRL) && !coreInput->getKeyState(KEY_RCTRL) && !coreInput->getKeyState(KEY_LALT) && !coreInput->getKeyState(KEY_RALT)) {
  1006. if (event->getEventCode() == InputEvent::EVENT_KEYDOWN) {
  1007. InputEvent *inputEvent = (InputEvent*)event;
  1008. switch (inputEvent->key) {
  1009. case KEY_s:
  1010. {
  1011. transforming = true;
  1012. transformConstraint = Vector3(1.0, 1.0, 1.0);
  1013. previousMode = mode;
  1014. mode = TRANSFORM_SCALE_VIEW;
  1015. setTransformPlaneFromView();
  1016. startingPoint = getTransformPlanePosition();
  1017. mouseStart2d = getCorrectedMousePosition();
  1018. scaleAmount = 0.0;
  1019. resetTransform();
  1020. }
  1021. break;
  1022. case KEY_r:
  1023. {
  1024. previousMode = mode;
  1025. mode = TRANSFORM_ROTATE_VIEW;
  1026. transforming = true;
  1027. transformConstraint = Vector3(1.0, 1.0, 1.0);
  1028. setTransformPlaneFromView();
  1029. transformConstraint = transformPlane;
  1030. mouseStart2d = getCorrectedMousePosition();
  1031. startingAngle = get2dAngle();
  1032. resetTransform();
  1033. }
  1034. break;
  1035. case KEY_g:
  1036. {
  1037. previousMode = mode;
  1038. mode = TRANSFORM_MOVE_VIEW;
  1039. transforming = true;
  1040. transformConstraint = Vector3(1.0, 1.0, 1.0);
  1041. setTransformPlaneFromView();
  1042. startingPoint = getTransformPlanePosition();
  1043. resetTransform();
  1044. }
  1045. break;
  1046. case KEY_x:
  1047. {
  1048. if(transforming && (mode == TRANSFORM_MOVE_VIEW || mode == TRANSFORM_SCALE_VIEW || ((mode == TRANSFORM_ROTATE_VIEW) && (gizmoMode == GIZMO_MODE_3D)))) {
  1049. if((coreInput->getKeyState(KEY_LSHIFT) || coreInput->getKeyState(KEY_RSHIFT)) && (mode != TRANSFORM_ROTATE_VIEW) && ((gizmoMode == GIZMO_MODE_2D_X) || (gizmoMode == GIZMO_MODE_3D))) {
  1050. if(transformConstraint != Vector3(0.0, 1.0, 1.0)) {
  1051. transformConstraint = Vector3(0.0, 1.0, 1.0);
  1052. setTransformPlane(false, true, true);
  1053. resetTransform();
  1054. } else {
  1055. toggleOrientation();
  1056. resetTransform();
  1057. }
  1058. } else if(gizmoMode != GIZMO_MODE_2D_X){
  1059. if(transformConstraint != Vector3(1.0, 0.0, 0.0)) {
  1060. transformConstraint = Vector3(1.0, 0.0, 0.0);
  1061. setTransformPlane(true, false, false);
  1062. resetTransform();
  1063. } else {
  1064. switch(gizmoMode) {
  1065. case GIZMO_MODE_3D:
  1066. toggleOrientation();
  1067. break;
  1068. case GIZMO_MODE_2D_Y:
  1069. transformConstraint = Vector3(1.0, 0.0, 1.0);
  1070. break;
  1071. case GIZMO_MODE_2D_Z:
  1072. transformConstraint = Vector3(1.0, 1.0, 0.0);
  1073. break;
  1074. }
  1075. resetTransform();
  1076. }
  1077. }
  1078. }
  1079. }
  1080. break;
  1081. case KEY_y:
  1082. {
  1083. if(transforming && (mode == TRANSFORM_MOVE_VIEW || mode == TRANSFORM_SCALE_VIEW || ((mode == TRANSFORM_ROTATE_VIEW) && (gizmoMode == GIZMO_MODE_3D)))) {
  1084. if((coreInput->getKeyState(KEY_LSHIFT) || coreInput->getKeyState(KEY_RSHIFT)) && (mode != TRANSFORM_ROTATE_VIEW) && ((gizmoMode == GIZMO_MODE_2D_Y) || (gizmoMode == GIZMO_MODE_3D))) {
  1085. if(transformConstraint != Vector3(1.0, 0.0, 1.0)) {
  1086. transformConstraint = Vector3(1.0, 0.0, 1.0);
  1087. setTransformPlane(true, false, true);
  1088. resetTransform();
  1089. } else {
  1090. toggleOrientation();
  1091. resetTransform();
  1092. }
  1093. } else if(gizmoMode != GIZMO_MODE_2D_Y){
  1094. if(transformConstraint != Vector3(0.0, 1.0, 0.0)) {
  1095. transformConstraint = Vector3(0.0, 1.0, 0.0);
  1096. setTransformPlane(false, true, false);
  1097. resetTransform();
  1098. } else {
  1099. switch(gizmoMode) {
  1100. case GIZMO_MODE_3D:
  1101. toggleOrientation();
  1102. break;
  1103. case GIZMO_MODE_2D_X:
  1104. transformConstraint = Vector3(0.0, 1.0, 1.0);
  1105. break;
  1106. case GIZMO_MODE_2D_Z:
  1107. transformConstraint = Vector3(1.0, 1.0, 0.0);
  1108. break;
  1109. }
  1110. resetTransform();
  1111. }
  1112. }
  1113. }
  1114. }
  1115. break;
  1116. case KEY_z:
  1117. {
  1118. if(transforming && (mode == TRANSFORM_MOVE_VIEW || mode == TRANSFORM_SCALE_VIEW || ((mode == TRANSFORM_ROTATE_VIEW) && (gizmoMode == GIZMO_MODE_3D)))) {
  1119. if((coreInput->getKeyState(KEY_LSHIFT) || coreInput->getKeyState(KEY_RSHIFT)) && (mode != TRANSFORM_ROTATE_VIEW) && ((gizmoMode == GIZMO_MODE_2D_Z) || (gizmoMode == GIZMO_MODE_3D))) {
  1120. if(transformConstraint != Vector3(1.0, 1.0, 0.0)) {
  1121. transformConstraint = Vector3(1.0, 1.0, 0.0);
  1122. setTransformPlane(true, true, false);
  1123. resetTransform();
  1124. } else {
  1125. toggleOrientation();
  1126. resetTransform();
  1127. }
  1128. } else if(gizmoMode != GIZMO_MODE_2D_Z){
  1129. if(transformConstraint != Vector3(0.0, 0.0, 1.0)) {
  1130. transformConstraint = Vector3(0.0, 0.0, 1.0);
  1131. setTransformPlane(false, false, true);
  1132. resetTransform();
  1133. } else {
  1134. switch(gizmoMode) {
  1135. case GIZMO_MODE_3D:
  1136. toggleOrientation();
  1137. break;
  1138. case GIZMO_MODE_2D_X:
  1139. transformConstraint = Vector3(0.0, 1.0, 1.0);
  1140. break;
  1141. case GIZMO_MODE_2D_Y:
  1142. transformConstraint = Vector3(1.0, 0.0, 1.0);
  1143. break;
  1144. }
  1145. resetTransform();
  1146. }
  1147. }
  1148. }
  1149. }
  1150. break;
  1151. case KEY_ESCAPE:
  1152. {
  1153. if (mode == TRANSFORM_SCALE_VIEW || mode == TRANSFORM_ROTATE_VIEW || mode == TRANSFORM_MOVE_VIEW) {
  1154. dispatchEndEvent();
  1155. mode = previousMode;
  1156. }
  1157. resetTransform();
  1158. transforming = false;
  1159. firstMove = true;
  1160. }
  1161. break;
  1162. }
  1163. }
  1164. }
  1165. if(transforming) {
  1166. switch(event->getEventCode()) {
  1167. case InputEvent::EVENT_MOUSEMOVE:
  1168. {
  1169. switch(mode) {
  1170. case TRANSFORM_MOVE:
  1171. {
  1172. Vector3 newPoint;
  1173. if(isConstrainedToSingleAxis())
  1174. newPoint = getPositionAlongAxis();
  1175. else
  1176. newPoint = getTransformPlanePosition();
  1177. Vector3 diff = (planeMatrix.Inverse() * newPoint) -(planeMatrix.Inverse() * startingPoint);
  1178. diff = diff * getCompoundScale();
  1179. transformSelectedEntities(transformConstraint * diff, Vector3(0.0, 0.0, 0.0), 0.0);
  1180. startingPoint = newPoint;
  1181. }
  1182. break;
  1183. case TRANSFORM_SCALE_VIEW:
  1184. {
  1185. Vector2 pos2d = getScreenPosition(targetCamera->getProjectionMatrix(), targetCamera->getAnchorAdjustedMatrix(), targetCamera->getViewport());
  1186. Vector2 currentMouse = getCorrectedMousePosition();
  1187. Number scaleNew = currentMouse.distance(pos2d) / mouseStart2d.distance(pos2d);
  1188. Vector3 scaleVec = transformConstraint * scaleNew;
  1189. scaleAmount = scaleNew;
  1190. if((mouseStart2d - pos2d).dot(currentMouse - pos2d) < 0.0)
  1191. scaleVec = -scaleVec;
  1192. scaleVec.x = (transformConstraint.x == 0.0) ? 1.0 : scaleVec.x;
  1193. scaleVec.y = (transformConstraint.y == 0.0) ? 1.0 : scaleVec.y;
  1194. scaleVec.z = (transformConstraint.z == 0.0) ? 1.0 : scaleVec.z;
  1195. transformSelectedEntities(Vector3(0.0, 0.0, 0.0), scaleVec, 0.0);
  1196. }
  1197. break;
  1198. case TRANSFORM_ROTATE_VIEW:
  1199. {
  1200. Number newAngle = get2dAngle();
  1201. Vector3 newPoint = planeMatrix.Inverse() *getTransformPlanePosition();
  1202. transformSelectedEntities(Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0), newAngle - startingAngle);
  1203. startingAngle = newAngle;
  1204. }
  1205. break;
  1206. case TRANSFORM_MOVE_VIEW:
  1207. {
  1208. Vector3 newPoint;
  1209. if(isConstrainedToSingleAxis())
  1210. newPoint = getPositionAlongAxis();
  1211. else
  1212. newPoint = getTransformPlanePosition();
  1213. Vector3 diff = newPoint - startingPoint;
  1214. transformSelectedEntities(transformConstraint * diff, Vector3(0.0, 0.0, 0.0), 0.0);
  1215. startingPoint = newPoint;
  1216. }
  1217. break;
  1218. case TRANSFORM_SCALE:
  1219. {
  1220. Vector3 newPoint = getTransformPlanePosition();
  1221. Vector3 diff = (planeMatrix.Inverse() * newPoint) -(planeMatrix.Inverse() * startingPoint);
  1222. diff = diff * getCompoundScale();
  1223. transformSelectedEntities(Vector3(0.0, 0.0, 0.0), (diff * transformConstraint) / getCompoundScale().x, 0.0);
  1224. startingPoint = newPoint;
  1225. }
  1226. break;
  1227. case TRANSFORM_ROTATE:
  1228. {
  1229. Number newAngle = get2dAngle();
  1230. transformSelectedEntities(Vector3(0.0, 0.0, 0.0), Vector3(0.0, 0.0, 0.0), newAngle - startingAngle);
  1231. startingAngle = newAngle;
  1232. }
  1233. break;
  1234. }
  1235. }
  1236. break;
  1237. case InputEvent::EVENT_MOUSEUP:
  1238. {
  1239. dispatchEndEvent();
  1240. if(mode == TRANSFORM_SCALE_VIEW || mode == TRANSFORM_ROTATE_VIEW || mode == TRANSFORM_MOVE_VIEW) {
  1241. mode = previousMode;
  1242. }
  1243. if( orientation != startingOrientation && startingOrientation != -1) {
  1244. orientation = startingOrientation;
  1245. startingOrientation = -1;
  1246. }
  1247. transforming = false;
  1248. firstMove = true;
  1249. }
  1250. break;
  1251. }
  1252. }
  1253. }
  1254. }
  1255. void TransformGizmo::dispatchEndEvent() {
  1256. switch(mode) {
  1257. case TRANSFORM_MOVE:
  1258. case TRANSFORM_MOVE_VIEW:
  1259. dispatchEvent(new TrasnformGizmoEvent(mode), Event::CHANGE_EVENT);
  1260. break;
  1261. case TRANSFORM_SCALE:
  1262. case TRANSFORM_SCALE_VIEW:
  1263. dispatchEvent(new TrasnformGizmoEvent(mode), Event::CHANGE_EVENT);
  1264. break;
  1265. case TRANSFORM_ROTATE:
  1266. case TRANSFORM_ROTATE_VIEW:
  1267. dispatchEvent(new TrasnformGizmoEvent(mode), Event::CHANGE_EVENT);
  1268. break;
  1269. }
  1270. }
  1271. TransformGizmo::~TransformGizmo() {
  1272. coreInput->removeAllHandlersForListener(this);
  1273. }
  1274. void TransformGizmo::updateOrientationForEntity(Entity *entity) {
  1275. Quaternion q;
  1276. switch(orientation) {
  1277. case ORIENTATION_GLOBAL:
  1278. setRotationByQuaternion(q);
  1279. break;
  1280. case ORIENTATION_LOCAL:
  1281. if(gizmoMode == GIZMO_MODE_3D || mode == TRANSFORM_SCALE)
  1282. q = entity->getRotationQuat();
  1283. setRotationByQuaternion(q);
  1284. break;
  1285. }
  1286. }
  1287. void TransformGizmo::fixedUpdate() {
  1288. if(selectedEntities.size() > 0) {
  1289. Vector3 centerPoint;
  1290. for(int i=0; i < selectedEntities.size(); i++) {
  1291. centerPoint += selectedEntities[i]->getConcatenatedMatrix().getPosition();
  1292. }
  1293. centerPoint = centerPoint / selectedEntities.size();
  1294. setPosition(centerPoint);
  1295. updateOrientationForEntity(selectedEntities[0]);
  1296. }
  1297. viewportRotateGripBase->setRotationByQuaternion(getRotationQuat().Inverse());
  1298. Number scale;
  1299. if(gizmoMode != GIZMO_MODE_3D) {
  1300. scale = targetCamera->getOrthoSizeX() * 0.1;
  1301. } else {
  1302. scale = getPosition().distance(targetCamera->getPosition()) * 0.1;
  1303. }
  1304. setScale(scale, scale, scale);
  1305. }