Renderer.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. "use strict";
  2. /**
  3. * The renderer is resposible for drawing the structure into the canvas element.
  4. *
  5. * Its also resposible for managing the canvas state.
  6. *
  7. * @class
  8. */
  9. function Renderer(canvas)
  10. {
  11. /**
  12. * Canvas DOM element, has to be managed by the user.
  13. */
  14. this.canvas = canvas;
  15. /**
  16. * Canvas 2D rendering context used to draw content.
  17. */
  18. this.context = canvas.getContext("2d");
  19. this.context.imageSmoothingEnabled = true;
  20. this.context.globalCompositeOperation = "source-over";
  21. /**
  22. * Mouse input handler object.
  23. */
  24. this.mouse = new Mouse();
  25. this.mouse.setCanvas(canvas);
  26. }
  27. /**
  28. * Update the renderer state, update the input handlers, calculate the object and viewport transformation matrices.
  29. *
  30. * @param object Object to be updated.
  31. * @param viewport Viewport to be updated (should be the one where the objects will be rendered after).
  32. */
  33. Renderer.prototype.update = function(object, viewport)
  34. {
  35. this.mouse.update();
  36. var mouse = this.mouse;
  37. // Viewport transform matrix
  38. viewport.updateControls(mouse);
  39. viewport.updateMatrix();
  40. // Project mouse coordinates
  41. var point = mouse.position.clone();
  42. var viewportPoint = viewport.inverseMatrix.transformPoint(point);
  43. // Object transformation matrices
  44. object.traverse(function(child)
  45. {
  46. child.updateMatrix();
  47. var childPoint = child.inverseGlobalMatrix.transformPoint(viewportPoint);
  48. // Check if the mouse pointer is inside
  49. if(child.isInside(childPoint))
  50. {
  51. // Pointer enter
  52. if(!child.pointerInside && child.onPointerEnter !== null)
  53. {
  54. child.onPointerEnter(mouse, viewport);
  55. }
  56. // Pointer over
  57. if(child.onPointerOver !== null)
  58. {
  59. child.onPointerOver(mouse, viewport);
  60. }
  61. // Pointer just pressed
  62. if(mouse.buttonJustPressed(Mouse.LEFT))
  63. {
  64. if(child.onButtonDown !== null)
  65. {
  66. child.onButtonDown(mouse, viewport);
  67. }
  68. if(child.draggable)
  69. {
  70. child.beingDragged = true;
  71. }
  72. }
  73. // Pointer pressed
  74. if(mouse.buttonPressed(Mouse.LEFT) && child.onButtonPressed !== null)
  75. {
  76. child.onButtonPressed(mouse, viewport);
  77. }
  78. // Just released
  79. if(mouse.buttonJustReleased(Mouse.LEFT) && child.onButtonUp !== null)
  80. {
  81. child.onButtonUp(mouse, viewport);
  82. }
  83. child.pointerInside = true;
  84. }
  85. else if(child.pointerInside)
  86. {
  87. // Pointer leave
  88. if(child.onPointerLeave !== null)
  89. {
  90. child.onPointerLeave(mouse, viewport);
  91. }
  92. child.pointerInside = false;
  93. }
  94. // Stop object drag
  95. if(mouse.buttonJustReleased(Mouse.LEFT))
  96. {
  97. if(child.draggable)
  98. {
  99. child.beingDragged = false;
  100. }
  101. }
  102. // Pointer drag event
  103. if(child.beingDragged)
  104. {
  105. var matrix = viewport.inverseMatrix.clone();
  106. matrix.multiply(child.inverseGlobalMatrix);
  107. matrix.setPosition(0, 0);
  108. var delta = matrix.transformPoint(mouse.delta);
  109. child.position.add(delta);
  110. if(child.onPointerDrag !== null)
  111. {
  112. child.onPointerDrag(mouse, viewport, delta)
  113. }
  114. }
  115. });
  116. };
  117. /**
  118. * Render the object using the viewport into a canvas element.
  119. *
  120. * The canvas state is saved and restored for each individual object, ensuring that the code of one object does not affect another one.
  121. *
  122. * @param object Object to be rendered.
  123. * @param viewport Viewport to render the objects.
  124. */
  125. Renderer.prototype.render = function(object, viewport)
  126. {
  127. var context = this.context;
  128. // Clear canvas
  129. context.setTransform(1, 0, 0, 1, 0, 0);
  130. context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  131. // Set viewport matrix transform
  132. viewport.matrix.setContextTransform(context);
  133. // Get objects to be rendered
  134. var objects = []
  135. object.traverse(function(child)
  136. {
  137. objects.push(child);
  138. });
  139. // Sort objects by layer
  140. objects.sort(function(a, b)
  141. {
  142. return a.layer - b.layer;
  143. });
  144. // Render into the canvas
  145. for(var i = 0; i < objects.length; i++)
  146. {
  147. context.save();
  148. objects[i].globalMatrix.tranformContext(context);
  149. objects[i].draw(context);
  150. context.restore();
  151. }
  152. };