123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- // SuperTux Editor
- // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- using System;
- using Gtk;
- using Gdk;
- using OpenGl;
- using Drawing;
- using SceneGraph;
- using DataStructures;
- public class RenderView : GLWidgetBase
- {
- public static TargetEntry [] DragTargetEntries = new TargetEntry[] {
- new TargetEntry("GameObject", TargetFlags.App, 0)
- };
- public Node SceneGraphRoot;
- private bool dragging;
- private Vector dragStartMouse;
- private Vector dragStartTranslation;
- private Vector MousePos;
- private ITool editor;
- public ITool Editor {
- set {
- if(this.editor != null) {
- this.editor.Redraw -= QueueDraw;
- if(this.editor is IToolCursorChange) {
- ((IToolCursorChange) this.editor).CursorChange -= CursorChange;
- //TODO: find a way how to reset it to default, this is wrong
- GdkWindow.Cursor = new Cursor(CursorType.LeftPtr);
- }
- if(this.editor is IDisposable)
- ((IDisposable) this.editor).Dispose();
- }
- this.editor = value;
- if(this.editor != null) {
- this.editor.Redraw += QueueDraw;
- if(this.editor is IToolCursorChange)
- ((IToolCursorChange) this.editor).CursorChange += CursorChange;
- }
- }
- get {
- return editor;
- }
- }
- public RenderView()
- {
- ButtonPressEvent += OnButtonPress;
- ButtonReleaseEvent += OnButtonRelease;
- MotionNotifyEvent += OnMotionNotify;
- ScrollEvent += OnScroll;
- AddEvents((int) Gdk.EventMask.ButtonPressMask);
- AddEvents((int) Gdk.EventMask.ButtonReleaseMask);
- AddEvents((int) Gdk.EventMask.PointerMotionMask);
- AddEvents((int) Gdk.EventMask.ScrollMask);
- CanFocus = true;
- Gtk.Drag.DestSet(this, DestDefaults.Drop | DestDefaults.Motion, DragTargetEntries, Gdk.DragAction.Copy);
- DragMotion += OnDragMotion;
- DragDataReceived += OnDragDataReceived;
- }
- protected override void DrawGl()
- {
- gl.ClearColor(0.4f, 0, 0.4f, 1);
- gl.Clear(gl.COLOR_BUFFER_BIT);
- if(SceneGraphRoot != null)
- SceneGraphRoot.Draw(GetClipRect());
- if(!dragging && Editor != null)
- Editor.Draw(GetClipRect());
- }
- private void OnDragMotion(object o, DragMotionArgs args)
- {
- //pass motion event to editor
- if(Editor != null) {
- MousePos = MouseToWorld(new Vector((float) args.X, (float) args.Y));
- Editor.OnMouseMotion(MousePos, ModifierType.Button1Mask);
- }
- }
- private void OnDragDataReceived(object o, DragDataReceivedArgs args)
- {
- // string data = System.Text.Encoding.UTF8.GetString (args.SelectionData.Data); //no data transmitted on "fake drag"s
- if(Editor != null) {
- MousePos = MouseToWorld(new Vector((float) args.X, (float) args.Y));
- //emulated click on current editor to place object and perform "fake drag"
- Editor.OnMouseButtonPress(MousePos, 1, ModifierType.Button1Mask);
- Editor.OnMouseButtonRelease(MousePos, 1, ModifierType.Button1Mask);
- Gtk.Drag.Finish (args.Context, true, false, args.Time);
- } else {
- LogManager.Log(LogLevel.Warning, "DragDataRecieved OK, but there is no editor that can handle it");
- Gtk.Drag.Finish (args.Context, false, false, args.Time);
- }
- }
- private void OnButtonPress(object o, ButtonPressEventArgs args)
- {
- try {
- MousePos = MouseToWorld(
- new Vector((float) args.Event.X, (float) args.Event.Y));
- if(args.Event.Button == 2) {
- dragStartMouse = new Vector((float) args.Event.X, (float) args.Event.Y);
- dragStartTranslation = Translation;
- dragging = true;
- QueueDraw();
- } else if(Editor != null) {
- Editor.OnMouseButtonPress(MousePos, (int) args.Event.Button, args.Event.State);
- }
- args.RetVal = true;
- } catch(Exception e) {
- ErrorDialog.Exception(e);
- }
- }
- private void OnButtonRelease(object o, ButtonReleaseEventArgs args)
- {
- try {
- MousePos = MouseToWorld(
- new Vector((float) args.Event.X, (float) args.Event.Y));
- if(args.Event.Button == 2) {
- dragging = false;
- QueueDraw();
- } else if(Editor != null) {
- Editor.OnMouseButtonRelease(MousePos, (int) args.Event.Button, args.Event.State);
- }
- args.RetVal = true;
- } catch(Exception e) {
- ErrorDialog.Exception(e);
- }
- }
- private void OnMotionNotify(object o, MotionNotifyEventArgs args)
- {
- try {
- Vector pos = new Vector((float) args.Event.X, (float) args.Event.Y);
- MousePos = MouseToWorld(pos);
- if(dragging) {
- SetTranslation(dragStartTranslation +
- (pos - dragStartMouse) / Zoom);
- } else if(Editor != null) {
- Editor.OnMouseMotion(MousePos, args.Event.State);
- }
- args.RetVal = true;
- } catch(Exception e) {
- ErrorDialog.Exception(e);
- }
- }
- private void OnScroll(object o, ScrollEventArgs args)
- {
- float oldZoom = Zoom;
- Vector realMousePos = (MousePos + Translation) * Zoom;
- if(args.Event.Direction == ScrollDirection.Down) {
- Zoom /= (float) Math.Sqrt(2);
- } else if(args.Event.Direction == ScrollDirection.Up) {
- Zoom *= (float) Math.Sqrt(2);
- }
- //Limit the Zoom to useful values;
- if( Zoom < 0.002 || Zoom > 500 ){
- Zoom = oldZoom;
- }
- SetTranslation(Translation
- + realMousePos / Zoom - realMousePos / oldZoom);
- MousePos = MouseToWorld(realMousePos);
- if(Editor != null) {
- Editor.OnMouseMotion(MousePos, args.Event.State);
- }
- args.RetVal = true;
- }
- private void UpdateAdjustments()
- {
- if(hadjustment != null) {
- hadjustment.SetBounds(minx, maxx, 32/Zoom, 256/Zoom, Allocation.Width/Zoom);
- hadjustment.ClampPage(-Translation.X, -Translation.X + (Allocation.Width/Zoom));
- }
- if(vadjustment != null) {
- vadjustment.SetBounds(miny, maxy, 32/Zoom, 256/Zoom, Allocation.Height/Zoom);
- vadjustment.ClampPage(-Translation.Y, -Translation.Y + (Allocation.Height/Zoom));
- }
- }
- public void SetZoom(float newZoom)
- {
- float oldZoom = Zoom;
- Zoom = newZoom;
- // Limit the Zoom to useful values;
- if( Zoom < 0.002 || Zoom > 500 ){
- Zoom = oldZoom;
- }
- UpdateAdjustments();
- QueueDraw();
- }
- public float GetZoom()
- {
- return Zoom;
- }
- public void ZoomIn()
- {
- SetZoom( Zoom * (float) Math.Sqrt(2));
- }
- public void ZoomOut()
- {
- SetZoom( Zoom / (float) Math.Sqrt(2));
- }
- /// <summary>Zoom by factor, while keeping pos (in World
- /// coordinates) at the same spot on the screen</summary>
- public void ZoomTo(Vector pos, float factor)
- {
- Vector old_translation = Translation;
- SetZoom(Zoom * factor);
- SetTranslation((pos * (1 - factor) + old_translation) / factor);
- }
- /// <summary>Zoom by factor, while keeping the center of the
- /// window at the same spot on the screen</summary>
- public void ZoomTo(float factor)
- {
- Vector pos = MouseToWorld(new Vector(Allocation.Width/2.0f, Allocation.Height/2.0f));
- ZoomTo(pos, factor);
- }
- public void ZoomTo(RectangleF rect)
- {
- float window_aspect = Allocation.Width / Allocation.Height;
- float rect_aspect = rect.Width / rect.Height;
- if (window_aspect > rect_aspect)
- {
- SetZoom(Allocation.Height / rect.Height);
- SetPosition(rect.Center);
- }
- else
- {
- SetZoom(Allocation.Width / rect.Width);
- SetPosition(rect.Center);
- }
- }
- /// <summary>Set the Translatation so that the center of the
- /// window poinst to pos (in World coordinates)</summary>
- public void SetPosition(Vector pos)
- {
- SetTranslation(new Vector(Allocation.Width/2.0f/Zoom - pos.X, Allocation.Height/2.0f/Zoom - pos.Y));
- }
- public void SetTranslation(Vector tr)
- {
- Translation = tr;
- UpdateAdjustments();
- QueueDraw();
- }
- public Vector GetTranslation()
- {
- return Translation;
- }
- /// <summary>
- /// Returns a <see cref="Gdk.Rectangle"/> for the currently
- /// visible area in world coordinates.
- /// </summary>
- /// <returns>A <see cref="Gdk.Rectangle"/>.</returns>
- public Gdk.Rectangle GetClipRect() {
- return new Gdk.Rectangle(
- (int)-Translation.X, (int)-Translation.Y,
- (int)(Allocation.Width / Zoom), (int)(Allocation.Height / Zoom));
- }
- private Vector MouseToWorld(Vector MousePos)
- {
- return MousePos / Zoom - Translation;
- }
- private void CursorChange(Cursor cursor)
- {
- GdkWindow.Cursor = cursor;
- }
- /**
- * Add gtk adjustments for vertical and horizontal scrolling
- * (This is used for scrollbars)
- */
- public void SetAdjustments(Adjustment hadjustment, Adjustment vadjustment)
- {
- this.vadjustment = vadjustment;
- this.hadjustment = hadjustment;
- if(vadjustment != null) {
- vadjustment.ValueChanged += OnVAdjustmentChanged;
- }
- if(hadjustment != null) {
- hadjustment.ValueChanged += OnHAdjustmentChanged;
- }
- UpdateAdjustments();
- }
- private void OnHAdjustmentChanged(object sender, EventArgs e)
- {
- SetTranslation(new Vector((float) -hadjustment.Value, Translation.Y));
- }
- private void OnVAdjustmentChanged(object sender, EventArgs e)
- {
- SetTranslation(new Vector(Translation.X, (float) -vadjustment.Value));
- }
- private Adjustment vadjustment;
- private Adjustment hadjustment;
- protected float minx = -1000, maxx = 1000;
- protected float miny = -1000, maxy = 1000;
- }
- /* EOF */
|