jeOS: The Game User Interface – Powered By The ZONE Object

Of all the questions about User Interfaces, one that I can’t answer is why I love them so much. Buttons and ScrollBars and TabStrips and all those amazing imaginary widgets are literally physical objects to my mind. Intelligent parts of machinery that can be constructed into infinite possibilities, using nothing more than words. A person can find fascination in anything, but as for why I’m so obsessed, I don’t get it either.

For some reason, ever since the first time I used a mouse to click a button, I could never let go. Every aspect of UI has fascinated me the same way that any master mechanic felt the first time someone popped the hood of a car engine. I still remember in grade school walking up to the brand new computer lab, hoping and praying that I’d get the one with the mouse. Call it what you want, divine intervention, or just observant teachers, it still feels like both.

At about 13 years old in 1995 I was learning Visual Basic 3 on Windows 3.1. And by 2000 I was writing my own GUI in C++ and OpenGL, a la Unreal Tournament. I got hired at a small company doing interface/database stuff and gained even more XP. Windows, I say Windows that is. After all the years I’ve toyed with with interfaces, I understand much of how Microsoft’s interfaces work on the inside. And while the Microsoft Zune didn’t attract people like it could have, I like calling them Zones as a tribute to the most intricate and over-powered interface system there is.

The JEOZ.Zone Object contains a List Collection of Child Zones. The best way to start building an interface is by using one transparent Root Zone that fills the whole screen. Then, Zones can be added to make “Windows”, although “Panels” is more appropriate. Games don’t need the ability to move and size Windows. Even draggable Splitter objects are too awkward for fast-paced gaming. I’ll go that far, but movable windows I can save for later, or leave out entirely.

Then you can add over a dozen kinds of User Interface Controls to these Panel Zones. It has most of the basics already: Buttons, ScrollBars, CheckBoxes, ListBoxes, CheckListBoxes, TabStrips, Grids, Data Displays, and last but not least, Faders. Also known as Sliders, but I prefer the Mixing Board term, especially because the GoNumbers have a Slide() Function.

I’ve also developed a Control I call the ThreeDee. It lets you move an X/Y position with the mouse, and adjust the Z coordinate with the mouse wheel. I started trying to make the Zone capable of being a HueMap RGB-HSL Color Selector, but then discovered I could do that with Inheritance.

Then I realized how far Inheritance could take this system, and that’s when things got weird.

By creating a Class that Inherits from the Zone Object, it feels as close to writing an App within an App. In fact, when I started discussing this with my father, who understands the basics of Visual Basic, he asked, “What language are you talking about?”. Just by the very sound of what I was doing, it seemed like I was working within another system, and in a lot of ways it basically is very much like writing Windows apps.

You can define several Zone Objects within an Inherited Zone, and instantiate them Public WithEvents. Then you can do all the Event Handling inside of the Inherited Zone, which of course is a clean slate, but contains all the Functions of this universally capable Zone. It’s like creating a User Control in Dot Net. Every User Control on a Windows Form is basically it’s own little program except without a window and border, and these Inherited Zones work the same way.

Public Class ColorZone : Inherits Zone

    Public WithEvents HueMap As New Zone
    Public PreviewPanel, CopyButton, PasteButton, HexLabel As New Zone
    Public Red, Green, Blue, Alpha As New Zone
    Public Hue, Saturation, Lightness As New Zone

    Public Sub SetupInterface(_Name As String, Parent As Zone,
                              _HueWidth As Single, _HueHeight As Single,
                              Optional _Bounds() As Single = Nothing,
                              Optional _FontScale As Single = Nothing)

        SetupZone(Zones.Region, Parent, _Name, _Name, _Bounds, 1,,, 0.25)
        Dim Spot As Point = NextAdd
        Dim PreviewSize As New Point(64, 32)
        FontScale = _FontScale
        If FontScale = Nothing Then FontScale = 0.27
        DefaultFontScale = FontScale
        '// Create the Color Preview box, HTML Hex Code, and Copy/Paste Buttons
        NextIsDown()
        PreviewPanel = Add_Caption("Color Preview", {Spot.X, -1, PreviewSize.X, PreviewSize.Y}, _Align:=Align.Center)
        '// The LastChild Property retrieves the most recently added Zone
        LastChild.Caption = ""
        HexLabel = Add_Caption("#000000", {-1, -1, PreviewSize.X, 16}, FontScale * 0.8)
        NextIsAcross()
        CopyButton = Add_Button("Copy", {-1, -1, 32, 18}, FontScale * 0.7)
        PasteButton = Add_Button("Paste", {-1, -1, 32, 18}, FontScale * 0.7)
        NextIsDown()

        '// Add the Hue Mapper Control
        HueMap = Add_HueMap("Hue Map", {Spot.X + PreviewSize.X + Padding.X * 2, Spot.Y,
                                        _HueWidth - PreviewSize.X - Padding.X, _HueHeight})
        LastChild.CaptionSize = 0

        '// Set up and create the horizontal Hue, Saturation, Lightness Faders
        DefaultHeight = (_Bounds(3) - _HueHeight + Padding.Y * 2) / 3
        CaptionSize = 100
        Padding.Y = 10
        Hue = Add_Fader("Hue", 0.0, 1.0, 0.5, 0.01, TrackerTypes.Hue, {Spot.X, _HueHeight + Padding.Y * 3, _HueWidth})
        Saturation = Add_Fader("Saturation", 0.0, 1.0, 0.5, 0.01, TrackerTypes.Saturation, {-1, -1, _HueWidth})
        Lightness = Add_Fader("Lightness", 0.0, 1.0, 0.5, 0.01, TrackerTypes.Lightness, {-1, -1, _HueWidth})
       
        '// Set up and create the vertical RGBA Faders (AKA ScrollBars)
        DefaultHeight = NextAdd.Y - Padding.Y
        DefaultWidth = (W - _HueWidth) / 4
        NextAdd = New Point(NextAdd.X + _HueWidth + Padding.X * 2, 0)
        CaptionSize = DefaultHeight
        NextIsAcross()
        ValueSize = FontMain.CharacterHeight * 0.5 * FontScale
        Padding.X = 6

        Red = Add_Scrollbar("Red", 0.0, 1.0, 0.5, 0.01, TrackerTypes.Red)
        Green = Add_Scrollbar("Green", 0.0, 1.0, 0.5, 0.01, TrackerTypes.Green)
        Blue = Add_Scrollbar("Blue", 0.0, 1.0, 0.5, 0.01, TrackerTypes.Blue)
        Alpha = Add_Scrollbar("Alpha", 0.0, 1.0, 0.5, 0.01, TrackerTypes.Normal)

    End Sub
    Private Sub HueMap_MouseMove(sender As Zone, e As MouseEvent) Handles HueMap.MouseMove
        If e.Button = MouseButtons.Left Then
            Dim x = e.X / HueMap.W
            Dim y = e.Y / HueMap.H
            Log($"{x}{vbTab}{y}")
            Dim Go As New GoColor(x, y, 1 - y)
            HueMap.ClickTarget = New Point(HueMap.ScreenBox.X + e.X, HueMap.ScreenBox.Y + e.Y)
            SetColor(Go)
            PreviewPanel.BackColor = Go
            SetFocusMouse()
            Child_MouseDown(Me, Me.Parent, e)
            Child_ColorChanged(Go, Me, Me.Parent, e)
        End If
    End Sub

    Public Sub SetColor(Clr As GoColor)

        PreviewPanel.BackColor = Clr

        HexLabel.Caption = RGBtoHEX(Clamp(Clr.R * 255, 0, 255),
                                    Clamp(Clr.G * 255, 0, 255),
                                    Clamp(Clr.B * 255, 0, 255))

        Dim Local As Point = New Point
        Local.X = HueMap.CaptionSize + ((Clr.Hue) * (HueMap.W - HueMap.CaptionSize))
        Local.Y = (1 - Clr.Lightness) * HueMap.H
        HueMap.ClickTarget = Local + HueMap.ScreenBox.Location

        Red.Value = Clr.R
        Green.Value = Clr.G
        Blue.Value = Clr.B
        Hue.Value = Clr.Hue
        Saturation.Value = Clr.Saturation
        Lightness.Value = Clr.Lightness

    End Sub

    Public Function GetColor() As Color
        Return Color.FromArgb(Child("Alpha").Value, Child("Red").Value, Child("Green").Value, Child("Blue").Value)
    End Function

    Public Sub SetHSL(Clr As Color)
        Child("Hue").Value = Clr.GetHue
        Child("Saturation").Value = Clr.GetSaturation * 255
        Child("Lightness").Value = Clr.GetBrightness * 255
    End Sub

    Public Sub SetGoColor(Clr As GoColor)
        Child("Hue").Value = Clr.Hue
        Child("Saturation").Value = Clr.Saturation
        Child("Lightness").Value = Clr.Lightness

        Child("Red").Value = Clr.R
        Child("Green").Value = Clr.G
        Child("Blue").Value = Clr.B
    End Sub
