Bumped version numbers.

WinRawInput now correctly subclasses WinGLNative or WinGLControl. WinRawKeyboard now correctly responds to events.
Removed T10_GLSL_Cube.cs which was erroneously moved outside the Examples/Tutorial directory.
Updated INativeWindow, IGameWindow and IGLControl interfaces.
Updated examples to use the new GameWindow interface.
Added documentation to GameWindow.
Improved GameWindow error handling. More defensive programming.
This commit is contained in:
the_fiddler 2007-08-04 12:09:58 +00:00
parent 2f64fb372e
commit 59b503b3c3
33 changed files with 1275 additions and 908 deletions

View file

@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion("0.9.7.2")] [assembly: AssemblyVersion("0.9.7.3")]
[assembly: AssemblyFileVersion("0.9.7.2")] [assembly: AssemblyFileVersion("0.9.7.3")]

View file

@ -12,6 +12,7 @@ using System.Diagnostics;
using System.Security; using System.Security;
using System.Security.Permissions; using System.Security.Permissions;
using System.Security.Policy; using System.Security.Policy;
using System.IO;
namespace Examples namespace Examples
{ {
@ -29,13 +30,12 @@ namespace Examples
Application.Run(exampleLauncher); Application.Run(exampleLauncher);
} }
} }
StreamWriter sw = new StreamWriter(Path.Combine(System.Environment.CurrentDirectory, "keymap.log"));
public ExampleLauncher() public ExampleLauncher()
{ {
InitializeComponent(); InitializeComponent();
System.Diagnostics.Debug.Listeners.Clear(); System.Diagnostics.Debug.Listeners.Clear();
System.Diagnostics.Debug.Listeners.Add(new TextWriterTraceListener(Console.Out)); System.Diagnostics.Debug.Listeners.Add(new TextWriterTraceListener(sw));
System.Diagnostics.Debug.AutoFlush = true; System.Diagnostics.Debug.AutoFlush = true;
System.Diagnostics.Trace.Listeners.Clear(); System.Diagnostics.Trace.Listeners.Clear();
System.Diagnostics.Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); System.Diagnostics.Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
@ -43,6 +43,12 @@ namespace Examples
Trace.AutoFlush = true; Trace.AutoFlush = true;
} }
~ExampleLauncher()
{
sw.Flush();
sw.Close();
}
private void listBox1_DoubleClick(object sender, EventArgs e) private void listBox1_DoubleClick(object sender, EventArgs e)
{ {
if (listBox1.SelectedItem != null) if (listBox1.SelectedItem != null)
@ -87,7 +93,15 @@ namespace Examples
void Launch(object example) void Launch(object example)
{ {
Type ex = example as Type; Type ex = example as Type;
try
{
(ex.GetConstructor(Type.EmptyTypes).Invoke(null) as IExample).Launch(); (ex.GetConstructor(Type.EmptyTypes).Invoke(null) as IExample).Launch();
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
//throw;
}
//(example as Type).InvokeMember("Launch", BindingFlags.InvokeMethod, null, example, null); //(example as Type).InvokeMember("Launch", BindingFlags.InvokeMethod, null, example, null);
/* /*
AppDomain app = AppDomain.CreateDomain((example as Type).Name); AppDomain app = AppDomain.CreateDomain((example as Type).Name);

View file

@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion("0.3.9.0")] [assembly: AssemblyVersion("0.3.9.2")]
[assembly: AssemblyFileVersion("0.3.9.0")] [assembly: AssemblyFileVersion("0.3.9.2")]

View file

@ -1,228 +0,0 @@
#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#endregion
#region --- Using Directives ---
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using OpenTK.OpenGL;
using Enums = OpenTK.OpenGL.GL.Enums;
using OpenTK;
using OpenTK.Input;
#endregion --- Using Directives ---
namespace Examples.Tutorial
{
public class T10_GLSL_Cube : GameWindow, IExample
{
#region --- Fields ---
#region Shaders
string[] vertex_shader_source =
{
"void main() {",
"gl_FrontColor = gl_Color;",
"gl_Position = ftransform();",
"}",
};
string[] fragment_shader_source =
{
"void main() { gl_FragColor = gl_Color; }\0"
};
#endregion
static float angle;
#endregion
#region --- Constructors ---
public T10_GLSL_Cube()
{
Context.MakeCurrent();
//Text =
// GL.GetString(Enums.StringName.VENDOR) + " " +
// GL.GetString(Enums.StringName.RENDERER) + " " +
// GL.GetString(Enums.StringName.VERSION);
GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f);
GL.Enable(Enums.EnableCap.DEPTH_TEST);
int vertex_shader_object, fragment_shader_object;
int status;
int shader_program;
vertex_shader_object = GL.CreateShader(Enums.VERSION_2_0.VERTEX_SHADER);
fragment_shader_object = GL.CreateShader(Enums.VERSION_2_0.FRAGMENT_SHADER);
GL.ShaderSource(vertex_shader_object, vertex_shader_source.Length, vertex_shader_source, (int[])null);
GL.CompileShader(vertex_shader_object);
GL.GetShader(vertex_shader_object, Enums.VERSION_2_0.COMPILE_STATUS, out status);
if (status != (int)Enums.Boolean.TRUE)
{
StringBuilder info = new StringBuilder(1024);
GL.GetShaderInfoLog(vertex_shader_object, info.MaxCapacity, (int[])null, info);
throw new Exception(info.ToString());
}
GL.ShaderSource(fragment_shader_object, fragment_shader_source.Length, fragment_shader_source, (int[])null);
GL.CompileShader(fragment_shader_object);
GL.GetShader(fragment_shader_object, Enums.VERSION_2_0.COMPILE_STATUS, out status);
if (status != (int)Enums.Boolean.TRUE)
{
StringBuilder info = new StringBuilder(1024);
GL.GetShaderInfoLog(fragment_shader_object, 1024, (int[])null, info);
throw new Exception(info.ToString());
}
shader_program = GL.CreateProgram();
GL.AttachShader(shader_program, fragment_shader_object);
GL.AttachShader(shader_program, vertex_shader_object);
GL.LinkProgram(shader_program);
GL.UseProgram(shader_program);
OnResize(new OpenTK.Platform.ResizeEventArgs(this.Width, this.Height));
}
#endregion
#region static public void Launch()
/// <summary>
/// Launches this example.
/// </summary>
/// <remarks>
/// Provides a simple way for the example launcher to launch the examples.
/// </remarks>
static public void Launch()
{
using (T10_GLSL_Cube ex = new T10_GLSL_Cube())
{
ex.Run();
}
}
#endregion
#region OnResize
protected override void OnResize(OpenTK.Platform.ResizeEventArgs e)
{
base.OnResize(e);
GL.Viewport(0, 0, this.Width, this.Height);
double ratio = 0.0;
ratio = this.Width / (double)this.Height;
GL.MatrixMode(Enums.MatrixMode.PROJECTION);
GL.LoadIdentity();
Glu.Perspective(45.0, ratio, 1.0, 64.0);
}
#endregion
#region UpdateFrame
public override void UpdateFrame()
{
base.UpdateFrame();
if (Key[OpenTK.Input.Keys.Escape])
{
this.Quit = true;
}
GL.MatrixMode(Enums.MatrixMode.MODELVIEW);
GL.LoadIdentity();
Glu.LookAt(
0.0, 5.0, 5.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0
);
GL.Rotatef(angle, 0.0f, 1.0f, 0.0f);
angle += 0.05f;
}
#endregion
#region RenderFrame
public override void RenderFrame()
{
base.RenderFrame();
GL.Clear(Enums.ClearBufferMask.COLOR_BUFFER_BIT | Enums.ClearBufferMask.DEPTH_BUFFER_BIT);
DrawCube();
Context.SwapBuffers();
}
#endregion
#region DrawCube
public void DrawCube()
{
GL.Begin(Enums.BeginMode.QUADS);
GL.Color3(1, 0, 0);
GL.Vertex3(-1.0f, -1.0f, -1.0f);
GL.Vertex3(-1.0f, 1.0f, -1.0f);
GL.Vertex3(1.0f, 1.0f, -1.0f);
GL.Vertex3(1.0f, -1.0f, -1.0f);
GL.Color3(1, 1, 0);
GL.Vertex3(-1.0f, -1.0f, -1.0f);
GL.Vertex3(1.0f, -1.0f, -1.0f);
GL.Vertex3(1.0f, -1.0f, 1.0f);
GL.Vertex3(-1.0f, -1.0f, 1.0f);
GL.Color3(1, 0, 1);
GL.Vertex3(-1.0f, -1.0f, -1.0f);
GL.Vertex3(-1.0f, -1.0f, 1.0f);
GL.Vertex3(-1.0f, 1.0f, 1.0f);
GL.Vertex3(-1.0f, 1.0f, -1.0f);
GL.Color3(0, 1, 0);
GL.Vertex3(-1.0f, -1.0f, 1.0f);
GL.Vertex3(1.0f, -1.0f, 1.0f);
GL.Vertex3(1.0f, 1.0f, 1.0f);
GL.Vertex3(-1.0f, 1.0f, 1.0f);
GL.Color3(0, 0, 1);
GL.Vertex3(-1.0f, 1.0f, -1.0f);
GL.Vertex3(-1.0f, 1.0f, 1.0f);
GL.Vertex3(1.0f, 1.0f, 1.0f);
GL.Vertex3(1.0f, 1.0f, -1.0f);
GL.Color3(0, 1, 1);
GL.Vertex3(1.0f, -1.0f, -1.0f);
GL.Vertex3(1.0f, 1.0f, -1.0f);
GL.Vertex3(1.0f, 1.0f, 1.0f);
GL.Vertex3(1.0f, -1.0f, 1.0f);
GL.End();
}
#endregion
}
}

View file

@ -103,5 +103,14 @@ namespace Examples.Tests
this.Close(); this.Close();
} }
} }
#region IExample Members
public void Launch()
{
}
#endregion
} }
} }

View file

@ -18,13 +18,6 @@ namespace Examples.Tests
public void Launch() public void Launch()
{ {
using (StreamWriter sw = new StreamWriter(Path.Combine(System.Environment.CurrentDirectory, "keymap.log")))
{
//Debug.Listeners.Clear();
Debug.Listeners.Add(new TextWriterTraceListener(sw));
Debug.AutoFlush = true;
Debug.WriteLine("Starting key dump");
//using (S02_RawInput_Logger ex = new S02_RawInput_Logger()) //using (S02_RawInput_Logger ex = new S02_RawInput_Logger())
{ {
try try
@ -57,7 +50,7 @@ namespace Examples.Tests
} }
Debug.Flush(); Debug.Flush();
Debug.Close(); Debug.Close();
}
} }
#endregion #endregion
@ -67,12 +60,23 @@ namespace Examples.Tests
GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
} }
public override void RenderFrame() public override void OnRenderFrame()
{ {
base.RenderFrame(); base.OnRenderFrame();
GL.Clear(GL.Enums.ClearBufferMask.COLOR_BUFFER_BIT); GL.Clear(GL.Enums.ClearBufferMask.COLOR_BUFFER_BIT);
Context.SwapBuffers(); Context.SwapBuffers();
} }
public override void Run()
{
while (!Quit)
{
ProcessEvents();
OnUpdateFrame();
OnRenderFrame();
Thread.Sleep(10);
}
}
} }
} }

View file

@ -34,6 +34,8 @@ namespace Examples.Tutorial
public T03_RotatingCube() public T03_RotatingCube()
{ {
CreateWindow(new DisplayMode(800, 600));
Context.MakeCurrent(); Context.MakeCurrent();
GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f); GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f);
@ -68,7 +70,7 @@ namespace Examples.Tutorial
#endregion #endregion
#region UpdateFrame function #region OnUpdateFrame function
/// <summary> /// <summary>
/// Prepares the next frame for rendering. /// Prepares the next frame for rendering.
@ -77,16 +79,16 @@ namespace Examples.Tutorial
/// Place your control logic here. This is the place to respond to user input, /// Place your control logic here. This is the place to respond to user input,
/// update object positions etc. /// update object positions etc.
/// </remarks> /// </remarks>
public override void UpdateFrame() public override void OnUpdateFrame()
{ {
if (Key[OpenTK.Input.Keys.Escape]) if (Keyboard[0][OpenTK.Input.Keys.Escape])
{ {
Quit = true; this.Exit();
return; return;
} }
if ((Key[OpenTK.Input.Keys.LeftAlt] || Key[OpenTK.Input.Keys.RightAlt]) && if ((Keyboard[0][OpenTK.Input.Keys.LeftAlt] || Keyboard[0][OpenTK.Input.Keys.RightAlt]) &&
Key[OpenTK.Input.Keys.Enter]) Keyboard[0][OpenTK.Input.Keys.Enter])
{ {
Fullscreen = true; Fullscreen = true;
} }
@ -105,12 +107,12 @@ namespace Examples.Tutorial
#endregion #endregion
#region RenderFrame function #region OnRenderFrame function
/// <summary> /// <summary>
/// Place your rendering code here. /// Place your rendering code here.
/// </summary> /// </summary>
public override void RenderFrame() public override void OnRenderFrame()
{ {
GL.Clear(Enums.ClearBufferMask.COLOR_BUFFER_BIT | Enums.ClearBufferMask.DEPTH_BUFFER_BIT); GL.Clear(Enums.ClearBufferMask.COLOR_BUFFER_BIT | Enums.ClearBufferMask.DEPTH_BUFFER_BIT);
@ -178,12 +180,8 @@ namespace Examples.Tutorial
/// </remarks> /// </remarks>
public void Launch() public void Launch()
{ {
//using (T03_RotatingCube ex = new T03_RotatingCube())
{
//ex.Run();
Run(); Run();
} }
}
#endregion #endregion
} }

View file

@ -34,6 +34,7 @@ namespace Examples.Tutorial
public T07_DisplayLists_Cube() public T07_DisplayLists_Cube()
{ {
this.CreateWindow(new OpenTK.Platform.DisplayMode(800, 600));
//Text = //Text =
// "DisplayLists example (" + // "DisplayLists example (" +
// GL.GetString(Enums.StringName.RENDERER) + " " + // GL.GetString(Enums.StringName.RENDERER) + " " +
@ -89,12 +90,8 @@ namespace Examples.Tutorial
/// </remarks> /// </remarks>
public void Launch() public void Launch()
{ {
//using (T03_RotatingCube ex = new T03_RotatingCube())
{
//ex.Run();
Run(); Run();
} }
}
#endregion #endregion
@ -123,11 +120,11 @@ namespace Examples.Tutorial
#endregion #endregion
#region RenderFrame #region OnRenderFrame
public override void RenderFrame() public override void OnRenderFrame()
{ {
base.RenderFrame(); base.OnRenderFrame();
GL.MatrixMode(Enums.MatrixMode.MODELVIEW); GL.MatrixMode(Enums.MatrixMode.MODELVIEW);
GL.LoadIdentity(); GL.LoadIdentity();
@ -151,15 +148,15 @@ namespace Examples.Tutorial
#endregion #endregion
#region UpdateFrame #region OnUpdateFrame
public override void UpdateFrame() public override void OnUpdateFrame()
{ {
base.UpdateFrame(); base.OnUpdateFrame();
if (Key[OpenTK.Input.Keys.Escape]) if (Keyboard[0][OpenTK.Input.Keys.Escape])
{ {
this.Quit = true; this.Exit();
} }
} }

View file

@ -72,6 +72,8 @@ namespace Examples.Tutorial
public T08_VBO() public T08_VBO()
{ {
this.CreateWindow(new DisplayMode(800, 600));
this.Context.MakeCurrent(); this.Context.MakeCurrent();
GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f); GL.ClearColor(0.1f, 0.1f, 0.5f, 0.0f);
@ -86,11 +88,11 @@ namespace Examples.Tutorial
#endregion #endregion
#region RenderFrame #region OnRenderFrame
public override void RenderFrame() public override void OnRenderFrame()
{ {
base.RenderFrame(); base.OnRenderFrame();
GL.Clear( GL.Clear(
GL.Enums.ClearBufferMask.COLOR_BUFFER_BIT | GL.Enums.ClearBufferMask.COLOR_BUFFER_BIT |
@ -117,7 +119,7 @@ namespace Examples.Tutorial
#endregion #endregion
#region UpdateFrame #region OnUpdateFrame
/// <summary> /// <summary>
/// Prepares the next frame for rendering. /// Prepares the next frame for rendering.
@ -126,11 +128,11 @@ namespace Examples.Tutorial
/// Place your control logic here. This is the place to respond to user input, /// Place your control logic here. This is the place to respond to user input,
/// update object positions etc. /// update object positions etc.
/// </remarks> /// </remarks>
public override void UpdateFrame() public override void OnUpdateFrame()
{ {
if (Key[OpenTK.Input.Keys.Escape]) if (Keyboard[0][OpenTK.Input.Keys.Escape])
{ {
Quit = true; this.Exit();
return; return;
} }

View file

@ -138,15 +138,15 @@ namespace Examples.Tutorial
#endregion #endregion
#region UpdateFrame #region OnUpdateFrame
public override void UpdateFrame() public override void OnUpdateFrame()
{ {
base.UpdateFrame(); base.OnUpdateFrame();
if (Key[OpenTK.Input.Keys.Escape]) if (Keyboard[0][OpenTK.Input.Keys.Escape])
{ {
this.Quit = true; this.Exit();
} }
GL.MatrixMode(GL.Enums.MatrixMode.MODELVIEW); GL.MatrixMode(GL.Enums.MatrixMode.MODELVIEW);
@ -162,11 +162,11 @@ namespace Examples.Tutorial
#endregion #endregion
#region RenderFrame #region OnRenderFrame
public override void RenderFrame() public override void OnRenderFrame()
{ {
base.RenderFrame(); base.OnRenderFrame();
GL.Clear(GL.Enums.ClearBufferMask.COLOR_BUFFER_BIT | GL.Enums.ClearBufferMask.DEPTH_BUFFER_BIT); GL.Clear(GL.Enums.ClearBufferMask.COLOR_BUFFER_BIT | GL.Enums.ClearBufferMask.DEPTH_BUFFER_BIT);

View file

@ -206,5 +206,14 @@ namespace Examples.WinForms
GL.End(); GL.End();
} }
#endregion #endregion
#region IExample Members
public void Launch()
{
}
#endregion
} }
} }

View file

@ -71,5 +71,14 @@ namespace Examples.WinForms
break; break;
} }
} }
#region IExample Members
public void Launch()
{
}
#endregion
} }
} }

View file

@ -249,11 +249,6 @@ namespace OpenTK
#endregion #endregion
public void ProcessEvents()
{
throw new Exception("The method or operation is not implemented.");
}
#endregion #endregion
#region --- IResizable Members --- #region --- IResizable Members ---

View file

@ -13,14 +13,23 @@ using OpenTK.Platform;
namespace OpenTK namespace OpenTK
{ {
public class GameWindow : OpenTK.Platform.IGLControl, OpenTK.Platform.IGameWindow public class GameWindow : OpenTK.Platform.IGameWindow
{ {
private INativeWindow glWindow; private INativeWindow glWindow;
private ResizeEventArgs resizeEventArgs = new ResizeEventArgs(); private ResizeEventArgs resizeEventArgs = new ResizeEventArgs();
private DisplayMode mode;
public Input.IKeyboard Keyboard { get { return inputDevices.Keyboards[0]; } } private InputDevices inputDevices;
public IList<Input.Keyboard> Keyboard { get { return Input.Keyboards; } }
private InputDevices inputDevices = new InputDevices(); public InputDevices Input
{
get
{
if (inputDevices == null)
inputDevices = new InputDevices(this.Handle);
return inputDevices;
}
}
#region --- Contructors --- #region --- Contructors ---
@ -29,13 +38,6 @@ namespace OpenTK
/// </summary> /// </summary>
public GameWindow() public GameWindow()
{ {
System.Diagnostics.Debug.Listeners.Clear();
System.Diagnostics.Debug.Listeners.Add(new TextWriterTraceListener(Console.Out));
System.Diagnostics.Debug.AutoFlush = true;
System.Diagnostics.Trace.Listeners.Clear();
System.Diagnostics.Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
System.Diagnostics.Trace.AutoFlush = true;
if (Environment.OSVersion.Platform == PlatformID.Win32NT || if (Environment.OSVersion.Platform == PlatformID.Win32NT ||
Environment.OSVersion.Platform == PlatformID.Win32Windows) Environment.OSVersion.Platform == PlatformID.Win32Windows)
{ {
@ -55,17 +57,15 @@ namespace OpenTK
); );
} }
glWindow.Context.MakeCurrent();
// When the glWindow construction is complete, hook the resize events.
resizeEventArgs.Width = this.Width;
resizeEventArgs.Height = this.Height;
glWindow.Resize += new ResizeEvent(glWindow_Resize); glWindow.Resize += new ResizeEvent(glWindow_Resize);
glWindow.Create += new CreateEvent(glWindow_Create); glWindow.Create += new CreateEvent(glWindow_Create);
} }
void glWindow_Create(object sender, EventArgs e) void glWindow_Create(object sender, EventArgs e)
{ {
//glWindow.Context.MakeCurrent();
inputDevices = new InputDevices(this.Handle);
this.OnCreate(e); this.OnCreate(e);
} }
@ -76,10 +76,59 @@ namespace OpenTK
#endregion #endregion
#region --- IGLControl Members --- #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
#region public bool IsIdle #region public bool IsIdle
/// <summary>
/// Gets a value indicating whether the current GameWindow is idle.
/// If true, the OnUpdateFrame and OnRenderFrame functions should be called.
/// </summary>
public bool IsIdle public bool IsIdle
{ {
get { return glWindow.IsIdle; } get { return glWindow.IsIdle; }
@ -87,6 +136,23 @@ namespace OpenTK
#endregion #endregion
#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
#region public bool Fullscreen #region public bool Fullscreen
public bool Fullscreen public bool Fullscreen
@ -97,21 +163,35 @@ namespace OpenTK
#endregion #endregion
#region public OpenTK.Platform.IGLContext Context #region public IGLContext Context
public OpenTK.Platform.IGLContext Context /// <summary>
/// Returns the opengl IGLontext associated with the current GameWindow.
/// Forces window creation.
/// </summary>
public IGLContext Context
{ {
get { return glWindow.Context; } get
{
if (!glWindow.Created)
{
mode = new DisplayMode(640, 480);
this.CreateWindow(mode);
}
return glWindow.Context;
}
} }
#endregion #endregion
#region public bool Quit #region public bool Created
public bool Quit /// <summary>
/// Gets a value indicating whether a render window has been created.
/// </summary>
public bool Created
{ {
get { return glWindow.Quit; } get { return glWindow.Created; }
set { glWindow.Quit = value; }
} }
#endregion #endregion
@ -120,8 +200,10 @@ namespace OpenTK
#region --- IGameWindow Members --- #region --- IGameWindow Members ---
#region public virtual void Run()
/// <summary> /// <summary>
/// Runs a default game loop on the GameWindow. /// Runs the default game loop on GameWindow (process event->update frame->render frame).
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
@ -131,7 +213,7 @@ namespace OpenTK
/// <para> /// <para>
/// Override this function if you want to change the behaviour of the /// Override this function if you want to change the behaviour of the
/// default game loop. If you override this function, you must place /// default game loop. If you override this function, you must place
/// a call to the ProcessEvents function, so that your window will respond /// a call to the ProcessEvents function, to ensure window will respond
/// to Operating System events. /// to Operating System events.
/// </para> /// </para>
/// </remarks> /// </remarks>
@ -140,16 +222,33 @@ namespace OpenTK
while (!this.Quit) while (!this.Quit)
{ {
this.ProcessEvents(); this.ProcessEvents();
this.UpdateFrame(); this.OnUpdateFrame();
this.RenderFrame(); this.OnRenderFrame();
} }
} }
#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>
public void ProcessEvents() public void ProcessEvents()
{ {
glWindow.ProcessEvents(); glWindow.ProcessEvents();
} }
#endregion
#region public event CreateEvent Create; #region public event CreateEvent Create;
public event CreateEvent Create; public event CreateEvent Create;
@ -164,20 +263,61 @@ namespace OpenTK
#endregion #endregion
public virtual void RenderFrame() #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()
{ {
if (RenderFrameNotify != null) if (!this.Created)
RenderFrameNotify(EventArgs.Empty); {
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);
} }
public virtual void UpdateFrame() #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()
{ {
if (UpdateFrameNotify != null) if (!this.Created)
UpdateFrameNotify(EventArgs.Empty); {
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);
} }
public event UpdateFrameEvent UpdateFrameNotify; #endregion
public event RenderFrameEvent RenderFrameNotify;
/// <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;
#endregion #endregion

View file

@ -4,10 +4,10 @@ using System.Text;
namespace OpenTK.Input namespace OpenTK.Input
{ {
public interface IInputDriver public interface IInputDriver : IKeyboardDriver
{ {
IList<IInputDevice> InputDevices { get; } IList<IInputDevice> InputDevices { get; }
IList<IKeyboard> Keyboards { get; } //void ProcessEvents
//IEnumerable<IMouse> Mice { get; } //IEnumerable<IMouse> Mice { get; }
//IEnumerable<IHid> Hids { get; } //IEnumerable<IHid> Hids { get; }
} }

View file

@ -9,5 +9,9 @@ namespace OpenTK.Input
public interface IKeyboard : IInputDevice public interface IKeyboard : IInputDevice
{ {
bool this[Keys k] { get; } bool this[Keys k] { get; }
int NumberOfKeys { get; }
int NumberOfFunctionKeys { get; }
int NumberOfLeds { get; }
long DeviceID { get; }
} }
} }

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Input
{
public interface IKeyboardDriver
{
IList<Keyboard> Keyboards { get; }
}
}

View file

@ -8,13 +8,20 @@
using System; using System;
using OpenTK.Input;
using System.Diagnostics;
#endregion #endregion
namespace OpenTK.Input namespace OpenTK.Input
{ {
public class Keyboard : IKeyboard public class Keyboard : IKeyboard
{ {
private IKeyboard keyboard; //private IKeyboard keyboard;
private bool[] keys = new bool[(int)Keys.MaxKeys];
private string description;
private int numKeys, numFKeys, numLeds;
private long devID;
#region --- Constructors --- #region --- Constructors ---
@ -23,7 +30,7 @@ namespace OpenTK.Input
if (Environment.OSVersion.Platform == PlatformID.Win32NT || if (Environment.OSVersion.Platform == PlatformID.Win32NT ||
Environment.OSVersion.Platform == PlatformID.Win32Windows) Environment.OSVersion.Platform == PlatformID.Win32Windows)
{ {
keyboard = new OpenTK.Platform.Windows.WinRawKeyboard(); //keyboard = new OpenTK.Platform.Windows.WinRawKeyboard();
} }
else if (Environment.OSVersion.Platform == PlatformID.Unix || else if (Environment.OSVersion.Platform == PlatformID.Unix ||
Environment.OSVersion.Platform == (PlatformID)128) // some older versions of Mono reported 128. Environment.OSVersion.Platform == (PlatformID)128) // some older versions of Mono reported 128.
@ -44,8 +51,39 @@ namespace OpenTK.Input
public bool this[Keys k] public bool this[Keys k]
{ {
get { return keyboard[k]; } get { return keys[(int)k]; }
//set { keyboard[k] = value; } internal set
{
Debug.Print("OpenTK key {0} {1}.", k, value ? "pressed" : "released");
keys[(int)k] = value;
}
}
public int NumberOfKeys
{
get { return numKeys; }
internal set { numKeys = value; }
}
public int NumberOfFunctionKeys
{
get { return numFKeys; }
internal set { numFKeys = value; }
}
public int NumberOfLeds
{
get { return numLeds; }
internal set { numLeds = value; }
}
/// <summary>
/// Device dependent ID.
/// </summary>
public long DeviceID
{
get { return devID; }
internal set { devID = value; }
} }
#endregion #endregion
@ -54,15 +92,29 @@ namespace OpenTK.Input
public string Description public string Description
{ {
get { return keyboard.Description; } get { return description; }
internal set { description = value; }
} }
public InputDeviceType DeviceType public InputDeviceType DeviceType
{ {
get { return keyboard.DeviceType; } get { return InputDeviceType.Keyboard; }
} }
#endregion #endregion
public override int GetHashCode()
{
//return base.GetHashCode();
return (int)(numKeys ^ numFKeys ^ numLeds ^ devID.GetHashCode() ^ description.GetHashCode());
}
public override string ToString()
{
//return base.ToString();
return String.Format("Keyboard: '{0}', {1} keys, {2} function keys, {3} leds. Device ID: {4}",
description, NumberOfKeys, NumberOfFunctionKeys, NumberOfLeds, DeviceID);
}
} }
#region public enum Keys : int #region public enum Keys : int

View file

@ -10,12 +10,12 @@ namespace OpenTK
{ {
IInputDriver inputDriver; IInputDriver inputDriver;
public InputDevices() public InputDevices(IntPtr parentHandle)
{ {
if (Environment.OSVersion.Version.Major > 5 || if (Environment.OSVersion.Version.Major > 5 ||
(Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1)) (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1))
{ {
inputDriver = new OpenTK.Platform.Windows.WinRawInput(); inputDriver = new OpenTK.Platform.Windows.WinRawInput(parentHandle);
} }
else else
{ {
@ -25,12 +25,12 @@ namespace OpenTK
#region --- IInputDriver Members --- #region --- IInputDriver Members ---
IList<OpenTK.Input.IInputDevice> OpenTK.Input.IInputDriver.InputDevices IList<IInputDevice> IInputDriver.InputDevices
{ {
get { return inputDriver.InputDevices; } get { return inputDriver.InputDevices; }
} }
public IList<OpenTK.Input.IKeyboard> Keyboards public IList<Keyboard> Keyboards
{ {
get { return inputDriver.Keyboards; } get { return inputDriver.Keyboards; }
} }

View file

@ -12435,7 +12435,7 @@ namespace OpenTK.OpenGL
} }
public static public static
void GetShaderInfoLog(Int32 shader, Int32 bufSize, [Out] out Int32 length, [In, Out] System.Text.StringBuilder infoLog) void GetShaderInfoLog(Int32 shader, Int32 bufSize, [Out] out Int32 length, [Out] System.Text.StringBuilder infoLog)
{ {
length = default(Int32); length = default(Int32);
infoLog = default(System.Text.StringBuilder); infoLog = default(System.Text.StringBuilder);

View file

@ -1527,7 +1527,7 @@ namespace OpenTK.OpenGL
internal extern static unsafe void GetShaderiv(UInt32 shader, GL.Enums.VERSION_2_0 pname, [Out] Int32* @params); internal extern static unsafe void GetShaderiv(UInt32 shader, GL.Enums.VERSION_2_0 pname, [Out] Int32* @params);
[System.Security.SuppressUnmanagedCodeSecurity()] [System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glGetShaderInfoLog", ExactSpelling = true)] [System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glGetShaderInfoLog", ExactSpelling = true)]
internal extern static unsafe void GetShaderInfoLog(UInt32 shader, Int32 bufSize, [Out] Int32* length, [In, Out] System.Text.StringBuilder infoLog); internal extern static unsafe void GetShaderInfoLog(UInt32 shader, Int32 bufSize, [Out] Int32* length, [Out] System.Text.StringBuilder infoLog);
[System.Security.SuppressUnmanagedCodeSecurity()] [System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glGetShaderSource", ExactSpelling = true)] [System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glGetShaderSource", ExactSpelling = true)]
internal extern static unsafe void GetShaderSource(UInt32 shader, Int32 bufSize, [Out] Int32* length, [Out] System.Text.StringBuilder[] source); internal extern static unsafe void GetShaderSource(UInt32 shader, Int32 bufSize, [Out] Int32* length, [Out] System.Text.StringBuilder[] source);

View file

@ -1528,7 +1528,7 @@ namespace OpenTK.OpenGL
internal unsafe delegate void GetShaderiv(UInt32 shader, GL.Enums.VERSION_2_0 pname, [Out] Int32* @params); internal unsafe delegate void GetShaderiv(UInt32 shader, GL.Enums.VERSION_2_0 pname, [Out] Int32* @params);
internal unsafe static GetShaderiv glGetShaderiv = (GetShaderiv)GL.GetDelegateForExtensionMethod("glGetShaderiv", typeof(GetShaderiv)) ?? new GetShaderiv(Imports.GetShaderiv); internal unsafe static GetShaderiv glGetShaderiv = (GetShaderiv)GL.GetDelegateForExtensionMethod("glGetShaderiv", typeof(GetShaderiv)) ?? new GetShaderiv(Imports.GetShaderiv);
[System.Security.SuppressUnmanagedCodeSecurity()] [System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void GetShaderInfoLog(UInt32 shader, Int32 bufSize, [Out] Int32* length, [In, Out] System.Text.StringBuilder infoLog); internal unsafe delegate void GetShaderInfoLog(UInt32 shader, Int32 bufSize, [Out] Int32* length, [Out] System.Text.StringBuilder infoLog);
internal unsafe static GetShaderInfoLog glGetShaderInfoLog = (GetShaderInfoLog)GL.GetDelegateForExtensionMethod("glGetShaderInfoLog", typeof(GetShaderInfoLog)) ?? new GetShaderInfoLog(Imports.GetShaderInfoLog); internal unsafe static GetShaderInfoLog glGetShaderInfoLog = (GetShaderInfoLog)GL.GetDelegateForExtensionMethod("glGetShaderInfoLog", typeof(GetShaderInfoLog)) ?? new GetShaderInfoLog(Imports.GetShaderInfoLog);
[System.Security.SuppressUnmanagedCodeSecurity()] [System.Security.SuppressUnmanagedCodeSecurity()]
internal unsafe delegate void GetShaderSource(UInt32 shader, Int32 bufSize, [Out] Int32* length, [Out] System.Text.StringBuilder[] source); internal unsafe delegate void GetShaderSource(UInt32 shader, Int32 bufSize, [Out] Int32* length, [Out] System.Text.StringBuilder[] source);

View file

@ -14,12 +14,9 @@ namespace OpenTK.Platform
{ {
public interface IGLControl : IDisposable public interface IGLControl : IDisposable
{ {
void ProcessEvents();
event CreateEvent Create; event CreateEvent Create;
bool IsIdle { get; } bool IsIdle { get; }
//bool Quit { get; set; }
bool Fullscreen { get; set; } bool Fullscreen { get; set; }
IGLContext Context { get; } IGLContext Context { get; }
} }

View file

@ -5,15 +5,15 @@ using System.Text;
namespace OpenTK.Platform namespace OpenTK.Platform
{ {
interface IGameWindow : IDisposable interface IGameWindow : INativeWindow
{ {
void Run(); void Run();
void RenderFrame(); void OnRenderFrame();
void UpdateFrame(); void OnUpdateFrame();
event UpdateFrameEvent UpdateFrameNotify; event UpdateFrameEvent UpdateFrame;
event RenderFrameEvent RenderFrameNotify; event RenderFrameEvent RenderFrame;
} }
public delegate void UpdateFrameEvent(EventArgs e); public delegate void UpdateFrameEvent(EventArgs e);

View file

@ -4,15 +4,16 @@ using System.Text;
namespace OpenTK.Platform namespace OpenTK.Platform
{ {
interface INativeWindow : IResizable, IDisposable interface INativeWindow : IGLControl, IResizable
{ {
void CreateWindow(DisplayMode mode);
void ProcessEvents(); void ProcessEvents();
void Exit();
event CreateEvent Create; event CreateEvent Create;
bool IsIdle { get; } bool Created { get; }
bool Quit { get; set; } bool Quit { get; }
bool Fullscreen { get; set; } IntPtr Handle { get; }
IGLContext Context { get; }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -23,6 +23,7 @@ namespace OpenTK.Platform.Windows
private ResizeEventArgs resizeEventArgs = new ResizeEventArgs(); private ResizeEventArgs resizeEventArgs = new ResizeEventArgs();
private bool disposed; private bool disposed;
private Message msg; // Used only by the IsIdle event.
#region --- Constructors --- #region --- Constructors ---
@ -48,16 +49,6 @@ namespace OpenTK.Platform.Windows
public event CreateEvent Create; public event CreateEvent Create;
#region public void ProcessEvents()
private API.Message msg;
public void ProcessEvents()
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
#region public bool IsIdle #region public bool IsIdle
public bool IsIdle public bool IsIdle
@ -70,15 +61,6 @@ namespace OpenTK.Platform.Windows
#endregion #endregion
#region public OpenTK.Platform.IGLContext Context
public OpenTK.Platform.IGLContext Context
{
get { return glContext; }
}
#endregion
#region public bool Fullscreen #region public bool Fullscreen
public bool Fullscreen public bool Fullscreen
@ -90,12 +72,20 @@ namespace OpenTK.Platform.Windows
set set
{ {
throw new NotImplementedException(); throw new NotImplementedException();
fullscreen = true;
} }
} }
#endregion #endregion
#region public IGLContext Context
public IGLContext Context
{
get { return glContext; }
}
#endregion
#endregion #endregion
#region --- IDisposable Members --- #region --- IDisposable Members ---

View file

@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows.Forms; using System.Windows.Forms;
using System.Diagnostics;
#endregion #endregion
@ -18,12 +19,16 @@ namespace OpenTK.Platform.Windows
{ {
sealed class WinGLNative : NativeWindow, OpenTK.Platform.INativeWindow, IDisposable sealed class WinGLNative : NativeWindow, OpenTK.Platform.INativeWindow, IDisposable
{ {
#region --- Fields ---
private WinGLContext glContext; private WinGLContext glContext;
private DisplayMode mode = new DisplayMode(); private DisplayMode mode = new DisplayMode();
private Input.IInputDriver inputDriver;
private bool disposed; private bool disposed;
private bool quit;
private bool created;
#endregion
#region --- Contructors --- #region --- Contructors ---
@ -32,24 +37,94 @@ namespace OpenTK.Platform.Windows
/// </summary> /// </summary>
public WinGLNative() public WinGLNative()
{ {
mode = new DisplayMode();
mode.Width = 640;
mode.Height = 480;
this.CreateWindow(mode);
} }
#endregion #endregion
#region private void CreateWindow() #region protected override void WndProc(ref Message m)
private void CreateWindow(DisplayMode mode) /// <summary>
/// For use in WndProc only.
/// </summary>
private int width, height;
/// <summary>
/// Processes incoming WM_* messages.
/// </summary>
/// <param name="m">Reference to the incoming Windows Message.</param>
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case API.Constants.WM_WINDOWPOSCHANGED:
// Get window size
width = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.WindowPosition), "cx"));
height = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.WindowPosition), "cy"));
//if (resizeEventArgs.Width != width || resizeEventArgs.Height != height)
if (mode.Width != width || mode.Height != height)
{
// If the size has changed, raise the ResizeEvent.
resizeEventArgs.Width = width;
resizeEventArgs.Height = height;
this.OnResize(resizeEventArgs);
// The message was processed.
return;
}
// If the message was not a resize notification, send it to the default WndProc.
break;
case API.Constants.WM_CREATE:
// Set the window width and height:
mode.Width = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.CreateStruct), "cx"));
mode.Height = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.CreateStruct), "cy"));
// Raise the Create event
this.OnCreate(EventArgs.Empty);
// Raise the resize event:
//resizeEventArgs.Width = width;
//resizeEventArgs.Height = height;
//this.OnResize(resizeEventArgs);
return;
//case API.Constants.WM_KEYDOWN: // Legacy input events
//case API.Constants.WM_KEYUP:
// break;
//case API.Constants.WM_INPUT: // Raw input
// WinRawInput.ProcessEvent(ref msg, key);
// break;
case API.Constants.WM_CLOSE:
case API.Constants.WM_DESTROY:
Debug.Print("Window handle {0} destroyed.", this.Handle);
this.DestroyHandle();
API.PostQuitMessage(0);
return;
case API.Constants.WM_QUIT:
quit = true;
Debug.WriteLine("Window quit.");
return;
}
//base.WndProc(ref m);
DefWndProc(ref m);
}
#endregion
#region --- INativeWindow Members ---
#region private void CreateWindow(DisplayMode mode)
public void CreateWindow(DisplayMode mode)
{ {
CreateParams cp = new CreateParams(); CreateParams cp = new CreateParams();
cp.ClassStyle = cp.ClassStyle =
(int)API.WindowClassStyle.OwnDC | (int)API.WindowClassStyle.OwnDC |
(int)API.WindowClassStyle.VRedraw | (int)API.WindowClassStyle.VRedraw |
(int)API.WindowClassStyle.HRedraw; (int)API.WindowClassStyle.HRedraw | (int)API.WindowClassStyle.Ime;
cp.Style = cp.Style =
(int)API.WindowStyle.Visible | (int)API.WindowStyle.Visible |
(int)API.WindowStyle.ClipChildren | (int)API.WindowStyle.ClipChildren |
@ -72,6 +147,17 @@ namespace OpenTK.Platform.Windows
0.0f 0.0f
) )
); );
if (this.Handle != IntPtr.Zero && glContext != null)
{
created = true;
}
else
{
throw new ApplicationException(String.Format(
"Could not create native window and/or context. Handle: {0}, Context {1}",
this.Handle, this.Context.ToString()));
}
} }
/* /*
@ -121,84 +207,34 @@ namespace OpenTK.Platform.Windows
*/ */
#endregion #endregion
#region protected override void WndProc(ref Message m) #region public void Exit()
/// <summary> /// <summary>
/// For use in WndProc only. /// Starts the teardown sequence for the current window.
/// </summary> /// </summary>
private int width, height; public void Exit()
/// <summary>
/// Processes incoming WM_* messages.
/// </summary>
/// <param name="m">Reference to the incoming Windows Message.</param>
protected override void WndProc(ref Message m)
{ {
switch (m.Msg) API.PostMessage(this.Handle, (uint)API.Constants.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
{
case API.Constants.WM_WINDOWPOSCHANGED:
// Get window size
width = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.WindowPosition), "cx"));
height = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.WindowPosition), "cy"));
//if (resizeEventArgs.Width != width || resizeEventArgs.Height != height)
if (mode.Width != width || mode.Height != height)
{
// If the size has changed, raise the ResizeEvent.
resizeEventArgs.Width = width;
resizeEventArgs.Height = height;
this.OnResize(resizeEventArgs);
// The message was processed.
return;
}
// If the message was not a resize notification, send it to the default WndProc.
break;
case API.Constants.WM_CREATE:
// Set the window width and height:
mode.Width = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.CreateStruct), "cx"));
mode.Height = Marshal.ReadInt32(m.LParam, (int)Marshal.OffsetOf(typeof(API.CreateStruct), "cy"));
// Raise the Create event
this.OnCreate(EventArgs.Empty);
// Raise the resize event:
//resizeEventArgs.Width = width;
//resizeEventArgs.Height = height;
//this.OnResize(resizeEventArgs);
return;
case API.Constants.WM_KEYDOWN: // Legacy input events
case API.Constants.WM_KEYUP:
break;
//case API.Constants.WM_INPUT: // Raw input
// WinRawInput.ProcessEvent(ref msg, key);
// break;
case API.Constants.WM_CLOSE:
API.PostQuitMessage(0);
return;
case API.Constants.WM_QUIT:
quit = true;
break;
}
base.WndProc(ref m);
} }
#endregion #endregion
#region --- INativeWindow Members ---
#region public void ProcessEvents() #region public void ProcessEvents()
private System.Windows.Forms.Message msg; private int ret;
System.Windows.Forms.Message msg;
public void ProcessEvents() public void ProcessEvents()
{ {
while (API.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0)) while (!IsIdle)
{ {
API.GetMessage(out msg, IntPtr.Zero, 0, 0); ret = API.GetMessage(out msg, Handle, 0, 0);
if (ret == -1)
{
throw new ApplicationException(String.Format(
"An error happened while processing the message queue. Windows error: {0}",
Marshal.GetLastWin32Error()));
}
API.DispatchMessage(ref msg);
WndProc(ref msg); WndProc(ref msg);
} }
} }
@ -219,20 +255,23 @@ namespace OpenTK.Platform.Windows
#endregion #endregion
#region public bool Created
/// <summary>
/// Returns true if a render window/context exists.
/// </summary>
public bool Created
{
get { return created; }
}
#endregion
#region public bool Quit #region public bool Quit
private bool quit;
public bool Quit public bool Quit
{ {
get { return quit; } get { return quit; }
set
{
if (value)
{
API.PostQuitMessage(0);
//quit = true;
}
}
} }
#endregion #endregion
@ -269,7 +308,9 @@ namespace OpenTK.Platform.Windows
{ {
get get
{ {
return !API.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0); //return !API.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
return !API.PeekMessage(out msg, this.Handle, 0, 0, 0);
//return API.GetQueueStatus(API.QueueStatusFlags.ALLEVENTS) == 0;
} }
} }

