using System; using System.Collections.Generic; using System.Linq; using System.Text; using Azimuth; namespace Blacklight.Core.Cameras { public class Viewport { public int Width { get; private set; } public int Height { get; private set; } /// /// Sometimes we have need to convert pixel coordinates into /// something called "clip space", which in this case means /// ([-1,1], [-1,1]). Think of clip space as a point's relative /// position on the screen, with the center of the screen being /// (0,0), and the x and y axis mapping to normal cartesian /// space (that is, positive y is up). /// public AffineMatrix ProjectionToClip { get; private set; } public AffineMatrix ClipToProjection { get; private set; } public Viewport(int width, int height) { SneakResize(width, height); } /// /// The window has been resized and/or moved. deltaDims is the change /// in the viewport size, in pixels. deltaPos is the change in window /// location, in pixels. /// public event ResizeEvent Resized = delegate(Vector deltaDims, Vector deltaPos) { }; public delegate void ResizeEvent(Vector deltaDims, Vector deltaPos); /// /// The user requested a translate either by dragging the mouse or /// moving the joystick or whatever. deltaPS is expressed in projection /// space, ie: it's in pixels. /// public event TranslatePSEvent TranslatedPS = delegate(Vector deltaPS) { }; public delegate void TranslatePSEvent(Vector deltaPS); public void TranslatePS(Vector deltaPS) { TranslatedPS.Invoke(deltaPS); } /// /// The user requested to change the magnification (to zoom) either by /// using the mouse wheel or whatever. Magnification factor is multiplied /// against the current magnification to get the desired magnification. /// /// For instance, suppose the camera is at zoom level 2x right now. /// And we supply a magnificationFactor of 4. The new zoom level will /// be 8x. We supply the factor instead of either a new magnification or /// a delta magnification so that the code which registers user input /// can be agnostic about how zoomed in the current camera is. /// public event ZoomEvent Zoomed = delegate(Scalar magnificationFactor, Vector centerPS) { }; public delegate void ZoomEvent(Scalar magnificationFactor, Vector centerPS); public void Zoom(Scalar magnificationFactor, Vector centerPS) { Zoomed.Invoke(magnificationFactor, centerPS); } private void SneakResize(int width, int height) { //Clamp to valid range Width = Math.Max(1, width); Height = Math.Max(1, height); ProjectionToClip = new AffineMatrix( 2.0 / Width, 0, 0, 0, 2.0 / Height, 0); ClipToProjection = new AffineMatrix( Width / 2.0, 0, 0, 0, Height / 2.0, 0); } // Just resize the window public void Resize(int Width, int Height) { Resize(Width, Height, 0, 0); } // Resize the window + move it public void Resize(int width, int height, int deltaPosX, int deltaPosY) { int oldWidth = Width; int oldHeight = Height; SneakResize(width, height); // Call the derived class's resize function ResizeDrawSurface(width, height, deltaPosX, deltaPosY); //TODO: Do I need to invert Y for some reason? Resized.Invoke(new Vector(Width - oldWidth, Height - oldHeight), new Vector(deltaPosX, deltaPosY)); } /// /// Called when the window gets resized. You should perform any necessary actions on the /// draw surface to stretch/shrink it to match the new dimensions of the window /// /// The new width, in pixels, of the window /// The new height, in pixels, of the window /// If the window was dragged, this is the change in X pos in pixels /// If the window was dragged, this is the change in Y pos in pixels protected virtual void ResizeDrawSurface(int Width, int Height, int deltaPosX, int deltaPosY) { } } }