plot_controller.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. from pyglet.window import key
  2. from pyglet.window.mouse import LEFT, RIGHT, MIDDLE
  3. from sympy.plotting.pygletplot.util import get_direction_vectors, get_basis_vectors
  4. class PlotController:
  5. normal_mouse_sensitivity = 4.0
  6. modified_mouse_sensitivity = 1.0
  7. normal_key_sensitivity = 160.0
  8. modified_key_sensitivity = 40.0
  9. keymap = {
  10. key.LEFT: 'left',
  11. key.A: 'left',
  12. key.NUM_4: 'left',
  13. key.RIGHT: 'right',
  14. key.D: 'right',
  15. key.NUM_6: 'right',
  16. key.UP: 'up',
  17. key.W: 'up',
  18. key.NUM_8: 'up',
  19. key.DOWN: 'down',
  20. key.S: 'down',
  21. key.NUM_2: 'down',
  22. key.Z: 'rotate_z_neg',
  23. key.NUM_1: 'rotate_z_neg',
  24. key.C: 'rotate_z_pos',
  25. key.NUM_3: 'rotate_z_pos',
  26. key.Q: 'spin_left',
  27. key.NUM_7: 'spin_left',
  28. key.E: 'spin_right',
  29. key.NUM_9: 'spin_right',
  30. key.X: 'reset_camera',
  31. key.NUM_5: 'reset_camera',
  32. key.NUM_ADD: 'zoom_in',
  33. key.PAGEUP: 'zoom_in',
  34. key.R: 'zoom_in',
  35. key.NUM_SUBTRACT: 'zoom_out',
  36. key.PAGEDOWN: 'zoom_out',
  37. key.F: 'zoom_out',
  38. key.RSHIFT: 'modify_sensitivity',
  39. key.LSHIFT: 'modify_sensitivity',
  40. key.F1: 'rot_preset_xy',
  41. key.F2: 'rot_preset_xz',
  42. key.F3: 'rot_preset_yz',
  43. key.F4: 'rot_preset_perspective',
  44. key.F5: 'toggle_axes',
  45. key.F6: 'toggle_axe_colors',
  46. key.F8: 'save_image'
  47. }
  48. def __init__(self, window, *, invert_mouse_zoom=False, **kwargs):
  49. self.invert_mouse_zoom = invert_mouse_zoom
  50. self.window = window
  51. self.camera = window.camera
  52. self.action = {
  53. # Rotation around the view Y (up) vector
  54. 'left': False,
  55. 'right': False,
  56. # Rotation around the view X vector
  57. 'up': False,
  58. 'down': False,
  59. # Rotation around the view Z vector
  60. 'spin_left': False,
  61. 'spin_right': False,
  62. # Rotation around the model Z vector
  63. 'rotate_z_neg': False,
  64. 'rotate_z_pos': False,
  65. # Reset to the default rotation
  66. 'reset_camera': False,
  67. # Performs camera z-translation
  68. 'zoom_in': False,
  69. 'zoom_out': False,
  70. # Use alternative sensitivity (speed)
  71. 'modify_sensitivity': False,
  72. # Rotation presets
  73. 'rot_preset_xy': False,
  74. 'rot_preset_xz': False,
  75. 'rot_preset_yz': False,
  76. 'rot_preset_perspective': False,
  77. # axes
  78. 'toggle_axes': False,
  79. 'toggle_axe_colors': False,
  80. # screenshot
  81. 'save_image': False
  82. }
  83. def update(self, dt):
  84. z = 0
  85. if self.action['zoom_out']:
  86. z -= 1
  87. if self.action['zoom_in']:
  88. z += 1
  89. if z != 0:
  90. self.camera.zoom_relative(z/10.0, self.get_key_sensitivity()/10.0)
  91. dx, dy, dz = 0, 0, 0
  92. if self.action['left']:
  93. dx -= 1
  94. if self.action['right']:
  95. dx += 1
  96. if self.action['up']:
  97. dy -= 1
  98. if self.action['down']:
  99. dy += 1
  100. if self.action['spin_left']:
  101. dz += 1
  102. if self.action['spin_right']:
  103. dz -= 1
  104. if not self.is_2D():
  105. if dx != 0:
  106. self.camera.euler_rotate(dx*dt*self.get_key_sensitivity(),
  107. *(get_direction_vectors()[1]))
  108. if dy != 0:
  109. self.camera.euler_rotate(dy*dt*self.get_key_sensitivity(),
  110. *(get_direction_vectors()[0]))
  111. if dz != 0:
  112. self.camera.euler_rotate(dz*dt*self.get_key_sensitivity(),
  113. *(get_direction_vectors()[2]))
  114. else:
  115. self.camera.mouse_translate(0, 0, dx*dt*self.get_key_sensitivity(),
  116. -dy*dt*self.get_key_sensitivity())
  117. rz = 0
  118. if self.action['rotate_z_neg'] and not self.is_2D():
  119. rz -= 1
  120. if self.action['rotate_z_pos'] and not self.is_2D():
  121. rz += 1
  122. if rz != 0:
  123. self.camera.euler_rotate(rz*dt*self.get_key_sensitivity(),
  124. *(get_basis_vectors()[2]))
  125. if self.action['reset_camera']:
  126. self.camera.reset()
  127. if self.action['rot_preset_xy']:
  128. self.camera.set_rot_preset('xy')
  129. if self.action['rot_preset_xz']:
  130. self.camera.set_rot_preset('xz')
  131. if self.action['rot_preset_yz']:
  132. self.camera.set_rot_preset('yz')
  133. if self.action['rot_preset_perspective']:
  134. self.camera.set_rot_preset('perspective')
  135. if self.action['toggle_axes']:
  136. self.action['toggle_axes'] = False
  137. self.camera.axes.toggle_visible()
  138. if self.action['toggle_axe_colors']:
  139. self.action['toggle_axe_colors'] = False
  140. self.camera.axes.toggle_colors()
  141. if self.action['save_image']:
  142. self.action['save_image'] = False
  143. self.window.plot.saveimage()
  144. return True
  145. def get_mouse_sensitivity(self):
  146. if self.action['modify_sensitivity']:
  147. return self.modified_mouse_sensitivity
  148. else:
  149. return self.normal_mouse_sensitivity
  150. def get_key_sensitivity(self):
  151. if self.action['modify_sensitivity']:
  152. return self.modified_key_sensitivity
  153. else:
  154. return self.normal_key_sensitivity
  155. def on_key_press(self, symbol, modifiers):
  156. if symbol in self.keymap:
  157. self.action[self.keymap[symbol]] = True
  158. def on_key_release(self, symbol, modifiers):
  159. if symbol in self.keymap:
  160. self.action[self.keymap[symbol]] = False
  161. def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
  162. if buttons & LEFT:
  163. if self.is_2D():
  164. self.camera.mouse_translate(x, y, dx, dy)
  165. else:
  166. self.camera.spherical_rotate((x - dx, y - dy), (x, y),
  167. self.get_mouse_sensitivity())
  168. if buttons & MIDDLE:
  169. self.camera.zoom_relative([1, -1][self.invert_mouse_zoom]*dy,
  170. self.get_mouse_sensitivity()/20.0)
  171. if buttons & RIGHT:
  172. self.camera.mouse_translate(x, y, dx, dy)
  173. def on_mouse_scroll(self, x, y, dx, dy):
  174. self.camera.zoom_relative([1, -1][self.invert_mouse_zoom]*dy,
  175. self.get_mouse_sensitivity())
  176. def is_2D(self):
  177. functions = self.window.plot._functions
  178. for i in functions:
  179. if len(functions[i].i_vars) > 1 or len(functions[i].d_vars) > 2:
  180. return False
  181. return True