View file

@ -28,42 +28,33 @@ namespace OpenTK.Platform.Windows
/// <summary> /// <summary>
/// The list of keyboards connected to this system. /// The list of keyboards connected to this system.
/// </summary> /// </summary>
private List<WinRawKeyboard> keyboards = new List<WinRawKeyboard>(); //internal List<WinRawKeyboard> keyboards = new List<WinRawKeyboard>();
WinRawKeyboard key; private WinRawKeyboard keyboardDriver;
internal IEnumerable<Input.IInputDevice> InputDevices internal WinRawInput(IntPtr parentHandle)
{ {
get Debug.WriteLine("Initalizing raw input driver.");
{ Debug.Indent();
return (IEnumerable<Input.IInputDevice>)key;
AssignHandle(parentHandle);
Debug.Print("Input window attached to parent {0}", this.Handle);
keyboardDriver = new WinRawKeyboard(this.Handle);
Debug.Unindent();
} }
}
internal WinRawInput()
{
CreateParams cp = new CreateParams();
/*cp.ClassStyle =
(int)API.WindowClassStyle.ParentDC;
cp.Style =
(int)API.WindowStyle.Disabled |
(int)API.WindowStyle.ChildWindow;*/
cp.Caption = "OpenTK hidden input handler window";
base.CreateHandle(cp);
//key = new WinRawKeyboard(this.Handle);
uint numKeyboards = WinRawKeyboard.Count;
}
private static uint deviceCount; private static uint deviceCount;
internal static uint DeviceCount internal static uint DeviceCount
{ {
get { return DeviceListChanged ? deviceCount : deviceCount; } get
{
API.GetRawInputDeviceList(null, ref deviceCount, API.RawInputDeviceListSize);
return deviceCount;
} }
}
/*
/// <summary> /// <summary>
/// Gets a value indicating whether the Device list has changed, for example /// Gets a value indicating whether the Device list has changed, for example
/// by removing or adding a device. /// by removing or adding a device.
@ -89,26 +80,29 @@ namespace OpenTK.Platform.Windows
} }
} }
} }
*/
#region protected override void WndProc(ref Message msg) #region protected override void WndProc(ref Message msg)
uint size = 0;
/// <summary> /// <summary>
/// Processes the input Windows Message, routing the data to the correct Keyboard, Mouse or HID. /// Processes the input Windows Message, routing the data to the correct Keyboard, Mouse or HID.
/// </summary> /// </summary>
/// <param name="msg">The WM_INPUT message, containing the data on the input event.</param> /// <param name="msg">The WM_INPUT message, containing the data on the input event.</param>
protected override void WndProc(ref Message msg) protected override void WndProc(ref Message msg)
{ {
if (msg.Msg == API.Constants.WM_INPUT) switch (msg.Msg)
{ {
uint size = 0; case API.Constants.WM_INPUT:
size = 0;
// Get the size of the input data // Get the size of the input data
API.GetRawInputData(msg.LParam, API.GetRawInputDataEnum.INPUT, API.GetRawInputData(msg.LParam, API.GetRawInputDataEnum.INPUT,
IntPtr.Zero, ref size, API.RawInputHeaderSize); IntPtr.Zero, ref size, API.RawInputHeaderSize);
if (data == null || API.RawInputSize < size) //if (data == null || API.RawInputSize < size)
{ //{
throw new ApplicationException("Critical error when processing raw windows input."); // throw new ApplicationException("Critical error when processing raw windows input.");
} //}
if (size == API.GetRawInputData(msg.LParam, API.GetRawInputDataEnum.INPUT, if (size == API.GetRawInputData(msg.LParam, API.GetRawInputDataEnum.INPUT,
data, ref size, API.RawInputHeaderSize)) data, ref size, API.RawInputHeaderSize))
@ -116,22 +110,35 @@ namespace OpenTK.Platform.Windows
switch (data.Header.Type) switch (data.Header.Type)
{ {
case API.RawInputDeviceType.KEYBOARD: case API.RawInputDeviceType.KEYBOARD:
ProcessKeyboardEvent(data); keyboardDriver.ProcessKeyboardEvent(data);
break; break;
case API.RawInputDeviceType.MOUSE: case API.RawInputDeviceType.MOUSE:
throw new NotImplementedException(); //throw new NotImplementedException();
break;
case API.RawInputDeviceType.HID: case API.RawInputDeviceType.HID:
throw new NotImplementedException(); //throw new NotImplementedException();
break;
} }
} }
else else
{ {
throw new ApplicationException( throw new ApplicationException(String.Format(
"GetRawInputData returned invalid data. Please file a bug at http://opentk.sourceforge.net" "GetRawInputData returned invalid data. Windows error {0}. Please file a bug at http://opentk.sourceforge.net",
); Marshal.GetLastWin32Error()));
} }
break;
case API.Constants.WM_CLOSE:
case API.Constants.WM_DESTROY:
Debug.Print("Input window detached from parent {0}.", Handle);
ReleaseHandle();
break;
case API.Constants.WM_QUIT:
Debug.WriteLine("Input window quit.");
break;
} }
base.WndProc(ref msg); base.WndProc(ref msg);
@ -139,64 +146,6 @@ namespace OpenTK.Platform.Windows
#endregion #endregion
#region internal bool ProcessKeyboardEvent(API.RawInput rin)
/// <summary>
/// Processes raw input events.
/// </summary>
/// <param name="rin"></param>
/// <returns></returns>
internal bool ProcessKeyboardEvent(API.RawInput rin)
{
switch (rin.Header.Type)
{
case API.RawInputDeviceType.KEYBOARD:
bool pressed =
rin.Data.Keyboard.Message == API.Constants.WM_KEYDOWN ||
rin.Data.Keyboard.Message == API.Constants.WM_SYSKEYDOWN;
// Generic control, shift, alt keys may be sent instead of left/right.
// It seems you have to explicitly register left/right events.
switch (rin.Data.Keyboard.VKey)
{
case API.VirtualKeys.SHIFT:
key[Input.Keys.LeftShift] = key[Input.Keys.RightShift] = pressed;
return false;
case API.VirtualKeys.CONTROL:
key[Input.Keys.LeftControl] = key[Input.Keys.RightControl] = pressed;
return false;
case API.VirtualKeys.MENU:
key[Input.Keys.LeftAlt] = key[Input.Keys.RightAlt] = pressed;
return false;
default:
if (!WinRawKeyboard.KeyMap.ContainsKey(rin.Data.Keyboard.VKey))
{
Debug.Print("Virtual key {0} not mapped.", rin.Data.Keyboard.VKey);
OpenTK.OpenGL.GL.ClearColor(1.0f, 0.3f, 0.3f, 0.0f);
}
else
{
key[WinRawKeyboard.KeyMap[rin.Data.Keyboard.VKey]] = pressed;
OpenTK.OpenGL.GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
break;
}
break;
case API.RawInputDeviceType.MOUSE:
break;
case API.RawInputDeviceType.HID:
break;
}
return false;
}
#endregion
#region --- IInputDriver Members --- #region --- IInputDriver Members ---
IList<Input.IInputDevice> Input.IInputDriver.InputDevices IList<Input.IInputDevice> Input.IInputDriver.InputDevices
@ -204,9 +153,9 @@ namespace OpenTK.Platform.Windows
get { throw new Exception("The method or operation is not implemented."); } get { throw new Exception("The method or operation is not implemented."); }
} }
public IList<IKeyboard> Keyboards public IList<Keyboard> Keyboards
{ {
get { return (IList<IKeyboard>)keyboards; } get { return keyboardDriver.Keyboards; }
} }
#endregion #endregion