End Class

Then you can add any of these Inherited Zones to another Zone as a Child Zone, just like adding UserControls to a Windows Form. All of the drawing and mouse handling is done automatically, triggered with just one Function call to the Root Zone’s Draw and MouseInput Functions. Everything is passed down through the hierarchy of Zones to draw everything, or for the mouse input, until a Control raises an Event. Then when Events are raised, they are given the Zone and MouseEvent details, and you use those to respond to user inputs when they happen.

My biggest worry is actually that some devs will see this, and really want to use it, but right now I’d be surprised if you could just drop it into another engine. Mostly because no ones tried it yet, so who knows.

The main point of posting all this code is that the jeOS Interface System is probably the most polished aspect of the engine so far. I feel the best way to demonstrate the value of this engine is to start here.

So I don’t guarantee anything about this code, if you manage to make it work in your engine, that would be amazing. The point of this is just to reveal some internals of JEOZ. This is the part that’s most ready for that, and the part I’m most proud of.

Imports OpenTK
Imports JEOCORE
Imports OpenTK.Graphics.OpenGL
Imports System.Drawing
Imports System.Windows.Forms

Partial Public Class Zone : Implements ICloneable
    Public TabType, Index As Integer, Name, Tag As String
    Public X, Y, W, H As Single
    Public ZoneType As Zones
    Public Children As New List(Of Zone)
    Public ChildName As New Dictionary(Of String, Integer)
    Public RootZone, Parent, ScrollBar As Zone, HasChildren As Boolean
    Public Visible, Enabled, Minimized, Checked, Focused As Boolean
    Public Hovering, MousePressed, PercentStyle As Boolean
    Public AnchorBottom, Border, Scissor As Boolean

    Public TrackerType As TrackerTypes
    Public AutoArrange As Boolean = True
    Public Scroll As New GoNumber(0)
    Private IsScrollable As Boolean
    Dim c As Color

    Public BorderSize, BorderFocus, BorderHover As Integer
    Public BackColor As New GoColor(0.3, 0.3, 0.3, 1.0)
    Public ForeColor As New GoColor(0.9, 0.9, 0.9, 1.0)
    Public HoverColor As New GoColor(1.0, 1.0, 1.0, 1.0)
    Public DefaultBackColor As New GoColor(0.05, 0.1, 0.3, 1.0)

    Public HoverAlpha As New GoNumber(1)
    Public Alpha, Alpha256, AlphaTo As Single
    Public Padding As New Point(5, 5), FontScale As Single = 0.5

    Public MouseDownButton As MouseButtons
    Public ListItems As New List(Of ZoneListItem)
    Public ListCheckBoxes As Boolean, ListChecked() As Boolean
    Public SelectedIndex As Integer, ItemSize, ItemTotalSize As Single

    Public GridMouse As New Point
    Public Kit As Sampler

    Public ShowCaption As Boolean = True
    Public Caption As String, CaptionSize As Integer = 164, ValueSize As Integer = 70, ValueSpacing As Integer = 15
    Public CaptionVertical, CaptionAlign As StringAlignment
    Public ValueMinimum As Single = 0, ValueMaximum As Single = 100, MyValue As Single = 50
    Public ValuePrecision As Single = 1, ValueRound As Integer = 2, WheelSpeed As Single = 1
    Public DefaultValue As Single, ValueNow As New GoNumber(1)
    Public ButtonSize, TrackMarks(), TabStops() As Integer

    Public ScreenBox As Rectangle
    Dim CaptionBox As Rectangle = New Rectangle(0, 0, CaptionSize, H)
    Dim TrackerBox As Rectangle = New Rectangle(CaptionSize, 0, W - ValueSize, H)
    Dim ValueBox As Rectangle = New Rectangle(W - ValueSize, 0, ValueSize, H)
    Dim PositionBox As Rectangle = New Rectangle(Value / ValueMaximum * TrackerBox.Width, 0, 5, H)
    Dim SubBox(3) As Rectangle

    Public NextIsDown As Boolean = True, NextAdd, ClickTarget As Point, Vector As Vector3
    Public DefaultWidth, DefaultHeight As Integer, DefaultFontScale As Single = 0.2
    Public ColumnWidth As Single = 300, CurrentColumn As Integer = 0
    Public Code As CodeText

