CameraController2D.hx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package hide.view.l3d;
  2. class CameraController2D extends h2d.Object {
  3. public var friction = 0.4;
  4. public var zoomAmount = 1.15;
  5. public var panSpeed = 1.;
  6. public var smooth = 0.6;
  7. var scene : h2d.Scene;
  8. var pushing = -1;
  9. var pushX = 0.;
  10. var pushY = 0.;
  11. var pushStartX = 0.;
  12. var pushStartY = 0.;
  13. var moveX = 0.;
  14. var moveY = 0.;
  15. var pushTime : Float;
  16. var curPos = new h3d.col.Point(0,0,1);
  17. var targetPos = new h3d.col.Point(0,0,1);
  18. public function new(?parent) {
  19. super(parent);
  20. name = "CameraController";
  21. }
  22. /**
  23. Set the controller parameters.
  24. Distance is ray distance from target.
  25. Theta and Phi are the two spherical angles
  26. Target is the target position
  27. **/
  28. public function set( x : Float, y : Float, ?zoom : Float ) {
  29. targetPos.x = x;
  30. targetPos.y = y;
  31. if( zoom != null ) targetPos.z = zoom;
  32. }
  33. /**
  34. Load current position from current camera position and target.
  35. Call if you want to modify manually the camera.
  36. **/
  37. public function loadFromScene( animate = false ) {
  38. var scene = if( scene == null ) getScene() else scene;
  39. if( scene == null ) throw "Not in scene";
  40. targetPos.set( (scene.width*0.5-parent.x) / parent.scaleX, (scene.height*0.5-parent.y) / parent.scaleX, parent.scaleX);
  41. if( !animate )
  42. toTarget();
  43. else
  44. syncCamera(); // reset camera to current
  45. }
  46. /**
  47. Initialize to look at the whole scene, based on reported scene bounds.
  48. **/
  49. public function initFromScene() {
  50. var scene = getScene();
  51. if( scene == null ) throw "Not in scene";
  52. var bounds = parent.getBounds(parent);
  53. var center = bounds.getCenter();
  54. var scale = Math.min(1, Math.min(scene.width / bounds.width, scene.height / bounds.height));
  55. parent.setScale(scale);
  56. parent.x = scene.width * 0.5 - center.x;
  57. parent.y = scene.height * 0.5 - center.y;
  58. loadFromScene();
  59. }
  60. /**
  61. Stop animation by directly moving to end position.
  62. Call after set() if you don't want to animate the change
  63. **/
  64. public function toTarget() {
  65. curPos.load(targetPos);
  66. syncCamera();
  67. }
  68. override function onAdd() {
  69. super.onAdd();
  70. scene = getScene();
  71. scene.addEventListener(onEvent);
  72. targetPos.load(curPos);
  73. }
  74. override function onRemove() {
  75. super.onRemove();
  76. scene.removeEventListener(onEvent);
  77. scene = null;
  78. }
  79. public dynamic function onClick( e : hxd.Event ) {
  80. }
  81. function onEvent( e : hxd.Event ) {
  82. var p : h2d.Object = this;
  83. while( p != null ) {
  84. if( !p.visible ) {
  85. e.propagate = true;
  86. return;
  87. }
  88. p = p.parent;
  89. }
  90. switch( e.kind ) {
  91. case EWheel:
  92. zoom(e.wheelDelta);
  93. case EPush:
  94. @:privateAccess scene.events.startCapture(onEvent, function() pushing = -1, e.touchId);
  95. pushing = e.button;
  96. pushTime = haxe.Timer.stamp();
  97. pushStartX = pushX = e.relX;
  98. pushStartY = pushY = e.relY;
  99. case ERelease, EReleaseOutside:
  100. if( pushing == e.button ) {
  101. pushing = -1;
  102. @:privateAccess scene.events.stopCapture();
  103. if( e.kind == ERelease && haxe.Timer.stamp() - pushTime < 0.2 && hxd.Math.distance(e.relX - pushStartX,e.relY - pushStartY) < 5 )
  104. onClick(e);
  105. }
  106. case EMove:
  107. switch( pushing ) {
  108. case 1:
  109. pan((e.relX - pushX) * panSpeed, (e.relY - pushY) * panSpeed);
  110. pushX = e.relX;
  111. pushY = e.relY;
  112. default:
  113. }
  114. default:
  115. }
  116. }
  117. function zoom(delta:Float) {
  118. targetPos.z *= Math.pow(zoomAmount, -delta);
  119. }
  120. function rot(dx, dy) {
  121. moveX += dx;
  122. moveY += dy;
  123. }
  124. function pan(dx:Float, dy:Float) {
  125. targetPos.x -= dx / parent.scaleX;
  126. targetPos.y -= dy / parent.scaleY;
  127. }
  128. function syncCamera() {
  129. var scene = getScene();
  130. if( scene == null ) return;
  131. parent.setScale(curPos.z);
  132. parent.x = scene.width * 0.5 - curPos.x * parent.scaleX;
  133. parent.y = scene.height * 0.5 - curPos.y * parent.scaleY;
  134. }
  135. override function sync(ctx:h2d.RenderContext) {
  136. var p : h2d.Object = this;
  137. while( p != null ) {
  138. if( !p.visible ) {
  139. super.sync(ctx);
  140. return;
  141. }
  142. p = p.parent;
  143. }
  144. /*
  145. if( moveX != 0 ) {
  146. targetPos.y += moveX * 0.003 * rotateSpeed;
  147. moveX *= 1 - friction;
  148. if( Math.abs(moveX) < 1 ) moveX = 0;
  149. }
  150. if( moveY != 0 ) {
  151. targetPos.z -= moveY * 0.003 * rotateSpeed;
  152. var E = 2e-5;
  153. var bound = Math.PI - E;
  154. if( targetPos.z < E ) targetPos.z = E;
  155. if( targetPos.z > bound ) targetPos.z = bound;
  156. moveY *= 1 - friction;
  157. if( Math.abs(moveY) < 1 ) moveY = 0;
  158. }*/
  159. var dt = hxd.Math.min(1, 1 - Math.pow(smooth, ctx.elapsedTime * 60));
  160. curPos.lerp(curPos, targetPos, dt );
  161. syncCamera();
  162. super.sync(ctx);
  163. }
  164. }