View file

@ -11,14 +11,17 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.Win32;
using OpenTK.Input;
#endregion #endregion
namespace OpenTK.Platform.Windows namespace OpenTK.Platform.Windows
{ {
internal class WinRawKeyboard : Input.IKeyboard internal class WinRawKeyboard : IKeyboardDriver
{ {
private bool[] keys = new bool[(int)Input.Keys.MaxKeys]; private List<Keyboard> keyboards = new List<Keyboard>();
private IntPtr windowHandle;
#region internal static Dictionary<API.VirtualKeys, Input.Keys> KeyMap #region internal static Dictionary<API.VirtualKeys, Input.Keys> KeyMap
@ -126,41 +129,6 @@ namespace OpenTK.Platform.Windows
#endregion #endregion
/// <summary>
/// The count of physical keyboards connected to this computer.
/// </summary>
private static uint keyboardCount;
internal static uint Count
{
get
{
if (!WinRawInput.DeviceListChanged && keyboardCount != 0)
{
return keyboardCount;
}
else
{
UpdateKeyboardList();
return keyboardCount;
}
}
}
internal static void UpdateKeyboardList()
{
uint count = WinRawInput.DeviceCount;
API.RawInputDeviceList[] ridl = new API.RawInputDeviceList[count];
for (int i = 0; i < count; i++)
ridl[i] = new API.RawInputDeviceList();
API.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
for (int i = 0; i < count; i++)
{
//do something with the information (see section on GetRawInputDeviceInfo)
}
}
#region --- Constructors --- #region --- Constructors ---
internal WinRawKeyboard() internal WinRawKeyboard()
@ -170,15 +138,108 @@ namespace OpenTK.Platform.Windows
internal WinRawKeyboard(IntPtr windowHandle) internal WinRawKeyboard(IntPtr windowHandle)
{ {
Debug.WriteLine("Keyboard driver: Windows raw input"); Debug.WriteLine("Initializing keyboard driver.");
Debug.Indent();
this.windowHandle = windowHandle;
InitKeyMap();
UpdateKeyboardList();
Debug.Unindent();
}
#endregion
#region internal static void UpdateKeyboardList()
internal void UpdateKeyboardList()
{
uint count = WinRawInput.DeviceCount;
API.RawInputDeviceList[] ridl = new API.RawInputDeviceList[count];
for (int i = 0; i < count; i++)
ridl[i] = new API.RawInputDeviceList();
API.GetRawInputDeviceList(ridl, ref count, API.RawInputDeviceListSize);
// Discover keyboard devices:
for (int i = 0; i < count; i++)
{
uint size = 0;
API.GetRawInputDeviceInfo(ridl[i].Device, API.RawInputDeviceInfoEnum.DEVICENAME, IntPtr.Zero, ref size);
IntPtr name_ptr = Marshal.AllocHGlobal((IntPtr)size);
API.GetRawInputDeviceInfo(ridl[i].Device, API.RawInputDeviceInfoEnum.DEVICENAME, name_ptr, ref size);
string name = Marshal.PtrToStringAnsi(name_ptr);
Marshal.FreeHGlobal(name_ptr);
if (name.ToLower().Contains("root"))
{
// This is a terminal services devices, skip it.
continue;
}
else if (
ridl[i].Type == API.RawInputDeviceType.KEYBOARD ||
ridl[i].Type == API.RawInputDeviceType.HID)
{
//It's a keyboard or a USB device that could be a keyboard
// remove the \??\
name = name.Substring(4);
string[] split = name.Split('#');
string id_01 = split[0]; // ACPI (Class code)
string id_02 = split[1]; // PNP0303 (SubClass code)
string id_03 = split[2]; // 3&13c0b0c5&0 (Protocol code)
// The final part is the class GUID and is not needed here
string findme = string.Format(
@"System\CurrentControlSet\Enum\{0}\{1}\{2}",
id_01, id_02, id_03);
RegistryKey regkey = Registry.LocalMachine.OpenSubKey(findme);
string deviceDesc =
(string)regkey.GetValue("DeviceDesc");
string deviceClass =
(string)regkey.GetValue("Class");
if (!String.IsNullOrEmpty(deviceClass) && deviceClass.ToLower().Equals("keyboard"))
{
Keyboard kb = new Keyboard();
kb.Description = deviceDesc;
// Register the keyboard:
API.RawInputDeviceInfo info = new API.RawInputDeviceInfo();
uint devInfoSize = API.RawInputDeviceInfoSize;
API.GetRawInputDeviceInfo(ridl[i].Device, API.RawInputDeviceInfoEnum.DEVICEINFO,
info, ref devInfoSize);
kb.NumberOfLeds = info.Device.Keyboard.NumberOfIndicators;
kb.NumberOfFunctionKeys = info.Device.Keyboard.NumberOfFunctionKeys;
kb.NumberOfKeys = info.Device.Keyboard.NumberOfKeysTotal;
kb.DeviceID = (info.Device.Keyboard.Type << 32) + info.Device.Keyboard.SubType;
if (!keyboards.Contains(kb))
{
this.RegisterKeyboardDevice(kb);
keyboards.Add(kb);
}
}
}
}
}
#endregion
#region internal void RegisterKeyboardDevice(Keyboard kb)
internal void RegisterKeyboardDevice(Keyboard kb)
{
API.RawInputDevice[] rid = new API.RawInputDevice[1]; API.RawInputDevice[] rid = new API.RawInputDevice[1];
// Keyboard is 1/6 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx // Keyboard is 1/6 (page/id). See http://www.microsoft.com/whdc/device/input/HID_HWID.mspx
rid[0] = new API.RawInputDevice(); rid[0] = new API.RawInputDevice();
rid[0].UsagePage = 1; rid[0].UsagePage = 1;
rid[0].Usage = 6; rid[0].Usage = 6;
rid[0].Flags = API.RawInputDeviceFlags.INPUTSINK; rid[0].Flags = API.RawInputDeviceFlags.INPUTSINK;
rid[0].Target = windowHandle; rid[0].Target = windowHandle;
if (!API.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize)) if (!API.RegisterRawInputDevices(rid, 1, API.RawInputDeviceSize))
@ -190,22 +251,67 @@ namespace OpenTK.Platform.Windows
rid[0].ToString()) rid[0].ToString())
); );
} }
else
InitKeyMap(); {
Debug.Print("Registered keyboard {0}", kb.ToString());
}
} }
#endregion #endregion
#region --- IKeyboard members --- #region internal bool ProcessKeyboardEvent(API.RawInput rin)
public bool this[Input.Keys k] /// <summary>
/// Processes raw input events.
/// </summary>
/// <param name="rin"></param>
/// <returns></returns>
internal bool ProcessKeyboardEvent(API.RawInput rin)
{ {
get { return keys[(int)k]; } //Keyboard key = keyboards[0];
internal set //rin.Header.Device;
switch (rin.Header.Type)
{ {
Debug.Print("OpenTK key {0} {1}.", k, value ? "pressed" : "released"); case API.RawInputDeviceType.KEYBOARD:
keys[(int)k] = value; bool pressed =
rin.Data.Keyboard.Message == API.Constants.WM_KEYDOWN ||
rin.Data.Keyboard.Message == API.Constants.WM_SYSKEYDOWN;
// Generic control, shift, alt keys may be sent instead of left/right.
// It seems you have to explicitly register left/right events.
switch (rin.Data.Keyboard.VKey)
{
case API.VirtualKeys.SHIFT:
keyboards[0][Input.Keys.LeftShift] = keyboards[0][Input.Keys.RightShift] = pressed;
return false;
case API.VirtualKeys.CONTROL:
keyboards[0][Input.Keys.LeftControl] = keyboards[0][Input.Keys.RightControl] = pressed;
return false;
case API.VirtualKeys.MENU:
keyboards[0][Input.Keys.LeftAlt] = keyboards[0][Input.Keys.RightAlt] = pressed;
return false;
default:
if (!WinRawKeyboard.KeyMap.ContainsKey(rin.Data.Keyboard.VKey))
{
Debug.Print("Virtual key {0} not mapped.", rin.Data.Keyboard.VKey);
OpenTK.OpenGL.GL.ClearColor(1.0f, 0.3f, 0.3f, 0.0f);
} }
else
{
keyboards[0][WinRawKeyboard.KeyMap[rin.Data.Keyboard.VKey]] = pressed;
OpenTK.OpenGL.GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
break;
}
break;
default:
throw new ApplicationException("Windows raw keyboard driver received invalid data.");
}
return false;
} }
#endregion #endregion
@ -223,5 +329,14 @@ namespace OpenTK.Platform.Windows
} }
#endregion #endregion
#region --- IKeyboardDriver Members ---
public IList<Keyboard> Keyboards
{
get { return keyboards; }
}
#endregion
} }
} }