When you Declare a Zone Object, you can specify the WithEvents clause. The following events will be raised when any events are triggered. The Event is given a Zone Object of the Sender, the Sender’s Parent, and the MouseEvent object. This MouseEvent Object is just like the one in the Dot Net Framework, but I defined my own for the JEOZ Engine.

    Public Event ColorChanged(Value As GoColor, sender As Zone, parent As Zone, e As MouseEvent)
    Public Event GridEvent(Value As Point, sender As Zone, parent As Zone, e As MouseEvent)
    Public Event ListItemClicked(sender As Zone, Index As Integer, Item As ZoneListItem, e As MouseEvent)
    Public Event ListItemChanged(sender As Zone, Index As Integer, Item As ZoneListItem, e As MouseEvent)
    Public Event MouseMove(sender As Zone, e As MouseEvent)
    Public Event MouseDown(sender As Zone, parent As Zone, e As MouseEvent)
    Public Event MouseUp(sender As Zone, parent As Zone, e As MouseEvent)
    Public Event MouseWheel(sender As Zone, e As MouseEvent)
    Public Event ValueChanged(Value As Double, sender As Zone, parent As Zone, e As MouseEvent)

    Public DrawAction As Action
#Region "Initializers"
    Public Sub New()
        Visible = True
        DefaultHeight = 20
        'DefaultWidth = 50
        'BackColor = DefaultBackColor
        NextAdd = New Point(0, 0)
        NextIsDown = True
        BorderHover = 3
        BorderSize = 1
        BorderFocus = 2
    End Sub

    Public Sub New(_Type As Zones, ByRef _Parent As Zone,
                   _Name As String, _Caption As String,
                   Optional _Bounds() As Single = Nothing,
                   Optional _Alpha As Single = 1,
                   Optional _BackColor As GoColor = Nothing,
                   Optional _ForeColor As GoColor = Nothing,
                   Optional _FontScale As Single = Nothing,
                   Optional _Align As Align = Align.Center,
                   Optional _Vertical As Align = Align.Center)

        If _Alpha = 0 Then _Alpha = 0.7
        SetupZone(_Type, _Parent, _Name, _Caption, _Bounds, _Alpha, _BackColor, _ForeColor, _FontScale, _Align, _Vertical)

    End Sub

    Public Sub SetupZone(_Type As Zones, ByRef _Parent As Zone,
                         _Name As String, _Caption As String,
                         Optional _Bounds() As Single = Nothing,
                         Optional _Alpha As Single = 1,
                         Optional _BackColor As GoColor = Nothing,
                         Optional _ForeColor As GoColor = Nothing,
                         Optional _FontScale As Single = Nothing,
                         Optional _Align As Align = Align.Center,
                         Optional _Vertical As Align = Align.Center)

        Dim _Left As Single = -1, _Top As Single = -1, _Width As Single = -1, _Height As Single = -1
        If _Name Is Nothing Then _Name = ""

        Parent = _Parent
        With Parent

            ZoneType = _Type
            CaptionSize = .CaptionSize

            FontScale = _FontScale
            If FontScale = Nothing Then FontScale = _Parent.FontScale
            If FontScale = 0 Or FontScale = Nothing Then FontScale = DefaultFontScale
            FontScale = Clamp(FontScale, 0.15, 1)
            RootZone = .RootZone
            Padding = .Padding
            ValueSize = .ValueSize
            .HasChildren = True
            If .ChildName.ContainsKey(_Name) Then
                Log($"{Parent.Name} already contains child {_Name}")
                _Name &= " 2"
            End If
            .ChildName.Add(_Name, .Children.Count)

            If Not _Bounds Is Nothing Then
                If _Bounds.Count > 0 Then _Left = _Bounds(0) Else _Left = Parent.NextAdd.X
                If _Bounds.Count > 1 Then _Top = _Bounds(1) Else _Top = Parent.NextAdd.Y
                If _Bounds.Count > 2 Then _Width = _Bounds(2) Else _Width = .DefaultWidth
                If _Bounds.Count > 3 Then _Height = _Bounds(3) Else _Height = .DefaultHeight
            End If
            If _Left = -1 Then _Left = .NextAdd.X Else .NextAdd.X = _Left
            If _Top = -1 Then _Top = .NextAdd.Y Else .NextAdd.Y = _Top
            If _Height = -1 Then _Height = .DefaultHeight
            If _Width = -1 Then _Width = .DefaultWidth
            If .NextIsDown Then           ' Set Width to parent's .W with proper padding
                If _Width = 0 Then _Width = .W - Padding.X * 2 - .NextAdd.X
            End If

            Box = New Rectangle(_Left + Padding.X, _Top + Padding.Y, _Width, _Height)
            ScreenBox = New Rectangle(Parent.ScreenBox.X + Box.X, .ScreenBox.Y + Box.Y, Box.Width, Box.Height)

            If .NextIsDown Then
                .NextAdd.Y += (_Height + Padding.Y)
            Else
                .NextAdd.X += (_Width + Padding.X)
            End If
            Index = .Children.Count

            Name = _Name
            Caption = _Caption
            CaptionAlign = _Align
            CaptionVertical = _Vertical
            Alpha = _Alpha
            AlphaTo = _Alpha
            HoverAlpha.Value = _Alpha

            BackColor = _BackColor
            ForeColor = _ForeColor
            If _BackColor Is Nothing Then BackColor = GlobalDefaultBackColor
            If _ForeColor Is Nothing Then ForeColor = GlobalDefaultForeColor
            If ZoneType <> Zones.Region Then BackColor = Parent.DefaultBackColor

            Visible = True

            Select Case ZoneType
                Case Zones.Button : DrawAction = New Action(AddressOf Draw_Button)
                Case Zones.Fader : DrawAction = New Action(AddressOf Draw_Fader)
                Case Zones.ScrollBar : DrawAction = New Action(AddressOf Draw_Fader)
                Case Zones.Label : DrawAction = New Action(AddressOf Draw_Label)
                Case Zones.List : DrawAction = New Action(AddressOf Draw_List)
                Case Zones.TabStrip : DrawAction = New Action(AddressOf Draw_TabStrip)
                Case Zones.HueMap : DrawAction = New Action(AddressOf Draw_HueMap)
                Case Zones.Button : DrawAction = New Action(AddressOf Draw_Button)
                Case Zones.CheckBox : DrawAction = New Action(AddressOf Draw_CheckBox)
                Case Zones.TheGrid : DrawAction = New Action(AddressOf Draw_TheGrid)
                Case Zones.Number : DrawAction = New Action(AddressOf Draw_Number)
                Case Zones.GamePad : DrawAction = New Action(AddressOf Draw_GamePad)
                Case Zones.Model : DrawAction = New Action(AddressOf Draw_Model)
                Case Zones.TextBox : DrawAction = New Action(AddressOf Draw_TextBox)
                Case Zones.ThreeDee : DrawAction = New Action(AddressOf Draw_ThreeDee)
            End Select
        End With
    End Sub

    Public Sub Setup(NewName As String, ItemPadding As Integer, HoverTransparency As Single,
                     _CaptionSize As Integer, NewBox As Rectangle)
        Box = NewBox : ScreenBox = Box
        'BackColor = DefaultBackColor
        Name = NewName
        Padding = New Point(ItemPadding, ItemPadding)
        BorderHover = 3
        BorderSize = 1
        BorderFocus = 2
        'HoverAlpha.Go = HoverTransparency
        CaptionSize = _CaptionSize
        ZoneType = Zones.Region
    End Sub

    Public Sub SetupSizes(_DefaultWidth As Integer, _DefaultHeight As Integer,
                          _CaptionSize As Integer, _ValueSize As Integer,
                          _PaddingX As Integer, _PaddingY As Integer, _FontScale As Single)

        DefaultWidth = _DefaultWidth
        DefaultHeight = _DefaultHeight
        CaptionSize = _CaptionSize
        ValueSize = _ValueSize
        Padding = New Point(_PaddingX, _PaddingY)
        FontScale = _FontScale

    End Sub
    Public Sub InheritParent(_Parent As Zone)
        Parent = _Parent
        With Parent
            DefaultWidth = .DefaultWidth
            DefaultHeight = .DefaultHeight
            CaptionSize = .CaptionSize
            ValueSize = .ValueSize
            Padding = .Padding
            FontScale = .FontScale
            RootZone = .RootZone
        End With
    End Sub

    Public Sub AddRegion(r As Zone)
        HasChildren = True
        Children.Add(r)
        r.Parent = Me
        r.RootZone = RootZone
        r.DefaultFontScale = 0.3
        With Children(Children.Count - 1)
            AddHandler .GridEvent, AddressOf Child_GridEvent
            AddHandler .ColorChanged, AddressOf Child_ColorChanged
            AddHandler .ListItemClicked, AddressOf Child_ListClicked
            AddHandler .ListItemChanged, AddressOf Child_ListChanged
            AddHandler .MouseDown, AddressOf Child_MouseDown
            AddHandler .MouseMove, AddressOf Child_MouseMoved
            AddHandler .ValueChanged, AddressOf Child_ValueChanged
        End With
    End Sub

    Public Sub Add_SubZone(Z As Zone)
        DefaultFontScale = 0.3
        AddRegion(Z)
        AdjustHeightToBox(LastChild.Box)
        If NextIsDown Then NextAdd.Y += Z.H
    End Sub
