├── GLGUI
├── bin
│ ├── OpenTK.dll
│ ├── OpenTK.GLControl.dll
│ ├── OpenTK.dll.config
│ └── OpenTK.GLControl.xml
├── GLGUI
│ ├── GLSplitterOrientation.cs
│ ├── GLFont
│ │ ├── GLFontMonospacing.cs
│ │ ├── GLFontAlignment.cs
│ │ ├── GLFontTextNodeType.cs
│ │ ├── GLFontTextPosition.cs
│ │ ├── GLFontText.cs
│ │ ├── GLFontTextNode.cs
│ │ ├── GLFontCharacterKerningRule.cs
│ │ ├── GLFontRenderHint.cs
│ │ ├── GLFontGlyph.cs
│ │ ├── GLFontTexture.cs
│ │ ├── GLFontBuilderConfiguration.cs
│ │ ├── GLFontVertexBuffer.cs
│ │ ├── GLFontData.cs
│ │ ├── GLFontKerningConfiguration.cs
│ │ ├── GLFontRenderOptions.cs
│ │ ├── GLFontKerningCalculator.cs
│ │ ├── GLFontTextNodeList.cs
│ │ └── GLFontBitmap.cs
│ ├── GLSliderOrientation.cs
│ ├── GLFlowDirection.cs
│ ├── GLAnchorStyles.cs
│ ├── Clipboard.cs
│ ├── GLContextMenuEntry.cs
│ ├── GLPadding.cs
│ ├── GLContextMenu.cs
│ ├── GLScrolledControl.cs
│ ├── GLOptions.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── GLGroupLayout.cs
│ ├── GLViewport.cs
│ ├── GLLabel.cs
│ ├── GLLinkLabel.cs
│ ├── GLDraw.cs
│ ├── GLButton.cs
│ ├── GLFlowLayout.cs
│ ├── GLSplitLayout.cs
│ ├── GLCursor.cs
│ ├── GLCheckBox.cs
│ ├── GLGUI.csproj
│ ├── GLSlider.cs
│ ├── GLScrollableControl.cs
│ ├── GLFontTextNodeList.cs
│ ├── GLForm.cs
│ ├── GLSkin.cs
│ └── Advanced
│ │ └── GLDataControl.cs
├── GLGUI.GLControlExample
│ ├── Properties
│ │ ├── Settings.settings
│ │ ├── Settings.Designer.cs
│ │ ├── AssemblyInfo.cs
│ │ ├── Resources.Designer.cs
│ │ └── Resources.resx
│ ├── MainForm.cs
│ ├── Program.cs
│ ├── LineWriter.cs
│ ├── GLGUI.GLControlExample.csproj
│ └── GuiControl.cs
├── GLGUI.Example
│ ├── Program.cs
│ ├── LineWriter.cs
│ ├── GLGUI.Example.csproj
│ └── MainForm.cs
└── GLGUI.sln
├── .gitignore
└── README.md
/GLGUI/bin/OpenTK.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ands/GLGUI/HEAD/GLGUI/bin/OpenTK.dll
--------------------------------------------------------------------------------
/GLGUI/bin/OpenTK.GLControl.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ands/GLGUI/HEAD/GLGUI/bin/OpenTK.GLControl.dll
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | .fuse_hidden*
3 | *.suo
4 | *.userprefs
5 | *.exe
6 | *.pdb
7 | *.mdb
8 | *.db
9 | *.manifest
10 | GLGUI.dll
11 | obj
12 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLSplitterOrientation.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | public enum GLSplitterOrientation : byte
4 | {
5 | Horizontal,
6 | Vertical
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontMonospacing.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | public enum GLFontMonospacing : byte
4 | {
5 | Natural = 0,
6 | Yes,
7 | No
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLSliderOrientation.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | public enum GLSliderOrientation : byte
4 | {
5 | Horizontal,
6 | Vertical
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontAlignment.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | public enum GLFontAlignment : byte
4 | {
5 | Left = 0,
6 | Right,
7 | Centre,
8 | Justify
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontTextNodeType.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | enum GLFontTextNodeType : byte
4 | {
5 | Word,
6 | LineBreak,
7 | Space,
8 | Tab
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFlowDirection.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | public enum GLFlowDirection : byte
4 | {
5 | LeftToRight,
6 | TopDown,
7 | RightToLeft,
8 | BottomUp
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontTextPosition.cs:
--------------------------------------------------------------------------------
1 | using OpenTK;
2 |
3 | namespace GLGUI
4 | {
5 | public struct GLFontTextPosition
6 | {
7 | public int Index;
8 | public Vector2 Position;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLAnchorStyles.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace GLGUI
4 | {
5 | [Flags]
6 | public enum GLAnchorStyles : byte
7 | {
8 | None = 0x00,
9 | Left = 0x01,
10 | Top = 0x02,
11 | Right = 0x04,
12 | Bottom = 0x08,
13 | All = 0x0f
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.GLControlExample/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/Clipboard.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace GLGUI
4 | {
5 | #if !REFERENCE_WINDOWS_FORMS
6 | public static class Clipboard
7 | {
8 | private static string contents = "";
9 | public static void SetText(string s) { contents = s; }
10 | public static bool ContainsText() { return contents.Length > 0; }
11 | public static string GetText() { return contents; }
12 | }
13 | #endif
14 | }
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLContextMenuEntry.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | public class GLContextMenuEntry : GLButton
4 | {
5 | public GLContextMenuEntry(GLGui gui) : base(gui)
6 | {
7 | SkinEnabled = Gui.Skin.ContextMenuEntryEnabled;
8 | SkinPressed = Gui.Skin.ContextMenuEntryPressed;
9 | SkinHover = Gui.Skin.ContextMenuEntryHover;
10 | SkinDisabled = Gui.Skin.ContextMenuEntryDisabled;
11 |
12 | Click += (s, e) => Gui.CloseContextMenu();
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.GLControlExample/MainForm.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace GLGUI.GLControlExample
4 | {
5 | public partial class MainForm : Form
6 | {
7 | public MainForm()
8 | {
9 | Text = "GLGUI.GLControlExample";
10 | Size = new System.Drawing.Size(1024, 600);
11 |
12 | var guiControl = new GuiControl();
13 | guiControl.Dock = DockStyle.Fill;
14 | Controls.Add(guiControl);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontText.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 |
3 | namespace GLGUI
4 | {
5 | ///
6 | /// Class to hide GLFontTextNodeList and related classes from
7 | /// user whilst allowing a textNodeList to be passed around.
8 | ///
9 | public class GLFontText
10 | {
11 | internal GLFontTextNodeList textNodeList;
12 | internal SizeF maxSize;
13 | internal GLFontAlignment alignment;
14 | public GLFontVertexBuffer[] VertexBuffers;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLPadding.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | public struct GLPadding
4 | {
5 | public int Left, Top, Right, Bottom;
6 |
7 | public int Horizontal { get { return Left + Right; } }
8 | public int Vertical { get { return Top + Bottom; } }
9 |
10 | public GLPadding(int all)
11 | {
12 | Left = Top = Right = Bottom = all;
13 | }
14 | public GLPadding(int left, int top, int right, int bottom)
15 | {
16 | Left = left;
17 | Top = top;
18 | Right = right;
19 | Bottom = bottom;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.GLControlExample/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Windows.Forms;
5 |
6 | namespace GLGUI.GLControlExample
7 | {
8 | static class Program
9 | {
10 | ///
11 | /// The main entry point for the application.
12 | ///
13 | [STAThread]
14 | static void Main()
15 | {
16 | Application.EnableVisualStyles();
17 | Application.SetCompatibleTextRenderingDefault(false);
18 | Application.Run(new MainForm());
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontTextNode.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | class GLFontTextNode
4 | {
5 | public GLFontTextNodeType Type;
6 | public string Text;
7 | public float Length; // pixel length (without tweaks)
8 | public float LengthTweak; // length tweak for justification
9 |
10 | public float ModifiedLength
11 | {
12 | get { return Length + LengthTweak; }
13 | }
14 |
15 | public GLFontTextNode(GLFontTextNodeType type, string text)
16 | {
17 | Type = type;
18 | Text = text;
19 | }
20 |
21 | public GLFontTextNode Next;
22 | public GLFontTextNode Previous;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontCharacterKerningRule.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | public enum GLFontCharacterKerningRule : byte
4 | {
5 | ///
6 | /// Ordinary kerning
7 | ///
8 | Normal,
9 | ///
10 | /// All kerning pairs involving this character will kern by 0. This will
11 | /// override both Normal and NotMoreThanHalf for any pair.
12 | ///
13 | Zero,
14 | ///
15 | /// Any kerning pairs involving this character will not kern
16 | /// by more than half the minimum width of the two characters
17 | /// involved. This will override Normal for any pair.
18 | ///
19 | NotMoreThanHalf
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | GLGUI
2 | =====
3 |
4 | 
5 |
6 | This OpenGL User Interface library is a WinForms-like object oriented GUI based on a custom OpenTK version which allows custom cursors (https://github.com/ands/opentk) and some QuickFont font generator code.
7 | Both GameWindows and GLControls, which use different input EventArgs, are supported.
8 |
9 | You can build the GLGUI assembly with or without System.Windows.Forms (=> with or without cursor support) by using the REFERENCE_WINDOWS_FORMS build flag.
10 |
11 | You can build the GLGUI assembly with or without OpenTK.GLControl (=> with or without OpenTK WinForms context support) by using the REFERENCE_OPENTK_GLCONTROL build flag.
12 | REFERENCE_OPENTK_GLCONTROL requires REFERENCE_WINDOWS_FORMS to be set.
13 |
14 |
15 | TODO
16 | ====
17 |
18 | - Clean up (example) code
19 | - Add documentation
20 | - Get rid of last few legacy OpenGL dependencies
21 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontRenderHint.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | public enum GLFontRenderHint : byte
4 | {
5 | ///
6 | /// Use AntiAliasGridFit when rendering the ttf character set to create the GLFont texture
7 | ///
8 | AntiAliasGridFit,
9 | ///
10 | /// Use AntiAlias when rendering the ttf character set to create the GLFont texture
11 | ///
12 | AntiAlias,
13 | ///
14 | /// Use ClearTypeGridFit if the font is smaller than 12, otherwise use AntiAlias
15 | ///
16 | SizeDependent,
17 | ///
18 | /// Use ClearTypeGridFit when rendering the ttf character set to create the GLFont texture
19 | ///
20 | ClearTypeGridFit,
21 | ///
22 | /// Use SystemDefault when rendering the ttf character set to create the GLFont texture
23 | ///
24 | SystemDefault
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLContextMenu.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Linq;
4 |
5 | namespace GLGUI
6 | {
7 | public class GLContextMenu : GLFlowLayout
8 | {
9 | public GLContextMenu(GLGui gui) : base(gui)
10 | {
11 | FlowDirection = GLFlowDirection.TopDown;
12 | AutoSize = true;
13 |
14 | Skin = Gui.Skin.ContextMenu;
15 | }
16 |
17 | protected override void UpdateLayout()
18 | {
19 | if (Controls.Count() > 0)
20 | {
21 | int maxWidth = 0;
22 | foreach (var entry in Controls)
23 | {
24 | entry.AutoSize = true;
25 | maxWidth = Math.Max(maxWidth, entry.Width);
26 | }
27 | foreach (var entry in Controls)
28 | {
29 | entry.AutoSize = false;
30 | entry.Size = new Size(maxWidth, entry.Height);
31 | }
32 | }
33 |
34 | base.UpdateLayout();
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.Example/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 |
4 | namespace GLGUI.Example
5 | {
6 | public static class Program
7 | {
8 | [STAThread]
9 | public static int Main(string[] args)
10 | {
11 | AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
12 |
13 | new MainForm().Run();
14 | return 0;
15 | }
16 |
17 | private static void HandleUnhandledException(Object o)
18 | {
19 | Exception e = o as Exception;
20 |
21 | if (e != null)
22 | {
23 | Console.WriteLine(e.ToString());
24 | }
25 | }
26 |
27 | private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs e)
28 | {
29 | HandleUnhandledException(e.ExceptionObject);
30 | }
31 |
32 | private static void OnGuiUnhandedException(object sender, System.Threading.ThreadExceptionEventArgs e)
33 | {
34 | HandleUnhandledException(e.Exception);
35 | }
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontGlyph.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 |
3 | namespace GLGUI
4 | {
5 | public class GLFontGlyph
6 | {
7 | ///
8 | /// Which texture page the glyph is on
9 | ///
10 | public int Page;
11 |
12 | ///
13 | /// The rectangle defining the glyphs position on the page
14 | ///
15 | public Rectangle Rect;
16 |
17 | ///
18 | /// How far the glyph would need to be vertically offset to be vertically in line with the tallest glyph in the set of all glyphs
19 | ///
20 | public int YOffset;
21 |
22 | ///
23 | /// Which character this glyph represents
24 | ///
25 | public char Character;
26 |
27 | public PointF TextureMin, TextureMax;
28 |
29 | public GLFontGlyph(int page, Rectangle rect, int yOffset, char character)
30 | {
31 | Page = page;
32 | Rect = rect;
33 | YOffset = yOffset;
34 | Character = character;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/GLGUI/bin/OpenTK.dll.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLScrolledControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Linq;
4 |
5 | namespace GLGUI
6 | {
7 | internal class GLScrolledControl : GLControl
8 | {
9 | public Size TotalSize;
10 |
11 | public GLScrolledControl(GLGui gui) : base(gui)
12 | {
13 | AutoSize = true;
14 | HandleMouseEvents = false;
15 | }
16 |
17 | protected override void UpdateLayout()
18 | {
19 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
20 | outer.Height = Math.Min(Math.Max(outer.Height, sizeMin.Height), sizeMax.Height);
21 | Inner = new Rectangle(0, 0, outer.Width, outer.Height);
22 |
23 | TotalSize = new Size(0, 0);
24 | if (Controls.Any())
25 | {
26 | TotalSize.Width = Controls.Max(c => c.Outer.Right);
27 | TotalSize.Height = Controls.Max(c => c.Outer.Bottom);
28 | }
29 |
30 | if (Parent != null && !Parent.AutoSize) // avoid repeated calls if autosize is true
31 | Parent.Invalidate();
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.GLControlExample/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18444
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace GLGUI.GLControlExample.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.Example/LineWriter.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 | using System.Text;
4 |
5 | namespace GLGUI.Example
6 | {
7 | public class LineWriter : TextWriter
8 | {
9 | public List Lines;
10 | public bool Changed = false;
11 | private StringBuilder currentLine;
12 |
13 | public LineWriter()
14 | {
15 | this.Lines = new List(1024);
16 | this.currentLine = new StringBuilder(256);
17 | }
18 |
19 | public override void Write(char value)
20 | {
21 | if (value == '\n')
22 | Flush();
23 | else
24 | currentLine.Append(value);
25 | }
26 |
27 | public override void Flush()
28 | {
29 | Lines.Add(currentLine.ToString());
30 | if (Lines.Count > 1024)
31 | Lines.RemoveAt(0);
32 | currentLine.Clear();
33 | Changed = true;
34 | }
35 |
36 | public override Encoding Encoding
37 | {
38 | get { return System.Text.Encoding.UTF8; }
39 | }
40 |
41 | public void Clear()
42 | {
43 | Lines.Clear();
44 | currentLine.Clear();
45 | Changed = true;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.GLControlExample/LineWriter.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 | using System.Text;
4 |
5 | namespace GLGUI.GLControlExample
6 | {
7 | public class LineWriter : TextWriter
8 | {
9 | public List Lines;
10 | public bool Changed = false;
11 | private StringBuilder currentLine;
12 |
13 | public LineWriter()
14 | {
15 | this.Lines = new List(1024);
16 | this.currentLine = new StringBuilder(256);
17 | }
18 |
19 | public override void Write(char value)
20 | {
21 | if (value == '\n')
22 | Flush();
23 | else
24 | currentLine.Append(value);
25 | }
26 |
27 | public override void Flush()
28 | {
29 | Lines.Add(currentLine.ToString());
30 | if (Lines.Count > 1024)
31 | Lines.RemoveAt(0);
32 | currentLine.Clear();
33 | Changed = true;
34 | }
35 |
36 | public override Encoding Encoding
37 | {
38 | get { return System.Text.Encoding.UTF8; }
39 | }
40 |
41 | public void Clear()
42 | {
43 | Lines.Clear();
44 | currentLine.Clear();
45 | Changed = true;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Linq;
4 |
5 | namespace GLGUI
6 | {
7 | public class GLOptions : GLFlowLayout
8 | {
9 | public GLCheckBox Selection { get { return selection; } set { if (Controls.Contains(value)) Select(value, EventArgs.Empty); } }
10 |
11 | public event EventHandler Changed;
12 |
13 | private GLCheckBox selection;
14 |
15 | public GLOptions(GLGui gui) : base(gui)
16 | {
17 | outer = new Rectangle(0, 0, 0, 0);
18 | }
19 |
20 | public override T Add(T control)
21 | {
22 | if (!(control is GLCheckBox))
23 | throw new InvalidOperationException("only GLCheckBoxes are allowed on GLOptions instances");
24 | base.Add(control);
25 | (control as GLCheckBox).Changed += Select;
26 | return control;
27 | }
28 |
29 | public override void Remove(GLControl control)
30 | {
31 | base.Remove(control);
32 | (control as GLCheckBox).Changed -= Select;
33 | }
34 |
35 | private void Select(object sender, EventArgs e)
36 | {
37 | if(selection != null)
38 | selection.Checked = false;
39 |
40 | GLCheckBox senderCheckBox = (GLCheckBox)sender;
41 | selection = senderCheckBox;
42 | senderCheckBox.Checked = true;
43 |
44 | if(Changed != null)
45 | Changed(sender, e);
46 | }
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("GLGUI")]
9 | [assembly: AssemblyDescription("Fast WinForms-like OpenGL GUI library")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("ands")]
12 | [assembly: AssemblyProduct("GLGUI")]
13 | [assembly: AssemblyCopyright("Copyright © ands 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("8fdc3f4a-6ae4-440d-90a6-e5625e84be05")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyFileVersion("1.0.*")]
37 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.GLControlExample/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("GLGUI.GLControlExample")]
9 | [assembly: AssemblyDescription("Fast WinForms-like OpenGL GUI library GLControl example")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("ands")]
12 | [assembly: AssemblyProduct("GLGUI")]
13 | [assembly: AssemblyCopyright("Copyright © ands 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("bc14cb32-d0f9-44b3-ae64-40104de95020")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyFileVersion("1.0.*")]
37 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLGroupLayout.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Linq;
4 |
5 | namespace GLGUI
6 | {
7 | public class GLGroupLayout : GLControl
8 | {
9 | public GLSkin.GLGroupLayoutSkin Skin { get { return skin; } set { skin = value; Invalidate(); } }
10 |
11 | private GLSkin.GLGroupLayoutSkin skin;
12 |
13 | public GLGroupLayout(GLGui gui) : base(gui)
14 | {
15 | Render += OnRender;
16 |
17 | skin = Gui.Skin.GroupLayout;
18 |
19 | outer = new Rectangle(0, 0, 100, 100);
20 | sizeMin = new Size(0, 0);
21 | sizeMax = new Size(int.MaxValue, int.MaxValue);
22 | }
23 |
24 | protected override void UpdateLayout()
25 | {
26 | if (AutoSize)
27 | {
28 | if (Controls.Count() > 0)
29 | {
30 | outer.Width = Controls.Max(c => c.Outer.Right) - Controls.Min(c => c.Outer.Left) + skin.Border.Horizontal;
31 | outer.Height = Controls.Max(c => c.Outer.Bottom) - Controls.Min(c => c.Outer.Top) + skin.Border.Vertical;
32 | }
33 | else
34 | {
35 | outer.Width = skin.Border.Horizontal;
36 | outer.Height = skin.Border.Vertical;
37 | }
38 | }
39 |
40 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
41 | outer.Height = Math.Min(Math.Max(outer.Height, sizeMin.Height), sizeMax.Height);
42 | Inner = new Rectangle(skin.Border.Left, skin.Border.Top, outer.Width - skin.Border.Horizontal, outer.Height - skin.Border.Vertical);
43 | }
44 |
45 | private void OnRender(object sender, double timeDelta)
46 | {
47 | GLDraw.Fill(ref skin.BorderColor);
48 | GLDraw.FillRect(Inner, ref skin.BackgroundColor);
49 | }
50 | }
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontTexture.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing.Imaging;
3 | using OpenTK.Graphics.OpenGL;
4 |
5 | namespace GLGUI
6 | {
7 | class GLFontTexture : IDisposable
8 | {
9 | public readonly int TextureID;
10 | public readonly int Width;
11 | public readonly int Height;
12 |
13 | public GLFontTexture(BitmapData dataSource)
14 | {
15 | Width = dataSource.Width;
16 | Height = dataSource.Height;
17 |
18 | GL.Enable(EnableCap.Texture2D);
19 |
20 | GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
21 |
22 | GL.GenTextures(1, out TextureID);
23 | GL.BindTexture(TextureTarget.Texture2D, TextureID);
24 |
25 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Clamp);
26 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Clamp);
27 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
28 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
29 |
30 | GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0,
31 | OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, dataSource.Scan0);
32 |
33 | GL.Disable(EnableCap.Texture2D);
34 |
35 | GLGui.usedTextures++;
36 | }
37 |
38 | public void Dispose()
39 | {
40 | GL.DeleteTexture(TextureID);
41 | GLGui.usedTextures--;
42 | }
43 |
44 | ~GLFontTexture()
45 | {
46 | lock(GLGui.toDispose)
47 | {
48 | GLGui.toDispose.Add(this);
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontBuilderConfiguration.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | ///
4 | /// What settings to use when building the font
5 | ///
6 | public class GLFontBuilderConfiguration
7 | {
8 | public GLFontKerningConfiguration KerningConfig = new GLFontKerningConfiguration();
9 |
10 | ///
11 | /// Whether to use super sampling when building font texture pages
12 | ///
13 | ///
14 | ///
15 | public int SuperSampleLevels = 1;
16 |
17 | ///
18 | /// The standard width of texture pages (the page will
19 | /// automatically be cropped if there is extra space)
20 | ///
21 | public int PageWidth = 512;
22 |
23 | ///
24 | /// The standard height of texture pages (the page will
25 | /// automatically be cropped if there is extra space)
26 | ///
27 | public int PageHeight = 512;
28 |
29 | ///
30 | /// Whether to force texture pages to use a power of two.
31 | ///
32 | public bool ForcePowerOfTwo = true;
33 |
34 | ///
35 | /// The margin (on all sides) around glyphs when rendered to
36 | /// their texture page
37 | ///
38 | public int GlyphMargin = 2;
39 |
40 | ///
41 | /// Set of characters to support
42 | ///
43 | public string CharSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.:,;'\"(!?)+-*/=_{}[]@~#\\<>|^%$£&";
44 |
45 | ///
46 | /// Which render hint to use when rendering the ttf character set to create the GLFont texture
47 | ///
48 | public GLFontRenderHint TextGenerationRenderHint = GLFontRenderHint.SizeDependent;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLViewport.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using OpenTK.Graphics.OpenGL;
4 |
5 | namespace GLGUI
6 | {
7 | public class GLViewport : GLControl
8 | {
9 | public float AspectRatio { get { return (float)Inner.Width / (float)Inner.Height; } }
10 | public event RenderEventHandler RenderViewport;
11 |
12 | public GLViewport(GLGui gui) : base(gui)
13 | {
14 | Render += OnRender;
15 |
16 | outer = new Rectangle(0, 0, 256, 256);
17 | sizeMin = new Size(1, 1);
18 | sizeMax = new Size(int.MaxValue, int.MaxValue);
19 | }
20 |
21 | protected override void UpdateLayout()
22 | {
23 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
24 | outer.Height = Math.Min(Math.Max(outer.Height, sizeMin.Height), sizeMax.Height);
25 | Inner = new Rectangle(0, 0, outer.Width, outer.Height);
26 | }
27 |
28 | private void OnRender(object sender, double timeDelta)
29 | {
30 | if (RenderViewport == null)
31 | return;
32 |
33 | // save
34 | int[] mainViewport = new int[4];
35 | GL.GetInteger(GetPName.Viewport, mainViewport);
36 | // TODO: get rid of these:
37 | GL.MatrixMode(MatrixMode.Projection);
38 | GL.PushMatrix();
39 | GL.MatrixMode(MatrixMode.Modelview);
40 | GL.PushMatrix();
41 |
42 | // render
43 | var vp = ToViewport(Inner);
44 | GL.Scissor(GLDraw.ScissorRect.X, Gui.Outer.Height - GLDraw.ScissorRect.Bottom, GLDraw.ScissorRect.Width, GLDraw.ScissorRect.Height);
45 | GL.Viewport(vp.X, mainViewport[3] - vp.Y - vp.Height, vp.Width, vp.Height);
46 | RenderViewport(this, timeDelta);
47 |
48 | // restore
49 | GL.Viewport(mainViewport[0], mainViewport[1], mainViewport[2], mainViewport[3]);
50 | // TODO: get rid of these:
51 | GL.MatrixMode(MatrixMode.Projection);
52 | GL.PopMatrix();
53 | GL.MatrixMode(MatrixMode.Modelview);
54 | GL.PopMatrix();
55 | }
56 | }
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.Example/GLGUI.Example.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 10.0.0
7 | 2.0
8 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}
9 | WinExe
10 | GLGUI.Example
11 | GLGUI.Example
12 |
13 |
14 | true
15 | full
16 | false
17 | ..\bin
18 | DEBUG;
19 | prompt
20 | 4
21 | x86
22 | false
23 |
24 |
25 | none
26 | true
27 | ..\bin
28 | prompt
29 | 4
30 | x86
31 | false
32 |
33 |
34 |
35 |
36 | False
37 | ..\bin\OpenTK.GLControl.dll
38 |
39 |
40 |
41 |
42 |
43 | ..\bin\OpenTK.dll
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}
55 | GLGUI
56 |
57 |
58 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLLabel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 |
4 | #if REFERENCE_WINDOWS_FORMS
5 | using Clipboard = System.Windows.Forms.Clipboard;
6 | #endif
7 |
8 | namespace GLGUI
9 | {
10 | public class GLLabel : GLControl
11 | {
12 | public string Text { get { return text; } set { if (value != text) { text = value; Invalidate(); } } }
13 | public bool Enabled { get { return enabled; } set { enabled = value; Invalidate(); } }
14 | public GLSkin.GLLabelSkin SkinEnabled { get { return skinEnabled; } set { skinEnabled = value; Invalidate(); } }
15 | public GLSkin.GLLabelSkin SkinDisabled { get { return skinDisabled; } set { skinDisabled = value; Invalidate(); } }
16 |
17 | public bool WordWrap = false;
18 | public bool Multiline = false;
19 |
20 | private string text = "";
21 | private GLFontText textProcessed = new GLFontText();
22 | private SizeF textSize;
23 | private GLSkin.GLLabelSkin skinEnabled, skinDisabled;
24 | private GLSkin.GLLabelSkin skin;
25 | private bool enabled = true;
26 |
27 | public GLLabel(GLGui gui) : base(gui)
28 | {
29 | Render += OnRender;
30 |
31 | skinEnabled = Gui.Skin.LabelEnabled;
32 | skinDisabled = Gui.Skin.LabelDisabled;
33 |
34 | outer = new Rectangle(0, 0, 0, 0);
35 | sizeMin = new Size(1, (int)skinEnabled.Font.LineSpacing + skinEnabled.Padding.Vertical);
36 | sizeMax = new Size(int.MaxValue, int.MaxValue);
37 |
38 | HandleMouseEvents = false;
39 | }
40 |
41 | protected override void UpdateLayout()
42 | {
43 | skin = Enabled ? skinEnabled : skinDisabled;
44 |
45 | textSize = skin.Font.ProcessText(textProcessed, text,
46 | new SizeF(WordWrap ? (AutoSize ? SizeMax.Width - skin.Padding.Horizontal : outer.Width - skin.Padding.Horizontal) : float.MaxValue, Multiline ? (AutoSize ? float.MaxValue : outer.Height - skin.Padding.Vertical) : skin.Font.LineSpacing),
47 | skin.TextAlign);
48 |
49 | if (AutoSize)
50 | {
51 | outer.Width = (int)textSize.Width + skin.Padding.Horizontal;
52 | outer.Height = (int)textSize.Height + skin.Padding.Vertical;
53 | }
54 |
55 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
56 | outer.Height = Math.Min(Math.Max(outer.Height, sizeMin.Height), sizeMax.Height);
57 |
58 | Inner = new Rectangle(skin.Padding.Left, skin.Padding.Top, outer.Width - skin.Padding.Horizontal, outer.Height - skin.Padding.Vertical);
59 | }
60 |
61 | private void OnRender(object sender, double timeDelta)
62 | {
63 | GLDraw.Fill(ref skin.BackgroundColor);
64 | GLDraw.Text(textProcessed, Inner, ref skin.Color);
65 | }
66 | }
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.GLControlExample/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18444
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace GLGUI.GLControlExample.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GLGUI.GLControlExample.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLLinkLabel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using OpenTK.Input;
4 |
5 | #if REFERENCE_WINDOWS_FORMS
6 | using Clipboard = System.Windows.Forms.Clipboard;
7 | #endif
8 |
9 | namespace GLGUI
10 | {
11 | public class GLLinkLabel : GLControl
12 | {
13 | public string Text { get { return text; } set { if (value != text) { text = value; Invalidate(); } } }
14 | public bool Enabled { get { return enabled; } set { enabled = value; Invalidate(); } }
15 | public GLSkin.GLLabelSkin SkinEnabled { get { return skinEnabled; } set { skinEnabled = value; Invalidate(); } }
16 | public GLSkin.GLLabelSkin SkinDisabled { get { return skinDisabled; } set { skinDisabled = value; Invalidate(); } }
17 |
18 | public bool WordWrap = false;
19 | public bool Multiline = false;
20 |
21 | public event EventHandler Click;
22 |
23 | private string text = "";
24 | private GLFontText textProcessed = new GLFontText();
25 | private SizeF textSize;
26 | private GLSkin.GLLabelSkin skinEnabled, skinDisabled;
27 | private GLSkin.GLLabelSkin skin;
28 | private bool enabled = true;
29 |
30 | public GLLinkLabel(GLGui gui) : base(gui)
31 | {
32 | Render += OnRender;
33 | MouseUp += OnMouseUp;
34 | MouseEnter += OnMouseEnter;
35 | MouseLeave += OnMouseLeave;
36 |
37 | skinEnabled = Gui.Skin.LinkLabelEnabled;
38 | skinDisabled = Gui.Skin.LinkLabelDisabled;
39 |
40 | outer = new Rectangle(0, 0, 0, 0);
41 | sizeMin = new Size(1, (int)skinEnabled.Font.LineSpacing + skinEnabled.Padding.Vertical);
42 | sizeMax = new Size(int.MaxValue, int.MaxValue);
43 |
44 | HandleMouseEvents = false;
45 | }
46 |
47 | protected override void UpdateLayout()
48 | {
49 | skin = Enabled ? skinEnabled : skinDisabled;
50 |
51 | textSize = skin.Font.ProcessText(textProcessed, text,
52 | new SizeF(WordWrap ? (AutoSize ? SizeMax.Width - skin.Padding.Horizontal : outer.Width - skin.Padding.Horizontal) : float.MaxValue, Multiline ? (AutoSize ? float.MaxValue : outer.Height - skin.Padding.Vertical) : skin.Font.LineSpacing),
53 | skin.TextAlign);
54 |
55 | if (AutoSize)
56 | {
57 | outer.Width = (int)textSize.Width + skin.Padding.Horizontal;
58 | outer.Height = (int)textSize.Height + skin.Padding.Vertical;
59 | }
60 |
61 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
62 | outer.Height = Math.Min(Math.Max(outer.Height, sizeMin.Height), sizeMax.Height);
63 |
64 | Inner = new Rectangle(skin.Padding.Left, skin.Padding.Top, outer.Width - skin.Padding.Horizontal, outer.Height - skin.Padding.Vertical);
65 | }
66 |
67 | private void OnRender(object sender, double timeDelta)
68 | {
69 | GLDraw.Fill(ref skin.BackgroundColor);
70 | GLDraw.Text(textProcessed, Inner, ref skin.Color);
71 | //GLDraw.Line(Inner.Left, Inner.Bottom, Inner.Right, Inner.Bottom, ref skin.Color); // very ugly on windows : /
72 | }
73 |
74 | private void OnMouseUp(object sender, MouseButtonEventArgs e)
75 | {
76 | if (enabled && e.Button == MouseButton.Left)
77 | {
78 | Gui.Cursor = GLCursor.Default;
79 | if (Click != null)
80 | Click(this, EventArgs.Empty);
81 | }
82 | }
83 |
84 | private void OnMouseEnter(object sender, EventArgs e)
85 | {
86 | Gui.Cursor = GLCursor.Hand;
87 | }
88 |
89 | private void OnMouseLeave(object sender, EventArgs e)
90 | {
91 | Gui.Cursor = GLCursor.Default;
92 | }
93 | }
94 | }
95 |
96 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLDraw.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using OpenTK.Graphics;
4 | using OpenTK.Graphics.OpenGL;
5 |
6 | namespace GLGUI
7 | {
8 | public static class GLDraw
9 | {
10 | public static Rectangle CurrentScreenRect { get { return ControlRect; } }
11 |
12 | internal static GLGui CurrentGui;
13 | internal static Rectangle ControlRect;
14 | internal static Rectangle ScissorRect;
15 |
16 | public static void PrepareCustomDrawing()
17 | {
18 | GL.Scissor(ScissorRect.X, CurrentGui.Outer.Height - ScissorRect.Bottom, ScissorRect.Width, ScissorRect.Height);
19 | }
20 |
21 | public static void Fill(ref Color4 color)
22 | {
23 | if (color.A == 0.0f)
24 | return;
25 |
26 | GL.ClearColor(color);
27 | GL.Scissor(ScissorRect.X, CurrentGui.Outer.Height - ScissorRect.Bottom, ScissorRect.Width, ScissorRect.Height);
28 | GL.Clear(ClearBufferMask.ColorBufferBit);
29 | }
30 |
31 | public static void FillRect(Rectangle rect, ref Color4 color)
32 | {
33 | FillRect(ref rect, ref color);
34 | }
35 |
36 | public static void FillRect(ref Rectangle rect, ref Color4 color)
37 | {
38 | if (color.A == 0.0f)
39 | return;
40 |
41 | int w = Math.Min(rect.Width, ScissorRect.Width - rect.X);
42 | int h = Math.Min(rect.Height, ScissorRect.Height - rect.Y);
43 | if (w > 0 && h > 0)
44 | {
45 | GL.ClearColor(color);
46 | GL.Scissor(ScissorRect.X + rect.X, CurrentGui.Outer.Height - (ScissorRect.Y + rect.Y + h), w, h);
47 | GL.Clear(ClearBufferMask.ColorBufferBit);
48 | }
49 | }
50 |
51 | public static void Text(GLFontText processedText, Rectangle rect, ref Color4 color)
52 | {
53 | Text(processedText, ref rect, ref color);
54 | }
55 |
56 | public static void Text(GLFontText processedText, ref Rectangle rect, ref Color4 color)
57 | {
58 | if (color.A == 0.0f)
59 | return;
60 |
61 | int w = Math.Min(rect.Width, ScissorRect.Width - rect.X);
62 | int h = Math.Min(rect.Height, ScissorRect.Height - rect.Y);
63 | if (w > 0 && h > 0)
64 | {
65 | GL.Scissor(ScissorRect.X + rect.X, CurrentGui.Outer.Height - (ScissorRect.Y + rect.Y + h), w, h);
66 | GL.PushMatrix();
67 | switch(processedText.alignment)
68 | {
69 | case GLFontAlignment.Left:
70 | case GLFontAlignment.Justify:
71 | GL.Translate(ControlRect.X + rect.X, ControlRect.Y + rect.Y, 0.0f);
72 | break;
73 | case GLFontAlignment.Centre:
74 | GL.Translate(ControlRect.X + rect.X + rect.Width / 2, ControlRect.Y + rect.Y, 0.0f);
75 | break;
76 | case GLFontAlignment.Right:
77 | GL.Translate(ControlRect.X + rect.X + rect.Width, ControlRect.Y + rect.Y, 0.0f);
78 | break;
79 | }
80 | GL.Color4(color);
81 | for (int i = 0; i < processedText.VertexBuffers.Length; i++)
82 | processedText.VertexBuffers[i].Draw();
83 | GL.PopMatrix();
84 | }
85 | }
86 | }
87 | }
88 |
89 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontVertexBuffer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using OpenTK.Graphics.OpenGL;
3 |
4 | namespace GLGUI
5 | {
6 | public class GLFontVertexBuffer : IDisposable
7 | {
8 | public int TextureID { get { return textureID; } internal set { textureID = value; } }
9 | public int VaoID { get { return vaoID; } }
10 | public int VertexCount { get { return vertexCount; } }
11 |
12 | int textureID;
13 | int vaoID, vboID;
14 | float[] vertices = new float[1024];
15 | int floatCount = 0;
16 | int vertexCount = 0;
17 |
18 | public GLFontVertexBuffer(int textureID)
19 | {
20 | this.textureID = textureID;
21 | vaoID = GL.GenVertexArray();
22 | vboID = GL.GenBuffer();
23 | GLGui.usedVertexArrays++;
24 | }
25 |
26 | ~GLFontVertexBuffer()
27 | {
28 | lock(GLGui.toDispose)
29 | {
30 | GLGui.toDispose.Add(this);
31 | }
32 | }
33 |
34 | public void Dispose()
35 | {
36 | GL.DeleteVertexArray(vaoID);
37 | GL.DeleteBuffer(vboID);
38 | GLGui.usedVertexArrays--;
39 | }
40 |
41 | public void Reset()
42 | {
43 | floatCount = 0;
44 | vertexCount = 0;
45 | }
46 |
47 | public void AddQuad(float minx, float miny, float maxx, float maxy, float mintx, float minty, float maxtx, float maxty)
48 | {
49 | if (floatCount + 16 >= vertices.Length)
50 | Array.Resize(ref vertices, vertices.Length * 2);
51 |
52 | vertices[floatCount + 0] = minx;
53 | vertices[floatCount + 1] = miny;
54 | vertices[floatCount + 2] = mintx;
55 | vertices[floatCount + 3] = minty;
56 |
57 | vertices[floatCount + 4] = minx;
58 | vertices[floatCount + 5] = maxy;
59 | vertices[floatCount + 6] = mintx;
60 | vertices[floatCount + 7] = maxty;
61 |
62 | vertices[floatCount + 8] = maxx;
63 | vertices[floatCount + 9] = maxy;
64 | vertices[floatCount + 10] = maxtx;
65 | vertices[floatCount + 11] = maxty;
66 |
67 | vertices[floatCount + 12] = maxx;
68 | vertices[floatCount + 13] = miny;
69 | vertices[floatCount + 14] = maxtx;
70 | vertices[floatCount + 15] = minty;
71 | floatCount += 16;
72 | vertexCount += 4;
73 | }
74 |
75 | public void Load()
76 | {
77 | if (floatCount == 0)
78 | return;
79 |
80 | GL.BindVertexArray(vaoID);
81 | GL.BindBuffer(BufferTarget.ArrayBuffer, vboID);
82 | GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(floatCount * 4), vertices, BufferUsageHint.StaticDraw);
83 |
84 | GL.VertexPointer(2, VertexPointerType.Float, 16, 0);
85 | GL.EnableClientState(ArrayCap.VertexArray);
86 | GL.TexCoordPointer(2, TexCoordPointerType.Float, 16, 8);
87 | GL.EnableClientState(ArrayCap.TextureCoordArray);
88 | GL.BindVertexArray(0);
89 | }
90 |
91 | public void Draw()
92 | {
93 | if (vertexCount == 0)
94 | return;
95 |
96 | GL.Enable(EnableCap.Texture2D);
97 | GL.BindTexture(TextureTarget.Texture2D, textureID);
98 |
99 | GL.BindVertexArray(vaoID);
100 | GL.DrawArrays(PrimitiveType.Quads, 0, vertexCount);
101 | GL.BindVertexArray(0);
102 |
103 | GL.Disable(EnableCap.Texture2D);
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace GLGUI
5 | {
6 | class GLFontData
7 | {
8 | ///
9 | /// Mapping from a pair of characters to a pixel offset
10 | ///
11 | public Dictionary KerningPairs;
12 |
13 | ///
14 | /// List of texture pages
15 | ///
16 | public GLFontTexture[] Pages;
17 |
18 | ///
19 | /// Mapping from character to glyph index
20 | ///
21 | public Dictionary CharSetMapping;
22 |
23 | ///
24 | /// The average glyph width
25 | ///
26 | public float meanGlyphWidth;
27 |
28 | ///
29 | /// The maximum glyph height
30 | ///
31 | public int maxGlyphHeight;
32 |
33 | ///
34 | /// Whether the original font (from ttf) was detected to be monospaced
35 | ///
36 | public bool naturallyMonospaced = false;
37 |
38 | public bool IsMonospacingActive(GLFontRenderOptions options)
39 | {
40 | return (options.Monospacing == GLFontMonospacing.Natural && naturallyMonospaced) || options.Monospacing == GLFontMonospacing.Yes;
41 | }
42 |
43 | public float GetMonoSpaceWidth(GLFontRenderOptions options)
44 | {
45 | return (float)Math.Ceiling(1 + (1 + options.CharacterSpacing) * meanGlyphWidth);
46 | }
47 |
48 | public void CalculateMeanWidth()
49 | {
50 | meanGlyphWidth = 0f;
51 | foreach (var glyph in CharSetMapping)
52 | meanGlyphWidth += glyph.Value.Rect.Width;
53 | meanGlyphWidth /= CharSetMapping.Count;
54 | }
55 |
56 | public void CalculateMaxHeight()
57 | {
58 | maxGlyphHeight = 0;
59 | foreach (var glyph in CharSetMapping)
60 | maxGlyphHeight = Math.Max(glyph.Value.Rect.Height, maxGlyphHeight);
61 | }
62 |
63 | ///
64 | /// Returns the kerning length correction for the character at the given index in the given string.
65 | /// Also, if the text is part of a textNode list, the nextNode is given so that the following
66 | /// node can be checked incase of two adjacent word nodes.
67 | ///
68 | ///
69 | ///
70 | ///
71 | ///
72 | public int GetKerningPairCorrection(int index, string text, GLFontTextNode textNode)
73 | {
74 | if (KerningPairs == null)
75 | return 0;
76 |
77 | var chars = new char[2];
78 |
79 | if (index + 1 == text.Length)
80 | {
81 | if (textNode != null && textNode.Next != null && textNode.Next.Type == GLFontTextNodeType.Word)
82 | chars[1] = textNode.Next.Text[0];
83 | else
84 | return 0;
85 | }
86 | else
87 | {
88 | chars[1] = text[index + 1];
89 | }
90 |
91 | chars[0] = text[index];
92 |
93 | String str = new String(chars);
94 |
95 | if (KerningPairs.ContainsKey(str))
96 | return KerningPairs[str];
97 |
98 | return 0;
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontKerningConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace GLGUI
5 | {
6 | public class GLFontKerningConfiguration
7 | {
8 | ///
9 | /// Kerning rules for particular characters
10 | ///
11 | private Dictionary CharacterKerningRules = new Dictionary();
12 |
13 | ///
14 | /// When measuring the bounds of glyphs, and performing kerning calculations,
15 | /// this is the minimum alpha level that is necessray for a pixel to be considered
16 | /// non-empty. This should be set to a value on the range [0,255]
17 | ///
18 | public byte AlphaEmptyPixelTolerance = 0;
19 |
20 |
21 | ///
22 | /// Sets all characters in the given string to the specified kerning rule.
23 | ///
24 | ///
25 | ///
26 | public void BatchSetCharacterKerningRule(String chars, GLFontCharacterKerningRule rule)
27 | {
28 | foreach (var c in chars)
29 | {
30 | CharacterKerningRules[c] = rule;
31 | }
32 | }
33 |
34 | ///
35 | /// Sets the specified character kerning rule.
36 | ///
37 | ///
38 | ///
39 | public void SetCharacterKerningRule(char c, GLFontCharacterKerningRule rule)
40 | {
41 | CharacterKerningRules[c] = rule;
42 | }
43 |
44 | public GLFontCharacterKerningRule GetCharacterKerningRule(char c)
45 | {
46 | if (CharacterKerningRules.ContainsKey(c))
47 | {
48 | return CharacterKerningRules[c];
49 | }
50 |
51 | return GLFontCharacterKerningRule.Normal;
52 | }
53 |
54 | ///
55 | /// Given a pair of characters, this will return the overriding
56 | /// CharacterKerningRule.
57 | ///
58 | ///
59 | ///
60 | public GLFontCharacterKerningRule GetOverridingCharacterKerningRuleForPair(String str)
61 | {
62 | if (str.Length < 2)
63 | {
64 | return GLFontCharacterKerningRule.Normal;
65 | }
66 |
67 | char c1 = str[0];
68 | char c2 = str[1];
69 |
70 | if (GetCharacterKerningRule(c1) == GLFontCharacterKerningRule.Zero || GetCharacterKerningRule(c2) == GLFontCharacterKerningRule.Zero)
71 | {
72 | return GLFontCharacterKerningRule.Zero;
73 | }
74 | else if (GetCharacterKerningRule(c1) == GLFontCharacterKerningRule.NotMoreThanHalf || GetCharacterKerningRule(c2) == GLFontCharacterKerningRule.NotMoreThanHalf)
75 | {
76 | return GLFontCharacterKerningRule.NotMoreThanHalf;
77 | }
78 |
79 | return GLFontCharacterKerningRule.Normal;
80 | }
81 |
82 | public GLFontKerningConfiguration()
83 | {
84 | SetCharacterKerningRule('^', GLFontCharacterKerningRule.NotMoreThanHalf);
85 | SetCharacterKerningRule('_', GLFontCharacterKerningRule.NotMoreThanHalf);
86 | SetCharacterKerningRule('\"', GLFontCharacterKerningRule.NotMoreThanHalf);
87 | SetCharacterKerningRule('\'', GLFontCharacterKerningRule.NotMoreThanHalf);
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GLGUI.Example", "GLGUI.Example\GLGUI.Example.csproj", "{1A5AACE1-D7FD-4ECA-871D-95881F7D635B}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GLGUI", "GLGUI\GLGUI.csproj", "{D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GLGUI.GLControlExample", "GLGUI.GLControlExample\GLGUI.GLControlExample.csproj", "{BE449F2C-0E37-4D16-9E5B-D30D3041759B}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|Mixed Platforms = Debug|Mixed Platforms
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|Mixed Platforms = Release|Mixed Platforms
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}.Debug|Any CPU.ActiveCfg = Debug|x86
21 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
22 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}.Debug|Mixed Platforms.Build.0 = Debug|x86
23 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}.Debug|x86.ActiveCfg = Debug|x86
24 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}.Debug|x86.Build.0 = Debug|x86
25 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}.Release|Any CPU.ActiveCfg = Release|x86
26 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}.Release|Mixed Platforms.ActiveCfg = Release|x86
27 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}.Release|Mixed Platforms.Build.0 = Release|x86
28 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}.Release|x86.ActiveCfg = Release|x86
29 | {1A5AACE1-D7FD-4ECA-871D-95881F7D635B}.Release|x86.Build.0 = Release|x86
30 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
33 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
34 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Debug|x86.ActiveCfg = Debug|Any CPU
35 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Debug|x86.Build.0 = Debug|Any CPU
36 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
39 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
40 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Release|x86.ActiveCfg = Release|Any CPU
41 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}.Release|x86.Build.0 = Release|Any CPU
42 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}.Debug|Any CPU.ActiveCfg = Debug|x86
43 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
44 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}.Debug|Mixed Platforms.Build.0 = Debug|x86
45 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}.Debug|x86.ActiveCfg = Debug|x86
46 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}.Debug|x86.Build.0 = Debug|x86
47 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}.Release|Any CPU.ActiveCfg = Release|x86
48 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}.Release|Mixed Platforms.ActiveCfg = Release|x86
49 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}.Release|Mixed Platforms.Build.0 = Release|x86
50 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}.Release|x86.ActiveCfg = Release|x86
51 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}.Release|x86.Build.0 = Release|x86
52 | EndGlobalSection
53 | GlobalSection(SolutionProperties) = preSolution
54 | HideSolutionNode = FALSE
55 | EndGlobalSection
56 | GlobalSection(MonoDevelopProperties) = preSolution
57 | StartupItem = GLGUI.Example\GLGUI.Example.csproj
58 | EndGlobalSection
59 | EndGlobal
60 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.GLControlExample/GLGUI.GLControlExample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {BE449F2C-0E37-4D16-9E5B-D30D3041759B}
9 | WinExe
10 | Properties
11 | GLGUI.GLControlExample
12 | GLGUI.GLControlExample
13 | v4.0
14 | Client
15 | 512
16 |
17 |
18 | x86
19 | true
20 | full
21 | false
22 | ..\bin\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | x86
29 | pdbonly
30 | true
31 | ..\bin\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 | ..\bin\OpenTK.dll
39 |
40 |
41 | ..\bin\OpenTK.GLControl.dll
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | Form
51 |
52 |
53 |
54 | UserControl
55 |
56 |
57 |
58 |
59 | ResXFileCodeGenerator
60 | Resources.Designer.cs
61 | Designer
62 |
63 |
64 | True
65 | Resources.resx
66 |
67 |
68 | SettingsSingleFileGenerator
69 | Settings.Designer.cs
70 |
71 |
72 | True
73 | Settings.settings
74 | True
75 |
76 |
77 |
78 |
79 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}
80 | GLGUI
81 |
82 |
83 |
84 |
91 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLButton.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using OpenTK.Input;
4 |
5 | namespace GLGUI
6 | {
7 | public class GLButton : GLControl
8 | {
9 | public string Text { get { return text; } set { if (value != text) { text = value; Invalidate(); } } }
10 | public bool Enabled { get { return enabled; } set { enabled = value; Invalidate(); } }
11 | public GLSkin.GLButtonSkin SkinEnabled { get { return skinEnabled; } set { skinEnabled = value; Invalidate(); } }
12 | public GLSkin.GLButtonSkin SkinPressed { get { return skinPressed; } set { skinPressed = value; Invalidate(); } }
13 | public GLSkin.GLButtonSkin SkinHover { get { return skinHover; } set { skinHover = value; Invalidate(); } }
14 | public GLSkin.GLButtonSkin SkinDisabled { get { return skinDisabled; } set { skinDisabled = value; Invalidate(); } }
15 |
16 | public event EventHandler Click;
17 |
18 | private string text = "";
19 | private GLFontText textProcessed = new GLFontText();
20 | private SizeF textSize;
21 | private GLSkin.GLButtonSkin skinEnabled, skinPressed, skinHover, skinDisabled;
22 | private GLSkin.GLButtonSkin skin;
23 | private bool enabled = true;
24 | private bool down = false;
25 | private bool over = false;
26 |
27 | public GLButton(GLGui gui) : base(gui)
28 | {
29 | Render += OnRender;
30 | MouseDown += OnMouseDown;
31 | MouseUp += OnMouseUp;
32 | MouseEnter += OnMouseEnter;
33 | MouseLeave += OnMouseLeave;
34 |
35 | skinEnabled = Gui.Skin.ButtonEnabled;
36 | skinPressed = Gui.Skin.ButtonPressed;
37 | skinHover = Gui.Skin.ButtonHover;
38 | skinDisabled = Gui.Skin.ButtonDisabled;
39 |
40 | outer = new Rectangle(0, 0, 75, 0);
41 | sizeMin = new Size(8, 8);
42 | sizeMax = new Size(int.MaxValue, int.MaxValue);
43 | }
44 |
45 | protected override void UpdateLayout()
46 | {
47 | skin = Enabled ? (down ? skinPressed : (over ? skinHover : skinEnabled)) : skinDisabled;
48 |
49 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
50 |
51 | int innerWidth = outer.Width - skin.Border.Horizontal;
52 | textSize = skin.Font.ProcessText(textProcessed, text, skin.TextAlign);
53 | int minHeight = Math.Max(sizeMin.Height, (int)textSize.Height + skin.Border.Vertical);
54 |
55 | if (AutoSize)
56 | {
57 | innerWidth = (int)textSize.Width;
58 | outer.Width = innerWidth + skin.Border.Horizontal;
59 | outer.Height = minHeight;
60 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
61 | }
62 |
63 | outer.Height = Math.Min(Math.Max(outer.Height, minHeight), sizeMax.Height);
64 |
65 | Inner = new Rectangle(
66 | skin.Border.Left, skin.Border.Top,
67 | innerWidth, outer.Height - skin.Border.Vertical);
68 | }
69 |
70 | private void OnRender(object sender, double timeDelta)
71 | {
72 | GLDraw.Fill(ref skin.BorderColor);
73 | GLDraw.FillRect(Inner, ref skin.BackgroundColor);
74 | GLDraw.Text(textProcessed, Inner, ref skin.Color);
75 | }
76 |
77 | private void OnMouseDown(object sender, MouseButtonEventArgs e)
78 | {
79 | if (enabled && e.Button == MouseButton.Left)
80 | {
81 | isDragged = true;
82 | down = true;
83 | Invalidate();
84 | }
85 | }
86 |
87 | private void OnMouseUp(object sender, MouseButtonEventArgs e)
88 | {
89 | if (enabled && e.Button == MouseButton.Left)
90 | {
91 | if (down)
92 | {
93 | down = false;
94 | isDragged = false;
95 | if(Click != null && new Rectangle(0, 0, outer.Width, outer.Height).Contains(e.Position))
96 | Click(this, e);
97 | Invalidate();
98 | }
99 | }
100 | }
101 |
102 | private void OnMouseEnter(object sender, EventArgs e)
103 | {
104 | over = true;
105 | Invalidate();
106 | }
107 |
108 | private void OnMouseLeave(object sender, EventArgs e)
109 | {
110 | over = false;
111 | Invalidate();
112 | }
113 | }
114 | }
115 |
116 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFlowLayout.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Linq;
4 |
5 | namespace GLGUI
6 | {
7 | public class GLFlowLayout : GLControl
8 | {
9 | public GLFlowDirection FlowDirection { get { return flowDirection; } set { flowDirection = value; Invalidate(); } }
10 | public GLSkin.GLFlowLayoutSkin Skin { get { return skin; } set { skin = value; Invalidate(); } }
11 |
12 | private GLFlowDirection flowDirection = GLFlowDirection.LeftToRight;
13 | private GLSkin.GLFlowLayoutSkin skin;
14 | private Rectangle background;
15 |
16 | public GLFlowLayout(GLGui gui) : base(gui)
17 | {
18 | Render += OnRender;
19 |
20 | skin = Gui.Skin.FlowLayout;
21 |
22 | outer = new Rectangle(0, 0, 100, 100);
23 | sizeMin = new Size(0, 0);
24 | sizeMax = new Size(int.MaxValue, int.MaxValue);
25 | }
26 |
27 | private void Invalidate(object sender, EventArgs e)
28 | {
29 | Invalidate();
30 | }
31 |
32 | private void UpdatePositions()
33 | {
34 | int current = 0;
35 | switch(FlowDirection)
36 | {
37 | case GLFlowDirection.LeftToRight:
38 | foreach(GLControl control in Controls)
39 | {
40 | Rectangle o = control.Outer;
41 | control.Outer = new Rectangle(current, 0, o.Width, o.Height);
42 | current += o.Width + skin.Space;
43 | }
44 | break;
45 | case GLFlowDirection.RightToLeft:
46 | current = Inner.Width;
47 | foreach(GLControl control in Controls)
48 | {
49 | Rectangle o = control.Outer;
50 | current -= o.Width;
51 | control.Outer = new Rectangle(current, 0, o.Width, o.Height);
52 | current -= skin.Space;
53 | }
54 | break;
55 | case GLFlowDirection.TopDown:
56 | foreach(GLControl control in Controls)
57 | {
58 | Rectangle o = control.Outer;
59 | control.Outer = new Rectangle(0, current, o.Width, o.Height);
60 | current += o.Height + skin.Space;
61 | }
62 | break;
63 | case GLFlowDirection.BottomUp:
64 | current = Inner.Height;
65 | foreach(GLControl control in Controls)
66 | {
67 | Rectangle o = control.Outer;
68 | current -= o.Height;
69 | control.Outer = new Rectangle(0, current, o.Width, o.Height);
70 | current -= skin.Space;
71 | }
72 | break;
73 | }
74 | }
75 |
76 | protected override void UpdateLayout()
77 | {
78 | UpdatePositions();
79 |
80 | if (AutoSize)
81 | {
82 | if (Controls.Count() > 0)
83 | {
84 | outer.Width = Controls.Max(c => c.Outer.Right) - Controls.Min(c => c.Outer.Left) + skin.Padding.Horizontal + skin.Border.Horizontal;
85 | outer.Height = Controls.Max(c => c.Outer.Bottom) - Controls.Min(c => c.Outer.Top) + skin.Padding.Vertical + skin.Border.Vertical;
86 | }
87 | else
88 | {
89 | outer.Width = skin.Padding.Horizontal + skin.Border.Horizontal;
90 | outer.Height = skin.Padding.Vertical + skin.Border.Vertical;
91 | }
92 | }
93 |
94 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
95 | outer.Height = Math.Min(Math.Max(outer.Height, sizeMin.Height), sizeMax.Height);
96 | background = new Rectangle(
97 | skin.Border.Left, skin.Border.Top,
98 | outer.Width - skin.Border.Horizontal, outer.Height - skin.Border.Vertical);
99 | Inner = new Rectangle(
100 | background.Left + skin.Padding.Left, background.Top + skin.Padding.Top,
101 | background.Width - skin.Padding.Horizontal, background.Height - skin.Padding.Vertical);
102 |
103 | if(flowDirection == GLFlowDirection.BottomUp || flowDirection == GLFlowDirection.RightToLeft)
104 | UpdatePositions();
105 | }
106 |
107 | private void OnRender(object sender, double timeDelta)
108 | {
109 | GLDraw.Fill(ref skin.BorderColor);
110 | GLDraw.FillRect(ref background, ref skin.BackgroundColor);
111 | }
112 |
113 | public override T Add(T control)
114 | {
115 | base.Add(control);
116 | control.Resize += Invalidate;
117 | Invalidate();
118 | return control;
119 | }
120 |
121 | public override void Remove(GLControl control)
122 | {
123 | base.Remove(control);
124 | control.Resize -= Invalidate;
125 | Invalidate();
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLSplitLayout.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using OpenTK.Input;
4 |
5 | namespace GLGUI
6 | {
7 | public class GLSplitLayout : GLControl
8 | {
9 | public GLSplitterOrientation Orientation { get { return orientation; } set { orientation = value; Invalidate(); } }
10 | public float SplitterPosition { get { return splitterPosition; } set { splitterPosition = value; Invalidate(); } }
11 | public GLSkin.GLSplitLayoutSkin Skin { get { return skin; } set { skin = value; Invalidate(); } }
12 | public GLControl First { get { return first; } }
13 | public GLControl Second { get { return second; } }
14 |
15 | private GLSplitterOrientation orientation = GLSplitterOrientation.Vertical;
16 | private GLSkin.GLSplitLayoutSkin skin;
17 | private GLControl first, second;
18 | private float splitterPosition = 0.5f;
19 |
20 | public GLSplitLayout(GLGui gui) : base(gui)
21 | {
22 | MouseDown += OnMouseDown;
23 | MouseUp += OnMouseUp;
24 | MouseMove += OnMouseMove;
25 | Render += OnRender;
26 |
27 | skin = Gui.Skin.SplitLayout;
28 |
29 | outer = new Rectangle(0, 0, 100, 100);
30 | sizeMin = new Size(0, 0);
31 | sizeMax = new Size(int.MaxValue, int.MaxValue);
32 | }
33 |
34 | protected override void UpdateLayout()
35 | {
36 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
37 | outer.Height = Math.Min(Math.Max(outer.Height, sizeMin.Height), sizeMax.Height);
38 | Inner = new Rectangle(0, 0, outer.Width, outer.Height);
39 |
40 | splitterPosition = Math.Min(Math.Max(splitterPosition, 0.0f), 1.0f);
41 | if (orientation == GLSplitterOrientation.Vertical)
42 | {
43 | int splitter = (int)((Inner.Width - skin.SplitterSize) * splitterPosition);
44 | if (first != null)
45 | first.Outer = new Rectangle(0, 0, splitter, Inner.Height);
46 | if (second != null)
47 | second.Outer = new Rectangle(splitter + skin.SplitterSize, 0, Inner.Width - splitter - skin.SplitterSize, Inner.Height);
48 | splitterRect = new Rectangle(splitter, 0, skin.SplitterSize, Inner.Height);
49 | }
50 | else
51 | {
52 | int splitter = (int)((Inner.Height - skin.SplitterSize) * splitterPosition);
53 | if (first != null)
54 | first.Outer = new Rectangle(0, 0, Inner.Width, splitter);
55 | if (second != null)
56 | second.Outer = new Rectangle(0, splitter + skin.SplitterSize, Inner.Width, Inner.Height - splitter - skin.SplitterSize);
57 | splitterRect = new Rectangle(0, splitter, Inner.Width, skin.SplitterSize);
58 | }
59 | }
60 |
61 | private Rectangle splitterRect;
62 | private void OnRender(object sender, double timeDelta)
63 | {
64 | GLDraw.FillRect(ref splitterRect, ref skin.BackgroundColor);
65 | }
66 |
67 | public override T Add(T control)
68 | {
69 | if (first != null && second != null)
70 | {
71 | string message = string.Format("{0} {1} already has two children.",
72 | control.GetType().Name, control.Name);
73 | throw new InvalidOperationException(message);
74 | }
75 | base.Add(control);
76 | if (first == null)
77 | first = control;
78 | else
79 | second = control;
80 | Invalidate();
81 | return control;
82 | }
83 |
84 | public override void Remove(GLControl control)
85 | {
86 | if (first == control)
87 | first = null;
88 | if (second == control)
89 | second = null;
90 | base.Remove(control);
91 | }
92 |
93 | private void OnMouseDown(object sender, MouseButtonEventArgs e)
94 | {
95 | if (e.Button == MouseButton.Left)
96 | {
97 | isDragged = true;
98 | }
99 | }
100 |
101 | private void OnMouseUp(object sender, MouseButtonEventArgs e)
102 | {
103 | if (e.Button == MouseButton.Left)
104 | {
105 | if (isDragged)
106 | {
107 | isDragged = false;
108 | Gui.Cursor = GLCursor.Default;
109 | }
110 | }
111 | }
112 |
113 | private void OnMouseMove(object sender, MouseEventArgs e)
114 | {
115 | if (isDragged)
116 | {
117 | if (orientation == GLSplitterOrientation.Vertical)
118 | splitterPosition = (float)(e.X - skin.SplitterSize / 2) / (float)Inner.Width;
119 | else
120 | splitterPosition = (float)(e.Y - skin.SplitterSize / 2) / (float)Inner.Height;
121 | Invalidate();
122 | }
123 | Gui.Cursor = orientation == GLSplitterOrientation.Horizontal ? GLCursor.SizeNS : GLCursor.SizeWE;
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLCursor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Drawing.Imaging;
4 | using System.Runtime.InteropServices;
5 | using System.Security;
6 | using OpenTK;
7 |
8 | namespace GLGUI
9 | {
10 | public class GLCursor
11 | {
12 | public static GLCursor Default, SizeAll, SizeNWSE, SizeNS, SizeNESW, SizeWE, IBeam, Hand, None;
13 |
14 | internal readonly IntPtr Handle;
15 | #if REFERENCE_WINDOWS_FORMS
16 | internal readonly System.Windows.Forms.Cursor Cursor;
17 | #endif
18 |
19 | private static bool loaded = false;
20 | private static bool usingSdl2 = false;
21 |
22 | #if REFERENCE_WINDOWS_FORMS
23 | private GLCursor()
24 | {
25 | if (usingSdl2)
26 | {
27 | byte[] dummy = new byte[4 * 32];
28 | unsafe
29 | {
30 | fixed(byte* d = dummy)
31 | {
32 | Handle = CreateCursor((IntPtr)d, (IntPtr)d, 32, 32, 0, 0);
33 | }
34 | }
35 | }
36 | else
37 | {
38 | Bitmap bmp = new Bitmap(1, 1);
39 | Handle = bmp.GetHicon();
40 | bmp.Dispose();
41 | Cursor = new System.Windows.Forms.Cursor(Handle);
42 | }
43 | }
44 |
45 | private GLCursor(System.Windows.Forms.Cursor cursor, bool centeredHotSpot = true)
46 | {
47 | if (!usingSdl2)
48 | {
49 | Handle = cursor.Handle;
50 | Cursor = cursor;
51 | return;
52 | }
53 |
54 | // now it's getting ugly...
55 | // this is converting our shiny cursors to the minimalistic cursor support of sdl2.
56 | // since there seems to be NO F*CKING WAY to get the cursor hot spot from X11,
57 | // we just center it for every cursor except the default pointer and the hand.
58 | int w = Math.Max(cursor.Size.Width, 32); // also, no size...
59 | int h = Math.Max(cursor.Size.Height, 32); // (╯°□°)╯︵ ┻━┻
60 | var rect = new Rectangle(0, 0, w, h);
61 |
62 | var bmp = new Bitmap(w, h);
63 | bmp.MakeTransparent();
64 | using(var g = Graphics.FromImage(bmp))
65 | {
66 | cursor.Draw(g, rect);
67 | }
68 | var data = bmp.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
69 | var color = new byte[data.Height * data.Width / 8];
70 | var visibility = new byte[data.Height * data.Width / 8];
71 |
72 | unsafe
73 | {
74 | fixed(byte* c = color, v = visibility)
75 | {
76 | Point min = new Point(int.MaxValue, int.MaxValue), max = new Point();
77 | byte* d = (byte*)data.Scan0;
78 | for(int y = 0; y < data.Height; y++)
79 | {
80 | for(int x = 0; x < data.Width; x++)
81 | {
82 | int a = d[y * data.Stride + x * 4 + 3];
83 | int l = d[y * data.Stride + x * 4 + 0] + d[y * data.Stride + x * 4 + 1] + d[y * data.Stride + x * 4 + 2];
84 | if (a > 100)
85 | {
86 | min.X = Math.Min(min.X, x); min.Y = Math.Min(min.Y, y);
87 | max.X = Math.Max(max.X, x); max.Y = Math.Max(max.Y, y);
88 |
89 | v[(y * data.Width + x) / 8] |= (byte)(1 << (7 - (x & 7)));
90 | if (l < 300)
91 | c[(y * data.Width + x) / 8] |= (byte)(1 << (7 - (x & 7)));
92 | }
93 | }
94 | }
95 | Point hotspot = centeredHotSpot ? new Point((min.X + max.X) / 2, (min.Y + max.Y) / 2) : min;
96 | Handle = CreateCursor((IntPtr)c, (IntPtr)v, data.Width, data.Height, hotspot.X, hotspot.Y);
97 | }
98 | }
99 | bmp.UnlockBits(data);
100 | bmp.Dispose();
101 | }
102 | #endif
103 |
104 | internal static void LoadCursors(NativeWindow window)
105 | {
106 | if (loaded)
107 | return;
108 |
109 | if (window != null)
110 | {
111 | string infoType = window.WindowInfo.GetType().Name;
112 | if (infoType == "Sdl2WindowInfo")
113 | usingSdl2 = true;
114 | }
115 |
116 | #if REFERENCE_WINDOWS_FORMS
117 | Default = new GLCursor(System.Windows.Forms.Cursors.Default, false);
118 | SizeAll = new GLCursor(System.Windows.Forms.Cursors.SizeAll);
119 | SizeNWSE = new GLCursor(System.Windows.Forms.Cursors.SizeNWSE);
120 | SizeNS = new GLCursor(System.Windows.Forms.Cursors.SizeNS);
121 | SizeNESW = new GLCursor(System.Windows.Forms.Cursors.SizeNESW);
122 | SizeWE = new GLCursor(System.Windows.Forms.Cursors.SizeWE);
123 | IBeam = new GLCursor(System.Windows.Forms.Cursors.IBeam);
124 | Hand = new GLCursor(System.Windows.Forms.Cursors.Hand, false);
125 | None = new GLCursor();
126 | #endif
127 |
128 | loaded = true;
129 | }
130 |
131 | [SuppressUnmanagedCodeSecurity]
132 | [DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateCursor", ExactSpelling = true)]
133 | private static extern IntPtr CreateCursor(IntPtr data, IntPtr mask, int w, int h, int hot_x, int hot_y);
134 | }
135 | }
136 |
137 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLCheckBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using OpenTK.Input;
4 |
5 | namespace GLGUI
6 | {
7 | public class GLCheckBox : GLControl
8 | {
9 | public string Text { get { return text; } set { if (value != text) { text = value; Invalidate(); } } }
10 | public bool Enabled { get { return enabled; } set { enabled = value; Invalidate(); } }
11 | public bool Checked { get { return _checked; } set { _checked = value; Invalidate(); } }
12 | public GLSkin.GLCheckBoxSkin SkinEnabled { get { return skinEnabled; } set { skinEnabled = value; Invalidate(); } }
13 | public GLSkin.GLCheckBoxSkin SkinPressed { get { return skinPressed; } set { skinPressed = value; Invalidate(); } }
14 | public GLSkin.GLCheckBoxSkin SkinHover { get { return skinHover; } set { skinHover = value; Invalidate(); } }
15 | public GLSkin.GLCheckBoxSkin SkinDisabled { get { return skinDisabled; } set { skinDisabled = value; Invalidate(); } }
16 |
17 | public event EventHandler Changed;
18 |
19 | private string text = "";
20 | private GLFontText textProcessed = new GLFontText();
21 | private SizeF textSize;
22 | private GLSkin.GLCheckBoxSkin skinEnabled, skinPressed, skinHover, skinDisabled;
23 | private GLSkin.GLCheckBoxSkin skin;
24 | private bool enabled = true;
25 | private bool _checked = false;
26 | private bool down = false;
27 | private bool over = false;
28 | private Rectangle outerBox = new Rectangle(0, 0, 10, 10);
29 | private Rectangle innerBox;
30 |
31 | public GLCheckBox(GLGui gui) : base(gui)
32 | {
33 | Render += OnRender;
34 | MouseDown += OnMouseDown;
35 | MouseUp += OnMouseUp;
36 | MouseEnter += OnMouseEnter;
37 | MouseLeave += OnMouseLeave;
38 |
39 | skinEnabled = Gui.Skin.CheckBoxEnabled;
40 | skinPressed = Gui.Skin.CheckBoxPressed;
41 | skinHover = Gui.Skin.CheckBoxHover;
42 | skinDisabled = Gui.Skin.CheckBoxDisabled;
43 |
44 | outer = outerBox;
45 | sizeMin = outerBox.Size;
46 | sizeMax = new Size(int.MaxValue, int.MaxValue);
47 |
48 | HandleMouseEvents = false;
49 | }
50 |
51 | protected override void UpdateLayout()
52 | {
53 | skin = Enabled ? (down ? skinPressed : (over ? skinHover : skinEnabled)) : skinDisabled;
54 |
55 | innerBox = new Rectangle(skin.Border.Left, skin.Border.Top,
56 | outerBox.Width - skin.Border.Horizontal, outerBox.Height - skin.Border.Vertical);
57 |
58 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
59 |
60 | int innerWidth = outer.Width - skin.Border.Horizontal - outerBox.Width;
61 | textSize = skin.Font.ProcessText(textProcessed, text, GLFontAlignment.Left);
62 | int minHeight = Math.Max(sizeMin.Height, (int)textSize.Height + skin.Border.Vertical);
63 |
64 | if (AutoSize)
65 | {
66 | innerWidth = (int)textSize.Width;
67 | outer.Width = innerWidth + outerBox.Width + skin.Border.Horizontal;
68 | outer.Height = minHeight;
69 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
70 | }
71 |
72 | outer.Height = Math.Min(Math.Max(outer.Height, minHeight), sizeMax.Height);
73 |
74 | Inner = new Rectangle(
75 | outerBox.Right + skin.Border.Left, skin.Border.Top,
76 | innerWidth, outer.Height - skin.Border.Vertical);
77 | }
78 |
79 | private void OnRender(object sender, double timeDelta)
80 | {
81 | GLDraw.FillRect(ref outerBox, ref skin.BorderColor);
82 | GLDraw.FillRect(ref innerBox, ref skin.BackgroundColor);
83 | if (_checked)
84 | GLDraw.FillRect(new Rectangle(innerBox.X + skin.Border.Left, innerBox.Y + skin.Border.Top,
85 | innerBox.Width - skin.Border.Horizontal, innerBox.Height - skin.Border.Vertical), ref skin.BorderColor);
86 | GLDraw.Text(textProcessed, Inner, ref skin.Color);
87 | }
88 |
89 | private void OnMouseDown(object sender, MouseButtonEventArgs e)
90 | {
91 | if (enabled && e.Button == MouseButton.Left)
92 | {
93 | isDragged = true;
94 | down = true;
95 | Invalidate();
96 | }
97 | }
98 |
99 | private void OnMouseUp(object sender, MouseButtonEventArgs e)
100 | {
101 | if (enabled && e.Button == MouseButton.Left)
102 | {
103 | if (down)
104 | {
105 | down = false;
106 | isDragged = false;
107 | _checked = !_checked;
108 | if(Changed != null)
109 | Changed(this, e);
110 | Invalidate();
111 | }
112 | }
113 | }
114 |
115 | private void OnMouseEnter(object sender, EventArgs e)
116 | {
117 | over = true;
118 | Invalidate();
119 | }
120 |
121 | private void OnMouseLeave(object sender, EventArgs e)
122 | {
123 | over = false;
124 | Invalidate();
125 | }
126 | }
127 | }
128 |
129 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontRenderOptions.cs:
--------------------------------------------------------------------------------
1 | namespace GLGUI
2 | {
3 | public class GLFontRenderOptions
4 | {
5 | ///
6 | /// Spacing between characters in units of average glyph width
7 | ///
8 | public float CharacterSpacing = 0.05f;
9 |
10 | ///
11 | /// Spacing between words in units of average glyph width
12 | ///
13 | public float WordSpacing = 0.6f;
14 |
15 | ///
16 | /// Line spacing in units of max glyph width
17 | ///
18 | public float LineSpacing = 1.0f;
19 |
20 | ///
21 | /// Whether to render the font in monospaced mode. If set to "Natural", then
22 | /// monospacing will be used if the font loaded font was detected to be monospaced.
23 | ///
24 | public GLFontMonospacing Monospacing = GLFontMonospacing.Natural;
25 |
26 | ///
27 | /// Locks the position to a particular pixel, allowing the text to be rendered pixel-perfectly.
28 | /// You need to turn this off if you wish to move text around the screen smoothly by fractions
29 | /// of a pixel.
30 | ///
31 | public bool LockToPixel;
32 |
33 | ///
34 | /// Only applies when LockToPixel is true:
35 | /// This is used to transition smoothly between being locked to pixels and not
36 | ///
37 | public float LockToPixelRatio = 1.0f;
38 |
39 | ///
40 | /// Wrap word to next line if max width hit
41 | ///
42 | public bool WordWrap = true;
43 |
44 |
45 | #region Justify Options
46 |
47 | ///
48 | /// When a line of text is justified, space may be inserted between
49 | /// characters, and between words.
50 | ///
51 | /// This parameter determines how this choice is weighted:
52 | ///
53 | /// 0.0f => word spacing only
54 | /// 1.0f => "fairly" distributed between both
55 | /// > 1.0 => in favour of character spacing
56 | ///
57 | /// This applies to expansions only.
58 | ///
59 | ///
60 | public float JustifyCharacterWeightForExpand
61 | {
62 | get { return justifyCharWeightForExpand; }
63 | set
64 | {
65 | justifyCharWeightForExpand = value;
66 | if (justifyCharWeightForExpand < 0f)
67 | justifyCharWeightForExpand = 0f;
68 | else if (justifyCharWeightForExpand > 1.0f)
69 | justifyCharWeightForExpand = 1.0f;
70 | }
71 | }
72 |
73 | private float justifyCharWeightForExpand = 0.5f;
74 |
75 | ///
76 | /// When a line of text is justified, space may be removed between
77 | /// characters, and between words.
78 | ///
79 | /// This parameter determines how this choice is weighted:
80 | ///
81 | /// 0.0f => word spacing only
82 | /// 1.0f => "fairly" distributed between both
83 | /// > 1.0 => in favour of character spacing
84 | ///
85 | /// This applies to contractions only.
86 | ///
87 | ///
88 | public float JustifyCharacterWeightForContract
89 | {
90 | get { return justifyCharWeightForContract; }
91 | set
92 | {
93 | justifyCharWeightForContract = value;
94 | if (justifyCharWeightForContract < 0f)
95 | justifyCharWeightForContract = 0f;
96 | else if (justifyCharWeightForContract > 1.0f)
97 | justifyCharWeightForContract = 1.0f;
98 | }
99 | }
100 |
101 | private float justifyCharWeightForContract = 0.2f;
102 |
103 | ///
104 | /// Total justification cap as a fraction of the boundary width.
105 | ///
106 | public float JustifyCapExpand = 0.5f;
107 |
108 | ///
109 | /// Total justification cap as a fraction of the boundary width.
110 | ///
111 | public float JustifyCapContract = 0.1f;
112 |
113 | ///
114 | /// By what factor justification is penalized for being negative.
115 | ///
116 | /// (e.g. if this is set to 3, then a contraction will only happen
117 | /// over an expansion if it is 3 of fewer times smaller than the
118 | /// expansion).
119 | ///
120 | ///
121 | ///
122 | public float JustifyContractionPenalty = 2;
123 |
124 | #endregion
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLGUI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 10.0.0
7 | 2.0
8 | {D0281455-4FAF-4AF6-ABE4-8F9E7A25828D}
9 | Library
10 | GLGUI
11 | GLGUI
12 |
13 |
14 | true
15 | full
16 | false
17 | ..\bin
18 | DEBUG;REFERENCE_WINDOWS_FORMS; REFERENCE_OPENTK_GLCONTROL
19 | prompt
20 | 4
21 | false
22 | true
23 |
24 |
25 | true
26 | ..\bin
27 | prompt
28 | 4
29 | false
30 | true
31 | REFERENCE_WINDOWS_FORMS; REFERENCE_OPENTK_GLCONTROL
32 |
33 |
34 |
35 | False
36 | ..\bin\OpenTK.GLControl.dll
37 |
38 |
39 |
40 | ..\bin\OpenTK.dll
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLSlider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using OpenTK.Input;
4 |
5 | namespace GLGUI
6 | {
7 | public class GLSlider : GLControl
8 | {
9 | public GLSliderOrientation Direction { get { return direction; } set { direction = value; Invalidate(); } }
10 | public float Value { get { return value; } set { this.value = value; Invalidate(); if (ValueChanged != null) ValueChanged(this, EventArgs.Empty); } }
11 | public bool Enabled { get { return enabled; } set { enabled = value; Invalidate(); } }
12 | public GLSkin.GLSliderSkin SkinEnabled { get { return skinEnabled; } set { skinEnabled = value; Invalidate(); } }
13 | public GLSkin.GLSliderSkin SkinPressed { get { return skinPressed; } set { skinPressed = value; Invalidate(); } }
14 | public GLSkin.GLSliderSkin SkinHover { get { return skinHover; } set { skinHover = value; Invalidate(); } }
15 | public GLSkin.GLSliderSkin SkinDisabled { get { return skinDisabled; } set { skinDisabled = value; Invalidate(); } }
16 | public float MouseWheelStep = 0.001f;
17 |
18 | public event EventHandler ValueChanged;
19 |
20 | private GLSkin.GLSliderSkin skinEnabled, skinPressed, skinHover, skinDisabled;
21 | private GLSkin.GLSliderSkin skin;
22 | private GLSliderOrientation direction = GLSliderOrientation.Vertical;
23 | private float value = 0.0f;
24 | private bool enabled = true;
25 | private bool down = false;
26 | private bool over = false;
27 |
28 | public GLSlider(GLGui gui) : base(gui)
29 | {
30 | Render += OnRender;
31 | MouseMove += OnMouseMove;
32 | MouseDown += OnMouseDown;
33 | MouseUp += OnMouseUp;
34 | MouseEnter += OnMouseEnter;
35 | MouseLeave += OnMouseLeave;
36 | MouseWheel += OnMouseWheel;
37 |
38 | skinEnabled = Gui.Skin.SliderEnabled;
39 | skinPressed = Gui.Skin.SliderPressed;
40 | skinHover = Gui.Skin.SliderHover;
41 | skinDisabled = Gui.Skin.SliderDisabled;
42 |
43 | outer = new Rectangle(0, 0, 8, 8);
44 | sizeMin = new Size(8, 8);
45 | sizeMax = new Size(int.MaxValue, int.MaxValue);
46 | }
47 |
48 | protected override void UpdateLayout()
49 | {
50 | skin = Enabled ? (down ? skinPressed : (over ? skinHover : skinEnabled)) : skinDisabled;
51 |
52 | if (AutoSize)
53 | {
54 | outer.Width = sizeMin.Width;
55 | outer.Height = sizeMin.Height;
56 | if (Parent != null)
57 | {
58 | if (direction == GLSliderOrientation.Horizontal)
59 | outer.Width = Parent.Inner.Width;
60 | else
61 | outer.Height = Parent.Inner.Height;
62 | }
63 | }
64 |
65 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
66 | outer.Height = Math.Min(Math.Max(outer.Height, sizeMin.Height), sizeMax.Height);
67 |
68 | if (!enabled)
69 | value = 0.0f;
70 | value = Math.Min(Math.Max(value, 0.0f), 1.0f);
71 | if (direction == GLSliderOrientation.Horizontal)
72 | Inner = new Rectangle((int)((outer.Width - 8) * value), 0, 8, 8);
73 | else
74 | Inner = new Rectangle(0, (int)((outer.Height - 8) * value), 8, 8);
75 | }
76 |
77 | private void OnRender(object sender, double timeDelta)
78 | {
79 | GLDraw.Fill(ref skin.BackgroundColor);
80 | GLDraw.FillRect(Inner, ref skin.KnobColor);
81 | }
82 |
83 | private void OnMouseMove(object sender, MouseMoveEventArgs e)
84 | {
85 | if (isDragged && enabled)
86 | {
87 | if (direction == GLSliderOrientation.Horizontal)
88 | Value = (float)(e.X - 4) / (float)(outer.Width - 8);
89 | else
90 | Value = (float)(e.Y - 4) / (float)(outer.Height - 8);
91 | }
92 | }
93 |
94 | private void OnMouseDown(object sender, MouseButtonEventArgs e)
95 | {
96 | if (e.Button == MouseButton.Left && enabled)
97 | {
98 | isDragged = true;
99 | down = true;
100 | if (direction == GLSliderOrientation.Horizontal)
101 | Value = (float)(e.X - 4) / (float)(outer.Width - 8);
102 | else
103 | Value = (float)(e.Y - 4) / (float)(outer.Height - 8);
104 | }
105 | }
106 |
107 | private void OnMouseUp(object sender, MouseButtonEventArgs e)
108 | {
109 | if (e.Button == MouseButton.Left && enabled)
110 | {
111 | if (down)
112 | {
113 | down = false;
114 | isDragged = false;
115 | Invalidate();
116 | }
117 | }
118 | }
119 |
120 | private void OnMouseEnter(object sender, EventArgs e)
121 | {
122 | over = true;
123 | Invalidate();
124 | }
125 |
126 | private void OnMouseLeave(object sender, EventArgs e)
127 | {
128 | over = false;
129 | Invalidate();
130 | }
131 |
132 | private void OnMouseWheel(object sender, MouseWheelEventArgs e)
133 | {
134 | if (Enabled)
135 | Value += -e.Delta * MouseWheelStep;
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontKerningCalculator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace GLGUI
5 | {
6 | class GLFontKerningCalculator
7 | {
8 | private struct XLimits
9 | {
10 | public int Min;
11 | public int Max;
12 | }
13 |
14 | private static int Kerning(GLFontGlyph g1, GLFontGlyph g2, XLimits[] lim1, XLimits[] lim2, GLFontKerningConfiguration config)
15 | {
16 | int yOffset1 = g1.YOffset;
17 | int yOffset2 = g2.YOffset;
18 |
19 | int startY = Math.Max(yOffset1, yOffset2);
20 | int endY = Math.Min(g1.Rect.Height + yOffset1, g2.Rect.Height + yOffset2);
21 |
22 | int w1 = g1.Rect.Width;
23 |
24 | int worstCase = w1;
25 |
26 | //TODO - offset startY, endY by yOffset1 so that lim1[j-yOffset1] can be written as lim1[j], will need another var for yOffset2
27 |
28 | for (int j = startY; j < endY; j++)
29 | worstCase = Math.Min(worstCase, w1 - lim1[j-yOffset1].Max + lim2[j-yOffset2].Min);
30 |
31 | worstCase = Math.Min(worstCase, g1.Rect.Width);
32 | worstCase = Math.Min(worstCase, g2.Rect.Width);
33 |
34 | //modify by character kerning rules
35 | GLFontCharacterKerningRule kerningRule = config.GetOverridingCharacterKerningRuleForPair(""+g1.Character + g2.Character);
36 | if (kerningRule == GLFontCharacterKerningRule.Zero)
37 | {
38 | return 0;
39 | }
40 | else if (kerningRule == GLFontCharacterKerningRule.NotMoreThanHalf)
41 | {
42 | return (int)Math.Min(Math.Min(g1.Rect.Width,g2.Rect.Width)*0.5f, worstCase);
43 | }
44 |
45 | return worstCase;
46 | }
47 |
48 | public static Dictionary CalculateKerning(char[] charSet, GLFontGlyph[] glyphs, List bitmapPages, GLFontKerningConfiguration config)
49 | {
50 | var kerningPairs = new Dictionary();
51 |
52 | //we start by computing the index of the first and last non-empty pixel in each row of each glyph
53 | XLimits[][] limits = new XLimits[charSet.Length][];
54 | int maxHeight = 0;
55 | for (int n = 0; n < charSet.Length; n++)
56 | {
57 | var rect = glyphs[n].Rect;
58 | var page = bitmapPages[glyphs[n].Page];
59 |
60 | limits[n] = new XLimits[rect.Height];
61 |
62 | maxHeight = Math.Max(rect.Height, maxHeight);
63 |
64 | int yStart = rect.Y;
65 | int yEnd = rect.Y + rect.Height;
66 | int xStart = rect.X;
67 | int xEnd = rect.X + rect.Width;
68 |
69 | for (int j = yStart; j < yEnd; j++)
70 | {
71 | int last = xStart;
72 |
73 | bool yetToFindFirst = true;
74 | for (int i = xStart; i < xEnd; i++)
75 | {
76 | if (!GLFontBitmap.EmptyAlphaPixel(page.bitmapData, i, j,config.AlphaEmptyPixelTolerance))
77 | {
78 |
79 | if (yetToFindFirst)
80 | {
81 | limits[n][j - yStart].Min = i - xStart;
82 | yetToFindFirst = false;
83 | }
84 | last = i;
85 | }
86 | }
87 |
88 | limits[n][j - yStart].Max = last - xStart;
89 |
90 | if (yetToFindFirst)
91 | limits[n][j - yStart].Min = xEnd - 1;
92 | }
93 | }
94 |
95 | //we now bring up each row to the max (or min) of it's two adjacent rows, this is to stop glyphs sliding together too closely
96 | var tmp = new XLimits[maxHeight];
97 |
98 | for (int n = 0; n < charSet.Length; n++)
99 | {
100 | //clear tmp
101 | for (int j = 0; j < limits[n].Length; j++)
102 | tmp[j] = limits[n][j];
103 |
104 | for (int j = 0; j < limits[n].Length; j++)
105 | {
106 | if(j != 0){
107 | tmp[j].Min = Math.Min(limits[n][j - 1].Min, tmp[j].Min);
108 | tmp[j].Max = Math.Max(limits[n][j - 1].Max, tmp[j].Max);
109 | }
110 |
111 | if (j != limits[n].Length - 1)
112 | {
113 | tmp[j].Min = Math.Min(limits[n][j + 1].Min, tmp[j].Min);
114 | tmp[j].Max = Math.Max(limits[n][j + 1].Max, tmp[j].Max);
115 | }
116 |
117 | }
118 |
119 | for (int j = 0; j < limits[n].Length; j++)
120 | limits[n][j] = tmp[j];
121 |
122 | }
123 |
124 | for (int i = 0; i < charSet.Length; i++)
125 | for (int j = 0; j < charSet.Length; j++)
126 | kerningPairs.Add("" + charSet[i] + charSet[j], 1-Kerning(glyphs[i], glyphs[j], limits[i], limits[j],config));
127 |
128 | return kerningPairs;
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLScrollableControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Linq;
4 | using OpenTK.Input;
5 |
6 | namespace GLGUI
7 | {
8 | public class GLScrollableControl : GLControl
9 | {
10 | public GLSlider Horizontal { get { return horizontal; } }
11 | public GLSlider Vertical { get { return vertical; } }
12 | public Point ScrollPosition { get { return scrollPosition; } }
13 | public Size ScrollFreedom { get { return scrollFreedom; } }
14 | public GLSkin.GLScrollableControlSkin Skin { get { return skin; } set { skin = value; Invalidate(); } }
15 | public override GLContextMenu ContextMenu { get { return base.ContextMenu; } set { base.ContextMenu = value; content.ContextMenu = value; } }
16 |
17 | private GLSkin.GLScrollableControlSkin skin;
18 | private Point scrollPosition;
19 | private Size scrollFreedom;
20 | private GLScrolledControl content;
21 | private GLSlider horizontal, vertical;
22 |
23 | public GLScrollableControl(GLGui gui) : base(gui)
24 | {
25 | Render += OnRender;
26 | MouseWheel += OnMouseWheel;
27 |
28 | skin = Gui.Skin.ScrollableControl;
29 |
30 | outer = new Rectangle(0, 0, 32, 32);
31 | horizontal = base.Add(new GLSlider(gui) { Direction = GLSliderOrientation.Horizontal/*, Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom*/ });
32 | vertical = base.Add(new GLSlider(gui) { Direction = GLSliderOrientation.Vertical/*, Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom*/ });
33 | content = base.Add(new GLScrolledControl(gui) { /*Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom*/ });
34 | content.MouseWheel += OnMouseWheel;
35 |
36 | horizontal.ValueChanged += (s, e) => Invalidate();
37 | vertical.ValueChanged += (s, e) => Invalidate();
38 | }
39 |
40 | protected override void UpdateLayout()
41 | {
42 | if (AutoSize)
43 | {
44 | if (Controls.Count() > 0)
45 | {
46 | outer.Width = Controls.Max(c => c.Outer.Right) + skin.Border.Horizontal;
47 | outer.Height = Controls.Max(c => c.Outer.Bottom) + skin.Border.Vertical;
48 | }
49 | else
50 | {
51 | outer.Width = skin.Border.Horizontal;
52 | outer.Height = skin.Border.Vertical;
53 | }
54 | }
55 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
56 | outer.Height = Math.Min(Math.Max(outer.Height, sizeMin.Height), sizeMax.Height);
57 | Inner = new Rectangle(skin.Border.Left, skin.Border.Top, outer.Width - skin.Border.Horizontal, outer.Height - skin.Border.Vertical);
58 |
59 | scrollFreedom = new Size(0, 0);
60 | if (content != null)
61 | {
62 | scrollFreedom = new Size(
63 | Math.Max(content.TotalSize.Width - (Inner.Width - vertical.Outer.Width), 0),
64 | Math.Max(content.TotalSize.Height - (Inner.Height - horizontal.Outer.Height), 0));
65 |
66 | if ((scrollFreedom.Width == 0) == horizontal.Enabled)
67 | horizontal.Enabled = !horizontal.Enabled;
68 | if ((scrollFreedom.Height == 0) == vertical.Enabled)
69 | vertical.Enabled = !vertical.Enabled;
70 |
71 | if ((horizontal.Parent == null) && horizontal.Enabled)
72 | base.Add(horizontal);
73 | if ((horizontal.Parent != null) && !horizontal.Enabled)
74 | base.Remove(horizontal);
75 | if ((vertical.Parent == null) && vertical.Enabled)
76 | base.Add(vertical);
77 | if ((vertical.Parent != null) && !vertical.Enabled)
78 | base.Remove(vertical);
79 |
80 | scrollPosition = new Point((int)(horizontal.Value * scrollFreedom.Width), (int)(vertical.Value * scrollFreedom.Height));
81 | horizontal.Outer = new Rectangle(0, Inner.Height - horizontal.Height, Inner.Width - (vertical.Enabled ? vertical.Width : 0), horizontal.Height);
82 | vertical.Outer = new Rectangle(Inner.Width - vertical.Width, 0, vertical.Width, Inner.Height - (horizontal.Enabled ? horizontal.Height : 0));
83 | horizontal.MouseWheelStep = 1.0f / scrollFreedom.Width;
84 | vertical.MouseWheelStep = 1.0f / scrollFreedom.Height;
85 |
86 | content.Outer = new Rectangle(-scrollPosition.X, -scrollPosition.Y,
87 | Inner.Width - (vertical.Enabled ? vertical.Width : 0) + scrollPosition.X,
88 | Inner.Height - (horizontal.Enabled ? horizontal.Height : 0) + scrollPosition.Y);
89 | }
90 | }
91 |
92 | private void OnRender(object sender, double timeDelta)
93 | {
94 | GLDraw.Fill(ref skin.BorderColor);
95 | GLDraw.FillRect(Inner, ref skin.BackgroundColor);
96 | }
97 |
98 | public override T Add(T control)
99 | {
100 | return content.Add(control);
101 | }
102 |
103 | public override void Clear()
104 | {
105 | content.Clear();
106 | }
107 |
108 | public override void Remove(GLControl control)
109 | {
110 | content.Remove(control);
111 | }
112 |
113 | private void OnMouseWheel(object sender, MouseWheelEventArgs e)
114 | {
115 | if (vertical.Enabled)
116 | vertical.DoMouseWheel(e);
117 | else
118 | horizontal.DoMouseWheel(e);
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.GLControlExample/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/GLGUI/bin/OpenTK.GLControl.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | OpenTK.GLControl
5 |
6 |
7 |
8 |
9 | OpenGL-aware WinForms control.
10 | The WinForms designer will always call the default constructor.
11 | Inherit from this class and call one of its specialized constructors
12 | to enable antialiasing or custom s.
13 |
14 |
15 |
16 |
17 | Required designer variable.
18 |
19 |
20 |
21 |
22 | Clean up any resources being used.
23 |
24 | true if managed resources should be disposed; otherwise, false.
25 |
26 |
27 |
28 | Required method for Designer support - do not modify
29 | the contents of this method with the code editor.
30 |
31 |
32 |
33 |
34 | Constructs a new instance.
35 |
36 |
37 |
38 |
39 | Constructs a new instance with the specified GraphicsMode.
40 |
41 | The OpenTK.Graphics.GraphicsMode of the control.
42 |
43 |
44 |
45 | Constructs a new instance with the specified GraphicsMode.
46 |
47 | The OpenTK.Graphics.GraphicsMode of the control.
48 | The major version for the OpenGL GraphicsContext.
49 | The minor version for the OpenGL GraphicsContext.
50 | The GraphicsContextFlags for the OpenGL GraphicsContext.
51 |
52 |
53 | Raises the HandleCreated event.
54 | Not used.
55 |
56 |
57 | Raises the HandleDestroyed event.
58 | Not used.
59 |
60 |
61 |
62 | Raises the System.Windows.Forms.Control.Paint event.
63 |
64 | A System.Windows.Forms.PaintEventArgs that contains the event data.
65 |
66 |
67 |
68 | Raises the Resize event.
69 | Note: this method may be called before the OpenGL context is ready.
70 | Check that IsHandleCreated is true before using any OpenGL methods.
71 |
72 | A System.EventArgs that contains the event data.
73 |
74 |
75 |
76 | Execute the delayed context update
77 |
78 |
79 |
80 |
81 | Raises the ParentChanged event.
82 |
83 | A System.EventArgs that contains the event data.
84 |
85 |
86 |
87 | Swaps the front and back buffers, presenting the rendered scene to the screen.
88 | This method will have no effect on a single-buffered GraphicsMode.
89 |
90 |
91 |
92 |
93 |
94 | Makes current in the calling thread.
95 | All OpenGL commands issued are hereafter interpreted by this context.
96 |
97 |
98 | When using multiple GLControls, calling MakeCurrent on
99 | one control will make all other controls non-current in the calling thread.
100 |
101 |
102 |
103 | A GLControl can only be current in one thread at a time.
104 | To make a control non-current, call GLControl.Context.MakeCurrent(null).
105 |
106 |
107 |
108 |
109 |
110 | Grabs a screenshot of the frontbuffer contents.
111 | When using multiple GLControls, ensure that
112 | is current before accessing this property.
113 |
114 |
115 |
116 | A System.Drawing.Bitmap, containing the contents of the frontbuffer.
117 |
118 | Occurs when no OpenTK.Graphics.GraphicsContext is current in the calling thread.
119 |
120 |
121 |
122 |
123 | Gets the CreateParams instance for this GLControl
124 |
125 |
126 |
127 |
128 | Gets a value indicating whether the current thread contains pending system messages.
129 |
130 |
131 |
132 |
133 | Gets the IGraphicsContext instance that is associated with the GLControl.
134 | The associated IGraphicsContext is updated whenever the GLControl
135 | handle is created or recreated.
136 | When using multiple GLControls, ensure that Context
137 | is current before performing any OpenGL operations.
138 |
139 |
140 |
141 |
142 |
143 | Gets the aspect ratio of this GLControl.
144 |
145 |
146 |
147 |
148 | Gets or sets a value indicating whether vsync is active for this GLControl.
149 | When using multiple GLControls, ensure that
150 | is current before accessing this property.
151 |
152 |
153 |
154 |
155 |
156 |
157 | Gets the GraphicsMode of the IGraphicsContext associated with
158 | this GLControl. If you wish to change GraphicsMode, you must
159 | destroy and recreate the GLControl.
160 |
161 |
162 |
163 |
164 | Gets the for this instance.
165 |
166 |
167 |
168 |
169 | Needed to delay the invoke on OS X. Also needed because OpenTK is .NET 2, otherwise I'd use an inline Action.
170 |
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.Example/MainForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using OpenTK;
4 | using OpenTK.Graphics;
5 | using OpenTK.Graphics.OpenGL;
6 |
7 | namespace GLGUI.Example
8 | {
9 | public class MainForm : GameWindow
10 | {
11 | GLGui glgui;
12 | GLLabel fpsLabel;
13 | GLLabel console;
14 | LineWriter consoleWriter;
15 |
16 | int fpsCounter = 0;
17 | int fpsSecond = 1;
18 | double time = 0.0;
19 |
20 | public MainForm() : base(1024, 600, new GraphicsMode(new ColorFormat(8, 8, 8, 8), 24, 0, 4), "GLGUI Example")
21 | {
22 | consoleWriter = new LineWriter();
23 | Console.SetOut(consoleWriter);
24 | Console.SetError(consoleWriter);
25 |
26 | this.Load += OnLoad;
27 | this.Resize += (s, e) => GL.Viewport(ClientSize);
28 | this.RenderFrame += OnRender;
29 | }
30 |
31 | private void OnLoad(object sender, EventArgs e)
32 | {
33 | VSync = VSyncMode.Off; // vsync is nice, but you can't really measure performance while it's on
34 |
35 | glgui = new GLGui(this);
36 |
37 | var mainAreaControl = glgui.Add(new GLGroupLayout(glgui) { Size = new Size(ClientSize.Width, ClientSize.Height - 200), Anchor = GLAnchorStyles.All });
38 | // change background color:
39 | var mainSkin = mainAreaControl.Skin;
40 | mainSkin.BackgroundColor = glgui.Skin.FormActive.BackgroundColor;
41 | mainSkin.BorderColor = glgui.Skin.FormActive.BorderColor;
42 | mainAreaControl.Skin = mainSkin;
43 |
44 | var consoleScrollControl = glgui.Add(new GLScrollableControl(glgui) { Outer = new Rectangle(0, ClientSize.Height - 200, ClientSize.Width, 200), Anchor = GLAnchorStyles.Left | GLAnchorStyles.Right | GLAnchorStyles.Bottom });
45 | console = consoleScrollControl.Add(new GLLabel(glgui) { AutoSize = true, Multiline = true });
46 |
47 | fpsLabel = mainAreaControl.Add(new GLLabel(glgui) { Location = new Point(10, 10), AutoSize = true });
48 | // change font and background color:
49 | var skin = fpsLabel.SkinEnabled;
50 | skin.Font = new GLFont(new Font("Arial", 12.0f));
51 | skin.BackgroundColor = glgui.Skin.TextBoxActive.BackgroundColor;
52 | fpsLabel.SkinEnabled = skin;
53 |
54 | var helloWorldForm = mainAreaControl.Add(new GLForm(glgui) { Title = "Hello World", Outer = new Rectangle(50, 100, 200, 150), AutoSize = false });
55 | helloWorldForm.Add(new GLForm(glgui) { Title = "Hello Form", Outer = new Rectangle(100, 32, 100, 100), AutoSize = false })
56 | .MouseMove += (s, w) => Console.WriteLine(w.Position.ToString());
57 |
58 | var flow = helloWorldForm.Add(new GLFlowLayout(glgui) { FlowDirection = GLFlowDirection.BottomUp, Location = new Point(10, 10), Size = helloWorldForm.InnerSize, AutoSize = true });
59 | for (int i = 0; i < 5; i++)
60 | flow.Add(new GLButton(glgui) { Text = "Button" + i, Size = new Size(150, 0) })
61 | .Click += (s, w) => Console.WriteLine(s + " pressed.");
62 | flow.Add(new GLButton(glgui) { Text = "Hide Cursor", Size = new Size(150, 0) })
63 | .Click += (s, w) => glgui.Cursor = GLCursor.None;
64 |
65 | var loremIpsumForm = mainAreaControl.Add(new GLForm(glgui) { Title = "Lorem Ipsum", Location = new Point(600, 100), Size = new Size(300, 200) });
66 | loremIpsumForm.Add(new GLTextBox(glgui) {
67 | Text = "Lorem ipsum dolor sit amet,\nconsetetur sadipscing elitr,\nsed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,\nsed diam voluptua.\n\nAt vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
68 | Multiline = true,
69 | WordWrap = true,
70 | Outer = new Rectangle(4, 4, loremIpsumForm.Inner.Width - 8, loremIpsumForm.Inner.Height - 8),
71 | Anchor = GLAnchorStyles.All
72 | }).Changed += (s, w) => Console.WriteLine(s + " text length: " + ((GLTextBox)s).Text.Length);
73 |
74 | var fixedSizeForm = mainAreaControl.Add(new GLForm(glgui) { Title = "Fixed size Form", Location = new Point(64, 300), Size = new Size(100, 200), AutoSize = true });
75 | var fooBarFlow = fixedSizeForm.Add(new GLFlowLayout(glgui) { FlowDirection = GLFlowDirection.TopDown, AutoSize = true });
76 | fooBarFlow.Add(new GLCheckBox(glgui) { Text = "CheckBox A", AutoSize = true })
77 | .Changed += (s, w) => Console.WriteLine(s + ": " + ((GLCheckBox)s).Checked);
78 | fooBarFlow.Add(new GLCheckBox(glgui) { Text = "CheckBox B", AutoSize = true })
79 | .Changed += (s, w) => Console.WriteLine(s + ": " + ((GLCheckBox)s).Checked);
80 | fooBarFlow.Add(new GLCheckBox(glgui) { Text = "Totally different CheckBox", AutoSize = true })
81 | .Changed += (s, w) => Console.WriteLine(s + ": " + ((GLCheckBox)s).Checked);
82 | fooBarFlow.Add(new GLCheckBox(glgui) { Text = "Go away!", AutoSize = true })
83 | .Changed += (s, w) => Console.WriteLine(s + ": " + ((GLCheckBox)s).Checked);
84 |
85 | for (int i = 0; i < 3; i++)
86 | {
87 | var viewportForm = mainAreaControl.Add(new GLForm(glgui) { Title = "Cube", Location = new Point(300 + i * 16, 64 + i * 16), Size = new Size(200, 200) });
88 | viewportForm.Add(new GLViewport(glgui) { Size = viewportForm.InnerSize, Anchor = GLAnchorStyles.All })
89 | .RenderViewport += OnRenderViewport;
90 | }
91 | }
92 |
93 | private void OnRender(object sender, FrameEventArgs e)
94 | {
95 | time += e.Time;
96 |
97 | if (time >= fpsSecond)
98 | {
99 | fpsLabel.Text = string.Format("Application: {0:0}FPS. GLGUI: {1:0.0}ms", fpsCounter, glgui.RenderDuration);
100 | fpsCounter = 0;
101 | fpsSecond++;
102 | }
103 |
104 | if (consoleWriter.Changed)
105 | {
106 | console.Text = string.Join("\n", consoleWriter.Lines);
107 | consoleWriter.Changed = false;
108 | }
109 |
110 | glgui.Render();
111 | SwapBuffers();
112 |
113 | fpsCounter++;
114 | }
115 |
116 | // draws a simple colored cube in a GLViewport control
117 | private void OnRenderViewport(object sender, double deltaTime)
118 | {
119 | var viewport = (GLViewport)sender;
120 |
121 | GL.Enable(EnableCap.DepthTest);
122 | GL.ClearColor(0, 0, 0, 1);
123 | GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
124 |
125 | GL.MatrixMode(MatrixMode.Projection);
126 | var proj = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(90.0f), viewport.AspectRatio, 1.0f, 100.0f);
127 | GL.LoadMatrix(ref proj);
128 | GL.MatrixMode(MatrixMode.Modelview);
129 | GL.LoadIdentity();
130 |
131 | GL.Translate(0, 0, -2.0f);
132 | GL.Rotate(time * 100.0f, 1, 0, 0);
133 | GL.Rotate(time * 42.0f, 0, 1, 0);
134 |
135 | GL.Begin(PrimitiveType.Quads);
136 | GL.Color3(1.0, 0.0, 0.0);
137 | GL.Vertex3(0.5, -0.5, -0.5);
138 | GL.Color3(0.0, 1.0, 0.0);
139 | GL.Vertex3(0.5, 0.5, -0.5);
140 | GL.Color3(0.0, 0.0, 1.0);
141 | GL.Vertex3(-0.5, 0.5, -0.5);
142 | GL.Color3(1.0, 0.0, 1.0);
143 | GL.Vertex3(-0.5, -0.5, -0.5);
144 |
145 | GL.Color3(1.0, 1.0, 1.0);
146 | GL.Vertex3(0.5, -0.5, 0.5);
147 | GL.Vertex3(0.5, 0.5, 0.5);
148 | GL.Vertex3(-0.5, 0.5, 0.5);
149 | GL.Vertex3(-0.5, -0.5, 0.5);
150 |
151 | GL.Color3(1.0, 0.0, 1.0);
152 | GL.Vertex3(0.5, -0.5, -0.5);
153 | GL.Vertex3(0.5, 0.5, -0.5);
154 | GL.Vertex3(0.5, 0.5, 0.5);
155 | GL.Vertex3(0.5, -0.5, 0.5);
156 |
157 | GL.Color3(0.0, 1.0, 0.0);
158 | GL.Vertex3(-0.5, -0.5, 0.5);
159 | GL.Vertex3(-0.5, 0.5, 0.5);
160 | GL.Vertex3(-0.5, 0.5, -0.5);
161 | GL.Vertex3(-0.5, -0.5, -0.5);
162 |
163 | GL.Color3(0.0, 0.0, 1.0);
164 | GL.Vertex3(0.5, 0.5, 0.5);
165 | GL.Vertex3(0.5, 0.5, -0.5);
166 | GL.Vertex3(-0.5, 0.5, -0.5);
167 | GL.Vertex3(-0.5, 0.5, 0.5);
168 |
169 | GL.Color3(1.0, 0.0, 0.0);
170 | GL.Vertex3(0.5, -0.5, -0.5);
171 | GL.Vertex3(0.5, -0.5, 0.5);
172 | GL.Vertex3(-0.5, -0.5, 0.5);
173 | GL.Vertex3(-0.5, -0.5, -0.5);
174 | GL.End();
175 |
176 | GL.Disable(EnableCap.DepthTest);
177 | }
178 | }
179 | }
180 |
181 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFontTextNodeList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Text;
4 |
5 | namespace GLGUI
6 | {
7 | ///
8 | /// A doubly linked list of text nodes
9 | ///
10 | class GLFontTextNodeList : IEnumerable
11 | {
12 | public GLFontTextNode Head;
13 | public GLFontTextNode Tail;
14 |
15 | ///
16 | /// Builds a doubly linked list of text nodes from the given input string
17 | ///
18 | ///
19 | public GLFontTextNodeList(string text)
20 | {
21 | bool carriageReturn = false;
22 | bool wordInProgress = false;
23 | StringBuilder currentWord = new StringBuilder();
24 |
25 | for (int i = 0; i < text.Length; i++)
26 | {
27 | if (text[i] == '\r' || text[i] == '\n' || text[i] == ' ' || text[i] == '\t')
28 | {
29 | if (text[i] == '\n' && carriageReturn) //text = text.Replace("\r\n", "\r");
30 | continue;
31 | carriageReturn = false;
32 | if (text[i] == '\r')
33 | carriageReturn = true;
34 |
35 | if (wordInProgress)
36 | {
37 | Add(new GLFontTextNode(GLFontTextNodeType.Word, currentWord.ToString()));
38 | wordInProgress = false;
39 | }
40 |
41 | if (text[i] == '\r' || text[i] == '\n')
42 | Add(new GLFontTextNode(GLFontTextNodeType.LineBreak, null));
43 | else if (text[i] == ' ')
44 | Add(new GLFontTextNode(GLFontTextNodeType.Space, null));
45 | else if (text[i] == '\t')
46 | Add(new GLFontTextNode(GLFontTextNodeType.Tab, null));
47 | }
48 | else
49 | {
50 | carriageReturn = false;
51 | if (!wordInProgress)
52 | {
53 | wordInProgress = true;
54 | currentWord = new StringBuilder();
55 | }
56 | currentWord.Append(text[i]);
57 | }
58 | }
59 |
60 | if (wordInProgress)
61 | Add(new GLFontTextNode(GLFontTextNodeType.Word, currentWord.ToString()));
62 | }
63 |
64 | public void MeasureNodes(GLFontData fontData, GLFontRenderOptions options)
65 | {
66 | bool monospaced = fontData.IsMonospacingActive(options);
67 | float monospaceWidth = fontData.GetMonoSpaceWidth(options);
68 | foreach (GLFontTextNode node in this)
69 | {
70 | if (node.Length == 0f)
71 | {
72 | if (node.Type == GLFontTextNodeType.Space)
73 | {
74 | if (monospaced)
75 | {
76 | node.Length = monospaceWidth;
77 | continue;
78 | }
79 | node.Length = (float)Math.Ceiling(fontData.meanGlyphWidth * options.WordSpacing);
80 | continue;
81 | }
82 |
83 | if (node.Type == GLFontTextNodeType.Tab)
84 | {
85 | if (monospaced)
86 | {
87 | node.Length = monospaceWidth * 4;
88 | continue;
89 | }
90 | node.Length = (float)Math.Ceiling(4 * fontData.meanGlyphWidth * options.WordSpacing);
91 | continue;
92 | }
93 |
94 | if (node.Type == GLFontTextNodeType.Word)
95 | {
96 | for (int i = 0; i < node.Text.Length; i++)
97 | {
98 | char c = node.Text[i];
99 | GLFontGlyph glyph;
100 | if (fontData.CharSetMapping.TryGetValue(c, out glyph))
101 | {
102 | if (monospaced)
103 | node.Length += monospaceWidth;
104 | else
105 | node.Length += (float)Math.Ceiling(glyph.Rect.Width + fontData.meanGlyphWidth * options.CharacterSpacing + fontData.GetKerningPairCorrection(i, node.Text, node));
106 | }
107 | }
108 | }
109 | }
110 | }
111 | }
112 |
113 | ///
114 | /// Splits a word into sub-words of size less than or equal to baseCaseSize
115 | ///
116 | ///
117 | ///
118 | public void Crumble(GLFontTextNode node, int baseCaseSize)
119 | {
120 | if(node.Text.Length <= baseCaseSize)
121 | return;
122 |
123 | var left = SplitNode(node);
124 | var right = left.Next;
125 | Crumble(left, baseCaseSize);
126 | Crumble(right, baseCaseSize);
127 | }
128 |
129 | ///
130 | /// Splits a word node in two, adding both new nodes to the list in sequence.
131 | ///
132 | ///
133 | /// The first new node
134 | public GLFontTextNode SplitNode(GLFontTextNode node)
135 | {
136 | if (node.Type != GLFontTextNodeType.Word)
137 | throw new Exception("Cannot split text node of type: " + node.Type);
138 |
139 | int midPoint = node.Text.Length / 2;
140 |
141 | string newFirstHalf = node.Text.Substring(0, midPoint);
142 | string newSecondHalf = node.Text.Substring(midPoint, node.Text.Length - midPoint);
143 |
144 | GLFontTextNode newFirst = new GLFontTextNode(GLFontTextNodeType.Word, newFirstHalf);
145 | GLFontTextNode newSecond = new GLFontTextNode(GLFontTextNodeType.Word, newSecondHalf);
146 | newFirst.Next = newSecond;
147 | newSecond.Previous = newFirst;
148 |
149 | //node is head
150 | if (node.Previous == null)
151 | Head = newFirst;
152 | else
153 | {
154 | node.Previous.Next = newFirst;
155 | newFirst.Previous = node.Previous;
156 | }
157 |
158 | //node is tail
159 | if (node.Next == null)
160 | Tail = newSecond;
161 | else
162 | {
163 | node.Next.Previous = newSecond;
164 | newSecond.Next = node.Next;
165 | }
166 |
167 | return newFirst;
168 | }
169 |
170 | public void Add(GLFontTextNode node)
171 | {
172 | if(Head == null)
173 | {
174 | Head = Tail = node;
175 | }
176 | else
177 | {
178 | Tail.Next = node;
179 | node.Previous = Tail;
180 | Tail = node;
181 | }
182 | }
183 |
184 | public override string ToString()
185 | {
186 | StringBuilder builder = new StringBuilder();
187 |
188 | foreach(GLFontTextNode node in this)
189 | {
190 | if (node.Type == GLFontTextNodeType.Space)
191 | builder.Append(" ");
192 | else if (node.Type == GLFontTextNodeType.Tab)
193 | builder.Append(" ");
194 | else if (node.Type == GLFontTextNodeType.LineBreak)
195 | builder.Append(System.Environment.NewLine);
196 | else if (node.Type == GLFontTextNodeType.Word)
197 | builder.Append("" + node.Text + "");
198 | }
199 |
200 | return builder.ToString();
201 | }
202 |
203 | public IEnumerator GetEnumerator()
204 | {
205 | return new TextNodeListEnumerator(this);
206 | }
207 |
208 | private class TextNodeListEnumerator : IEnumerator
209 | {
210 | private GLFontTextNode currentNode = null;
211 | private GLFontTextNodeList targetList;
212 |
213 | public TextNodeListEnumerator(GLFontTextNodeList targetList)
214 | {
215 | this.targetList = targetList;
216 | }
217 |
218 | public object Current
219 | {
220 | get { return currentNode; }
221 | }
222 |
223 | public virtual bool MoveNext()
224 | {
225 | if (currentNode == null)
226 | currentNode = targetList.Head;
227 | else
228 | currentNode = currentNode.Next;
229 | return currentNode != null;
230 | }
231 |
232 | public void Reset()
233 | {
234 | currentNode = null;
235 | }
236 | }
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontTextNodeList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Text;
4 |
5 | namespace GLGUI
6 | {
7 | ///
8 | /// A doubly linked list of text nodes
9 | ///
10 | class GLFontTextNodeList : IEnumerable
11 | {
12 | public GLFontTextNode Head;
13 | public GLFontTextNode Tail;
14 |
15 | ///
16 | /// Builds a doubly linked list of text nodes from the given input string
17 | ///
18 | ///
19 | public GLFontTextNodeList(string text)
20 | {
21 | bool carriageReturn = false;
22 | bool wordInProgress = false;
23 | StringBuilder currentWord = new StringBuilder();
24 |
25 | for (int i = 0; i < text.Length; i++)
26 | {
27 | if (text[i] == '\r' || text[i] == '\n' || text[i] == ' ' || text[i] == '\t')
28 | {
29 | if (text[i] == '\n' && carriageReturn) //text = text.Replace("\r\n", "\r");
30 | continue;
31 | carriageReturn = false;
32 | if (text[i] == '\r')
33 | carriageReturn = true;
34 |
35 | if (wordInProgress)
36 | {
37 | Add(new GLFontTextNode(GLFontTextNodeType.Word, currentWord.ToString()));
38 | wordInProgress = false;
39 | }
40 |
41 | if (text[i] == '\r' || text[i] == '\n')
42 | Add(new GLFontTextNode(GLFontTextNodeType.LineBreak, null));
43 | else if (text[i] == ' ')
44 | Add(new GLFontTextNode(GLFontTextNodeType.Space, null));
45 | else if (text[i] == '\t')
46 | Add(new GLFontTextNode(GLFontTextNodeType.Tab, null));
47 | }
48 | else
49 | {
50 | carriageReturn = false;
51 | if (!wordInProgress)
52 | {
53 | wordInProgress = true;
54 | currentWord = new StringBuilder();
55 | }
56 | currentWord.Append(text[i]);
57 | }
58 | }
59 |
60 | if (wordInProgress)
61 | Add(new GLFontTextNode(GLFontTextNodeType.Word, currentWord.ToString()));
62 | }
63 |
64 | public void MeasureNodes(GLFontData fontData, GLFontRenderOptions options)
65 | {
66 | bool monospaced = fontData.IsMonospacingActive(options);
67 | float monospaceWidth = fontData.GetMonoSpaceWidth(options);
68 | foreach (GLFontTextNode node in this)
69 | {
70 | if (node.Length == 0f)
71 | {
72 | if (node.Type == GLFontTextNodeType.Space)
73 | {
74 | if (monospaced)
75 | {
76 | node.Length = monospaceWidth;
77 | continue;
78 | }
79 | node.Length = (float)Math.Ceiling(fontData.meanGlyphWidth * options.WordSpacing);
80 | continue;
81 | }
82 |
83 | if (node.Type == GLFontTextNodeType.Tab)
84 | {
85 | if (monospaced)
86 | {
87 | node.Length = monospaceWidth * 4;
88 | continue;
89 | }
90 | node.Length = (float)Math.Ceiling(4 * fontData.meanGlyphWidth * options.WordSpacing);
91 | continue;
92 | }
93 |
94 | if (node.Type == GLFontTextNodeType.Word)
95 | {
96 | for (int i = 0; i < node.Text.Length; i++)
97 | {
98 | char c = node.Text[i];
99 | GLFontGlyph glyph;
100 | if (fontData.CharSetMapping.TryGetValue(c, out glyph))
101 | {
102 | if (monospaced)
103 | node.Length += monospaceWidth;
104 | else
105 | node.Length += (float)Math.Ceiling(glyph.Rect.Width + fontData.meanGlyphWidth * options.CharacterSpacing + fontData.GetKerningPairCorrection(i, node.Text, node));
106 | }
107 | }
108 | }
109 | }
110 | }
111 | }
112 |
113 | ///
114 | /// Splits a word into sub-words of size less than or equal to baseCaseSize
115 | ///
116 | ///
117 | ///
118 | public void Crumble(GLFontTextNode node, int baseCaseSize)
119 | {
120 | if(node.Text.Length <= baseCaseSize)
121 | return;
122 |
123 | var left = SplitNode(node);
124 | var right = left.Next;
125 | Crumble(left, baseCaseSize);
126 | Crumble(right, baseCaseSize);
127 | }
128 |
129 | ///
130 | /// Splits a word node in two, adding both new nodes to the list in sequence.
131 | ///
132 | ///
133 | /// The first new node
134 | public GLFontTextNode SplitNode(GLFontTextNode node)
135 | {
136 | if (node.Type != GLFontTextNodeType.Word)
137 | throw new Exception("Cannot split text node of type: " + node.Type);
138 |
139 | int midPoint = node.Text.Length / 2;
140 |
141 | string newFirstHalf = node.Text.Substring(0, midPoint);
142 | string newSecondHalf = node.Text.Substring(midPoint, node.Text.Length - midPoint);
143 |
144 | GLFontTextNode newFirst = new GLFontTextNode(GLFontTextNodeType.Word, newFirstHalf);
145 | GLFontTextNode newSecond = new GLFontTextNode(GLFontTextNodeType.Word, newSecondHalf);
146 | newFirst.Next = newSecond;
147 | newSecond.Previous = newFirst;
148 |
149 | //node is head
150 | if (node.Previous == null)
151 | Head = newFirst;
152 | else
153 | {
154 | node.Previous.Next = newFirst;
155 | newFirst.Previous = node.Previous;
156 | }
157 |
158 | //node is tail
159 | if (node.Next == null)
160 | Tail = newSecond;
161 | else
162 | {
163 | node.Next.Previous = newSecond;
164 | newSecond.Next = node.Next;
165 | }
166 |
167 | return newFirst;
168 | }
169 |
170 | public void Add(GLFontTextNode node)
171 | {
172 | if(Head == null)
173 | {
174 | Head = Tail = node;
175 | }
176 | else
177 | {
178 | Tail.Next = node;
179 | node.Previous = Tail;
180 | Tail = node;
181 | }
182 | }
183 |
184 | public override string ToString()
185 | {
186 | StringBuilder builder = new StringBuilder();
187 |
188 | foreach(GLFontTextNode node in this)
189 | {
190 | if (node.Type == GLFontTextNodeType.Space)
191 | builder.Append(" ");
192 | else if (node.Type == GLFontTextNodeType.Tab)
193 | builder.Append(" ");
194 | else if (node.Type == GLFontTextNodeType.LineBreak)
195 | builder.Append(System.Environment.NewLine);
196 | else if (node.Type == GLFontTextNodeType.Word)
197 | builder.Append("" + node.Text + "");
198 | }
199 |
200 | return builder.ToString();
201 | }
202 |
203 | public IEnumerator GetEnumerator()
204 | {
205 | return new TextNodeListEnumerator(this);
206 | }
207 |
208 | private class TextNodeListEnumerator : IEnumerator
209 | {
210 | private GLFontTextNode currentNode = null;
211 | private GLFontTextNodeList targetList;
212 |
213 | public TextNodeListEnumerator(GLFontTextNodeList targetList)
214 | {
215 | this.targetList = targetList;
216 | }
217 |
218 | public object Current
219 | {
220 | get { return currentNode; }
221 | }
222 |
223 | public virtual bool MoveNext()
224 | {
225 | if (currentNode == null)
226 | currentNode = targetList.Head;
227 | else
228 | currentNode = currentNode.Next;
229 | return currentNode != null;
230 | }
231 |
232 | public void Reset()
233 | {
234 | currentNode = null;
235 | }
236 | }
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI.GLControlExample/GuiControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using OpenTK;
4 | using OpenTK.Graphics;
5 | using OpenTK.Graphics.OpenGL;
6 | using System.Windows.Forms;
7 | using System.Diagnostics;
8 |
9 | namespace GLGUI.GLControlExample
10 | {
11 | public class GuiControl : OpenTK.GLControl
12 | {
13 | GLGui glgui;
14 | GLLabel fpsLabel;
15 | GLLabel console;
16 | LineWriter consoleWriter;
17 |
18 | Stopwatch stopwatch;
19 | int fpsCounter = 0;
20 | int fpsSecond = 1;
21 | double time = 0.0;
22 |
23 | public GuiControl() : base(new GraphicsMode(new ColorFormat(8, 8, 8, 8), 24, 0, 4))
24 | {
25 | consoleWriter = new LineWriter();
26 | Console.SetOut(consoleWriter);
27 | Console.SetError(consoleWriter);
28 |
29 | this.Load += OnLoad;
30 | }
31 |
32 | private void OnLoad(object sender, EventArgs e)
33 | {
34 | VSync = false; // vsync is nice, but you can't really measure performance while it's on
35 |
36 | glgui = new GLGui(this);
37 |
38 | var mainAreaControl = glgui.Add(new GLGroupLayout(glgui) { Size = new Size(ClientSize.Width, ClientSize.Height - 200), Anchor = GLAnchorStyles.All });
39 | // change background color:
40 | var mainSkin = mainAreaControl.Skin;
41 | mainSkin.BackgroundColor = glgui.Skin.FormActive.BackgroundColor;
42 | mainSkin.BorderColor = glgui.Skin.FormActive.BorderColor;
43 | mainAreaControl.Skin = mainSkin;
44 |
45 | var consoleScrollControl = glgui.Add(new GLScrollableControl(glgui) { Outer = new Rectangle(0, ClientSize.Height - 200, ClientSize.Width, 200), Anchor = GLAnchorStyles.Left | GLAnchorStyles.Right | GLAnchorStyles.Bottom });
46 | console = consoleScrollControl.Add(new GLLabel(glgui) { AutoSize = true, Multiline = true });
47 |
48 | fpsLabel = mainAreaControl.Add(new GLLabel(glgui) { Location = new Point(10, 10), AutoSize = true });
49 | // change font and background color:
50 | var skin = fpsLabel.SkinEnabled;
51 | skin.Font = new GLFont(new Font("Arial", 12.0f));
52 | skin.BackgroundColor = glgui.Skin.TextBoxActive.BackgroundColor;
53 | fpsLabel.SkinEnabled = skin;
54 |
55 | var helloWorldForm = mainAreaControl.Add(new GLForm(glgui) { Title = "Hello World", Outer = new Rectangle(50, 100, 200, 150), AutoSize = false });
56 | helloWorldForm.Add(new GLForm(glgui) { Title = "Hello Form", Outer = new Rectangle(100, 32, 100, 100), AutoSize = false })
57 | .MouseMove += (s, w) => Console.WriteLine(w.Position.ToString());
58 |
59 | var flow = helloWorldForm.Add(new GLFlowLayout(glgui) { FlowDirection = GLFlowDirection.BottomUp, Location = new Point(10, 10), Size = helloWorldForm.InnerSize, AutoSize = true });
60 | for (int i = 0; i < 5; i++)
61 | flow.Add(new GLButton(glgui) { Text = "Button" + i, Size = new Size(150, 0) })
62 | .Click += (s, w) => Console.WriteLine(s + " pressed.");
63 | flow.Add(new GLButton(glgui) { Text = "Hide Cursor", Size = new Size(150, 0) })
64 | .Click += (s, w) => glgui.Cursor = GLCursor.None;
65 |
66 | var loremIpsumForm = mainAreaControl.Add(new GLForm(glgui) { Title = "Lorem Ipsum", Location = new Point(600, 100), Size = new Size(300, 200) });
67 | loremIpsumForm.Add(new GLTextBox(glgui) {
68 | Text = "Lorem ipsum dolor sit amet,\nconsetetur sadipscing elitr,\nsed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,\nsed diam voluptua.\n\nAt vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
69 | Multiline = true,
70 | WordWrap = true,
71 | Outer = new Rectangle(4, 4, loremIpsumForm.Inner.Width - 8, loremIpsumForm.Inner.Height - 8),
72 | Anchor = GLAnchorStyles.All
73 | }).Changed += (s, w) => Console.WriteLine(s + " text length: " + ((GLTextBox)s).Text.Length);
74 |
75 | var fixedSizeForm = mainAreaControl.Add(new GLForm(glgui) { Title = "Fixed size Form", Location = new Point(64, 300), Size = new Size(100, 200), AutoSize = true });
76 | var fooBarFlow = fixedSizeForm.Add(new GLFlowLayout(glgui) { FlowDirection = GLFlowDirection.TopDown, AutoSize = true });
77 | fooBarFlow.Add(new GLCheckBox(glgui) { Text = "CheckBox A", AutoSize = true })
78 | .Changed += (s, w) => Console.WriteLine(s + ": " + ((GLCheckBox)s).Checked);
79 | fooBarFlow.Add(new GLCheckBox(glgui) { Text = "CheckBox B", AutoSize = true })
80 | .Changed += (s, w) => Console.WriteLine(s + ": " + ((GLCheckBox)s).Checked);
81 | fooBarFlow.Add(new GLCheckBox(glgui) { Text = "Totally different CheckBox", AutoSize = true })
82 | .Changed += (s, w) => Console.WriteLine(s + ": " + ((GLCheckBox)s).Checked);
83 | fooBarFlow.Add(new GLCheckBox(glgui) { Text = "Go away!", AutoSize = true })
84 | .Changed += (s, w) => Console.WriteLine(s + ": " + ((GLCheckBox)s).Checked);
85 |
86 | for (int i = 0; i < 3; i++)
87 | {
88 | var viewportForm = mainAreaControl.Add(new GLForm(glgui) { Title = "Cube", Location = new Point(300 + i * 16, 64 + i * 16), Size = new Size(200, 200) });
89 | viewportForm.Add(new GLViewport(glgui) { Size = viewportForm.InnerSize, Anchor = GLAnchorStyles.All })
90 | .RenderViewport += OnRenderViewport;
91 | }
92 |
93 | stopwatch = new Stopwatch();
94 | Resize += (s, ev) => GL.Viewport(ClientSize);
95 | Paint += OnRender;
96 |
97 | stopwatch.Start();
98 | Application.Idle += (s, ev) => Invalidate();
99 | }
100 |
101 | private void OnRender(object sender, PaintEventArgs e)
102 | {
103 | stopwatch.Stop();
104 | double delta = stopwatch.Elapsed.TotalMilliseconds * 0.001;
105 | stopwatch.Restart();
106 | time += delta;
107 |
108 | if (time >= fpsSecond)
109 | {
110 | fpsLabel.Text = string.Format("Application: {0:0}FPS. GLGUI: {1:0.0}ms", fpsCounter, glgui.RenderDuration);
111 | fpsCounter = 0;
112 | fpsSecond++;
113 | }
114 |
115 | if (consoleWriter.Changed)
116 | {
117 | console.Text = string.Join("\n", consoleWriter.Lines);
118 | consoleWriter.Changed = false;
119 | }
120 |
121 | glgui.Render();
122 | SwapBuffers();
123 |
124 | fpsCounter++;
125 | }
126 |
127 | // draws a simple colored cube in a GLViewport control
128 | private void OnRenderViewport(object sender, double deltaTime)
129 | {
130 | var viewport = (GLViewport)sender;
131 |
132 | GL.Enable(EnableCap.DepthTest);
133 | GL.ClearColor(0, 0, 0, 1);
134 | GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
135 |
136 | GL.MatrixMode(MatrixMode.Projection);
137 | var proj = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(90.0f), viewport.AspectRatio, 1.0f, 100.0f);
138 | GL.LoadMatrix(ref proj);
139 | GL.MatrixMode(MatrixMode.Modelview);
140 | GL.LoadIdentity();
141 |
142 | GL.Translate(0, 0, -2.0f);
143 | GL.Rotate(time * 100.0f, 1, 0, 0);
144 | GL.Rotate(time * 42.0f, 0, 1, 0);
145 |
146 | GL.Begin(PrimitiveType.Quads);
147 | GL.Color3(1.0, 0.0, 0.0);
148 | GL.Vertex3(0.5, -0.5, -0.5);
149 | GL.Color3(0.0, 1.0, 0.0);
150 | GL.Vertex3(0.5, 0.5, -0.5);
151 | GL.Color3(0.0, 0.0, 1.0);
152 | GL.Vertex3(-0.5, 0.5, -0.5);
153 | GL.Color3(1.0, 0.0, 1.0);
154 | GL.Vertex3(-0.5, -0.5, -0.5);
155 |
156 | GL.Color3(1.0, 1.0, 1.0);
157 | GL.Vertex3(0.5, -0.5, 0.5);
158 | GL.Vertex3(0.5, 0.5, 0.5);
159 | GL.Vertex3(-0.5, 0.5, 0.5);
160 | GL.Vertex3(-0.5, -0.5, 0.5);
161 |
162 | GL.Color3(1.0, 0.0, 1.0);
163 | GL.Vertex3(0.5, -0.5, -0.5);
164 | GL.Vertex3(0.5, 0.5, -0.5);
165 | GL.Vertex3(0.5, 0.5, 0.5);
166 | GL.Vertex3(0.5, -0.5, 0.5);
167 |
168 | GL.Color3(0.0, 1.0, 0.0);
169 | GL.Vertex3(-0.5, -0.5, 0.5);
170 | GL.Vertex3(-0.5, 0.5, 0.5);
171 | GL.Vertex3(-0.5, 0.5, -0.5);
172 | GL.Vertex3(-0.5, -0.5, -0.5);
173 |
174 | GL.Color3(0.0, 0.0, 1.0);
175 | GL.Vertex3(0.5, 0.5, 0.5);
176 | GL.Vertex3(0.5, 0.5, -0.5);
177 | GL.Vertex3(-0.5, 0.5, -0.5);
178 | GL.Vertex3(-0.5, 0.5, 0.5);
179 |
180 | GL.Color3(1.0, 0.0, 0.0);
181 | GL.Vertex3(0.5, -0.5, -0.5);
182 | GL.Vertex3(0.5, -0.5, 0.5);
183 | GL.Vertex3(-0.5, -0.5, 0.5);
184 | GL.Vertex3(-0.5, -0.5, -0.5);
185 | GL.End();
186 |
187 | GL.Disable(EnableCap.DepthTest);
188 | }
189 |
190 | protected override bool IsInputKey(Keys key)
191 | {
192 | return true;
193 | }
194 | }
195 | }
196 |
197 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Linq;
4 | using OpenTK.Input;
5 |
6 | namespace GLGUI
7 | {
8 | public class GLForm : GLControl
9 | {
10 | public string Title { get { return title; } set { if (value != title) { title = value; Invalidate(); } } }
11 | public bool Maximized { get { return maximized; } set { Maximize(value); } }
12 | public GLSkin.GLFormSkin SkinActive { get { return skinActive; } set { skinActive = value; Invalidate(); } }
13 | public GLSkin.GLFormSkin SkinInactive { get { return skinInactive; } set { skinInactive = value; Invalidate(); } }
14 |
15 | private string title = "";
16 | private GLFontText titleProcessed = new GLFontText();
17 | private GLSkin.GLFormSkin skinActive, skinInactive;
18 | private GLSkin.GLFormSkin skin;
19 | private enum DragOperation { Move = 0, ResizeNW, ResizeN, ResizeNE, ResizeE, ResizeSE, ResizeS, ResizeSW, ResizeW }
20 | private DragOperation dragOp;
21 | private Rectangle moveClickRegion;
22 | private Point mouseOffset;
23 | private SizeF titleSize;
24 | private int minHeight;
25 | private DateTime lastClick;
26 |
27 | private static GLCursor[] dragOpCursors = new GLCursor[]
28 | {
29 | GLCursor.SizeAll,
30 | GLCursor.SizeNWSE, GLCursor.SizeNS, GLCursor.SizeNESW, GLCursor.SizeWE,
31 | GLCursor.SizeNWSE, GLCursor.SizeNS, GLCursor.SizeNESW, GLCursor.SizeWE
32 | };
33 |
34 | public GLForm(GLGui gui) : base(gui)
35 | {
36 | Render += OnRender;
37 | MouseDown += OnMouseDown;
38 | MouseUp += OnMouseUp;
39 | MouseMove += OnMouseMove;
40 | MouseLeave += OnMouseLeave;
41 | //MouseDoubleClick += OnMouseDoubleClick;
42 | Focus += (s, e) => Invalidate();
43 | FocusLost += (s, e) => Invalidate();
44 |
45 | skinActive = Gui.Skin.FormActive;
46 | skinInactive = Gui.Skin.FormInactive;
47 |
48 | outer = new Rectangle(0, 0, 100, 100);
49 | sizeMin = new Size(64, 32);
50 | sizeMax = new Size(int.MaxValue, int.MaxValue);
51 | }
52 |
53 | protected override void UpdateLayout()
54 | {
55 | skin = HasFocus ? skinActive : skinInactive;
56 |
57 | if (AutoSize)
58 | {
59 | if (Controls.Count() > 0)
60 | {
61 | outer.Width = Controls.Max(c => c.Outer.Right) + skin.Border.Horizontal;
62 | outer.Height = Controls.Max(c => c.Outer.Bottom) + skin.Border.Vertical + (int)titleSize.Height + skin.Border.Top;
63 | }
64 | else
65 | {
66 | outer.Width = 0;
67 | outer.Height = 0;
68 | }
69 | }
70 |
71 | outer.Width = Math.Min(Math.Max(outer.Width, sizeMin.Width), sizeMax.Width);
72 |
73 | int innerWidth = outer.Width - skin.Border.Horizontal;
74 | titleSize = skin.Font.ProcessText(titleProcessed, title, GLFontAlignment.Left);
75 | minHeight = Math.Max(sizeMin.Height, (int)titleSize.Height + skin.Border.Vertical + skin.Border.Top);
76 |
77 | outer.Height = Math.Min(Math.Max(outer.Height, minHeight), sizeMax.Height);
78 | if (Parent != null)
79 | {
80 | outer.X = Math.Max(Math.Min(outer.X, Parent.Inner.Width - outer.Width), 0);
81 | outer.Y = Math.Max(Math.Min(outer.Y, Parent.Inner.Height - outer.Height), 0);
82 | outer.Width = Math.Min(outer.Right, Parent.Inner.Width) - outer.X;
83 | outer.Height = Math.Min(outer.Bottom, Parent.Inner.Height) - outer.Y;
84 | }
85 |
86 | Inner = new Rectangle(
87 | skin.Border.Left, skin.Border.Top + (int)titleSize.Height + skin.Border.Top,
88 | innerWidth, outer.Height - skin.Border.Vertical - (int)titleSize.Height - skin.Border.Top);
89 | moveClickRegion = new Rectangle(skin.Border.Left, skin.Border.Top, Inner.Width, (int)titleSize.Height);
90 | }
91 |
92 | private void OnRender(object sender, double timeDelta)
93 | {
94 | GLDraw.Fill(ref skin.BorderColor);
95 | GLDraw.FillRect(Inner, ref skin.BackgroundColor);
96 | GLDraw.Text(titleProcessed, ref moveClickRegion, ref skin.Color);
97 | }
98 |
99 | private void StartDragOperation(DragOperation op, Point p)
100 | {
101 | if ((AutoSize || maximized) && op != DragOperation.Move)
102 | return;
103 |
104 | mouseOffset = p;
105 | isDragged = true;
106 | dragOp = op;
107 | Gui.Cursor = dragOpCursors[(int)op];
108 | }
109 |
110 | private void OnMouseDown(object sender, MouseButtonEventArgs e)
111 | {
112 | if (e.Button == MouseButton.Left)
113 | {
114 | if (moveClickRegion.Contains(e.Position))
115 | StartDragOperation (DragOperation.Move, e.Position);
116 | else if(e.X < skin.Border.Left)
117 | {
118 | if (e.Y < skin.Border.Top)
119 | StartDragOperation (DragOperation.ResizeNW, e.Position);
120 | else if (e.Y >= outer.Height - skin.Border.Bottom)
121 | StartDragOperation (DragOperation.ResizeSW, e.Position);
122 | else
123 | StartDragOperation (DragOperation.ResizeW, e.Position);
124 | }
125 | else if (e.X >= outer.Width - skin.Border.Right)
126 | {
127 | if (e.Y < skin.Border.Top)
128 | StartDragOperation (DragOperation.ResizeNE, e.Position);
129 | else if (e.Y >= outer.Height - skin.Border.Bottom)
130 | StartDragOperation (DragOperation.ResizeSE, e.Position);
131 | else
132 | StartDragOperation (DragOperation.ResizeE, e.Position);
133 | }
134 | else if (e.Y < skin.Border.Top)
135 | StartDragOperation (DragOperation.ResizeN, e.Position);
136 | else if (e.Y >= outer.Height - skin.Border.Bottom)
137 | StartDragOperation (DragOperation.ResizeS, e.Position);
138 | }
139 |
140 | justDoubleClicked = false;
141 | }
142 |
143 | private void OnMouseUp(object sender, MouseButtonEventArgs e)
144 | {
145 | if (e.Button == MouseButton.Left)
146 | {
147 | if (isDragged)
148 | {
149 | isDragged = false;
150 | Gui.Cursor = GLCursor.Default;
151 | }
152 | var now = DateTime.Now;
153 | if ((now - lastClick).TotalMilliseconds < 500.0)
154 | OnMouseDoubleClick(this, e);
155 | lastClick = now;
156 | }
157 | }
158 |
159 | private void OnMouseMove(object sender, MouseEventArgs e)
160 | {
161 | if (isDragged)
162 | {
163 | Point p = e.Position;
164 | if (Parent != null)
165 | {
166 | p.X = Math.Min(Math.Max(p.X + outer.X, 0), Parent.Inner.Width) - outer.X;
167 | p.Y = Math.Min(Math.Max(p.Y + outer.Y, 0), Parent.Inner.Height) - outer.Y;
168 | }
169 | int dx = p.X - mouseOffset.X;
170 | int dy = p.Y - mouseOffset.Y;
171 | switch (dragOp)
172 | {
173 | case DragOperation.Move:
174 | if (maximized && !justDoubleClicked)
175 | {
176 | if (Math.Max(dx, dy) > 16)
177 | {
178 | mouseOffset.X = restoreOuter.Width / 2;
179 | Maximize(false);
180 | }
181 | }
182 | else
183 | Outer = new Rectangle(outer.X + dx, outer.Y + dy, outer.Width, outer.Height);
184 | return;
185 | case DragOperation.ResizeNW:
186 | dx = outer.Width - Math.Min(Math.Max(outer.Width - dx, sizeMin.Width), sizeMax.Width);
187 | dy = outer.Height - Math.Min(Math.Max(outer.Height - dy, minHeight), sizeMax.Height);
188 | Outer = new Rectangle(outer.X + dx, outer.Y + dy, outer.Width - dx, outer.Height - dy);
189 | return;
190 | case DragOperation.ResizeN:
191 | dy = outer.Height - Math.Min(Math.Max(outer.Height - dy, minHeight), sizeMax.Height);
192 | Outer = new Rectangle(outer.X, outer.Y + dy, outer.Width, outer.Height - dy);
193 | return;
194 | case DragOperation.ResizeNE:
195 | dx = Math.Min(Math.Max(p.X, sizeMin.Width), sizeMax.Width);
196 | dy = outer.Height - Math.Min(Math.Max(outer.Height - dy, minHeight), sizeMax.Height);
197 | Outer = new Rectangle(outer.X, outer.Y + dy, dx, outer.Height - dy);
198 | return;
199 | case DragOperation.ResizeE:
200 | dx = Math.Min(Math.Max(p.X, sizeMin.Width), sizeMax.Width);
201 | Outer = new Rectangle(outer.X, outer.Y, dx, outer.Height);
202 | return;
203 | case DragOperation.ResizeSE:
204 | dx = Math.Min(Math.Max(p.X, sizeMin.Width), sizeMax.Width);
205 | dy = Math.Min(Math.Max(p.Y, minHeight), sizeMax.Height);
206 | Outer = new Rectangle(outer.X, outer.Y, dx, dy);
207 | return;
208 | case DragOperation.ResizeS:
209 | dy = Math.Min(Math.Max(p.Y, minHeight), sizeMax.Height);
210 | Outer = new Rectangle(outer.X, outer.Y, outer.Width, dy);
211 | return;
212 | case DragOperation.ResizeSW:
213 | dx = outer.Width - Math.Min(Math.Max(outer.Width - dx, sizeMin.Width), sizeMax.Width);
214 | dy = Math.Min(Math.Max(p.Y, minHeight), sizeMax.Height);
215 | Outer = new Rectangle(outer.X + dx, outer.Y, outer.Width - dx, dy);
216 | return;
217 | case DragOperation.ResizeW:
218 | dx = outer.Width - Math.Min(Math.Max(outer.Width - dx, sizeMin.Width), sizeMax.Width);
219 | Outer = new Rectangle(outer.X + dx, outer.Y, outer.Width - dx, outer.Height);
220 | return;
221 | }
222 | }
223 |
224 | if (!AutoSize && !maximized)
225 | {
226 | if (e.X < skin.Border.Left)
227 | {
228 | if (e.Y < skin.Border.Top)
229 | Gui.Cursor = GLCursor.SizeNWSE;
230 | else if (e.Y >= outer.Height - skin.Border.Bottom)
231 | Gui.Cursor = GLCursor.SizeNESW;
232 | else
233 | Gui.Cursor = GLCursor.SizeWE;
234 | }
235 | else if (e.X >= Outer.Width - skin.Border.Right)
236 | {
237 | if (e.Y < skin.Border.Top)
238 | Gui.Cursor = GLCursor.SizeNESW;
239 | else if (e.Y >= outer.Height - skin.Border.Bottom)
240 | Gui.Cursor = GLCursor.SizeNWSE;
241 | else
242 | Gui.Cursor = GLCursor.SizeWE;
243 | }
244 | else if (e.Y < skin.Border.Top || e.Y >= outer.Height - skin.Border.Bottom)
245 | Gui.Cursor = GLCursor.SizeNS;
246 | else
247 | Gui.Cursor = GLCursor.Default;
248 | }
249 | }
250 |
251 | private void OnMouseLeave(object sender, EventArgs e)
252 | {
253 | Gui.Cursor = GLCursor.Default;
254 | }
255 |
256 | private bool justDoubleClicked = false;
257 | private bool maximized = false;
258 | private Rectangle restoreOuter;
259 | private GLAnchorStyles restoreAnchor;
260 | private void Maximize(bool maximize)
261 | {
262 | if (maximized == maximize)
263 | return;
264 | if (!maximize) // restore
265 | {
266 | maximized = false;
267 | anchor = restoreAnchor;
268 | outer = restoreOuter;
269 | Invalidate();
270 | }
271 | else // maximize
272 | {
273 | maximized = true;
274 | restoreOuter = outer;
275 | restoreAnchor = anchor;
276 | outer = Parent.Inner;
277 | anchor = GLAnchorStyles.Left | GLAnchorStyles.Top | GLAnchorStyles.Right | GLAnchorStyles.Bottom;
278 | Invalidate();
279 | }
280 | }
281 |
282 | private void OnMouseDoubleClick(object sender, MouseEventArgs e)
283 | {
284 | if (!AutoSize && Parent != null && moveClickRegion.Contains(e.Position))
285 | Maximize(!maximized);
286 |
287 | Gui.Cursor = GLCursor.Default; // hack to avoid move operation cursor
288 | justDoubleClicked = true;
289 | }
290 | }
291 | }
292 |
293 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLFont/GLFontBitmap.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Drawing.Imaging;
4 |
5 | namespace GLGUI
6 | {
7 | public class GLFontBitmap
8 | {
9 | public Bitmap bitmap;
10 | public BitmapData bitmapData;
11 |
12 | public GLFontBitmap(string filePath)
13 | {
14 | bitmap = new Bitmap(filePath);
15 | bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
16 | }
17 |
18 | public GLFontBitmap(Bitmap bitmap)
19 | {
20 | this.bitmap = bitmap;
21 | bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
22 | }
23 |
24 | public void Clear32(byte r, byte g, byte b, byte a)
25 | {
26 | unsafe
27 | {
28 | byte* sourcePtr = (byte*)(bitmapData.Scan0);
29 |
30 | for (int i = 0; i < bitmapData.Height; i++)
31 | {
32 | for (int j = 0; j < bitmapData.Width; j++)
33 | {
34 | *(sourcePtr) = b;
35 | *(sourcePtr + 1) = g;
36 | *(sourcePtr + 2) = r;
37 | *(sourcePtr + 3) = a;
38 |
39 | sourcePtr += 4;
40 | }
41 | sourcePtr += bitmapData.Stride - bitmapData.Width * 4; //move to the end of the line (past unused space)
42 | }
43 | }
44 | }
45 |
46 | ///
47 | /// Returns try if the given pixel is empty (i.e. black)
48 | ///
49 | public static unsafe bool EmptyPixel(BitmapData bitmapData, int px, int py)
50 | {
51 | byte* addr = (byte*)(bitmapData.Scan0) + bitmapData.Stride * py + px * 3;
52 | return (*addr == 0 && *(addr + 1) == 0 && *(addr + 2) == 0);
53 | }
54 |
55 | ///
56 | /// Returns try if the given pixel is empty (i.e. alpha is zero)
57 | ///
58 | public static unsafe bool EmptyAlphaPixel(BitmapData bitmapData, int px, int py, byte alphaEmptyPixelTolerance)
59 | {
60 | byte* addr = (byte*)(bitmapData.Scan0) + bitmapData.Stride * py + px * 4;
61 | return (*(addr + 3) <= alphaEmptyPixelTolerance);
62 | }
63 |
64 | ///
65 | /// Blits a block of a bitmap data from source to destination, using the luminance of the source to determine the
66 | /// alpha of the target. Source must be 24-bit, target must be 32-bit.
67 | ///
68 | public static void BlitMask(BitmapData source, BitmapData target, int srcPx, int srcPy, int srcW, int srcH, int px, int py)
69 | {
70 | int sourceBpp = 3;
71 | int targetBpp = 4;
72 |
73 | int targetStartX, targetEndX;
74 | int targetStartY, targetEndY;
75 | int copyW, copyH;
76 |
77 | targetStartX = Math.Max(px, 0);
78 | targetEndX = Math.Min(px + srcW, target.Width);
79 |
80 | targetStartY = Math.Max(py, 0);
81 | targetEndY = Math.Min(py + srcH, target.Height);
82 |
83 | copyW = targetEndX - targetStartX;
84 | copyH = targetEndY - targetStartY;
85 |
86 | if (copyW < 0)
87 | {
88 | return;
89 | }
90 |
91 | if (copyH < 0)
92 | {
93 | return;
94 | }
95 |
96 | int sourceStartX = srcPx + targetStartX - px;
97 | int sourceStartY = srcPy + targetStartY - py;
98 |
99 | unsafe
100 | {
101 | byte* sourcePtr = (byte*)(source.Scan0);
102 | byte* targetPtr = (byte*)(target.Scan0);
103 |
104 |
105 | byte* targetY = targetPtr + targetStartY * target.Stride;
106 | byte* sourceY = sourcePtr + sourceStartY * source.Stride;
107 | for (int y = 0; y < copyH; y++, targetY += target.Stride, sourceY += source.Stride)
108 | {
109 |
110 | byte* targetOffset = targetY + targetStartX * targetBpp;
111 | byte* sourceOffset = sourceY + sourceStartX * sourceBpp;
112 | for (int x = 0; x < copyW; x++, targetOffset += targetBpp, sourceOffset += sourceBpp)
113 | {
114 | int lume = *(sourceOffset) + *(sourceOffset + 1) + *(sourceOffset + 2);
115 |
116 | lume /= 3;
117 |
118 | if (lume > 255)
119 | lume = 255;
120 |
121 | *(targetOffset + 3) = (byte)lume;
122 |
123 | }
124 |
125 | }
126 | }
127 | }
128 |
129 | ///
130 | /// Blits from source to target. Both source and target must be 32-bit
131 | ///
132 | public static void Blit(BitmapData source, BitmapData target, Rectangle sourceRect, int px, int py)
133 | {
134 | Blit(source, target, sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height, px, py);
135 | }
136 |
137 | ///
138 | /// Blits from source to target. Both source and target must be 32-bit
139 | ///
140 | public static void Blit(BitmapData source, BitmapData target, int srcPx, int srcPy, int srcW, int srcH, int destX, int destY)
141 | {
142 | int bpp = 4;
143 |
144 | int targetStartX, targetEndX;
145 | int targetStartY, targetEndY;
146 | int copyW, copyH;
147 |
148 | targetStartX = Math.Max(destX, 0);
149 | targetEndX = Math.Min(destX + srcW, target.Width);
150 |
151 | targetStartY = Math.Max(destY, 0);
152 | targetEndY = Math.Min(destY + srcH, target.Height);
153 |
154 | copyW = targetEndX - targetStartX;
155 | copyH = targetEndY - targetStartY;
156 |
157 | if (copyW < 0)
158 | {
159 | return;
160 | }
161 |
162 | if (copyH < 0)
163 | {
164 | return;
165 | }
166 |
167 | int sourceStartX = srcPx + targetStartX - destX;
168 | int sourceStartY = srcPy + targetStartY - destY;
169 |
170 | unsafe
171 | {
172 | byte* sourcePtr = (byte*)(source.Scan0);
173 | byte* targetPtr = (byte*)(target.Scan0);
174 |
175 |
176 | byte* targetY = targetPtr + targetStartY * target.Stride;
177 | byte* sourceY = sourcePtr + sourceStartY * source.Stride;
178 | for (int y = 0; y < copyH; y++, targetY += target.Stride, sourceY += source.Stride)
179 | {
180 |
181 | byte* targetOffset = targetY + targetStartX * bpp;
182 | byte* sourceOffset = sourceY + sourceStartX * bpp;
183 | for (int x = 0; x < copyW*bpp; x++, targetOffset ++, sourceOffset ++)
184 | *(targetOffset) = *(sourceOffset);
185 |
186 | }
187 | }
188 | }
189 |
190 | public unsafe void PutPixel32(int px, int py, byte r, byte g, byte b, byte a)
191 | {
192 | byte* addr = (byte*)(bitmapData.Scan0) + bitmapData.Stride * py + px * 4;
193 |
194 | *addr = b;
195 | *(addr + 1) = g;
196 | *(addr + 2) = r;
197 | *(addr + 3) = a;
198 | }
199 |
200 | public unsafe void GetPixel32(int px, int py, ref byte r, ref byte g, ref byte b, ref byte a)
201 | {
202 | byte* addr = (byte*)(bitmapData.Scan0) + bitmapData.Stride * py + px * 4;
203 |
204 | b = *addr;
205 | g = *(addr + 1);
206 | r = *(addr + 2);
207 | a = *(addr + 3);
208 | }
209 |
210 | public void DownScale32(int newWidth, int newHeight)
211 | {
212 | GLFontBitmap newBitmap = new GLFontBitmap(new Bitmap(newWidth, newHeight, bitmap.PixelFormat));
213 |
214 | if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
215 | throw new Exception("DownsScale32 only works on 32 bit images");
216 |
217 | float xscale = (float)bitmapData.Width / newWidth;
218 | float yscale = (float)bitmapData.Height / newHeight;
219 |
220 | byte r = 0, g = 0, b = 0, a = 0;
221 | float summedR = 0f;
222 | float summedG = 0f;
223 | float summedB = 0f;
224 | float summedA = 0f;
225 |
226 | int left, right, top, bottom; //the area of old pixels covered by the new bitmap
227 |
228 |
229 | float targetStartX, targetEndX;
230 | float targetStartY, targetEndY;
231 |
232 | float leftF, rightF, topF, bottomF; //edges of new pixel in old pixel coords
233 | float weight;
234 | float weightScale = xscale * yscale;
235 | float totalColourWeight = 0f;
236 |
237 | for (int m = 0; m < newHeight; m++)
238 | {
239 | for (int n = 0; n < newWidth; n++)
240 | {
241 |
242 | leftF = n * xscale;
243 | rightF = (n + 1) * xscale;
244 |
245 | topF = m * yscale;
246 | bottomF = (m + 1) * yscale;
247 |
248 | left = (int)leftF;
249 | right = (int)rightF;
250 |
251 | top = (int)topF;
252 | bottom = (int)bottomF;
253 |
254 | if (left < 0) left = 0;
255 | if (top < 0) top = 0;
256 | if (right >= bitmapData.Width) right = bitmapData.Width - 1;
257 | if (bottom >= bitmapData.Height) bottom = bitmapData.Height - 1;
258 |
259 | summedR = 0f;
260 | summedG = 0f;
261 | summedB = 0f;
262 | summedA = 0f;
263 | totalColourWeight = 0f;
264 |
265 | for (int j = top; j <= bottom; j++)
266 | {
267 | for (int i = left; i <= right; i++)
268 | {
269 | targetStartX = Math.Max(leftF, i);
270 | targetEndX = Math.Min(rightF, i + 1);
271 |
272 | targetStartY = Math.Max(topF, j);
273 | targetEndY = Math.Min(bottomF, j + 1);
274 |
275 | weight = (targetEndX - targetStartX) * (targetEndY - targetStartY);
276 |
277 | GetPixel32(i, j, ref r, ref g, ref b, ref a);
278 |
279 | summedA += weight * a;
280 |
281 | if (a != 0)
282 | {
283 | summedR += weight * r;
284 | summedG += weight * g;
285 | summedB += weight * b;
286 | totalColourWeight += weight;
287 | }
288 |
289 | }
290 | }
291 |
292 | summedR /= totalColourWeight;
293 | summedG /= totalColourWeight;
294 | summedB /= totalColourWeight;
295 | summedA /= weightScale;
296 |
297 | if (summedR < 0) summedR = 0f;
298 | if (summedG < 0) summedG = 0f;
299 | if (summedB < 0) summedB = 0f;
300 | if (summedA < 0) summedA = 0f;
301 |
302 | if (summedR >= 256) summedR = 255;
303 | if (summedG >= 256) summedG = 255;
304 | if (summedB >= 256) summedB = 255;
305 | if (summedA >= 256) summedA = 255;
306 |
307 | newBitmap.PutPixel32(n, m, (byte)summedR, (byte)summedG, (byte)summedB, (byte)summedA);
308 | }
309 |
310 | }
311 |
312 | this.Free();
313 | this.bitmap = newBitmap.bitmap;
314 | this.bitmapData = newBitmap.bitmapData;
315 | }
316 |
317 | public void Free()
318 | {
319 | bitmap.UnlockBits(bitmapData);
320 | bitmap.Dispose();
321 | }
322 | }
323 | }
324 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/GLSkin.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using OpenTK.Graphics;
3 |
4 | namespace GLGUI
5 | {
6 | public class GLSkin
7 | {
8 | public struct GLFormSkin
9 | {
10 | public GLFont Font;
11 | public Color4 Color;
12 | public GLPadding Border;
13 | public Color4 BorderColor;
14 | public Color4 BackgroundColor;
15 | }
16 |
17 | public struct GLButtonSkin
18 | {
19 | public GLFont Font;
20 | public Color4 Color;
21 | public GLFontAlignment TextAlign;
22 | public GLPadding Border;
23 | public Color4 BorderColor;
24 | public Color4 BackgroundColor;
25 | }
26 |
27 | public struct GLLabelSkin
28 | {
29 | public GLFont Font;
30 | public Color4 Color;
31 | public GLFontAlignment TextAlign;
32 | public GLPadding Padding;
33 | public Color4 BackgroundColor;
34 | }
35 |
36 | public struct GLTextBoxSkin
37 | {
38 | public GLFont Font;
39 | public Color4 Color;
40 | public Color4 SelectionColor;
41 | public GLFontAlignment TextAlign;
42 | public GLPadding Border;
43 | public GLPadding Padding;
44 | public Color4 BorderColor;
45 | public Color4 BackgroundColor;
46 | }
47 |
48 | public struct GLCheckBoxSkin
49 | {
50 | public GLFont Font;
51 | public Color4 Color;
52 | public GLPadding Border;
53 | public Color4 BorderColor;
54 | public Color4 BackgroundColor;
55 | }
56 |
57 | public struct GLGroupLayoutSkin
58 | {
59 | public GLPadding Border;
60 | public Color4 BorderColor;
61 | public Color4 BackgroundColor;
62 | }
63 |
64 | public struct GLFlowLayoutSkin
65 | {
66 | public GLPadding Padding;
67 | public GLPadding Border;
68 | public Color4 BorderColor;
69 | public Color4 BackgroundColor;
70 | public int Space;
71 | }
72 |
73 | public struct GLSplitLayoutSkin
74 | {
75 | public Color4 BackgroundColor;
76 | public int SplitterSize;
77 | }
78 |
79 | public struct GLSliderSkin
80 | {
81 | public Color4 KnobColor;
82 | public Color4 BackgroundColor;
83 | }
84 |
85 | public struct GLScrollableControlSkin
86 | {
87 | public GLPadding Border;
88 | public Color4 BorderColor;
89 | public Color4 BackgroundColor;
90 | }
91 |
92 | public GLFormSkin FormActive = new GLFormSkin();
93 | public GLFormSkin FormInactive = new GLFormSkin();
94 |
95 | public GLButtonSkin ButtonEnabled = new GLButtonSkin();
96 | public GLButtonSkin ButtonDisabled = new GLButtonSkin();
97 | public GLButtonSkin ButtonHover = new GLButtonSkin();
98 | public GLButtonSkin ButtonPressed = new GLButtonSkin();
99 |
100 | public GLLabelSkin LabelEnabled = new GLLabelSkin();
101 | public GLLabelSkin LabelDisabled = new GLLabelSkin();
102 |
103 | public GLLabelSkin LinkLabelEnabled = new GLLabelSkin();
104 | public GLLabelSkin LinkLabelDisabled = new GLLabelSkin();
105 |
106 | public GLTextBoxSkin TextBoxEnabled = new GLTextBoxSkin();
107 | public GLTextBoxSkin TextBoxActive = new GLTextBoxSkin();
108 | public GLTextBoxSkin TextBoxHover = new GLTextBoxSkin();
109 | public GLTextBoxSkin TextBoxDisabled = new GLTextBoxSkin();
110 |
111 | public GLCheckBoxSkin CheckBoxEnabled = new GLCheckBoxSkin();
112 | public GLCheckBoxSkin CheckBoxPressed = new GLCheckBoxSkin();
113 | public GLCheckBoxSkin CheckBoxHover = new GLCheckBoxSkin();
114 | public GLCheckBoxSkin CheckBoxDisabled = new GLCheckBoxSkin();
115 |
116 | public GLGroupLayoutSkin GroupLayout = new GLGroupLayoutSkin();
117 |
118 | public GLFlowLayoutSkin FlowLayout = new GLFlowLayoutSkin();
119 |
120 | public GLSplitLayoutSkin SplitLayout = new GLSplitLayoutSkin();
121 |
122 | public GLSliderSkin SliderEnabled = new GLSliderSkin();
123 | public GLSliderSkin SliderDisabled = new GLSliderSkin();
124 | public GLSliderSkin SliderHover = new GLSliderSkin();
125 | public GLSliderSkin SliderPressed = new GLSliderSkin();
126 |
127 | public GLScrollableControlSkin ScrollableControl = new GLScrollableControlSkin();
128 |
129 | public GLFlowLayoutSkin ContextMenu = new GLFlowLayoutSkin();
130 |
131 | public GLButtonSkin ContextMenuEntryEnabled = new GLButtonSkin();
132 | public GLButtonSkin ContextMenuEntryDisabled = new GLButtonSkin();
133 | public GLButtonSkin ContextMenuEntryHover = new GLButtonSkin();
134 | public GLButtonSkin ContextMenuEntryPressed = new GLButtonSkin();
135 |
136 | public GLSkin(GLFont defaultFont = null)
137 | {
138 | if(defaultFont == null)
139 | defaultFont = new GLFont(new Font("Arial", 8.0f));
140 |
141 | FormActive.Font = defaultFont;
142 | FormActive.Color = Color.FromArgb(240, 240, 240);
143 | FormActive.Border = new GLPadding(2);
144 | FormActive.BorderColor = Color.FromArgb(192, 56, 56, 56);
145 | FormActive.BackgroundColor = Color.FromArgb(41, 41, 41);
146 |
147 | FormInactive.Font = defaultFont;
148 | FormInactive.Color = Color.FromArgb(160, 160, 160);
149 | FormInactive.Border = new GLPadding(2);
150 | FormInactive.BorderColor = Color.FromArgb(192, 56, 56, 56);
151 | FormInactive.BackgroundColor = Color.FromArgb(41, 41, 41);
152 |
153 |
154 | ButtonEnabled.Font = defaultFont;
155 | ButtonEnabled.Color = Color.FromArgb(240, 240, 240);
156 | ButtonEnabled.TextAlign = GLFontAlignment.Centre;
157 | ButtonEnabled.Border = new GLPadding(2);
158 | ButtonEnabled.BorderColor = Color.FromArgb(56, 56, 56);
159 | ButtonEnabled.BackgroundColor = Color.Transparent;
160 |
161 | ButtonDisabled.Font = defaultFont;
162 | ButtonDisabled.Color = Color.FromArgb(128, 128, 128);
163 | ButtonDisabled.TextAlign = GLFontAlignment.Centre;
164 | ButtonDisabled.Border = new GLPadding(2);
165 | ButtonDisabled.BorderColor = Color.FromArgb(56, 56, 56);
166 | ButtonDisabled.BackgroundColor = Color.Transparent;
167 |
168 | ButtonHover.Font = defaultFont;
169 | ButtonHover.Color = Color.FromArgb(255, 255, 255);
170 | ButtonHover.TextAlign = GLFontAlignment.Centre;
171 | ButtonHover.Border = new GLPadding(2);
172 | ButtonHover.BorderColor = Color.FromArgb(64, 64, 64);
173 | ButtonHover.BackgroundColor = Color.Transparent;
174 |
175 | ButtonPressed.Font = defaultFont;
176 | ButtonPressed.Color = Color.FromArgb(96, 96, 96);
177 | ButtonPressed.TextAlign = GLFontAlignment.Centre;
178 | ButtonPressed.Border = new GLPadding(2);
179 | ButtonPressed.BorderColor = Color.FromArgb(32, 32, 32);
180 | ButtonPressed.BackgroundColor = Color.Transparent;
181 |
182 |
183 | LabelEnabled.Font = defaultFont;
184 | LabelEnabled.Color = Color.FromArgb(192, 192, 192);
185 | LabelEnabled.TextAlign = GLFontAlignment.Left;
186 | LabelEnabled.Padding = new GLPadding(1, 1, 1, 1);
187 | LabelEnabled.BackgroundColor = Color.Transparent;
188 |
189 | LabelDisabled.Font = defaultFont;
190 | LabelDisabled.Color = Color.FromArgb(128, 128, 128);
191 | LabelDisabled.TextAlign = GLFontAlignment.Left;
192 | LabelDisabled.Padding = new GLPadding(1, 1, 1, 1);
193 | LabelDisabled.BackgroundColor = Color.Transparent;
194 |
195 |
196 | LinkLabelEnabled.Font = defaultFont;
197 | LinkLabelEnabled.Color = Color.FromArgb(128, 128, 255);
198 | LinkLabelEnabled.TextAlign = GLFontAlignment.Left;
199 | LinkLabelEnabled.Padding = new GLPadding(1, 1, 1, 1);
200 | LinkLabelEnabled.BackgroundColor = Color.Transparent;
201 |
202 | LinkLabelDisabled.Font = defaultFont;
203 | LinkLabelDisabled.Color = Color.FromArgb(96, 96, 192);
204 | LinkLabelDisabled.TextAlign = GLFontAlignment.Left;
205 | LinkLabelDisabled.Padding = new GLPadding(1, 1, 1, 1);
206 | LinkLabelDisabled.BackgroundColor = Color.Transparent;
207 |
208 |
209 | TextBoxEnabled.Font = defaultFont;
210 | TextBoxEnabled.Color = Color.FromArgb(192, 192, 192);
211 | TextBoxEnabled.SelectionColor = Color.FromArgb(80, 80, 80);
212 | TextBoxEnabled.TextAlign = GLFontAlignment.Left;
213 | TextBoxEnabled.Border = new GLPadding(1);
214 | TextBoxEnabled.Padding = new GLPadding(1, 0, 1, 2);
215 | TextBoxEnabled.BorderColor = Color.FromArgb(96, 96, 96);
216 | TextBoxEnabled.BackgroundColor = Color.FromArgb(56, 56, 56);
217 |
218 | TextBoxActive.Font = defaultFont;
219 | TextBoxActive.Color = Color.FromArgb(192, 192, 192);
220 | TextBoxActive.SelectionColor = Color.FromArgb(96, 96, 96);
221 | TextBoxActive.TextAlign = GLFontAlignment.Left;
222 | TextBoxActive.Border = new GLPadding(1);
223 | TextBoxActive.Padding = new GLPadding(1, 0, 1, 2);
224 | TextBoxActive.BorderColor = Color.FromArgb(255, 192, 96);
225 | TextBoxActive.BackgroundColor = Color.FromArgb(56, 56, 56);
226 |
227 | TextBoxHover.Font = defaultFont;
228 | TextBoxHover.Color = Color.FromArgb(192, 192, 192);
229 | TextBoxHover.SelectionColor = Color.FromArgb(80, 80, 80);
230 | TextBoxHover.TextAlign = GLFontAlignment.Left;
231 | TextBoxHover.Border = new GLPadding(1);
232 | TextBoxHover.Padding = new GLPadding(1, 0, 1, 2);
233 | TextBoxHover.BorderColor = Color.FromArgb(128, 128, 128);
234 | TextBoxHover.BackgroundColor = Color.FromArgb(56, 56, 56);
235 |
236 | TextBoxDisabled.Font = defaultFont;
237 | TextBoxDisabled.Color = Color.FromArgb(128, 128, 128);
238 | TextBoxDisabled.SelectionColor = Color.FromArgb(80, 80, 80);
239 | TextBoxDisabled.TextAlign = GLFontAlignment.Left;
240 | TextBoxDisabled.Border = new GLPadding(1);
241 | TextBoxDisabled.Padding = new GLPadding(1, 0, 1, 2);
242 | TextBoxDisabled.BorderColor = Color.FromArgb(128, 128, 128);
243 | TextBoxDisabled.BackgroundColor = Color.FromArgb(56, 56, 56);
244 |
245 |
246 | CheckBoxEnabled.Font = defaultFont;
247 | CheckBoxEnabled.Color = Color.FromArgb(192, 192, 192);
248 | CheckBoxEnabled.Border = new GLPadding(1);
249 | CheckBoxEnabled.BorderColor = Color.FromArgb(96, 96, 96);
250 | CheckBoxEnabled.BackgroundColor = Color.FromArgb(56, 56, 56);
251 |
252 | CheckBoxPressed.Font = defaultFont;
253 | CheckBoxPressed.Color = Color.FromArgb(192, 192, 192);
254 | CheckBoxPressed.Border = new GLPadding(1);
255 | CheckBoxPressed.BorderColor = Color.FromArgb(255, 192, 96);
256 | CheckBoxPressed.BackgroundColor = Color.FromArgb(56, 56, 56);
257 |
258 | CheckBoxHover.Font = defaultFont;
259 | CheckBoxHover.Color = Color.FromArgb(192, 192, 192);
260 | CheckBoxHover.Border = new GLPadding(1);
261 | CheckBoxHover.BorderColor = Color.FromArgb(128, 128, 128);
262 | CheckBoxHover.BackgroundColor = Color.FromArgb(56, 56, 56);
263 |
264 | CheckBoxDisabled.Font = defaultFont;
265 | CheckBoxDisabled.Color = Color.FromArgb(128, 128, 128);
266 | CheckBoxDisabled.Border = new GLPadding(1);
267 | CheckBoxDisabled.BorderColor = Color.FromArgb(128, 128, 128);
268 | CheckBoxDisabled.BackgroundColor = Color.FromArgb(56, 56, 56);
269 |
270 |
271 | GroupLayout.Border = new GLPadding(1);
272 | GroupLayout.BorderColor = Color.Transparent;//Color.FromArgb(96, 96, 96);
273 | GroupLayout.BackgroundColor = Color.Transparent;//Color.FromArgb(240, 240, 240);
274 |
275 |
276 | FlowLayout.Padding = new GLPadding(2);
277 | FlowLayout.Border = new GLPadding(0);
278 | FlowLayout.BorderColor = Color.Transparent;
279 | FlowLayout.BackgroundColor = Color.Transparent;
280 | FlowLayout.Space = 2;
281 |
282 |
283 | SplitLayout.BackgroundColor = Color.FromArgb(0, 0, 0);
284 | SplitLayout.SplitterSize = 1;
285 |
286 |
287 | SliderEnabled.KnobColor = Color.FromArgb(80, 80, 80);
288 | SliderEnabled.BackgroundColor = Color.FromArgb(28, 28, 28);//Color.FromArgb(56, 56, 56);
289 |
290 | SliderDisabled.KnobColor = Color.Transparent; //Color.FromArgb(96, 96, 96);
291 | SliderDisabled.BackgroundColor = Color.FromArgb(28, 28, 28);//Color.FromArgb(56, 56, 56);
292 |
293 | SliderHover.KnobColor = Color.FromArgb(96, 96, 96);
294 | SliderHover.BackgroundColor = Color.FromArgb(32, 32, 32);
295 |
296 | SliderPressed.KnobColor = Color.FromArgb(80, 80, 80);
297 | SliderPressed.BackgroundColor = Color.FromArgb(32, 32, 32);
298 |
299 |
300 | ScrollableControl.Border = new GLPadding(1);
301 | ScrollableControl.BorderColor = Color.FromArgb(56, 56, 56);
302 | ScrollableControl.BackgroundColor = Color.FromArgb(41, 41, 41);
303 |
304 |
305 | ContextMenu.Padding = new GLPadding(1);
306 | ContextMenu.Border = new GLPadding(1);
307 | ContextMenu.BorderColor = Color.FromArgb(128, 128, 128);
308 | ContextMenu.BackgroundColor = Color.FromArgb(32, 32, 32);
309 | ContextMenu.Space = 1;
310 |
311 |
312 | ContextMenuEntryEnabled.Font = defaultFont;
313 | ContextMenuEntryEnabled.Color = Color.FromArgb(240, 240, 240);
314 | ContextMenuEntryEnabled.TextAlign = GLFontAlignment.Left;
315 | ContextMenuEntryEnabled.Border = new GLPadding(2);
316 | ContextMenuEntryEnabled.BorderColor = Color.FromArgb(56, 56, 56);
317 | ContextMenuEntryEnabled.BackgroundColor = Color.Transparent;
318 |
319 | ContextMenuEntryDisabled.Font = defaultFont;
320 | ContextMenuEntryDisabled.Color = Color.FromArgb(128, 128, 128);
321 | ContextMenuEntryDisabled.TextAlign = GLFontAlignment.Left;
322 | ContextMenuEntryDisabled.Border = new GLPadding(2);
323 | ContextMenuEntryDisabled.BorderColor = Color.FromArgb(56, 56, 56);
324 | ContextMenuEntryDisabled.BackgroundColor = Color.Transparent;
325 |
326 | ContextMenuEntryHover.Font = defaultFont;
327 | ContextMenuEntryHover.Color = Color.FromArgb(255, 255, 255);
328 | ContextMenuEntryHover.TextAlign = GLFontAlignment.Left;
329 | ContextMenuEntryHover.Border = new GLPadding(2);
330 | ContextMenuEntryHover.BorderColor = Color.FromArgb(64, 64, 64);
331 | ContextMenuEntryHover.BackgroundColor = Color.Transparent;
332 |
333 | ContextMenuEntryPressed.Font = defaultFont;
334 | ContextMenuEntryPressed.Color = Color.FromArgb(96, 96, 96);
335 | ContextMenuEntryPressed.TextAlign = GLFontAlignment.Left;
336 | ContextMenuEntryPressed.Border = new GLPadding(2);
337 | ContextMenuEntryPressed.BorderColor = Color.FromArgb(32, 32, 32);
338 | ContextMenuEntryPressed.BackgroundColor = Color.Transparent;
339 | }
340 | }
341 | }
342 |
--------------------------------------------------------------------------------
/GLGUI/GLGUI/Advanced/GLDataControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 |
7 | namespace GLGUI.Advanced
8 | {
9 | public class GLDataControl : GLScrollableControl
10 | {
11 | public GLSkin.GLLabelSkin LabelSkin { get { return labelSkin; } set { labelSkin = value; if(history.Count > 0) SetData(history.First()); } }
12 | public GLSkin.GLLabelSkin LinkLabelSkin { get { return linkLabelSkin; } set { linkLabelSkin = value; if (history.Count > 0) SetData(history.First()); } }
13 |
14 | public Dictionary Hidden = new Dictionary();
15 | public Dictionary>[]> Links = new Dictionary>[]>();
16 | public Dictionary> Shortcuts = new Dictionary>();
17 |
18 | private int row;
19 | private Stack> history = new Stack>();
20 | private List, GLLabel>> updateData = new List, GLLabel>>(256);
21 |
22 | private GLFlowLayout horizontal, left, right;
23 | private GLSkin.GLLabelSkin labelSkin, linkLabelSkin;
24 |
25 | public GLDataControl(GLGui gui) : base(gui)
26 | {
27 | Render += (s, d) => UpdateData();
28 |
29 | horizontal = Add(new GLFlowLayout(gui) { FlowDirection = GLFlowDirection.LeftToRight, AutoSize = true });
30 | left = horizontal.Add(new GLFlowLayout(gui) { FlowDirection = GLFlowDirection.TopDown, AutoSize = true });
31 | var skin = left.Skin;
32 | skin.Space = 0;
33 | left.Skin = skin;
34 | right = horizontal.Add(new GLFlowLayout(gui) { FlowDirection = GLFlowDirection.TopDown, AutoSize = true });
35 | right.Skin = skin;
36 |
37 | labelSkin = gui.Skin.LabelEnabled;
38 | linkLabelSkin = gui.Skin.LinkLabelEnabled;
39 |
40 | // defaults
41 | Hidden.Add(typeof(IEnumerable), new string[] {
42 | "_items", "_size", "_version", "_syncRoot",
43 | "m_buckets", "m_slots", "m_count", "m_lastIndex", "m_freeList", "m_comparer",
44 | "m_version", "m_siInfo", "m_collection", "m_boundedCapacity", "m_freeNodes",
45 | "m_occupiedNodes", "m_isDisposed", "m_ConsumersCancellationTokenSource",
46 | "m_ProducersCancellationTokenSource", "m_currentAdders",
47 | "buckets", "entries", "count", "version", "freeList", "freeCount", "comparer", "keys", "values",
48 | "IsFixedSize", "IsReadOnly", "IsSynchronized", "SyncRoot" });
49 | Hidden.Add(typeof(Array), new string[] { "LongLength", "Rank", "Count" });
50 | Hidden.Add(typeof(KeyValuePair<,>), new string[] { "key", "value" });
51 | Hidden.Add(typeof(Dictionary<,>), new string[] { "Keys", "Values" });
52 | }
53 |
54 | private void AddRow(string name, EventHandler click, Func