View file

@ -20,8 +20,8 @@ namespace OpenTK.Platform.X11
X11GLContext glContext; X11GLContext glContext;
private bool quit; private bool quit;
private bool disposed; private bool disposed;
private bool fullscreen;
#region --- Contructors --- #region --- Contructors ---
@ -136,19 +136,7 @@ namespace OpenTK.Platform.X11
this.Create(sender, e); this.Create(sender, e);
} }
#region public bool Quit #region public bool IsIdle
public bool Quit
{
get { return quit; }
set
{
throw new NotImplementedException();
quit = value;
}
}
#endregion
public bool IsIdle public bool IsIdle
{ {
@ -158,11 +146,15 @@ namespace OpenTK.Platform.X11
} }
} }
#endregion
#region public bool Fullscreen
public bool Fullscreen public bool Fullscreen
{ {
get get
{ {
throw new Exception("The method or operation is not implemented."); return fullscreen;
} }
set set
{ {
@ -170,7 +162,11 @@ namespace OpenTK.Platform.X11
} }
} }
public OpenTK.Platform.IGLContext Context #endregion
#region public IGLContext Context
public IGLContext Context
{ {
get get
{ {
@ -178,10 +174,7 @@ namespace OpenTK.Platform.X11
} }
} }
public void ProcessEvents() #endregion
{
throw new Exception("The method or operation is not implemented.");
}
#endregion #endregion
@ -198,7 +191,7 @@ namespace OpenTK.Platform.X11
if (!disposed) if (!disposed)
{ {
// Clean unmanaged resources: // Clean unmanaged resources:
// Nothing
if (manuallyCalled) if (manuallyCalled)
{ {

View file

@ -27,6 +27,8 @@ namespace OpenTK.Platform.X11
private DisplayMode mode = new DisplayMode(); private DisplayMode mode = new DisplayMode();
private bool created;
//private X11Keyboard key; //private X11Keyboard key;
// Number of pending events. // Number of pending events.
@ -74,6 +76,17 @@ namespace OpenTK.Platform.X11
Trace.WriteLine(String.Format("Display mode: {0}", mode)); Trace.WriteLine(String.Format("Display mode: {0}", mode));
this.CreateWindow(mode);
}
#endregion
#region --- INativeWindow Members ---
#region public void CreateWindow(DisplayMode mode)
public void CreateWindow(DisplayMode mode)
{
windowInfo.Display = display = API.OpenDisplay(null); // null == default display windowInfo.Display = display = API.OpenDisplay(null); // null == default display
if (display == IntPtr.Zero) if (display == IntPtr.Zero)
{ {
@ -157,6 +170,8 @@ namespace OpenTK.Platform.X11
*/ */
//glContext.ContainingWindow = windowInfo.Window; //glContext.ContainingWindow = windowInfo.Window;
glContext.windowInfo.Window = window; glContext.windowInfo.Window = window;
glContext.CreateContext(null, true); glContext.CreateContext(null, true);
@ -172,7 +187,20 @@ namespace OpenTK.Platform.X11
#endregion #endregion
#region --- INativeWindow Members --- #region public void Exit()
public void Exit()
{
/*Event e = new Event();
X11Api.SendEvent(
display,
window,
false,
0,*/
//quit = true;
}
#endregion
#region public void ProcessEvents() #region public void ProcessEvents()
@ -270,11 +298,14 @@ namespace OpenTK.Platform.X11
#endregion #endregion
#region public Keyboard Key #region public bool Created
public Input.IKeyboard Key /// <summary>
/// Returns true if a render window/context exists.
/// </summary>
public bool Created
{ {
get { throw new NotImplementedException(); } get { return created; }
} }
#endregion #endregion
@ -285,19 +316,6 @@ namespace OpenTK.Platform.X11
public bool Quit public bool Quit
{ {
get { return quit; } get { return quit; }
set
{
if (value)
{
/*Event e = new Event();
X11Api.SendEvent(
display,
window,
false,
0,*/
//quit = true;
}
}
} }
#endregion #endregion
@ -336,6 +354,18 @@ namespace OpenTK.Platform.X11
#endregion #endregion
#region public IntPtr Handle
/// <summary>
/// Gets the current window handle.
/// </summary>
public IntPtr Handle
{
get { return this.window; }
}
#endregion
#endregion #endregion
#region --- IResizable Members --- #region --- IResizable Members ---

View file

@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// //
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("0.3.9.4")] [assembly: AssemblyVersion("0.3.9.5")]
[assembly: AssemblyFileVersion("0.3.9.4")] [assembly: AssemblyFileVersion("0.3.9.5")]