#End Region
#Region "Properties"
    Public Property Height As Integer
        Get
            Return H
        End Get
        Set(value As Integer)
            H = value
            ScreenBox.Height = value
            For Each This As Zone In Children
                ' Z.ScreenBox = New Rectangle(ScreenBox.X + Z.X, ScreenBox.Y + Z.Y, Z.W, Z.H)
                If This.AnchorBottom Then
                    This.Height = H - This.Y - 5
                End If
            Next
        End Set
    End Property

    Public Sub Minimize()
        Minimized = Not Minimized
        H = If(Minimized, 2, LastChild.Box.Bottom)
        ScreenBox.Height = H
    End Sub

    Public Property Value As Single
        Get
            Return MyValue
        End Get
        Set(Value As Single)
            MyValue = Clamp(Value, ValueMinimum, ValueMaximum) '* ValuePrecision
        End Set
    End Property

    Public Property Box As Rectangle
        Get
            Return New Rectangle(X, Y, W, H)
        End Get
        Set(Value As Rectangle)
            X = Value.X
            Y = Value.Y
            W = Value.Width
            H = Value.Height
        End Set
    End Property

    Public ReadOnly Property LastChild As Zone
        Get
            If Children.Count > 0 Then
                Return Children(Children.Count - 1)
            End If
        End Get
    End Property

    Public ReadOnly Property SelectedItem() As ZoneListItem
        Get
            If ZoneType = Zones.List Then
                Return ListItems(SelectedIndex)
            Else
                If ChildName.ContainsKey("Tabs") = False Then Return Nothing
                Return Child("Tabs").ListItems(Child("Tabs").SelectedIndex)
            End If
        End Get
    End Property

    Public ReadOnly Property SelectedTab() As Integer
        Get
            If ChildName.ContainsKey("Tabs") = False Then Return Nothing
            Return Child("Tabs").SelectedIndex
        End Get
    End Property
