manipulation.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, 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
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell 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
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. // Sandbox manipulation modes are:
  23. // - Off
  24. // - Pan
  25. // - Pull
  26. Sandbox.ManipulationMode = "off";
  27. // Reset the sandbox pull object.
  28. Sandbox.ManipulationPullMaxForce = 1000;
  29. // Reset the touch events.
  30. Sandbox.InputController = new ScriptObject()
  31. {
  32. class = SandboxInputController;
  33. TouchEventCount = 0;
  34. TouchEventActive[0] = false;
  35. TouchEventActive[1] = false;
  36. TouchEventActive[2] = false;
  37. TouchEventActive[3] = false;
  38. TouchEventActive[4] = false;
  39. LastTouchId = -1;
  40. LatestTouchId = -1;
  41. };
  42. //-----------------------------------------------------------------------------
  43. function SandboxInputController::initialize( %this )
  44. {
  45. // Add sandbox touch gester as an input listener.
  46. SandboxWindow.addInputListener( %this );
  47. }
  48. //-----------------------------------------------------------------------------
  49. function SandboxInputController::onTouchDown(%this, %touchID, %worldPosition)
  50. {
  51. // Finish if the drag mode is off.
  52. if ( Sandbox.ManipulationMode $= "off" )
  53. return;
  54. // Sanity!
  55. if ( %this.TouchEventActive[%touchId] == true )
  56. {
  57. error( "SandboxInputController::onTouchDown() - Touch Id already active." );
  58. }
  59. else
  60. {
  61. // Calculate window position.
  62. %windowPosition = SandboxWindow.getWindowPoint( %worldPosition );
  63. // Store the new touch position.
  64. %this.NewTouchPosition[%touchId] = %windowPosition;
  65. // Set the old touch position as new touch position.
  66. %this.OldTouchPosition[%touchId] = %windowPosition;
  67. // Flag event as active.
  68. %this.TouchEventActive[%touchId] = true;
  69. // Insert the new touch Id.
  70. %this.PreviousTouchId = %this.CurrentTouchId;
  71. %this.CurrentTouchId = %touchId;
  72. // Increase event count.
  73. %this.TouchEventCount++;
  74. }
  75. // Handle "pull" mode.
  76. if ( Sandbox.ManipulationMode $= "pull" )
  77. {
  78. // Reset the pull
  79. Sandbox.ManipulationPullObject[%touchID] = "";
  80. Sandbox.ManipulationPullJointId[%touchID] = "";
  81. // Pick an object.
  82. %picked = SandboxScene.pickPoint( %worldPosition );
  83. // Finish if nothing picked.
  84. if ( %picked $= "" )
  85. return;
  86. // Fetch the pick count.
  87. %pickCount = %picked.Count;
  88. for( %n = 0; %n < %pickCount; %n++ )
  89. {
  90. // Fetch the picked object.
  91. %pickedObject = getWord( %picked, %n );
  92. // Skip if the object is static.
  93. if ( %pickedObject.getBodyType() $= "static" )
  94. continue;
  95. // Set the pull object.
  96. Sandbox.ManipulationPullObject[%touchID] = %pickedObject;
  97. Sandbox.ManipulationPullJointId[%touchID] = SandboxScene.createTargetJoint( %pickedObject, %worldPosition, Sandbox.ManipulationPullMaxForce );
  98. return;
  99. }
  100. return;
  101. }
  102. }
  103. //-----------------------------------------------------------------------------
  104. function SandboxInputController::onTouchUp(%this, %touchID, %worldPosition)
  105. {
  106. // Finish if the drag mode is off.
  107. if ( Sandbox.ManipulationMode $= "off" )
  108. return;
  109. // Sanity!
  110. if ( %this.TouchEventActive[%touchId] == false )
  111. {
  112. error( "SandboxInputController::onTouchUp() - Touch Id not active." );
  113. }
  114. else
  115. {
  116. // Reset previous touch.
  117. %this.OldTouchPosition[%touchId] = "";
  118. // Reset current touch.
  119. %this.NewTouchPosition[%touchId] = "";
  120. // Flag event as inactive.
  121. %this.TouchEventActive[%touchId] = false;
  122. // Remove the touch Id.
  123. if ( %this.PreviousTouchId == %touchId )
  124. {
  125. %this.PreviousTouchId = "";
  126. }
  127. if ( %this.CurrentTouchId == %touchId )
  128. {
  129. %this.CurrentTouchId = %this.PreviousTouchId;
  130. %this.PreviousTouchId = "";
  131. }
  132. // Decrease event count.
  133. %this.TouchEventCount--;
  134. }
  135. // Handle "pull" mode.
  136. if ( Sandbox.ManipulationMode $= "pull" )
  137. {
  138. // Finish if nothing is being pulled.
  139. if ( !isObject(Sandbox.ManipulationPullObject[%touchID]) )
  140. return;
  141. // Reset the pull object.
  142. Sandbox.ManipulationPullObject[%touchID] = "";
  143. // Remove the pull joint.
  144. SandboxScene.deleteJoint( Sandbox.ManipulationPullJointId[%touchID] );
  145. Sandbox.ManipulationPullJointId[%touchID] = "";
  146. return;
  147. }
  148. }
  149. //-----------------------------------------------------------------------------
  150. function SandboxInputController::onTouchDragged(%this, %touchID, %worldPosition)
  151. {
  152. // Finish if the drag mode is off.
  153. if ( Sandbox.ManipulationMode $= "off" )
  154. return;
  155. // Sanity!
  156. if ( %this.TouchEventActive[%touchId] == false )
  157. {
  158. error( "SandboxInputController::onTouchDraggedEvent() - Touch Id not active." );
  159. }
  160. else
  161. {
  162. // Calculate window position.
  163. %windowPosition = SandboxWindow.getWindowPoint( %worldPosition );
  164. // Set the current touch as the previous touch.
  165. %this.OldTouchPosition[%touchId] = %this.NewTouchPosition[%touchId];
  166. // Store the touch event.
  167. %this.NewTouchPosition[%touchId] = %windowPosition;
  168. }
  169. // Handle "pan" mode.
  170. if ( Sandbox.ManipulationMode $= "pan" )
  171. {
  172. // Fetch the touch event count.
  173. %touchEventCount = Sandbox.InputController.TouchEventCount;
  174. // Do we have a single touch event?
  175. if ( %touchEventCount == 1 )
  176. {
  177. // Yes, so perform pan gesture.
  178. Sandbox.InputController.performPanGesture();
  179. return;
  180. }
  181. // Do we have two event counts?
  182. if ( %touchEventCount == 2 )
  183. {
  184. // Yes, so perform zoom gesture.
  185. Sandbox.InputController.performZoomGesture();
  186. return;
  187. }
  188. }
  189. // Handle "pull" mode.
  190. if ( Sandbox.ManipulationMode $= "pull" )
  191. {
  192. // Finish if nothing is being pulled.
  193. if ( !isObject(Sandbox.ManipulationPullObject[%touchID]) )
  194. return;
  195. // Set a new target for the target joint.
  196. SandboxScene.setTargetJointTarget( Sandbox.ManipulationPullJointId[%touchID], %worldPosition );
  197. return;
  198. }
  199. }
  200. //-----------------------------------------------------------------------------
  201. function SandboxInputController::onTouchMoved(%this, %touchID, %worldPosition)
  202. {
  203. // Finish if the drag mode is off.
  204. if ( Sandbox.ManipulationMode $= "off" )
  205. return;
  206. }
  207. //-----------------------------------------------------------------------------
  208. function SandboxInputController::onMouseWheelUp(%this, %modifier, %mousePoint, %mouseClickCount)
  209. {
  210. // Finish if the drag mode is not "pan".
  211. if ( !Sandbox.ManipulationMode $= "pan" )
  212. return;
  213. // Increase the zoom.
  214. SandboxWindow.setCameraZoom( SandboxWindow.getCameraZoom() + $pref::Sandbox::cameraMouseZoomRate );
  215. }
  216. //-----------------------------------------------------------------------------
  217. function SandboxInputController::onMouseWheelDown(%this, %modifier, %mousePoint, %mouseClickCount)
  218. {
  219. // Finish if the drag mode is not "pan".
  220. if ( !Sandbox.ManipulationMode $= "pan" )
  221. return;
  222. // Increase the zoom.
  223. SandboxWindow.setCameraZoom( SandboxWindow.getCameraZoom() - $pref::Sandbox::cameraMouseZoomRate );
  224. }
  225. //-----------------------------------------------------------------------------
  226. function SandboxInputController::performPanGesture( %this )
  227. {
  228. // Finish if we don't have two touch events.
  229. if ( %this.TouchEventCount != 1 )
  230. return;
  231. // Fetch the last touch event Id.
  232. %touchId = %this.CurrentTouchId;
  233. // Sanity!
  234. if ( %touchId $= "" )
  235. {
  236. error( "SandboxInputController::performPanGesture() - Current touch Id not available." );
  237. return;
  238. }
  239. // Calculate pan offset.
  240. %panOffset = Vector2Sub( %this.NewTouchPosition[%touchId], %this.OldTouchPosition[%touchId] );
  241. // Inverse the Y offset.
  242. %panOffset = Vector2InverseY( %panOffset );
  243. // Scale the pan offset by the camera world scale.
  244. %panOffset = Vector2Mult( %panOffset, SandboxWindow.getCameraWorldScale() );
  245. // Update the camera position.
  246. SandboxWindow.setCameraPosition( Vector2Sub( SandboxWindow.getCameraPosition(), %panOffset ) );
  247. }
  248. //-----------------------------------------------------------------------------
  249. function SandboxInputController::performZoomGesture( %this )
  250. {
  251. // Finish if we don't have two touch events.
  252. if ( %this.TouchEventCount != 2 )
  253. return;
  254. // Fetch current and previous touch Ids.
  255. %currentTouchId = %this.CurrentTouchId;
  256. %previousTouchId = %this.PreviousTouchId;
  257. // Finish if we don't have touch Ids active.
  258. if ( !%this.TouchEventActive[%currentTouchId] || !%this.TouchEventActive[%previousTouchId] )
  259. {
  260. error( "SandboxInputController::performZoomGesture() - Current or previous touch events were no active." );
  261. return;
  262. }
  263. %currentNewPosition = %this.NewTouchPosition[%currentTouchId];
  264. %currentOldPosition = %this.OldTouchPosition[%currentTouchId];
  265. %previousNewPosition = %this.NewTouchPosition[%previousTouchId];
  266. %previousOldPosition = %this.OldTouchPosition[%previousTouchId];
  267. // Calculate the last and current separations.
  268. %lastLength = Vector2Length( Vector2Abs( %currentOldPosition, %previousOldPosition ) );
  269. %currentLength = Vector2Length( Vector2Abs( %currentNewPosition, %previousNewPosition ) );
  270. // Calculate the change in separation length.
  271. %separationDelta = %currentLength - %lastLength;
  272. // Finish if no separation change occurred.
  273. if ( %separationDelta == 0 || %separationDelta $= "" )
  274. return;
  275. // Fetch the camera zoom.
  276. %cameraZoom = SandboxWindow.getCameraZoom();
  277. // Calculate new camera zoom.
  278. %newCameraZoom = %cameraZoom + ( %separationDelta * $pref::Sandbox::cameraTouchZoomRate );
  279. // Change the zoom.
  280. SandboxWindow.setCameraZoom( %newCameraZoom ) ;
  281. }
  282. //-----------------------------------------------------------------------------
  283. function Sandbox::resetManipulationModes( %this )
  284. {
  285. // These control which drag modes are available or not.
  286. Sandbox.ManipulationModeState["off"] = true;
  287. Sandbox.ManipulationModeState["pan"] = false;
  288. Sandbox.ManipulationModeState["pull"] = false;
  289. // Set the sandbox drag mode default.
  290. Sandbox.useManipulation( "off" );
  291. }
  292. //-----------------------------------------------------------------------------
  293. function Sandbox::resetManipulationModes( %this )
  294. {
  295. // These control which drag modes are available or not.
  296. Sandbox.ManipulationModeState["off"] = true;
  297. Sandbox.ManipulationModeState["pan"] = false;
  298. Sandbox.ManipulationModeState["pull"] = false;
  299. // Set the sandbox drag mode default.
  300. Sandbox.useManipulation( "off" );
  301. }
  302. //-----------------------------------------------------------------------------
  303. function Sandbox::allowManipulation( %this, %mode )
  304. {
  305. // Cannot turn-off the "off" manipulation.
  306. if ( %mode $= "off" )
  307. return;
  308. Sandbox.ManipulationModeState[%mode] = true;
  309. }
  310. //-----------------------------------------------------------------------------
  311. function Sandbox::useManipulation( %this, %mode )
  312. {
  313. // Is the drag mode available?
  314. if ( %mode !$= "off" && !Sandbox.ManipulationModeState[%mode] )
  315. {
  316. // No, so warn.
  317. error( "Cannot set sandbox drag mode to " @ %mode @ " as it is currently disabled." );
  318. return;
  319. }
  320. // Set the manipulation mode.
  321. Sandbox.ManipulationMode = %mode;
  322. // Set the current mode as text on the button.
  323. if ( isObject(ManipulationModeButton) )
  324. {
  325. // Make the displayed mode more consistent.
  326. if ( %mode $= "off" )
  327. %mode = "Off";
  328. else if ( %mode $= "pan" )
  329. %mode = "Pan";
  330. else if ( %mode $= "pull" )
  331. %mode = "Pull";
  332. // Make the mode consistent when showed.
  333. ManipulationModeButton.Text = %mode;
  334. }
  335. // Reset pulled object and joint.
  336. Sandbox.ManipulationPullObject = "";
  337. if ( Sandbox.ManipulationPullJointId !$= "" && SandboxScene.isJoint(Sandbox.ManipulationPullJointId) )
  338. {
  339. SandboxScene.deleteJoint( Sandbox.ManipulationPullJointId );
  340. Sandbox.ManipulationPullJointId = "";
  341. }
  342. }
  343. //-----------------------------------------------------------------------------
  344. function cycleManipulation( %make )
  345. {
  346. // Finish if being released.
  347. if ( !%make )
  348. return;
  349. // "off" to "pan" transition.
  350. if ( Sandbox.ManipulationMode $= "off" )
  351. {
  352. if ( Sandbox.ManipulationModeState["pan"] )
  353. {
  354. Sandbox.useManipulation("pan");
  355. return;
  356. }
  357. Sandbox.ManipulationMode = "pan";
  358. }
  359. // "pan" to "pull" transition.
  360. if ( Sandbox.ManipulationMode $= "pan" )
  361. {
  362. if ( Sandbox.ManipulationModeState["pull"] )
  363. {
  364. Sandbox.useManipulation("pull");
  365. return;
  366. }
  367. Sandbox.ManipulationMode = "pull";
  368. }
  369. // "pull" to "off" transition.
  370. if ( Sandbox.ManipulationMode $= "pull" )
  371. {
  372. Sandbox.useManipulation("off");
  373. }
  374. }