wxMax > MaxGUI

wxMaxThe title of this article says it all. I'm currently working on the next 'iteration' of Gunstyle with a fellow developer and over the past weekend we were in need of a GUI library to help develop our map editor. In the past maxGUI 'worked' more or less....emphasis on the less. The design of maxGUI left me with a bad taste in my mouth. It's a procedural library that is cobbled together with some weak OO on top that didn't provide much flexibility (not to mention it wasn't exactly 'native' UI on different platforms). Either way, it was a good library for small projects and prototypes.

Now we're working on something of a little bit bigger in scale, and needing a more heavy duty gui library to go with it. So we chose Brucey's wxMax GUI Module for Blitzmax. Just picking it up over the weekend has been a joy to work with. It's object-oriented from the get go so it's a bit easier to integrate into already established OO code.  It also boasts being cross-platform (Win/Linux/Mac), but I've yet to test or need this functionality yet. It's also wrapping a rather solid and established library, wxWidgets.

One of the main requirements was for us to develop a GUI around a game framework that would allow us to switch in and out of an editor on the fly. To test this type of functionality I whipped up a basic test file that switches from the standard Blitzmax graphics window to a wxMax GUI with a GLCanvas and back again several times. Below is the actual source for doing that type of switching, in case anyone wants to do something similar:

SuperStrict

Framework wx.wxApp
Import brl.glmax2d
Import brl.standardio
Import wx.wxFrame
Import wx.wxPanel
Import wx.wxGLCanvas
Import wx.wxglmax2d
Import brl.max2d
Import wx.wxTimer
Import brl.pngloader

Global app:TestApp = New TestApp
Global imgTest:TImage
Global imgPath:String = "myTestImage.png"

SetGraphicsDriver(brl.GLMax2D.GLMax2DDriver()) ' needed in order for the normal gfx driver to run
SetGraphics(Graphics(800, 600)) ' set context back to main window

' test switching between max2D and wxMax
' while loading an image that is shared between the two modes
If FileType(imgPath) = 0 Then
    Notify "invalid path for image. file does not exist"
    EndGraphics()
    End
End If

imgTest = LoadImage(imgPath)
SetBlend(ALPHABLEND)

RunBmaxGraphics()
app.Run()
RunBmaxGraphics()
app.Run()

Function RunBmaxGraphics()
    SetGraphicsDriver(brl.GLMax2D.GLMax2DDriver()) ' needed in order for the normal gfx driver to run
    SetGraphics(Graphics(800, 600)) ' set context back to main window
    While Not(KeyHit(KEY_ESCAPE))
        Cls
        If KeyHit(KEY_D) Then
            Exit
        End If
        DrawImage(imgTest, 100, 100)
        Flip
    WEnd
    EndGraphics()
End Function

Type TestApp Extends wxApp
    Field frame:wxFrame
    Field panel:wxPanel
    Field canvas:TMax2DCanvas
   
    Method OnInit:Int()
        frame = New wxFrame.Create(,, "Test", 0, 0, 1024, 768)
        frame.Center()
       
        panel = New wxPanel.Create(frame, wxID_ANY, 160, 0, 1024, 768)
        canvas = TMax2DCanvas(New TMax2DCanvas.Create(panel, wxID_ANY, GRAPHICS_BACKBUFFER | GRAPHICS_DEPTHBUFFER, 0, 0, 1024, 768))
       
        frame.Show()
       
        Return True
    End Method
   
End Type

Type GLFrame Extends wxFrame
    Field canvas:TMax2DCanvas
   
    Method OnInit()
        canvas = TMax2DCanvas(New TMax2DCanvas.Create(Self, -1, GRAPHICS_BACKBUFFER | GRAPHICS_DEPTHBUFFER))
        ConnectAny(wxEVT_CLOSE, OnClose)
       
    End Method
   
    Function OnClose(event:wxEvent)
        GLFrame(event.parent).canvas.timer.Stop()
        event.Skip()
       
    End Function
End Type

Type TMax2DCanvas Extends wxGLCanvas
    Field timer:wxTimer
   
    Method OnInit()
        SetBackgroundStyle(wxBG_STYLE_CUSTOM)
        timer = New wxTimer.Create(Self)
        wx.wxglmax2d.GLMax2DDriver().SetBlend(ALPHABLEND)
        timer.Start(100)
        ConnectAny(wxEVT_TIMER, OnTick)
    End Method
   
    Method OnPaint(event:wxPaintEvent)
        Render()
    End Method
   
    Method Render()
        SetGraphics CanvasGraphics2D(Self)
       
        Cls
            DrawImage(imgTest, 100, 100)
        Flip
       
    End Method
    Function OnTick(event:wxEvent)
        wxWindow(event.parent).Refresh()
    End Function
End Type

The main benefit of the above setup is seen in the switching between 'RunBmaxGraphics()' and 'app.run()'. I can switch from my normal game logic, to an editor logic, but still use the same rendering routines! Now I'm not 100% positive that resources such as TImage will persist after a graphics change (in my case they do, but I don't think that's universal) so you may be required to reload textures.

Leave a Comment