#End Region
#Region "Child and Setting Functions"
    Public Function Child(Name As String) As Zone
        If ChildName.ContainsKey(Name) = False Then
            Log($"Child Zone {Name} not found.")
            Return New Zone
        End If
        Return Children(ChildName(Name))
    End Function

    Public Function Setting(Name As String) As Single
        If ChildName.ContainsKey(Name) = False Then
            Log($"Setting {Name} Not Found.")
            Return 1
        End If
        Return Children(ChildName(Name)).Value
    End Function

    Public Function GetDictionary() As Dictionary(Of String, Single)
        Dim D As New Dictionary(Of String, Single)
        For Each C As Zone In Children
            D.Add(C.Name, C.Value)
        Next
        Return D
    End Function

    Public Sub SetupValue(_Minimum As Double, _Maximum As Double, _Value As Double, _Default As Double, _Precision As Single)
        ValuePrecision = _Precision
        ValueMinimum = _Minimum / ValuePrecision
        ValueMaximum = _Maximum / ValuePrecision
        MyValue = _Value / ValuePrecision
        DefaultValue = _Default / ValuePrecision
        ReDim TrackMarks(0)
    End Sub

    Public Sub SetValue(NewValue As Double)
        MyValue = Clamp(System.Math.Round(NewValue * ValuePrecision, 3),
                        ValueMinimum * ValuePrecision, ValueMaximum * ValuePrecision)
    End Sub
    Public Sub SetValuePercent(Percent As Double)
        'Value =
        SetValue(ValueMinimum + Percent * (ValueMaximum - ValueMinimum))
        RaiseEvent ValueChanged(Value, Me, Nothing, Nothing)

    End Sub

#End Region
#Region "Miscellaneous Functions"
    Public Function Clone() As Object Implements ICloneable.Clone
        Return MyBase.MemberwiseClone
    End Function
   
    Public Overrides Function ToString() As String
        Return $"Zone:{Parent?.Name}{Name} = {ZoneType.ToString}{vbTab}{Box.ToString}{vbTab}{ScreenBox.ToString}"
    End Function

    Public Sub ScrollGo(e As MouseEvent)
        Scroll.Go -= (e.Delta / 120) * 100
        Scroll.Go = Clamp(Scroll.Go, 0, ItemTotalSize)
        ScrollBar.Value = (Scroll.Go / ItemTotalSize) * 100

    End Sub
    Public Property Scrollable As Boolean
        Get
            Return IsScrollable
        End Get
        Set(value As Boolean)
            IsScrollable = value
            If IsScrollable And ScrollBar Is Nothing Then
                ScrollBar = New Zone(Zones.ScrollBar, Me, "ScrollBar", "", {0, W - 20, 20, H}) With
                                    {.ShowCaption = False, .CaptionSize = 0, .ValueSize = 0}
            End If
        End Set
    End Property

    Private Sub ScrollBar_ValueChanged(Value As Double, sender As Zone, parent As Zone, e As MouseEvent)
        Scroll.Go = Value
    End Sub
    Public Sub LineBreak(Optional Height As Integer = 0)
        If Height = 0 Then Height = DefaultHeight + Padding.Y
        NextAdd.Y += Height
    End Sub
    Public Sub AddAt(X As Single, Y As Single)
        NextAdd = New Point(X, Y)
    End Sub
    Public Sub NextColumn(Optional Start As Single = 0, Optional _Y As Single = 0, Optional _ColumnWidth As Single = Nothing)
        If _ColumnWidth <> Nothing Then ColumnWidth = _ColumnWidth
        AddAt(Start + (ColumnWidth + Padding.X) * CurrentColumn, _Y)
        CurrentColumn += 1
    End Sub

    Public Sub Arrange()

        If AutoArrange = False Then Exit Sub
        Dim LastBottom = 0 ' Track(0).Box.Bottom
        Dim PY As Single
        If Parent IsNot Nothing Then PY = Parent.ScreenBox.Y

        For Each Z In Children
            Z.Y = LastBottom
            Z.ScreenBox.Y = Z.Y + ScreenBox.Y
            Z.MoveRegion()
            LastBottom = Z.Box.Bottom + If(Z.Minimized, 0, 2)
        Next
        H = LastBottom
        ScreenBox.Height = LastBottom + Padding.Y

    End Sub

    Public Sub MoveRegion()
        For Each R As Zone In Children
            If R.H = -1 Then R.H = ScreenBox.Height - R.Y - Padding.Y * 2
            R.ScreenBox = New Rectangle(ScreenBox.X + R.X, ScreenBox.Y + R.Y, R.W, R.H)
            R.MoveRegion()
        Next
    End Sub
    Public Sub MoveChilden()
        For Each R As Zone In Children
            R.ScreenBox = New Rectangle(R.Parent.ScreenBox.X + R.X, R.Parent.ScreenBox.Y + R.Y, R.W, R.H)
            R.MoveChilden()
        Next
    End Sub

    Public Sub AdjustHeightToBox(_Box As Rectangle)
        If ScreenBox.Height < _Box.Bottom + Padding.Y Then
            H = _Box.Bottom + Padding.Y
            ScreenBox.Height = _Box.Bottom + Padding.Y
        End If
    End Sub
#End Region
#Region "Focus / Hovering Functions"
    Public Sub UnFocusAll()
        If RootZone Is Nothing Then
            Log(Name & " rootzone nothing")
            Exit Sub
        End If
        For Each Z As Zone In RootZone.Children
            UnFocusChildren(Z)
        Next
    End Sub

    Public Sub UnFocusChildren(Root As Zone)
        For Each Z As Zone In Children
            Z.Focused = False
            Z.Hovering = False
            Z.MousePressed = False
            Z.UnFocusChildren(Z)
        Next
    End Sub

    Public Sub UnHoverAll()
        For Each Z As Zone In Children
            Z.Hovering = False
            If Z.HasChildren Then Z.UnHoverAll()
        Next
    End Sub
    Public Sub SetFocusMouse()
        If MouseLocked = False Then
            SetFocus()
            MousePressed = True
            MouseLocked = True
        End If
    End Sub
    Public Sub UnFocusMouse()
        MousePressed = False
        MouseLocked = False
        If Focused Then FocusRegion = Nothing
    End Sub
    Public Sub SetFocus()
        Parent.RootZone.UnFocusAll()
        If FocusRegion IsNot Nothing Then FocusRegion.Focused = False
        FocusRegion = Me
        Focused = True
    End Sub
    Public Sub SetHovering()
        ' UnHoverAll()
        GlobalUI.UnHoverAll()
        If HoverRegion IsNot Nothing Then HoverRegion.Hovering = False
        HoverRegion = Me
        Hovering = True
    End Sub
#End Region

ZoneAdd.vb

Imports JEOCORE
Imports OpenTK.Graphics.OpenGL
Imports System.Drawing
Imports System.Windows.Forms
Partial Public Class Zone

    Public Function Add(Type As Zones, ByRef _Parent As Zone,
                        Name As String, Caption As String,
                        Optional _Bounds() As Single = Nothing,
                        Optional _Alpha As Single = Nothing,
                        Optional _BackColor As GoColor = Nothing,
                        Optional _ForeColor As GoColor = Nothing,
                        Optional _FontScale As Single = Nothing,
                        Optional _Align As Align = Align.Center,
                        Optional _Vertical As Align = Align.Center) As Zone

        Dim This As New Zone(Type, _Parent, Name, Caption, _Bounds,
                             _Alpha, _BackColor, _ForeColor, _FontScale, _Align, _Vertical)
        AdjustHeightToBox(This.Box)
        Children.Add(This)
        AddHandler This.MouseDown, AddressOf Child_MouseDown
        If Type = Zones.CheckBox Then
            AddHandler This.ValueChanged, AddressOf Child_ValueChanged
        End If
        Return This

    End Function

    Public Function Add_Button(Caption As String, Optional _Bounds() As Single = Nothing,
                               Optional _FontScale As Single = Nothing,
                               Optional _Alpha As Single = 0,
                               Optional _BackColor As GoColor = Nothing,
                               Optional _ForeColor As GoColor = Nothing,
                               Optional _Align As Align = Align.Center,
                               Optional _Vertical As Align = Align.Center) As Zone

        Return Add(Zones.Button, Me, Caption, Caption, _Bounds,
                   _Alpha, New GoColor(0.5, 0.5, 0.5, 1.0), New GoColor(0.5, 0.5, 0.5, 1.0), _FontScale, _Align, _Vertical)

    End Function

    Public Function Add_Caption(Caption As String, Optional _Bounds() As Single = Nothing,
                                Optional _FontScale As Single = Nothing,
                                Optional _Alpha As Single = 0,
                                Optional _BackColor As GoColor = Nothing,
                                Optional _ForeColor As GoColor = Nothing,
                                Optional _Align As Align = Align.Near,
                                Optional _Vertical As Align = Align.Center) As Zone

        Return Add(Zones.Label, Me, Caption, Caption, _Bounds,
                   _Alpha, _BackColor, _ForeColor, _FontScale, _Align, _Vertical)

    End Function

    Public Function Add_HueMap(Caption As String, Optional _Bounds() As Single = Nothing) As Zone

        Dim This As New Zone(Zones.HueMap, Me, Caption, Caption, _Bounds, 0.7, BackColor)
        AdjustHeightToBox(This.Box)
        CaptionSize = 0
        Children.Add(This)
        AddHandler This.MouseDown, AddressOf Child_MouseDown
        Return This

    End Function

    Public Function Add_Color(_Name As String, HueWidth As Single, HueHeight As Single,
                              Optional _Bounds() As Single = Nothing,
                              Optional _FontScale As Single = Nothing,
                              Optional _Alpha As Single = 0,
                              Optional _BackColor As GoColor = Nothing,
                              Optional _ForeColor As GoColor = Nothing) As Zone

        Dim Color As New ColorZone
        Color.SetupInterface(_Name, Me, HueWidth, HueHeight, _Bounds, _FontScale)
        Add_SubZone(Color)
        Return Color

    End Function

    Public Function Add_Check(Caption As String,
                              Optional _Bounds() As Single = Nothing,
                              Optional _FontScale As Single = Nothing,
                              Optional _Alpha As Single = 0,
                              Optional _Checked As Boolean = False,
                              Optional _BackColor As GoColor = Nothing,
                              Optional _ForeColor As GoColor = Nothing,
                              Optional _Align As Align = Align.Near,
                              Optional _Vertical As Align = Align.Center) As Zone

        Return Add(Zones.CheckBox, Me, Caption, Caption, _Bounds,
                   _Alpha, _BackColor, _ForeColor, _FontScale, _Align, _Vertical)

        Checked = _Checked

    End Function

    Public Function Add_GamePad(Name As String,
                                Optional _Bounds() As Single = Nothing,
                                Optional _FontScale As Single = Nothing,
                                Optional _Alpha As Single = 0) As Zone

        ' Dim This As New Zone
        Dim This As New Zone(Zones.GamePad, Me, Name, Name & ":", _Bounds,
                             _Alpha, Nothing, Nothing, _FontScale)
        This.FontScale = _FontScale
        AdjustHeightToBox(This.Box)
        Children.Add(This)
        AddHandler This.MouseDown, AddressOf Child_MouseDown
        Return This

    End Function

    Public Function Add_GoFaders(GoNumbers() As GoNumber, Optional _FontScale As Single = Nothing,
                                 Optional _Alpha As Single = Nothing)

        For Each G As GoNumber In GoNumbers
            Add_FaderGo(G, _FontScale:=_FontScale, _Alpha:=_Alpha)
        Next

    End Function

    Public Function Add_FaderGo(Go As GoNumber, Optional Caption As String = "",
                                Optional TrackType As TrackerTypes = TrackerTypes.Normal,
                                Optional _Bounds() As Single = Nothing,
                                Optional _FontScale As Single = Nothing,
                                Optional _Alpha As Single = Nothing,
                                Optional _BackColor As GoColor = Nothing,
                                Optional _ForeColor As GoColor = Nothing)

        If Caption = "" Then Caption = Go.SpaceName

        Dim This As New Zone(Zones.Fader, Me, Go.GoName, Caption & ":", _Bounds,
                             _Alpha, _BackColor, _ForeColor, _FontScale)
        This.TrackerType = TrackType
        This.SetupValue(Go.Minimum, Go.Maximum, Go.Go, Go.DefaultValue, Go.Precision)
        This.WheelSpeed = 10 * Go.Precision
        'This.ValuePrecision = _Precision
        This.CaptionSize = CaptionSize

        AdjustHeightToBox(This.Box)
        Children.Add(This)
        AddHandler This.ValueChanged, AddressOf Child_ValueChanged
        Return This

    End Function

    Public Function Add_Fader(Caption As String, Min As Double, Max As Double, Value As Double,
                              Optional _Precision As Single = 1,
                              Optional TrackType As TrackerTypes = TrackerTypes.Normal,
                              Optional _Bounds() As Single = Nothing,
                              Optional _FontScale As Single = Nothing,
                              Optional _Alpha As Single = Nothing,
                              Optional _BackColor As GoColor = Nothing,
                              Optional _ForeColor As GoColor = Nothing) As Zone

        Dim This As New Zone(Zones.Fader, Me, Caption, Caption & ":", _Bounds,
                             _Alpha, _BackColor, _ForeColor, _FontScale)
        This.TrackerType = TrackType
        This.SetupValue(Min, Max, Value, Value, _Precision)
        This.WheelSpeed = 10 * _Precision
        If _Precision = 1 Then This.WheelSpeed = 1
        'This.ValuePrecision = _Precision
        This.CaptionSize = CaptionSize

        AdjustHeightToBox(This.Box)
        Children.Add(This)
        AddHandler This.ValueChanged, AddressOf Child_ValueChanged
        Return This

    End Function

    Public Function Add_Scrollbar(Caption As String, Min As Double, Max As Double, Value As Double,
                                  Optional _Precision As Single = 1,
                                  Optional TrackType As TrackerTypes = TrackerTypes.Normal,
                                  Optional _Bounds() As Single = Nothing,
                                  Optional _FontScale As Single = Nothing,
                                  Optional _Alpha As Single = 0,
                                  Optional _BackColor As GoColor = Nothing,
                                  Optional _ForeColor As GoColor = Nothing) As Zone

        Dim This As New Zone
        With This
            .TrackerType = TrackType
            '.ParentRegion = Me
            .SetupZone(Zones.ScrollBar, Me, Caption, Caption & ":", _Bounds,
                       _Alpha, _BackColor, _ForeColor, _FontScale)
            .CaptionSize = 0
            .SetupValue(Min, Max, Value, Value, _Precision)
            '.ShowCaption = False
            AdjustHeightToBox(.Box)
        End With
        Children.Add(This)
        AddHandler This.ValueChanged, AddressOf Child_ValueChanged
        Return This

    End Function
    Public Function Add_Number(Caption As String, Min As Double, Max As Double, Value As Double,
                               Optional _Bounds() As Single = Nothing,
                               Optional _FontScale As Single = 0,
                               Optional _Alpha As Single = 0,
                               Optional _ButtonSize As Integer = 0,
                               Optional _BackColor As GoColor = Nothing,
                               Optional _ForeColor As GoColor = Nothing) As Zone

        Dim This As New Zone(Zones.Number, Me, Caption, Caption, _Bounds,
                             _Alpha, _BackColor, _ForeColor, _FontScale)
        This.SetupValue(Min, Max, Value, Value, 1)
        AdjustHeightToBox(This.Box)
        If _ButtonSize <> 0 Then This.ButtonSize = _ButtonSize Else This.ButtonSize = Box.Width - 8
        Children.Add(This)
        AddHandler This.MouseDown, AddressOf Child_MouseDown
        AddHandler This.ValueChanged, AddressOf Child_ValueChanged
        Return This

    End Function

    Public Function TrackerPosition(_Value As Single) As Single
        If Single.IsInfinity(ValueMinimum) Then Return 0
        Return CaptionSize + ((_Value - ValueMinimum) / (ValueMaximum - ValueMinimum)) * TrackerBox.Width
    End Function

    Public Function Add_Model(Caption As String, Optional _Bounds() As Single = Nothing,
                              Optional _FontScale As Single = Nothing,
                              Optional _Alpha As Single = 0,
                              Optional _BackColor As GoColor = Nothing,
                              Optional _ForeColor As GoColor = Nothing,
                              Optional _Align As Align = Align.Center,
                              Optional _Vertical As Align = Align.Center) As Zone

        Dim This As New Zone(Zones.Model, Me, Caption, Caption, _Bounds,
                             _Alpha, _BackColor, _ForeColor, _FontScale, _Align, _Vertical)
        'This.DrawAction = New Action(AddressOf Draw_Model)
        Return This

    End Function


    Public Function Add_ListItem(ByRef Caption As String, Optional _BackColor As GoColor = Nothing, Optional Tag As String = "") As Integer

        Dim NewItem As New ZoneListItem
        NewItem.Caption = Caption
        If _BackColor Is Nothing Then _BackColor = Parent.DefaultBackColor
        NewItem.BackColor = _BackColor
        NewItem.Tag = Tag
        ListItems.Add(NewItem)
        ItemSize = ListItems.Count / Box.Height
        ItemTotalSize = ListItems.Count * ItemSize

        Return ListItems.Count

    End Function
    Public Sub Add_ListArray(Captions() As String, Tags() As String, Optional Append As Boolean = False)
        If Append = False Then ListItems.Clear()
        'Items = New List()
        If Tags Is Nothing Then Tags = Captions
        For i = 0 To Captions.Count - 1
            'For Each s As String In Captions
            Add_ListItem(Captions(i), Parent.DefaultBackColor, Tags(i))
        Next
    End Sub
    Public Sub Add_ListCheckBoxes(_Count As Integer, Optional Append As Boolean = False)
        If Append = False Then ListItems.Clear()
        For i = 0 To _Count - 1
            Add_ListItem(i, BackColor)
        Next
    End Sub
    Public Function Add_Data(Name As String, Optional _Default As String = "",
                             Optional _Bounds() As Single = Nothing,
                             Optional _FontScale As Single = Nothing,
                             Optional _Alpha As Single = 0,
                             Optional _Scrollable As Boolean = False,
                             Optional _BackColor As GoColor = Nothing,
                             Optional _ForeColor As GoColor = Nothing)

        Dim This As New Zone(Zones.Data, Me, Name, Name, _Bounds, _Alpha, _BackColor, _ForeColor, _FontScale)
        AdjustHeightToBox(This.Box)
        This.Scrollable = _Scrollable
        If This.Scrollable Then This.Scissor = True

    End Function
    Public Function Add_List(Name As String, Captions() As String, Optional Tags() As String = Nothing,
                             Optional _Bounds() As Single = Nothing,
                             Optional _FontScale As Single = Nothing,
                             Optional _Alpha As Single = 0,
                             Optional _Align As Align = Align.Near,
                             Optional CheckBoxes As Boolean = False,
                             Optional _ShowCaptions As Boolean = True,
                             Optional _Scrollable As Boolean = False,
                             Optional _BackColor As GoColor = Nothing,
                             Optional _ForeColor As GoColor = Nothing) As Zone

        Dim This As New Zone(Zones.List, Me, Name, Name, _Bounds,
                             _Alpha, _BackColor, _ForeColor, _FontScale)
        AdjustHeightToBox(This.Box)
        This.BackColor = GlobalDefaultBackColor
        This.DefaultBackColor = _BackColor
        This.Add_ListArray(Captions, Tags)
        This.ListCheckBoxes = CheckBoxes
        This.ShowCaption = _ShowCaptions
        This.CaptionAlign = _Align
        This.Scrollable = _Scrollable
        If This.Scrollable Then This.Scissor = True
        Children.Add(This)
        AddHandler This.MouseWheel, AddressOf Child_MouseWheel
        AddHandler This.ListItemClicked, AddressOf Child_ListClicked
        'This.DrawAction = New Action(AddressOf Draw_List)
        Return This

    End Function
    Public Function Add_TabStrip(Name As String, Captions() As String,
                                 Optional _Bounds() As Single = Nothing,
                                 Optional _FontScale As Single = Nothing,
                                 Optional _Alpha As Single = 0,
                                 Optional _BackColor As GoColor = Nothing,
                                 Optional _ForeColor As GoColor = Nothing) As Zone

        Dim This As New Zone(Zones.TabStrip, Me, Name, Name, _Bounds,
                             _Alpha, _BackColor, _ForeColor, _FontScale)
        AdjustHeightToBox(This.Box)
        This.Add_ListArray(Captions, Captions)
        Children.Add(This)
        AddHandler This.ListItemClicked, AddressOf Child_ListClicked
        'This.DrawAction = New Action(AddressOf Draw_TabStrip)
        Return This

    End Function



    Public Function Add_TextBox(Name As String, Optional DefaultText As String = "",
                               Optional _Bounds() As Single = Nothing,
                               Optional _FontScale As Single = Nothing,
                               Optional _Alpha As Single = Nothing,
                               Optional _BackColor As GoColor = Nothing,
                               Optional _ForeColor As GoColor = Nothing)



        Dim This As New Zone(Zones.TextBox, Me, Name, DefaultText, _Bounds,
                             _Alpha, _BackColor, _ForeColor, _FontScale)
        This.Code = New CodeText("")

        AddHandler This.MouseMove, AddressOf Child_MouseMoved
        AddHandler This.MouseWheel, AddressOf Child_MouseWheel

        'This.DrawAction = New Action(AddressOf Draw_TextBox)
        Return This


    End Function


    Public Function Add_ThreeDee(_Name As String,
                                 Optional _Bounds() As Single = Nothing,
                                 Optional _FontScale As Single = Nothing,
                                 Optional _Alpha As Single = 0,
                                 Optional _BackColor As GoColor = Nothing,
                                 Optional _ForeColor As GoColor = Nothing) As Zone

        Dim This As New Zone(Zones.ThreeDee, Me, _Name, _Name & ":", _Bounds,
                             _Alpha, _BackColor, _ForeColor, _FontScale)
        This.WheelSpeed = 0.05

        AdjustHeightToBox(This.Box)
        Children.Add(This)
        AddHandler This.ValueChanged, AddressOf Child_ValueChanged
        'This.DrawAction = New Action(AddressOf Draw_ThreeDee)
        Return This

    End Function


    Public Function Add_TheGrid(Name As String, Cols As Integer, Rows As Integer,
                                Optional _Bounds() As Single = Nothing,
                                Optional _FontScale As Single = Nothing,
                                Optional _Alpha As Single = 0,
                                Optional _BackColor As GoColor = Nothing,
                                Optional _ForeColor As GoColor = Nothing) As Zone

        Dim This As New Zone
        With This
            '.ParentRegion = Me
            Caption = Name
            .SetupZone(Zones.TheGrid, Me, Caption, Caption & ":", _Bounds,
                       _Alpha, BackColor, ForeColor, _FontScale)
            .CaptionSize = 0
            '.GridSize = New Point(Cols, Rows)
            .ShowCaption = False
            AdjustHeightToBox(.Box)
        End With
        Children.Add(This)
        '   AddHandler This.ValueChanged, AddressOf Child_ValueChanged
        AddHandler This.GridEvent, AddressOf Child_GridEvent
        Return This

    End Function

End Class
 
 
 
 
MyBBXP is having trouble with the MyBB database connection, perhaps re-check your settings
?

Leave a Reply