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.