CSharpGL(26)在opengl中实现控件布局/渲染文字

CSharpGL(26)在opengl中实现控件布局/渲染文字

如图所示,可以将文字、坐标轴固定在窗口的一角。

下载

CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入(https://github.com/bitzhuwei/CSharpGL

UI控件布局关键点

ILayout

类似Winform控件那样,控件的位置、大小由其Anchor等属性决定。窗口大小改变时,控件的位置、大小会随之改变。

所以模仿Control类,直接使用Anchor作为UIRenderer的接口。

 1     /// <summary>
 2     /// Supports layout UI element in OpenGL canvas.
 3     /// 实现在OpenGL窗口中的UI布局
 4     /// </summary>
 5     public interface ILayout : ITreeNode<UIRenderer>
 6     {
 7         //event EventHandler afterLayout;
 8 
 9         /// <summary>
10         /// the edges of the <see cref="GLCanvas"/> to which a UI’s rect is bound and determines how it is resized with its parent.
11         /// <para>something like AnchorStyles.Left | AnchorStyles.Bottom.</para>
12         /// </summary>
13         System.Windows.Forms.AnchorStyles Anchor { get; set; }
14 
15         /// <summary>
16         /// Gets or sets the space between viewport and SimpleRect.
17         /// </summary>
18         System.Windows.Forms.Padding Margin { get; set; }
19 
20         /// <summary>
21         /// 相对于Parent左下角的位置(Left Down location)
22         /// </summary>
23         System.Drawing.Point Location { get; set; }
24 
25         /// <summary>
26         /// Stores width when <see cref="Anchor"/>.Left &amp; <see cref="Anchor"/>.Right is <see cref="Anchor"/>.None.
27         /// <para> and height when <see cref="Anchor"/>.Top &amp; <see cref="Anchor"/>.Bottom is <see cref="Anchor"/>.None.</para>
28         /// </summary>
29         System.Drawing.Size Size { get; set; }
30 
31         /// <summary>
32         /// 
33         /// </summary>
34         System.Drawing.Size ParentLastSize { get; set; }
35 
36         /// <summary>
37         /// 
38         /// </summary>
39         int zNear { get; set; }
40 
41         /// <summary>
42         /// 
43         /// </summary>
44         int zFar { get; set; }
45 
46     }

 

实现在OpenGL窗口中的UI布局

有了数据结构,就可以实现窗口中的UI布局了。当窗口大小改变时,调用下面的函数。

  1         /// <summary>
  2         /// layout controls in OpenGL canvas.
  3         /// <para>This coordinate system is as below.</para>
  4         /// <para>   /\ y</para>
  5         /// <para>   |</para>
  6         /// <para>   |</para>
  7         /// <para>   |</para>
  8         /// <para>   |</para>
  9         /// <para>   |</para>
 10         /// <para>   |-----------------&gt;x</para>
 11         /// <para>(0, 0)</para>
 12         /// </summary>
 13         /// <param name="uiRenderer"></param>
 14         internal static void Layout(this ILayout uiRenderer)
 15         {
 16             ILayout parent = uiRenderer.Parent;
 17             if (parent != null)
 18             {
 19                 uiRenderer.Self.DoBeforeLayout();
 20                 NonRootNodeLayout(uiRenderer, parent);
 21                 uiRenderer.Self.DoAfterLayout();
 22             }
 23 
 24             foreach (var item in uiRenderer.Children)
 25             {
 26                 item.Layout();
 27             }
 28 
 29             if (parent != null)
 30             {
 31                 uiRenderer.ParentLastSize = parent.Size;
 32             }
 33         }
 34 
 35         /// <summary>
 36         /// leftRightAnchor = (AnchorStyles.Left | AnchorStyles.Right); 
 37         /// </summary>
 38         private const AnchorStyles leftRightAnchor = (AnchorStyles.Left | AnchorStyles.Right);
 39 
 40         /// <summary>
 41         /// topBottomAnchor = (AnchorStyles.Top | AnchorStyles.Bottom);
 42         /// </summary>
 43         private const AnchorStyles topBottomAnchor = (AnchorStyles.Top | AnchorStyles.Bottom);
 44 
 45         /// <summary>
 46         /// Gets <paramref name="currentNode"/>'s location and size according to its state and parent's information.
 47         /// </summary>
 48         /// <param name="currentNode"></param>
 49         /// <param name="parent"></param>
 50         private static void NonRootNodeLayout(ILayout currentNode, ILayout parent)
 51         {
 52             int x, y, width, height;
 53             if ((currentNode.Anchor & leftRightAnchor) == leftRightAnchor)
 54             {
 55                 width = parent.Size.Width - currentNode.Margin.Left - currentNode.Margin.Right;
 56                 //width = currentNode.Size.Width + (parent.Size.Width - currentNode.ParentLastSize.Width);
 57                 if (width < 0) { width = 0; }
 58             }
 59             else
 60             {
 61                 width = currentNode.Size.Width;
 62             }
 63 
 64             if ((currentNode.Anchor & topBottomAnchor) == topBottomAnchor)
 65             {
 66                 height = parent.Size.Height - currentNode.Margin.Top - currentNode.Margin.Bottom;
 67                 //height = currentNode.Size.Height + (parent.Size.Height - currentNode.ParentLastSize.Height);
 68                 if (height < 0) { height = 0; }
 69             }
 70             else
 71             {
 72                 height = currentNode.Size.Height;
 73             }
 74 
 75             if ((currentNode.Anchor & leftRightAnchor) == AnchorStyles.None)
 76             {
 77                 x = (int)(
 78                     (parent.Size.Width - width)
 79                     * ((double)currentNode.Margin.Left / (double)(currentNode.Margin.Left + currentNode.Margin.Right)));
 80             }
 81             else if ((currentNode.Anchor & leftRightAnchor) == AnchorStyles.Left)
 82             {
 83                 x = parent.Location.X + currentNode.Margin.Left;
 84             }
 85             else if ((currentNode.Anchor & leftRightAnchor) == AnchorStyles.Right)
 86             {
 87                 x = parent.Location.X + parent.Size.Width - currentNode.Margin.Right - width;
 88             }
 89             else if ((currentNode.Anchor & leftRightAnchor) == leftRightAnchor)
 90             {
 91                 x = parent.Location.X + currentNode.Margin.Left;
 92             }
 93             else
 94             { throw new Exception("uiRenderer should not happen!"); }
 95 
 96             if ((currentNode.Anchor & topBottomAnchor) == AnchorStyles.None)
 97             {
 98                 y = (int)(
 99                     (parent.Size.Height - height)
100                     * ((double)currentNode.Margin.Bottom / (double)(currentNode.Margin.Bottom + currentNode.Margin.Top)));
101             }
102             else if ((currentNode.Anchor & topBottomAnchor) == AnchorStyles.Bottom)
103             {
104                 //y = currentNode.Margin.Bottom;
105                 y = parent.Location.Y + currentNode.Margin.Bottom;
106             }
107             else if ((currentNode.Anchor & topBottomAnchor) == AnchorStyles.Top)
108             {
109                 //y = parent.Size.Height - height - currentNode.Margin.Top;
110                 y = parent.Location.Y + parent.Size.Height - currentNode.Margin.Top - height;
111             }
112             else if ((currentNode.Anchor & topBottomAnchor) == topBottomAnchor)
113             {
114                 //y = currentNode.Margin.Top + parent.Location.Y;
115                 y = parent.Location.Y + currentNode.Margin.Bottom;
116             }
117             else
118             { throw new Exception("This should not happen!"); }
119 
120             currentNode.Location = new System.Drawing.Point(x, y);
121             currentNode.Size = new Size(width, height);
122         }
public static void Layout(this ILayout uiRenderer)

相关文章: