2007-07-23 00:15:18 +00:00
#region - - - License - - -
/ * Copyright ( c ) 2006 , 2007 Stefanos Apostolopoulos
* See license . txt for license info
* /
#endregion
using System ;
using System.Collections.Generic ;
using System.Text ;
2007-07-26 22:56:55 +00:00
using System.Diagnostics ;
2007-07-23 00:15:18 +00:00
using OpenTK.Platform ;
namespace OpenTK
{
2007-08-04 12:09:58 +00:00
public class GameWindow : OpenTK . Platform . IGameWindow
2007-07-23 00:15:18 +00:00
{
2007-07-26 22:56:55 +00:00
private INativeWindow glWindow ;
2007-07-23 00:15:18 +00:00
private ResizeEventArgs resizeEventArgs = new ResizeEventArgs ( ) ;
2007-08-04 12:09:58 +00:00
private DisplayMode mode ;
2007-07-23 00:15:18 +00:00
2007-08-04 13:28:16 +00:00
private InputDriver inputDevices ;
public IList < Input . Keyboard > Keyboard { get { return Input . Keyboard ; } }
public InputDriver Input
2007-08-04 12:09:58 +00:00
{
get
{
if ( inputDevices = = null )
2007-08-04 13:28:16 +00:00
inputDevices = new InputDriver ( this . Handle ) ;
2007-08-04 12:09:58 +00:00
return inputDevices ;
}
}
2007-08-03 00:14:31 +00:00
2007-07-23 00:15:18 +00:00
#region - - - Contructors - - -
/// <summary>
/// Constructs a new GameWindow, using a safe DisplayMode.
/// </summary>
public GameWindow ( )
{
if ( Environment . OSVersion . Platform = = PlatformID . Win32NT | |
Environment . OSVersion . Platform = = PlatformID . Win32Windows )
{
// Create a new Windows native window. We want to be notified when it's ready,
// in order to do some preparatory work.
glWindow = new OpenTK . Platform . Windows . WinGLNative ( ) ;
}
else if ( Environment . OSVersion . Platform = = PlatformID . Unix | |
Environment . OSVersion . Platform = = ( PlatformID ) 128 ) // some older versions of Mono reported 128.
{
glWindow = new OpenTK . Platform . X11 . X11GLNative ( ) ;
}
else
{
throw new PlatformNotSupportedException (
"Your operating system is not currently supported. We are sorry for the inconvenience."
) ;
}
glWindow . Resize + = new ResizeEvent ( glWindow_Resize ) ;
glWindow . Create + = new CreateEvent ( glWindow_Create ) ;
}
void glWindow_Create ( object sender , EventArgs e )
{
2007-08-04 12:09:58 +00:00
//glWindow.Context.MakeCurrent();
2007-08-04 13:28:16 +00:00
inputDevices = new InputDriver ( this . Handle ) ;
2007-08-04 12:09:58 +00:00
2007-07-23 00:15:18 +00:00
this . OnCreate ( e ) ;
}
void glWindow_Resize ( object sender , ResizeEventArgs e )
{
this . OnResize ( e ) ;
}
#endregion
2007-08-04 12:09:58 +00:00
#region - - - INativeWindow Members - - -
#region public void CreateWindow ( DisplayMode mode )
/// <summary>
/// Creates a new render window.
/// </summary>
/// <param name="mode">The DisplayMode of the render window.</param>
/// <exception cref="ApplicationException">Occurs when a render window already exists.</exception>
public void CreateWindow ( DisplayMode mode )
{
if ( ! Created )
{
glWindow . CreateWindow ( mode ) ;
}
else
{
throw new ApplicationException ( "A render window already exists" ) ;
}
}
#endregion
#region public IntPtr Handle
/// <summary>
/// Gets the handle of the current GameWindow.
/// </summary>
public IntPtr Handle
{
get { return glWindow . Handle ; }
}
#endregion
#region public void Exit ( )
/// <summary>
/// Gracefully exits the current GameWindow.
/// </summary>
public void Exit ( )
{
glWindow . Exit ( ) ;
}
#endregion
2007-07-23 00:15:18 +00:00
#region public bool IsIdle
2007-08-04 12:09:58 +00:00
/// <summary>
/// Gets a value indicating whether the current GameWindow is idle.
/// If true, the OnUpdateFrame and OnRenderFrame functions should be called.
/// </summary>
2007-07-23 00:15:18 +00:00
public bool IsIdle
{
get { return glWindow . IsIdle ; }
}
#endregion
2007-08-04 12:09:58 +00:00
#region public bool Quit
/// <summary>
/// Gets a value indicating whether the current GameWindow is quitting.
/// </summary>
/// <remarks>
/// You should not call OnRenderFrame, Resize, and other GameWindow related function
/// when the quit sequence has been initiated, as indicated by the Quitting property.
/// NullReference- or ApplicationExceptions may occur otherwise.
/// </remarks>
public bool Quit
{
get { return glWindow . Quit ; }
}
#endregion
2007-07-23 00:15:18 +00:00
#region public bool Fullscreen
public bool Fullscreen
{
get { return glWindow . Fullscreen ; }
set { glWindow . Fullscreen = value ; }
}
#endregion
2007-08-04 12:09:58 +00:00
#region public IGLContext Context
2007-07-23 00:15:18 +00:00
2007-08-04 12:09:58 +00:00
/// <summary>
/// Returns the opengl IGLontext associated with the current GameWindow.
/// Forces window creation.
/// </summary>
public IGLContext Context
2007-07-23 00:15:18 +00:00
{
2007-08-04 12:09:58 +00:00
get
{
if ( ! glWindow . Created )
{
2007-08-04 12:17:30 +00:00
Debug . WriteLine ( "WARNING: OpenGL Context accessed before creating a render window. This may indicate a programming error. Force-creating a render window." ) ;
2007-08-04 12:09:58 +00:00
mode = new DisplayMode ( 640 , 480 ) ;
this . CreateWindow ( mode ) ;
}
return glWindow . Context ;
}
2007-07-23 00:15:18 +00:00
}
#endregion
2007-08-04 12:09:58 +00:00
#region public bool Created
2007-07-23 00:15:18 +00:00
2007-08-04 12:09:58 +00:00
/// <summary>
/// Gets a value indicating whether a render window has been created.
/// </summary>
public bool Created
2007-07-23 00:15:18 +00:00
{
2007-08-04 12:09:58 +00:00
get { return glWindow . Created ; }
2007-07-23 00:15:18 +00:00
}
#endregion
#endregion
#region - - - IGameWindow Members - - -
2007-08-04 12:09:58 +00:00
#region public virtual void Run ( )
2007-07-23 00:15:18 +00:00
/// <summary>
2007-08-04 12:09:58 +00:00
/// Runs the default game loop on GameWindow (process event->update frame->render frame).
2007-07-23 00:15:18 +00:00
/// </summary>
/// <remarks>
/// <para>
/// A default game loop consists of three parts: Event processing,
/// a frame update and a frame render.
/// </para>
/// <para>
/// Override this function if you want to change the behaviour of the
/// default game loop. If you override this function, you must place
2007-08-04 12:09:58 +00:00
/// a call to the ProcessEvents function, to ensure window will respond
2007-07-23 00:15:18 +00:00
/// to Operating System events.
/// </para>
/// </remarks>
public virtual void Run ( )
{
while ( ! this . Quit )
{
this . ProcessEvents ( ) ;
2007-08-04 12:09:58 +00:00
this . OnUpdateFrame ( ) ;
this . OnRenderFrame ( ) ;
2007-07-23 00:15:18 +00:00
}
}
2007-08-04 12:09:58 +00:00
#endregion
#region public void ProcessEvents ( )
/// <summary>
/// Processes operating system events until the GameWindow becomes idle.
/// </summary>
/// <remarks>
/// When overriding the default GameWindow game loop (provided by the Run() function)
/// you should call ProcessEvents() to ensure that your GameWindow responds to
/// operating system events.
/// <para>
/// Once ProcessEvents() returns, it is time to call update and render the next frame.
/// </para>
/// </remarks>
2007-07-23 00:15:18 +00:00
public void ProcessEvents ( )
{
glWindow . ProcessEvents ( ) ;
}
2007-08-04 12:09:58 +00:00
#endregion
2007-07-23 00:15:18 +00:00
#region public event CreateEvent Create ;
public event CreateEvent Create ;
private void OnCreate ( EventArgs e )
{
if ( this . Create ! = null )
{
this . Create ( this , e ) ;
}
}
#endregion
2007-08-04 12:09:58 +00:00
#region public virtual void OnRenderFrame ( )
/// <summary>
/// Raises the RenderFrame event. Override in derived classes to render a frame.
/// </summary>
/// <remarks>
/// If overriden, the base.OnRenderFrame() function should be called, to ensure
/// listeners are notified of RenderFrame events.
/// </remarks>
public virtual void OnRenderFrame ( )
2007-07-23 00:15:18 +00:00
{
2007-08-04 12:09:58 +00:00
if ( ! this . Created )
{
Debug . Print ( "WARNING: RenderFrame event raised, without a valid render window. This may indicate a programming error. Creating render window." ) ;
mode = new DisplayMode ( 640 , 480 ) ;
this . CreateWindow ( mode ) ;
}
if ( RenderFrame ! = null )
RenderFrame ( EventArgs . Empty ) ;
2007-07-23 00:15:18 +00:00
}
2007-08-04 12:09:58 +00:00
#endregion
#region public virtual void OnUpdateFrame ( )
/// <summary>
/// Raises the UpdateFrame event. Override in derived classes to update a frame.
/// </summary>
/// <remarks>
/// If overriden, the base.OnUpdateFrame() function should be called, to ensure
/// listeners are notified of UpdateFrame events.
/// </remarks>
public virtual void OnUpdateFrame ( )
2007-07-23 00:15:18 +00:00
{
2007-08-04 12:09:58 +00:00
if ( ! this . Created )
{
Debug . Print ( "WARNING: UpdateFrame event raised, without a valid render window. This may indicate a programming error. Creating render window." ) ;
mode = new DisplayMode ( 640 , 480 ) ;
this . CreateWindow ( mode ) ;
}
if ( UpdateFrame ! = null )
UpdateFrame ( EventArgs . Empty ) ;
2007-07-23 00:15:18 +00:00
}
2007-08-04 12:09:58 +00:00
#endregion
/// <summary>
/// Occurs when it is time to update the next frame.
/// </summary>
public event UpdateFrameEvent UpdateFrame ;
/// <summary>
/// Occurs when it is time to render the next frame.
/// </summary>
public event RenderFrameEvent RenderFrame ;
2007-07-23 00:15:18 +00:00
#endregion
#region - - - IResizable Members - - -
#region public int Width , Height
public int Width
{
get { return glWindow . Width ; }
set
{
if ( value = = this . Width )
{
return ;
}
else if ( value > 0 )
{
glWindow . Width = value ;
}
else
{
throw new ArgumentOutOfRangeException (
"Width" ,
value ,
"Width must be greater than 0"
) ;
}
}
}
public int Height
{
get { return glWindow . Height ; }
set
{
if ( value = = this . Height )
{
return ;
}
else if ( value > 0 )
{
glWindow . Height = value ;
}
else
{
throw new ArgumentOutOfRangeException (
"Height" ,
value ,
"Height must be greater than 0"
) ;
}
}
}
#endregion
#region public event ResizeEvent Resize ;
public event ResizeEvent Resize ;
/// <summary>
/// Raises the Resize event.
/// </summary>
/// <param name="e">Contains the new Width and Height of the window.</param>
protected virtual void OnResize ( ResizeEventArgs e )
{
if ( this . Resize ! = null )
this . Resize ( this , e ) ;
}
#endregion
#endregion
#region - - - IDisposable Members - - -
public void Dispose ( )
{
glWindow . Dispose ( ) ;
glWindow = null ;
}
#endregion
}
}