From ab87f2cf6229484ad50e40508e5f239b1f85f71c Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Fri, 13 Jan 2017 14:45:47 +0100 Subject: [PATCH] InterfaceControler --- Tests/BasicTests.cs | 88 ++++++------ Tests/CrowWindow.cs | 268 +++++++++++++++++------------------- Tests/CrowWindow3D.cs | 240 -------------------------------- Tests/Hello3D.cs | 99 +++++++++---- Tests/HelloCube.cs | 2 +- Tests/HelloWorld.cs | 2 +- Tests/InterfaceControler.cs | 220 +++++++++++++++++++++++++++++ Tests/OpenGL/Extensions.cs | 64 +++++++++ Tests/Tests.csproj | 3 +- Tests/UIEditor.cs | 2 +- 10 files changed, 537 insertions(+), 451 deletions(-) delete mode 100644 Tests/CrowWindow3D.cs create mode 100644 Tests/InterfaceControler.cs create mode 100644 Tests/OpenGL/Extensions.cs diff --git a/Tests/BasicTests.cs b/Tests/BasicTests.cs index 761775b9..8b9f1afb 100644 --- a/Tests/BasicTests.cs +++ b/Tests/BasicTests.cs @@ -10,7 +10,7 @@ using System.Diagnostics; namespace Tests { - class BasicTests : CrowWindow3D + class BasicTests : CrowWindow { public BasicTests () : base(800, 600,"test: press to toogle test files") @@ -129,7 +129,7 @@ namespace Tests testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Unsorted", "*.crow")).ToArray (); object tc = Color.AirForceBlueRaf; - CrowInterface.LoadInterface(testFiles[idx]).DataSource = this; + Load(testFiles[idx]).DataSource = this; } void KeyboardKeyDown1 (object sender, OpenTK.Input.KeyboardKeyEventArgs e) { @@ -141,19 +141,19 @@ namespace Tests NotifyValueChanged ("TestList", TestList); return; } else if (e.Key == OpenTK.Input.Key.F4) { - GraphicObject w = CrowInterface.LoadInterface ("Interfaces/TemplatedContainer/testWindow.goml"); + GraphicObject w = Load ("Interfaces/TemplatedContainer/testWindow.goml"); w.DataSource = this; return; } else if (e.Key == OpenTK.Input.Key.F5) { - GraphicObject w = CrowInterface.LoadInterface ("Interfaces/TemplatedContainer/testWindow2.goml"); + GraphicObject w = Load ("Interfaces/TemplatedContainer/testWindow2.goml"); w.DataSource = this; return; }else if (e.Key == OpenTK.Input.Key.F6) { - GraphicObject w = CrowInterface.LoadInterface ("Interfaces/Divers/0.crow"); + GraphicObject w = Load ("Interfaces/Divers/0.crow"); w.DataSource = this; return; }else if (e.Key == OpenTK.Input.Key.F7) { - GraphicObject w = CrowInterface.LoadInterface ("Interfaces/Divers/perfMeasures.crow"); + GraphicObject w = Load ("Interfaces/Divers/perfMeasures.crow"); w.DataSource = this; return; } else if (e.Key == OpenTK.Input.Key.F2) @@ -162,61 +162,61 @@ namespace Tests idx++; else return; - + try { - CrowInterface.ClearInterface (); + ClearInterface (); if (idx == testFiles.Length) idx = 0; else if (idx < 0) idx = testFiles.Length - 1; - + this.Title = testFiles [idx] + ". Press to cycle examples."; - GraphicObject obj = CrowInterface.LoadInterface(testFiles[idx]); + GraphicObject obj = Load (testFiles[idx]); obj.DataSource = this; } catch (Exception ex) { Debug.WriteLine (ex.Message + ex.InnerException); } } - void Tv_SelectedItemChanged (object sender, SelectionChangeEventArgs e) - { - FileInfo fi = e.NewValue as FileInfo; - if (fi == null) - return; - if (fi.Extension == ".crow" || fi.Extension == ".goml") { - Instantiator i = new Instantiator(fi.FullName); - lock (CrowInterface.UpdateMutex) { - (CrowInterface.FindByName ("crowContainer") as Container).SetChild - (i.CreateInstance(CrowInterface)); - //CurSources = i.GetImlSourcesCode(); - } - } - } - void onImlSourceChanged(Object sender, TextChangeEventArgs e){ - Instantiator i; - try { - i = Instantiator.CreateFromImlFragment (e.Text); - } catch (Exception ex) { - Debug.WriteLine (ex); - return; - } - lock (CrowInterface.UpdateMutex) { - (CrowInterface.FindByName ("crowContainer") as Container).SetChild - (i.CreateInstance(CrowInterface)); - } - } +// void Tv_SelectedItemChanged (object sender, SelectionChangeEventArgs e) +// { +// FileInfo fi = e.NewValue as FileInfo; +// if (fi == null) +// return; +// if (fi.Extension == ".crow" || fi.Extension == ".goml") { +// Instantiator i = new Instantiator(fi.FullName); +// lock (ifaceControl.CrowInterface.UpdateMutex) { +// (ifaceControl.CrowInterface.FindByName ("crowContainer") as Container).SetChild +// (i.CreateInstance(ifaceControl.CrowInterface)); +// //CurSources = i.GetImlSourcesCode(); +// } +// } +// } +// void onImlSourceChanged(Object sender, TextChangeEventArgs e){ +// Instantiator i; +// try { +// i = Instantiator.CreateFromImlFragment (e.Text); +// } catch (Exception ex) { +// Debug.WriteLine (ex); +// return; +// } +// lock (ifaceControl.CrowInterface.UpdateMutex) { +// (ifaceControl.CrowInterface.FindByName ("crowContainer") as Container).SetChild +// (i.CreateInstance(ifaceControl.CrowInterface)); +// } +// } void onButClick(object send, MouseButtonEventArgs e) { Console.WriteLine ("button clicked:" + send.ToString()); } - void onAddTabButClick(object sender, MouseButtonEventArgs e){ - - TabView tv = CrowInterface.FindByName("tabview1") as TabView; - if (tv == null) - return; - tv.AddChild (new TabItem () { Caption = "NewTab" }); - } +// void onAddTabButClick(object sender, MouseButtonEventArgs e){ +// +// TabView tv = ifaceControl.CrowInterface.FindByName("tabview1") as TabView; +// if (tv == null) +// return; +// tv.AddChild (new TabItem () { Caption = "NewTab" }); +// } [STAThread] static void Main () { diff --git a/Tests/CrowWindow.cs b/Tests/CrowWindow.cs index feb43101..25211744 100644 --- a/Tests/CrowWindow.cs +++ b/Tests/CrowWindow.cs @@ -32,13 +32,11 @@ namespace Crow public event EventHandler ValueChanged; public virtual void NotifyValueChanged(string MemberName, object _value) { - if (ValueChanged != null) + if (ValueChanged != null) ValueChanged.Invoke(this, new ValueChangeEventArgs(MemberName, _value)); } #endregion - public Interface CrowInterface; - #region FPS int frameCpt = 0; int _fps = 0; @@ -50,7 +48,7 @@ namespace Crow return; _fps = value; - + #if MEASURE_TIME if (_fps > fpsMax) { fpsMax = _fps; ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMax", fpsMax)); @@ -58,15 +56,19 @@ namespace Crow fpsMin = _fps; ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMin", fpsMin)); } + #endif if (frameCpt % 3 == 0) ValueChanged.Raise(this, new ValueChangeEventArgs ("fps", _fps)); #if MEASURE_TIME - foreach (PerformanceMeasure m in PerfMeasures) - m.NotifyChanges(); +// foreach (PerformanceMeasure m in PerfMeasures) +// m.NotifyChanges(); #endif } } + #if MEASURE_TIME + public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); + public int fpsMin = int.MaxValue; public int fpsMax = 0; @@ -76,12 +78,6 @@ namespace Crow fpsMax = 0; _fps = 0; } - public string update = ""; - public string drawing = ""; - public string layouting = ""; - public string clipping = ""; - #if MEASURE_TIME - public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); #endif #endregion @@ -98,42 +94,52 @@ namespace Crow public CrowWindow (int width, int height, OpenTK.Graphics.GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device, int major, int minor, OpenTK.Graphics.GraphicsContextFlags flags) : base(width,height,mode,title,options,device,major,minor,flags) { - CrowInterface = new Interface (); - - #if MEASURE_TIME - PerfMeasures = new List ( - new PerformanceMeasure[] { - this.CrowInterface.updateMeasure, - this.CrowInterface.layoutingMeasure, - this.CrowInterface.clippingMeasure, - this.CrowInterface.drawingMeasure, - this.glDrawMeasure - } - ); - #endif - - Thread t = new Thread (interfaceThread); - t.IsBackground = true; - t.Start (); } #endregion - #if MEASURE_TIME - public List PerfMeasures; - #endif + protected Shader shader; + public List ifaceControl = new List(); + int focusedIdx = -1, activeIdx = -2; - void interfaceThread() + void addInterfaceControler(InterfaceControler ifaceControler) { - CrowInterface.Quit += Quit; - CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged; - while (CrowInterface.ClientRectangle.Size.Width == 0) - Thread.Sleep (5); - - while (true) { - CrowInterface.Update (); - //Thread.Sleep (1); + ifaceControler.CrowInterface.Quit += Quit; + ifaceControler.CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged; + + ifaceControl.Add (ifaceControler); + } + void openGLDraw(){ + //save GL states + bool blend, depthTest, cullFace; + GL.GetBoolean (GetPName.Blend, out blend); + GL.GetBoolean (GetPName.DepthTest, out depthTest); + GL.GetBoolean (GetPName.CullFace, out cullFace); + GL.Enable (EnableCap.Blend); + GL.Disable (EnableCap.DepthTest); + GL.Disable (EnableCap.CullFace); + + #if MEASURE_TIME + glDrawMeasure.StartCycle(); + #endif + + shader.Enable (); + for (int i = 0; i < ifaceControl.Count; i++) { + shader.SetMVP (ifaceControl [i].InterfaceMVP); + ifaceControl [i].OpenGLDraw (); } + + #if MEASURE_TIME + glDrawMeasure.StopCycle(); + #endif + + //restore GL states + if (!blend) + GL.Disable (EnableCap.Blend); + if (depthTest) + GL.Enable (EnableCap.DepthTest); + if (cullFace) + GL.Enable (EnableCap.CullFace); } public void Quit (object sender, EventArgs e) @@ -162,73 +168,27 @@ namespace Crow #endregion - #region graphic context - public int texID; - public Shader shader; - public vaoMesh quad; - public Matrix4 projection; - - protected virtual Matrix4 InterfaceMVP { - get { return projection; } + public ProjectiveIFaceControler Add3DInterface(int width, int height, Matrix4 ifaceModelMat){ + ProjectiveIFaceControler tmp = new ProjectiveIFaceControler (new Rectangle (0, 0, width, height), ifaceModelMat); + ifaceControl.Add (tmp); + return tmp; } - - /// Create the texture for the interface redering - protected virtual void createContext() - { - if (GL.IsTexture(texID)) - GL.DeleteTexture (texID); - GL.GenTextures(1, out texID); - GL.ActiveTexture (TextureUnit.Texture0); - GL.BindTexture(TextureTarget.Texture2D, texID); - - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, - ClientRectangle.Width, ClientRectangle.Height, 0, - OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.bmp); - - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); - - GL.BindTexture(TextureTarget.Texture2D, 0); + public GraphicObject AddWidget (GraphicObject g, int interfaceIdx = 0){ + if (ifaceControl.Count == 0)//create default orthogonal interface + addInterfaceControler (new InterfaceControler ( + new Rectangle (0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height))); + ifaceControl [interfaceIdx].CrowInterface.AddWidget (g); + return g; } - /// Rendering of the interface - protected virtual void OpenGLDraw() - { - #if MEASURE_TIME - glDrawMeasure.StartCycle(); - #endif - bool blend, depthTest; - GL.GetBoolean (GetPName.Blend, out blend); - GL.GetBoolean (GetPName.DepthTest, out depthTest); - GL.Enable (EnableCap.Blend); - GL.Disable (EnableCap.DepthTest); - - shader.Enable (); - shader.SetMVP (InterfaceMVP); - GL.ActiveTexture (TextureUnit.Texture0); - GL.BindTexture (TextureTarget.Texture2D, texID); - if (Monitor.TryEnter(CrowInterface.RenderMutex)) { - if (CrowInterface.IsDirty) { - GL.TexSubImage2D (TextureTarget.Texture2D, 0, - CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top, - CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height, - OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.dirtyBmp); - CrowInterface.IsDirty = false; - } - Monitor.Exit (CrowInterface.RenderMutex); - } - quad.Render (BeginMode.TriangleStrip); - GL.BindTexture(TextureTarget.Texture2D, 0); - - if (!blend) - GL.Disable (EnableCap.Blend); - if (depthTest) - GL.Enable (EnableCap.DepthTest); - #if MEASURE_TIME - glDrawMeasure.StopCycle(); - #endif + public GraphicObject Load (string path, int interfaceIdx = 0){ + if (ifaceControl.Count == 0)//create default orthogonal interface + addInterfaceControler (new InterfaceControler ( + new Rectangle (0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height))); + return ifaceControl [interfaceIdx].CrowInterface.LoadInterface (path); + } + public void ClearInterface (int interfaceIdx = 0){ + ifaceControl [interfaceIdx].CrowInterface.ClearInterface (); } - #endregion - /// Override this method for your OpenGL rendering calls public virtual void OnRender(FrameEventArgs e) { @@ -238,12 +198,7 @@ namespace Crow { GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit); } - protected virtual void initGL(){ - GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); - projection = OpenTK.Matrix4.CreateOrthographicOffCenter (-0.5f, 0.5f, -0.5f, 0.5f, 1, -1); - shader = new Shader (); - quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1); - } + #region Game win overrides protected override void OnLoad(EventArgs e) { @@ -265,15 +220,17 @@ namespace Crow Console.WriteLine("*************************************\n"); #endif - initGL (); - } + shader = new Shader (); + shader.Enable (); + GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); + } protected override void OnUpdateFrame(FrameEventArgs e) { base.OnUpdateFrame(e); fps = (int)RenderFrequency; - + #if MEASURE_TIME if (frameCpt > 500) { resetFps (); frameCpt = 0; @@ -283,6 +240,8 @@ namespace Crow // NotifyValueChanged("memory", GC.GetTotalMemory (false).ToString()); // #endif } + #endif + frameCpt++; } protected override void OnRenderFrame(FrameEventArgs e) @@ -292,26 +251,26 @@ namespace Crow base.OnRenderFrame(e); OnRender (e); - OpenGLDraw (); + openGLDraw (); + SwapBuffers (); } - protected override void OnResize(EventArgs e) { base.OnResize (e); - CrowInterface.ProcessResize( - new Rectangle( - 0, - 0, - this.ClientRectangle.Width, - this.ClientRectangle.Height)); - createContext (); - GL.Viewport (0, 0, ClientRectangle.Width, ClientRectangle.Height); + for (int i = 0; i < ifaceControl.Count; i++) { + ifaceControl[i].ProcessResize( + new Rectangle( + 0, + 0, + this.ClientRectangle.Width, + this.ClientRectangle.Height)); + } } #endregion - #region Mouse Handling + #region Mouse and Keyboard Handling void update_mouseButtonStates(ref MouseState e, OpenTK.Input.MouseState otk_e){ for (int i = 0; i < MouseState.MaxButtons; i++) { if (otk_e.IsButtonDown ((OpenTK.Input.MouseButton)i)) @@ -320,40 +279,71 @@ namespace Crow } protected virtual void Mouse_Move(object sender, OpenTK.Input.MouseMoveEventArgs otk_e) { - if (!CrowInterface.ProcessMouseMove (otk_e.X, otk_e.Y)) + if (activeIdx == -2) { + focusedIdx = -1; + for (int i = 0; i < ifaceControl.Count; i++) { + if (ifaceControl [i].ProcessMouseMove (otk_e.X, otk_e.Y)) { + focusedIdx = i; + return; + } + } + } else if (focusedIdx >= 0) { + ifaceControl [focusedIdx].ProcessMouseMove (otk_e.X, otk_e.Y); + return; + } + if (focusedIdx < 0) MouseMove.Raise (sender, otk_e); } protected virtual void Mouse_ButtonUp(object sender, OpenTK.Input.MouseButtonEventArgs otk_e) { - if (!CrowInterface.ProcessMouseButtonUp ((int)otk_e.Button)) - MouseButtonUp.Raise (sender, otk_e); + activeIdx = -2; + if (focusedIdx >= 0) { + if (ifaceControl [focusedIdx].ProcessMouseButtonUp ((int)otk_e.Button)) + return; + } + MouseButtonUp.Raise (sender, otk_e); } protected virtual void Mouse_ButtonDown(object sender, OpenTK.Input.MouseButtonEventArgs otk_e) { - if (!CrowInterface.ProcessMouseButtonDown ((int)otk_e.Button)) - MouseButtonDown.Raise (sender, otk_e); + activeIdx = focusedIdx; + if (focusedIdx >= 0) { + if (ifaceControl [focusedIdx].ProcessMouseButtonDown ((int)otk_e.Button)) + return; + } + MouseButtonDown.Raise (sender, otk_e); } protected virtual void Mouse_WheelChanged(object sender, OpenTK.Input.MouseWheelEventArgs otk_e) { - if (!CrowInterface.ProcessMouseWheelChanged (otk_e.DeltaPrecise)) - MouseWheelChanged.Raise (sender, otk_e); + if (focusedIdx >= 0) { + if (ifaceControl [focusedIdx].ProcessMouseWheelChanged (otk_e.DeltaPrecise)) + return; + } + MouseWheelChanged.Raise (sender, otk_e); } - #endregion - #region keyboard Handling protected virtual void Keyboard_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e) { - if (!CrowInterface.ProcessKeyDown((int)otk_e.Key)) - KeyboardKeyDown.Raise (this, otk_e); + if (focusedIdx >= 0) { + if (ifaceControl [focusedIdx].ProcessKeyDown((int)otk_e.Key)) + return; + } + KeyboardKeyDown.Raise (this, otk_e); } protected virtual void Keyboard_KeyUp(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e) { - if (!CrowInterface.ProcessKeyUp((int)otk_e.Key)) - KeyboardKeyUp.Raise (this, otk_e); + if (focusedIdx >= 0) { + if (ifaceControl [focusedIdx].ProcessKeyUp((int)otk_e.Key)) + return; + } + KeyboardKeyUp.Raise (this, otk_e); } protected virtual void OpenTKGameWindow_KeyPress (object sender, OpenTK.KeyPressEventArgs e) { - CrowInterface.ProcessKeyPress (e.KeyChar); + if (focusedIdx >= 0) { + if (ifaceControl [focusedIdx].ProcessKeyPress (e.KeyChar)) + return; + } + //TODO:create keyboardkeypress evt } #endregion } diff --git a/Tests/CrowWindow3D.cs b/Tests/CrowWindow3D.cs deleted file mode 100644 index 6ce918ef..00000000 --- a/Tests/CrowWindow3D.cs +++ /dev/null @@ -1,240 +0,0 @@ -// -// OpenTKGameWindow.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2016 jp -// -// 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 . -using System; -using System.Threading; -using OpenTK; -using OpenTK.Graphics.OpenGL; -using System.Collections.Generic; - -namespace Crow -{ - public class CrowWindow3D : CrowWindow - { - #region ctor - public CrowWindow3D(int _width = 800, int _height = 600, string _title="Crow", - int colors = 32, int depth = 24, int stencil = 0, int samples = 1, - int major=3, int minor=3) - : this(_width, _height, new OpenTK.Graphics.GraphicsMode(colors, depth, stencil, samples), - _title,GameWindowFlags.Default,DisplayDevice.Default, - major,minor,OpenTK.Graphics.GraphicsContextFlags.Default) - { - } - public CrowWindow3D (int width, int height, OpenTK.Graphics.GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device, int major, int minor, OpenTK.Graphics.GraphicsContextFlags flags) - : base(width,height,mode,title,options,device,major,minor,flags) - { - } - - #endregion - - #region graphic context - protected Matrix4 modelview; - protected int[] viewport = new int[4]; - protected Vector3 vEyeTarget = new Vector3(0f, 0f, 0f); - protected Vector3 vEye; - protected Vector3 vLookInit = Vector3.Normalize(new Vector3(0.0f, 1.0f, 0.0f)); - protected Vector3 vLook; // Camera vLook Vector - protected float zNear = 0.001f, zFar = 300.0f; - protected float fovY = (float)Math.PI / 4; - protected float eyeDist = 1.2f; - protected float viewZangle, viewXangle; - protected const float MoveSpeed = 0.02f; - protected const float RotationSpeed = 0.005f; - protected const float ZoomSpeed = 0.22f; - - public Matrix4 interfaceModelView; - Rectangle iRect = new Rectangle(0,0,2048,2048); - - protected override Matrix4 InterfaceMVP { - get { return interfaceModelView * modelview * projection; } - } - - protected override void initGL(){ - GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); - shader = new Shader (); - //quad = new Crow.vaoMesh (0, 0, 0, 1, iRect.Height / (float)iRect.Width, 1, -1); - quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1); - interfaceModelView = Matrix4.CreateRotationX(MathHelper.PiOver2) * Matrix4.CreateTranslation(Vector3.UnitY); - createContext (); - CrowInterface.ProcessResize (iRect); - } - /// Create the texture for the interface redering - protected override void createContext () - { - if (GL.IsTexture(texID)) - GL.DeleteTexture (texID); - GL.GenTextures(1, out texID); - GL.ActiveTexture (TextureUnit.Texture0); - GL.BindTexture(TextureTarget.Texture2D, texID); - - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, - iRect.Width, iRect.Height, 0, - OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.bmp); - - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); - - GL.BindTexture(TextureTarget.Texture2D, 0); - } - - #endregion - - - #region Game win overrides - - protected override void OnResize(EventArgs e) - { - //base.OnResize (e); - UpdateViewMatrix (); - } - #endregion - - #region Mouse Handling - Point mousePosition; - bool mouseIsInInterface = false; - - void updateMousePosition(OpenTK.Input.MouseMoveEventArgs otk_e) - { - Matrix4 mv = interfaceModelView * modelview; - Vector3 vMouse = UnProject(ref projection, ref mv, viewport, new Vector2 (otk_e.X, otk_e.Y)).Xyz; - Vector3 vE = vEye.Transform (interfaceModelView.Inverted()); - Vector3 vMouseRay = Vector3.Normalize(vMouse - vE); - float a = vE.Z / vMouseRay.Z; - vMouse = vE - vMouseRay * a; - //vMouse = vMouse.Transform (interfaceModelView.Inverted()); - mousePosition = new Point ((int)Math.Truncate ((vMouse.X + 0.5f) * iRect.Width), - iRect.Height - (int)Math.Truncate ((vMouse.Y + 0.5f) * iRect.Height)); - mouseIsInInterface = mousePosition.X.IsInBetween (0, iRect.Width) & mousePosition.Y.IsInBetween (0, iRect.Height); - //System.Diagnostics.Debug.WriteLine ("vMouse={0} newPos={1}", vMouse, mousePosition); - } - public void UpdateViewMatrix() - { - Rectangle r = this.ClientRectangle; - GL.Viewport( r.X, r.Y, r.Width, r.Height); - projection = Matrix4.CreatePerspectiveFieldOfView (fovY, r.Width / (float)r.Height, zNear, zFar); - vLook = vLookInit.Transform( - Matrix4.CreateRotationX (viewXangle)* - Matrix4.CreateRotationZ (viewZangle)); - vLook.Normalize(); - vEye = vEyeTarget + vLook * eyeDist; - modelview = Matrix4.LookAt(vEye, vEyeTarget, Vector3.UnitZ); - GL.GetInteger(GetPName.Viewport, viewport); - } - - protected override void Mouse_Move(object sender, OpenTK.Input.MouseMoveEventArgs otk_e) - { - updateMousePosition (otk_e); - - if (mouseIsInInterface & !(Keyboard [OpenTK.Input.Key.ShiftLeft])) { - if (CrowInterface.ProcessMouseMove (mousePosition.X, mousePosition.Y)) - return; - } - if (otk_e.Mouse.MiddleButton == OpenTK.Input.ButtonState.Pressed) { - viewZangle -= (float)otk_e.XDelta * RotationSpeed; - viewXangle += (float)otk_e.YDelta * RotationSpeed; - UpdateViewMatrix (); - } else if (otk_e.Mouse.LeftButton == OpenTK.Input.ButtonState.Pressed) { - return; - } else if (otk_e.Mouse.RightButton == OpenTK.Input.ButtonState.Pressed) { - Vector2 v2Look = vLook.Xy.Normalized (); - Vector2 disp = v2Look.PerpendicularLeft * otk_e.XDelta * MoveSpeed + - v2Look * otk_e.YDelta * MoveSpeed; - vEyeTarget += new Vector3 (disp.X, disp.Y, 0); - UpdateViewMatrix (); - } - - //MouseMove.Raise (sender, otk_e); - } - - protected override void Mouse_ButtonUp(object sender, OpenTK.Input.MouseButtonEventArgs otk_e) - { - if (mouseIsInInterface & !Keyboard [OpenTK.Input.Key.ShiftLeft]) - CrowInterface.ProcessMouseButtonUp ((int)otk_e.Button); -// else -// MouseButtonUp.Raise (sender, otk_e); - } - protected override void Mouse_ButtonDown(object sender, OpenTK.Input.MouseButtonEventArgs otk_e) - { - if (mouseIsInInterface & !Keyboard [OpenTK.Input.Key.ShiftLeft]) - CrowInterface.ProcessMouseButtonDown ((int)otk_e.Button); -// else -// MouseButtonDown.Raise (sender, otk_e); - } - protected override void Mouse_WheelChanged(object sender, OpenTK.Input.MouseWheelEventArgs otk_e) - { - if (mouseIsInInterface & !Keyboard [OpenTK.Input.Key.ShiftLeft]) { - CrowInterface.ProcessMouseWheelChanged (otk_e.DeltaPrecise); - return; - } - - float speed = ZoomSpeed; - if (Keyboard[OpenTK.Input.Key.ControlLeft]) - speed *= 20.0f; - - eyeDist -= otk_e.Delta * speed; - if (eyeDist < zNear) - eyeDist = zNear; - else if (eyeDist > zFar) - eyeDist = zFar; - UpdateViewMatrix (); - -// MouseWheelChanged.Raise (sender, otk_e); - } - #endregion - - static Vector4 UnProject(ref Matrix4 projection, ref Matrix4 view, int[] viewport, Vector2 mouse) - { - Vector4 vec; - - vec.X = 2.0f * mouse.X / (float)viewport[2] - 1; - vec.Y = -(2.0f * mouse.Y / (float)viewport[3] - 1); - vec.Z = 0f; - vec.W = 1.0f; - - Matrix4 viewInv = Matrix4.Invert(view); - Matrix4 projInv = Matrix4.Invert(projection); - - Vector4.Transform(ref vec, ref projInv, out vec); - Vector4.Transform(ref vec, ref viewInv, out vec); - - if (vec.W > float.Epsilon || vec.W < float.Epsilon) - { - vec.X /= vec.W; - vec.Y /= vec.W; - vec.Z /= vec.W; - } - - return vec; - } - } - - public static class Extensions { - public static Vector4 ToVector4(this Color c){ - float[] f = c.floatArray; - return new Vector4 (f [0], f [1], f [2], f [3]); - } - public static Vector3 Transform(this Vector3 v, Matrix4 m){ - return Vector4.Transform(new Vector4(v, 1), m).Xyz; - } - public static bool IsInBetween(this int v, int min, int max){ - return v >= min & v <= max; - } - } -} diff --git a/Tests/Hello3D.cs b/Tests/Hello3D.cs index ed7087b6..c03a5ced 100644 --- a/Tests/Hello3D.cs +++ b/Tests/Hello3D.cs @@ -26,7 +26,7 @@ using Crow; namespace Tests { - class Hello3D : CrowWindow3D + class Hello3D : CrowWindow { [STAThread] static void Main () @@ -40,9 +40,23 @@ namespace Tests { } + public Matrix4 modelview, projection; + public int[] viewport = new int[4]; + public Vector3 vEyeTarget = new Vector3(0f, 0f, 0f); + public Vector3 vEye; + public Vector3 vLookInit = Vector3.Normalize(new Vector3(-1.0f, -1.0f, 1.0f)); + public Vector3 vLook; // Camera vLook Vector + public float zNear = 0.001f, zFar = 300.0f; + public float fovY = (float)Math.PI / 4; + public float eyeDist = 10.2f; + public float viewZangle, viewXangle; + public const float MoveSpeed = 0.02f; + public const float RotationSpeed = 0.005f; + public const float ZoomSpeed = 0.22f; + vaoMesh cube; Texture texture; - + ProjectiveIFaceControler iface3D; void initGL(){ GL.Enable (EnableCap.CullFace); @@ -51,38 +65,30 @@ namespace Tests cube = vaoMesh.CreateCube (); texture = new Texture ("image/textest.png"); - -// projection = -// Matrix4.CreatePerspectiveFieldOfView ( -// MathHelper.PiOver4, -// ClientRectangle.Width / (float)ClientRectangle.Height, 1.0f, 10.0f); -// modelview = Matrix4.LookAt(vEye*eyeDist, Vector3.Zero, Vector3.UnitZ); } -// Vector3 vEye = new Vector3(1,1,1).Normalized(); -// float eyeDist = 5f; -// const float rotSpeed = -0.03f; + protected override void OnLoad (EventArgs e) { base.OnLoad (e); - //MouseMove += HelloCube_MouseMove; + MouseMove += HelloCube_MouseMove; + MouseWheelChanged += Hello3D_MouseWheelChanged; - CrowInterface.LoadInterface (@"Interfaces/Divers/0.crow"); + iface3D = Add3DInterface (2048, 2048, + Matrix4.CreateScale (6f) * + Matrix4.CreateRotationX (MathHelper.PiOver2) * + Matrix4.CreateTranslation (Vector3.UnitY * -1.1f)); + Load (@"Interfaces/Divers/0.crow").DataSource = this; initGL (); shader.Enable (); } -// void HelloCube_MouseMove (object sender, OpenTK.Input.MouseMoveEventArgs e) -// { -// if (e.Mouse.MiddleButton == OpenTK.Input.ButtonState.Pressed) { -// Vector2 vPerp = vEye.Xy.PerpendicularLeft; -// vEye = vEye.Transform ( -// Matrix4.CreateFromAxisAngle (new Vector3 (vPerp.X, vPerp.Y, 0), e.YDelta * rotSpeed) * -// Matrix4.CreateRotationZ (e.XDelta * rotSpeed) -// ).Normalized (); -// modelview = Matrix4.LookAt (vEye * eyeDist, Vector3.Zero, Vector3.UnitZ); -// } -// } + protected override void OnResize (EventArgs e) + { + base.OnResize (e); + UpdateViewMatrix (); + } + public override void OnRender (FrameEventArgs e) { base.OnRender (e); @@ -94,5 +100,50 @@ namespace Tests GL.BindTexture (TextureTarget.Texture2D, 0); } + public void UpdateViewMatrix() + { + Rectangle r = this.ClientRectangle; + GL.Viewport( r.X, r.Y, r.Width, r.Height); + projection = Matrix4.CreatePerspectiveFieldOfView (fovY, r.Width / (float)r.Height, zNear, zFar); + vLook = vLookInit.Transform( + Matrix4.CreateRotationX (viewXangle)* + Matrix4.CreateRotationZ (viewZangle)); + vLook.Normalize(); + vEye = vEyeTarget + vLook * eyeDist; + modelview = Matrix4.LookAt(vEye, vEyeTarget, Vector3.UnitZ); + GL.GetInteger(GetPName.Viewport, viewport); + + iface3D.UpdateView (projection, modelview, viewport, vEye); + } + + void HelloCube_MouseMove(object sender, OpenTK.Input.MouseMoveEventArgs otk_e) + { + if (otk_e.Mouse.MiddleButton == OpenTK.Input.ButtonState.Pressed) { + viewZangle -= (float)otk_e.XDelta * RotationSpeed; + viewXangle -= (float)otk_e.YDelta * RotationSpeed; + UpdateViewMatrix (); + } else if (otk_e.Mouse.LeftButton == OpenTK.Input.ButtonState.Pressed) { + return; + } else if (otk_e.Mouse.RightButton == OpenTK.Input.ButtonState.Pressed) { + Vector2 v2Look = vLook.Xy.Normalized (); + Vector2 disp = v2Look.PerpendicularLeft * otk_e.XDelta * MoveSpeed + + v2Look * otk_e.YDelta * MoveSpeed; + vEyeTarget += new Vector3 (disp.X, disp.Y, 0); + UpdateViewMatrix (); + } + } + void Hello3D_MouseWheelChanged (object sender, OpenTK.Input.MouseWheelEventArgs e) + { + float speed = ZoomSpeed; + if (Keyboard[OpenTK.Input.Key.ControlLeft]) + speed *= 20.0f; + + eyeDist -= e.Delta * speed; + if (eyeDist < zNear) + eyeDist = zNear; + else if (eyeDist > zFar) + eyeDist = zFar; + UpdateViewMatrix (); + } } } \ No newline at end of file diff --git a/Tests/HelloCube.cs b/Tests/HelloCube.cs index 8f6f185c..d9223f5a 100644 --- a/Tests/HelloCube.cs +++ b/Tests/HelloCube.cs @@ -63,7 +63,7 @@ namespace Tests { base.OnLoad (e); - CrowInterface.AddWidget( + AddWidget( new Window () { Title = "Hello World" diff --git a/Tests/HelloWorld.cs b/Tests/HelloWorld.cs index 5006d48d..a38c7974 100644 --- a/Tests/HelloWorld.cs +++ b/Tests/HelloWorld.cs @@ -14,7 +14,7 @@ namespace Tests { base.OnLoad (e); - CrowInterface.AddWidget(new Label("Hello World")); + AddWidget(new Label("Hello World")); } [STAThread] diff --git a/Tests/InterfaceControler.cs b/Tests/InterfaceControler.cs new file mode 100644 index 00000000..6cb13b2f --- /dev/null +++ b/Tests/InterfaceControler.cs @@ -0,0 +1,220 @@ +// +// InterfaceControler.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2017 jp +// +// 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 . +using System; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using System.Threading; +using System.Collections.Generic; + +namespace Crow +{ + public class ProjectiveIFaceControler : InterfaceControler { + Matrix4 modelview; + int[] viewport = new int[4]; + Vector3 vEyePosition; + + public Matrix4 ifaceModelMat; + Point localMousePos; + + public ProjectiveIFaceControler(Rectangle ifaceBounds, Matrix4 _ifaceModelMat) + : base(ifaceBounds){ + ifaceModelMat = _ifaceModelMat; + } + + public override Matrix4 InterfaceMVP { + get { return ifaceModelMat * modelview * projection; } + } + + public override void initGL(){ + quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1); + //ifaceModelMat = Matrix4.CreateRotationX(MathHelper.PiOver2) * Matrix4.CreateTranslation(Vector3.UnitY); + CrowInterface.ProcessResize(iRect); + createContext (); + //CrowInterface.ProcessResize (iRect); + } + public override void ProcessResize (Rectangle newSize) + { + } + + public void UpdateView (Matrix4 _projection, Matrix4 _modelview, int[] _viewport, Vector3 _vEyePosition) + { + projection = _projection; + modelview = _modelview; + viewport = _viewport; + vEyePosition = _vEyePosition; + } + public override bool ProcessMouseMove (int x, int y) + { + Matrix4 mv = ifaceModelMat * modelview; + Vector3 vMouse = Extensions.UnProject(ref projection, ref mv, viewport, new Vector2 (x, y)).Xyz; + Vector3 vE = vEyePosition.Transform (ifaceModelMat.Inverted()); + Vector3 vMouseRay = Vector3.Normalize(vMouse - vE); + float a = vE.Z / vMouseRay.Z; + vMouse = vE - vMouseRay * a; + //vMouse = vMouse.Transform (interfaceModelView.Inverted()); + localMousePos = new Point ((int)Math.Truncate ((vMouse.X + 0.5f) * iRect.Width), + iRect.Height - (int)Math.Truncate ((vMouse.Y + 0.5f) * iRect.Height)); + mouseIsInInterface = localMousePos.X.IsInBetween (0, iRect.Width) & localMousePos.Y.IsInBetween (0, iRect.Height); + + return mouseIsInInterface ? CrowInterface.ProcessMouseMove (localMousePos.X, localMousePos.Y) : false; + } + } + public class InterfaceControler { + public Interface CrowInterface; + public int texID; + public vaoMesh quad; + public Rectangle iRect = new Rectangle(0,0,2048,2048); + public bool mouseIsInInterface = false; + + protected Matrix4 projection; + public virtual Matrix4 InterfaceMVP { + get { return projection; } + } + + #if MEASURE_TIME + public List PerfMeasures; + public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); + #endif + + #region CTOR + public InterfaceControler(Rectangle ifaceBounds){ + iRect = ifaceBounds; + + CrowInterface = new Interface (); + + #if MEASURE_TIME + PerfMeasures = new List ( + new PerformanceMeasure[] { + this.CrowInterface.updateMeasure, + this.CrowInterface.layoutingMeasure, + this.CrowInterface.clippingMeasure, + this.CrowInterface.drawingMeasure, + this.glDrawMeasure + } + ); + #endif + + Thread t = new Thread (interfaceThread); + t.IsBackground = true; + t.Start (); + + initGL (); + } + #endregion + + void interfaceThread() + { + while (CrowInterface.ClientRectangle.Size.Width == 0) + Thread.Sleep (5); + + while (true) { + CrowInterface.Update (); + //Thread.Sleep (1); + } + } + + #region Mouse And Keyboard handling + public virtual void ProcessResize(Rectangle newSize){ + iRect = newSize; + CrowInterface.ProcessResize(newSize); + createContext (); + GL.Viewport (0, 0, newSize.Width, newSize.Height);//TODO:find a better place for this + } + public virtual bool ProcessMouseMove(int x, int y){ + return CrowInterface.ProcessMouseMove (x, y); + } + public virtual bool ProcessMouseButtonUp(int button) + { + return CrowInterface.ProcessMouseButtonUp (button); + } + public virtual bool ProcessMouseButtonDown(int button) + { + return CrowInterface.ProcessMouseButtonDown (button); + } + public virtual bool ProcessMouseWheelChanged(float delta) + { + return CrowInterface.ProcessMouseWheelChanged (delta); + } + public virtual bool ProcessKeyDown(int Key){ + return CrowInterface.ProcessKeyDown(Key); + } + public virtual bool ProcessKeyUp(int Key){ + return CrowInterface.ProcessKeyUp(Key); + } + public virtual bool ProcessKeyPress(char Key){ + return CrowInterface.ProcessKeyPress(Key); + } + #endregion + + #region graphic context + public virtual void initGL(){ + projection = OpenTK.Matrix4.CreateOrthographicOffCenter (-0.5f, 0.5f, -0.5f, 0.5f, 1, -1); + quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1); + createContext (); + } + /// Create the texture for the interface redering + public virtual void createContext() + { + if (GL.IsTexture(texID)) + GL.DeleteTexture (texID); + GL.GenTextures(1, out texID); + GL.ActiveTexture (TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, texID); + + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, + iRect.Width, iRect.Height, 0, + OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.bmp); + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + + GL.BindTexture(TextureTarget.Texture2D, 0); + } + /// Rendering of the interface + public virtual void OpenGLDraw() + { + #if MEASURE_TIME + glDrawMeasure.StartCycle(); + #endif + + GL.ActiveTexture (TextureUnit.Texture0); + GL.BindTexture (TextureTarget.Texture2D, texID); + if (Monitor.TryEnter(CrowInterface.RenderMutex)) { + if (CrowInterface.IsDirty) { + GL.TexSubImage2D (TextureTarget.Texture2D, 0, + CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top, + CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height, + OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.dirtyBmp); + CrowInterface.IsDirty = false; + } + Monitor.Exit (CrowInterface.RenderMutex); + } + quad.Render (BeginMode.TriangleStrip); + GL.BindTexture(TextureTarget.Texture2D, 0); + + #if MEASURE_TIME + glDrawMeasure.StopCycle(); + #endif + } + #endregion + } +} + diff --git a/Tests/OpenGL/Extensions.cs b/Tests/OpenGL/Extensions.cs new file mode 100644 index 00000000..17fe6086 --- /dev/null +++ b/Tests/OpenGL/Extensions.cs @@ -0,0 +1,64 @@ +// +// Extensions.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2017 jp +// +// 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 . +using System; +using OpenTK; +using Crow; + +namespace Crow +{ + public static class Extensions { + public static Vector4 ToVector4(this Color c){ + float[] f = c.floatArray; + return new Vector4 (f [0], f [1], f [2], f [3]); + } + public static Vector3 Transform(this Vector3 v, Matrix4 m){ + return Vector4.Transform(new Vector4(v, 1), m).Xyz; + } + public static bool IsInBetween(this int v, int min, int max){ + return v >= min & v <= max; + } + public static Vector4 UnProject(ref Matrix4 projection, ref Matrix4 view, int[] viewport, Vector2 mouse) + { + Vector4 vec; + + vec.X = 2.0f * mouse.X / (float)viewport[2] - 1; + vec.Y = -(2.0f * mouse.Y / (float)viewport[3] - 1); + vec.Z = 0f; + vec.W = 1.0f; + + Matrix4 viewInv = Matrix4.Invert(view); + Matrix4 projInv = Matrix4.Invert(projection); + + Vector4.Transform(ref vec, ref projInv, out vec); + Vector4.Transform(ref vec, ref viewInv, out vec); + + if (vec.W > float.Epsilon || vec.W < float.Epsilon) + { + vec.X /= vec.W; + vec.Y /= vec.W; + vec.Z /= vec.W; + } + + return vec; + } + } +} + diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index a294141f..4e19b4d8 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -58,9 +58,10 @@ - + + diff --git a/Tests/UIEditor.cs b/Tests/UIEditor.cs index 9e1b26bc..2c03bdbb 100644 --- a/Tests/UIEditor.cs +++ b/Tests/UIEditor.cs @@ -44,7 +44,7 @@ namespace Tests { base.OnLoad (e); - CrowInterface.AddWidget( + AddWidget( new Window () { Title = "Hello World" -- 2.47.3