RenderView.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // $Id$
  2. using System;
  3. using Gtk;
  4. using Gdk;
  5. using OpenGl;
  6. using Drawing;
  7. using SceneGraph;
  8. using DataStructures;
  9. public class RenderView : GLWidgetBase
  10. {
  11. public Node SceneGraphRoot;
  12. private bool dragging;
  13. private Vector dragStartMouse;
  14. private Vector dragStartTranslation;
  15. private Vector MousePos;
  16. private IEditor editor;
  17. public IEditor Editor {
  18. set {
  19. if(this.editor != null) {
  20. this.editor.Redraw -= QueueDraw;
  21. if(this.editor is IEditorCursorChange)
  22. ((IEditorCursorChange) this.editor).CursorChange -= CursorChange;
  23. if(this.editor is IDisposable)
  24. ((IDisposable) this.editor).Dispose();
  25. }
  26. this.editor = value;
  27. this.editor.Redraw += QueueDraw;
  28. if(this.editor is IEditorCursorChange)
  29. ((IEditorCursorChange) this.editor).CursorChange += CursorChange;
  30. }
  31. get {
  32. return editor;
  33. }
  34. }
  35. public RenderView()
  36. {
  37. ButtonPressEvent += OnButtonPress;
  38. ButtonReleaseEvent += OnButtonRelease;
  39. MotionNotifyEvent += OnMotionNotify;
  40. ScrollEvent += OnScroll;
  41. AddEvents((int) Gdk.EventMask.ButtonPressMask);
  42. AddEvents((int) Gdk.EventMask.ButtonReleaseMask);
  43. AddEvents((int) Gdk.EventMask.PointerMotionMask);
  44. AddEvents((int) Gdk.EventMask.ScrollMask);
  45. CanFocus = true;
  46. }
  47. protected override void DrawGl()
  48. {
  49. gl.ClearColor(0.4f, 0, 0.4f, 1);
  50. gl.Clear(gl.COLOR_BUFFER_BIT);
  51. if(SceneGraphRoot != null)
  52. SceneGraphRoot.Draw(GetClipRect());
  53. if(!dragging && Editor != null)
  54. Editor.Draw(GetClipRect());
  55. }
  56. private void OnButtonPress(object o, ButtonPressEventArgs args)
  57. {
  58. try {
  59. MousePos = MouseToWorld(
  60. new Vector((float) args.Event.X, (float) args.Event.Y));
  61. if(args.Event.Button == 2) {
  62. dragStartMouse = new Vector((float) args.Event.X, (float) args.Event.Y);
  63. dragStartTranslation = Translation;
  64. dragging = true;
  65. QueueDraw();
  66. } else if(Editor != null) {
  67. Editor.OnMouseButtonPress(MousePos, (int) args.Event.Button, args.Event.State);
  68. }
  69. args.RetVal = true;
  70. } catch(Exception e) {
  71. ErrorDialog.Exception(e);
  72. }
  73. }
  74. private void OnButtonRelease(object o, ButtonReleaseEventArgs args)
  75. {
  76. try {
  77. MousePos = MouseToWorld(
  78. new Vector((float) args.Event.X, (float) args.Event.Y));
  79. if(args.Event.Button == 2) {
  80. dragging = false;
  81. QueueDraw();
  82. } else if(Editor != null) {
  83. Editor.OnMouseButtonRelease(MousePos, (int) args.Event.Button, args.Event.State);
  84. }
  85. args.RetVal = true;
  86. } catch(Exception e) {
  87. ErrorDialog.Exception(e);
  88. }
  89. }
  90. private void OnMotionNotify(object o, MotionNotifyEventArgs args)
  91. {
  92. try {
  93. Vector pos = new Vector((float) args.Event.X, (float) args.Event.Y);
  94. MousePos = MouseToWorld(pos);
  95. if(dragging) {
  96. SetTranslation(dragStartTranslation +
  97. (pos - dragStartMouse) / Zoom);
  98. } else if(Editor != null) {
  99. Editor.OnMouseMotion(MousePos, args.Event.State);
  100. }
  101. args.RetVal = true;
  102. } catch(Exception e) {
  103. ErrorDialog.Exception(e);
  104. }
  105. }
  106. private void OnScroll(object o, ScrollEventArgs args)
  107. {
  108. float oldZoom = Zoom;
  109. Vector realMousePos = (MousePos + Translation) * Zoom;
  110. if(args.Event.Direction == ScrollDirection.Down) {
  111. Zoom /= (float) Math.Sqrt(2);
  112. } else if(args.Event.Direction == ScrollDirection.Up) {
  113. Zoom *= (float) Math.Sqrt(2);
  114. }
  115. //Limit the Zoom to useful values;
  116. if( Zoom < 0.002 || Zoom > 500 ){
  117. Zoom = oldZoom;
  118. }
  119. SetTranslation(Translation
  120. + realMousePos / Zoom - realMousePos / oldZoom);
  121. MousePos = MouseToWorld(realMousePos);
  122. if(Editor != null) {
  123. Editor.OnMouseMotion(MousePos, args.Event.State);
  124. }
  125. args.RetVal = true;
  126. }
  127. private void UpdateAdjustments()
  128. {
  129. if(hadjustment != null) {
  130. hadjustment.SetBounds(minx, maxx, 32/Zoom, 256/Zoom, Allocation.Width/Zoom);
  131. hadjustment.ClampPage(-Translation.X, -Translation.X + (Allocation.Width/Zoom));
  132. }
  133. if(vadjustment != null) {
  134. vadjustment.SetBounds(miny, maxy, 32/Zoom, 256/Zoom, Allocation.Height/Zoom);
  135. vadjustment.ClampPage(-Translation.Y, -Translation.Y + (Allocation.Height/Zoom));
  136. }
  137. }
  138. public void SetZoom(float newZoom)
  139. {
  140. float oldZoom = Zoom;
  141. Zoom = newZoom;
  142. // Limit the Zoom to useful values;
  143. if( Zoom < 0.002 || Zoom > 500 ){
  144. Zoom = oldZoom;
  145. }
  146. UpdateAdjustments();
  147. QueueDraw();
  148. }
  149. public float GetZoom()
  150. {
  151. return Zoom;
  152. }
  153. public void ZoomIn()
  154. {
  155. SetZoom( Zoom * (float) Math.Sqrt(2));
  156. }
  157. public void ZoomOut()
  158. {
  159. SetZoom( Zoom / (float) Math.Sqrt(2));
  160. }
  161. public void SetTranslation(Vector tr)
  162. {
  163. Translation = tr;
  164. UpdateAdjustments();
  165. QueueDraw();
  166. }
  167. public Vector GetTranslation()
  168. {
  169. return Translation;
  170. }
  171. /// <summary>
  172. /// Returns a <see cref="Gdk.Rectangle"/> for the currently
  173. /// visible area in world coordinates.
  174. /// </summary>
  175. /// <returns>A <see cref="Gdk.Rectangle"/>.</returns>
  176. public Gdk.Rectangle GetClipRect() {
  177. return new Gdk.Rectangle(
  178. (int)-Translation.X, (int)-Translation.Y,
  179. (int)(Allocation.Width / Zoom), (int)(Allocation.Height / Zoom));
  180. }
  181. private Vector MouseToWorld(Vector MousePos)
  182. {
  183. return MousePos / Zoom - Translation;
  184. }
  185. private void CursorChange(Cursor cursor)
  186. {
  187. GdkWindow.Cursor = cursor;
  188. }
  189. /**
  190. * Add gtk adjustments for vertical and horizontal scrolling
  191. * (This is used for scrollbars)
  192. */
  193. public void SetAdjustments(Adjustment hadjustment, Adjustment vadjustment)
  194. {
  195. this.vadjustment = vadjustment;
  196. this.hadjustment = hadjustment;
  197. if(vadjustment != null) {
  198. vadjustment.ValueChanged += OnVAdjustmentChanged;
  199. }
  200. if(hadjustment != null) {
  201. hadjustment.ValueChanged += OnHAdjustmentChanged;
  202. }
  203. UpdateAdjustments();
  204. }
  205. private void OnHAdjustmentChanged(object sender, EventArgs e)
  206. {
  207. SetTranslation(new Vector((float) -hadjustment.Value, Translation.Y));
  208. }
  209. private void OnVAdjustmentChanged(object sender, EventArgs e)
  210. {
  211. SetTranslation(new Vector(Translation.X, (float) -vadjustment.Value));
  212. }
  213. private Adjustment vadjustment;
  214. private Adjustment hadjustment;
  215. protected float minx = -1000, maxx = 1000;
  216. protected float miny = -1000, maxy = 1000;
  217. }