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) { }
}
}