I have another problem, perhaps somebody knows how to fix this. In my current project I'm using the OpenB3D framework, a MaxGUI window with two canvases and a custom OTF font loaded using TImagefont. There is an interesting problem with the second canvas (depends on which one is activated): the font doesn't work correct in either the first or the second canvas. I've even tried to fix the BeginMax2D/EndMax2D functions but this didn't work. I've reduced the problem to a small demo (here using the Arial TTF from the OS instead of a custom OTF, makes no difference), press SPACE to switch between the MAXGUI BeginMax2D command and a fixed Begin2D command.
I must have two different canvases in MaxGUI (one uses 2D only, one 2D+3D) and they should be updated separately as they are organized in tabs in my application, with an additional third tab which contains a textfield for debug output. Everything works in the second canvas but the font in the first only shows a "filled" version of the font. beside that I'm absolutely unsure about if I've implemented the Hook/Mainloop and the Timer/Paint events correct. It's a real showstopper for my project, a tiny tool for Explorers in the game Elite Dangerous :(
EDIT: oh and by the way - does somebody know how to get Bruceys wx.mod (https://github.com/maxmods/wx.mod) running on BlitzMaxOS? It compiled but I only get errors when I try to run an example. I'm not very happy with MAXGUI and would like to change to a more customizable GUI.
SuperStrict
Framework openb3d.b3dglgraphics
Import MaxGui.Drivers
Import brl.Timer
Import brl.EventQueue
Import BRL.freetypefont
SetGraphicsDriver GLMax2DDriver()
' MAXGUI stuff
Global width:Int = 320
Global Height:Int = 240
Global wx:Int = (ClientWidth(Desktop()) - width) / 2
Global wy:Int = (ClientHeight(Desktop()) - Height) / 2
Global Window1:TGadget = CreateWindow("First Canvas", wx, wy, width, Height, Null, WINDOW_TITLEBAR | WINDOW_CLIENTCOORDS)
Global canvas1:TGadget = CreateCanvas(0, 0, 320, 240, Window1)
Global window2:TGadget = CreateWindow("Second Canvas", wx * 1.25, wy * 1.25, width, Height, Null, WINDOW_TITLEBAR | WINDOW_CLIENTCOORDS)
Global canvas2:TGadget = CreateCanvas(0, 0, 320, 240, window2)
ActivateGadget(canvas2)
' load font
Global Font:TImageFont = LoadImageFont(getenv_("WINDIR") + "/Fonts/Arial.ttf", 32)
Global switch:Int = 0
Global switchtext:String[] = ["MAX2D", "MAX2D fixed"]
' OpenB3D stuff
SetGraphics CanvasGraphics(canvas1)
Graphics3D width, Height, 0, 2, 60, -1, True
Global cam:TCamera = CreateCamera()
Global mesh:TMesh = CreateCube()
Global light:TLight = CreateLight(1)
AmbientLight 0, 0, 0
PositionEntity mesh, 0, 0, 3
CreateTimer 60
' hook
AddHook EmitEventHook, LoopHook
' main loop
Repeat
WaitEvent()
Forever
End
' ----------------------------------------------------------------------------
' Loop Hook
' ----------------------------------------------------------------------------
Function LoopHook:Object(id:Int, data:Object, context:Object)
Local Event:TEvent = TEvent(data)
If Event = Null Then Return Event
Select Event.id
Case EVENT_TIMERTICK
TurnEntity mesh, 0.5, 1, 0.5
RedrawGadget canvas1
RedrawGadget canvas2
Case EVENT_GADGETPAINT
Select Event.source
Case canvas1
SetGraphics CanvasGraphics(canvas1)
Cls
RenderWorld
If switch Then Begin2D() Else BeginMax2D()
SetBlend ALPHABLEND
SetColor(255, 0, 0)
SetImageFont Font
DrawText switchtext[switch], 0, 0
If switch Then End2D() Else EndMax2D()
Flip False
Case canvas2
SetGraphics CanvasGraphics(canvas2)
Cls
RenderWorld
If switch Then Begin2D() Else BeginMax2D()
SetBlend ALPHABLEND
SetColor(0, 255, 0)
SetImageFont Font
DrawText switchtext[switch], 0, 0
If switch Then End2D() Else EndMax2D()
Flip false
End Select
Case EVENT_KEYDOWN
Select Event.data
Case KEY_SPACE
switch = 1 - switch
End Select
Case EVENT_WINDOWCLOSE
FreeGadget canvas1
FreeGadget canvas2
End
Case EVENT_APPTERMINATE
End
End Select
End Function
' Fixed BeginMax2D()
Function Begin2D()
Local x:Int, y:Int, w:Int, h:Int
GetViewport(x, y, w, h)
glDisable(GL_LIGHTING)
glDisable(GL_DEPTH_TEST)
glDisable(GL_SCISSOR_TEST)
glDisable(GL_FOG)
glDisable(GL_CULL_FACE)
glMatrixMode GL_TEXTURE
glLoadIdentity
glMatrixMode GL_PROJECTION
glLoadIdentity
glOrtho 0, width, Height, 0, -1, 1
glMatrixMode GL_MODELVIEW
glLoadIdentity
SetViewport x, y, w, h
Local MaxTex:Int
glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))
For Local Layer:Int = 0 Until MaxTex
glActiveTexture(GL_TEXTURE0+Layer)
glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)
glDisable(GL_TEXTURE_2D)
Next
glActiveTexture(GL_TEXTURE0)
glViewport(0, 0, width, Height)
glScissor(0, 0, width, Height)
glEnable GL_BLEND
glEnable(GL_TEXTURE_2D)
End Function
' Fixed EndMax2D()
Function End2D()
glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)
glDisable(GL_TEXTURE_2D)
glDisable GL_BLEND
TGlobal.EnableStates()
TGlobal.alpha_enable[0] = 0 ' alpha blending was disabled by Max2d (GL_BLEND)
TGlobal.blend_mode[0] = 1 ' force alpha blending
TGlobal.fx1[0] = 0 ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
TGlobal.fx2[0] = 1 ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)
glClearDepth(1.0)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
glAlphaFunc(GL_GEQUAL, 0.5)
For Local cam:TCamera=EachIn TCamera.cam_list
' active camera - was if cam.hide[0]=0
If cam = TGlobal.camera_in_use
' fog with Max2d fix
cam.UpdateFog()
Exit
EndIf
Next
End Function
wx.mod: works here (linux).
For Windows it is always a matter of using the right MinGW ... I think I was using TDM 4.6 to do the job - so you might give it a try.
Of course error lines would help (blitzmax errors or gcc errors?).
@ font error
cannot try it now but did you check if it works with 2 max2d-canvases only? Maybe openb3d is changing a opengl-variable (matrix, modes,....) which disturbs the font rendering?
bye
Ron
I remember doing Max2D and OpenB3D and have to do the Max2D Begin and End functions. I think you also need to play around with the AlphaBlend settings and if I'm not mistaken there's a fix/patch that you need to apply to make it work, though I'm not sure and I have to dig it up when I get a chance.
I have not tried using MaxGUI and OpenB3D, but there's a demo on both provided in the download or repo.
MaxGUI
https://github.com/markcwm/openb3d.mod/blob/master/examples/minib3d/maxgui.bmx
Max2D
https://github.com/markcwm/openb3d.mod/blob/master/examples/minib3d/max2d.bmx
Hmm, without OpenB3D it works, but only when I comment the SetGraphicsDriver GLMax2DDriver() line, uncommented the same error occurs.
For the wx problem, I'm using BlitzMaxOS with MinGW 5.1.0.2 here. I'm only getting a fatal error (see attachment), the modules compiles without any errors, the program too (in Debug and Release mode). But it just crashes. Does it work with 5.1 or only with 4.x? This would be too bad and I must stay with MAXGUI then. And is it normal that a simple demo like aboutbox takes 10MB space? Huh?
I'll take a look at the OpenB3D examples later, my wife is hungry and she shouldn't wait for the cook ;)
SuperStrict
Import maxgui.Drivers
Import brl.Timer
Import brl.EventQueue
Import BRL.freetypefont
'SetGraphicsDriver GLMax2DDriver()
' MAXGUI stuff
Global width:Int = 320
Global Height:Int = 240
Global wx:Int = (ClientWidth(Desktop()) - width) / 2
Global wy:Int = (ClientHeight(Desktop()) - Height) / 2
Global Window1:TGadget = CreateWindow("First Canvas", wx, wy, width, Height, Null, WINDOW_TITLEBAR | WINDOW_CLIENTCOORDS)
Global canvas1:TGadget = CreateCanvas(0, 0, 320, 240, Window1)
Global window2:TGadget = CreateWindow("Second Canvas", wx * 1.25, wy * 1.25, width, Height, Null, WINDOW_TITLEBAR | WINDOW_CLIENTCOORDS)
Global canvas2:TGadget = CreateCanvas(0, 0, 320, 240, window2)
ActivateGadget(canvas1)
' load font
Global Font:TImageFont = LoadImageFont(getenv_("WINDIR") + "/Fonts/Arial.ttf", 32)
Global switch:Int = 0
Global switchtext:String[] = ["MAX2D", "MAX2D fixed"]
SetGraphics CanvasGraphics(canvas1)
CreateTimer 60
' hook
AddHook EmitEventHook, LoopHook
' main loop
Repeat
WaitEvent()
Forever
End
' ----------------------------------------------------------------------------
' Loop Hook
' ----------------------------------------------------------------------------
Function LoopHook:Object(id:Int, data:Object, context:Object)
Local Event:TEvent = TEvent(data)
If Event = Null Then Return Event
Select Event.id
Case EVENT_TIMERTICK
RedrawGadget canvas1
RedrawGadget canvas2
Case EVENT_GADGETPAINT
Select Event.source
Case canvas1
SetGraphics CanvasGraphics(canvas1)
Cls
SetBlend ALPHABLEND
SetColor(255, 0, 0)
SetImageFont Font
DrawText switchtext[switch], 0, 0
Flip False
Case canvas2
SetGraphics CanvasGraphics(canvas2)
Cls
SetBlend ALPHABLEND
SetColor(0, 255, 0)
SetImageFont Font
DrawText switchtext[switch], 0, 0
Flip False
End Select
Case EVENT_KEYDOWN
Select Event.data
Case KEY_SPACE
switch = 1 - switch
End Select
Case EVENT_WINDOWCLOSE
FreeGadget canvas1
FreeGadget canvas2
End
Case EVENT_APPTERMINATE
End
End Select
End Function
10 megs is because it contains the complete wx library - so even if you only added a button, you compile the code for rich edits etc into the exe. And wx creates everything "on its own", so it does not rely on some simple calls to a windows library.
This explains the 10 mb.
Stripping it might reduce file size a bit.
@ EAV
You might consider trying to build it in "debug" mode and you will see where it errors out...
(https://www.syntaxbomb.com/proxy.php?request=http%3A%2F%2Fi.imgur.com%2FVzDo5iZ.png&hash=44505f32e0b072989f7e7fd0a3d570efb4102d41)
I then used "GLMax2DDriver()" (as I am running my XP in a VirtualBox and so only have proper access to OpenGL). ... it created two windows but they do not refresh without artifacts (might be my VirtualBox thing...).
So might it be that with D3D (and the blitzmax-implementation) you cannot have 2 canvases?
bye
Ron
If I run the app with SetGraphicsDriver GLMax2DDriver() commented, it works a charm here...
If I uncomment it, canvas1 is fine and the text is clear, canvas2 on the other hand, the text is garbage!
Dabz
Little more detail that I've found...
Right, canvasthing3.png is the one that runs as expected (With SetGraphicsDriver GLMax2DDriver() commented out)...
canvasthing1.png is what I get (When SetGraphicsDriver GLMax2DDriver() isnt commented out) when I click on canvas1 first, then hit Space...
canvasthing2.png on the other hand, is what I get (When SetGraphicsDriver GLMax2DDriver() isnt commented out) when I click on canvas2 first (Bringing it to the front), then hitting Space!
Not a clue whats happening there mind, because as I recall... That did work as expected, and I cannot see nothing wrong with the code!?!
Dabz
You should be able to create multiple windows with the direct3d drivers too.
I get an EAV on the D3D9Max2DDriver.
I also get the same garbage text that Dabz is getting without bringing in the openb3d module.
Win7 x64.
Without digging deep I *think* the problem is because the font uses textures for the glyphs. The textures are created by an underlying context. That context is different for each window. If I recall correctly you shouldn't share textures across glcontexts ( across windows ) ?? Someone should correct me there. Also isn't there glShareContexts type of function that may be of use?
Creating and using a second font for the second window solves the immediate issue for me.
Not sure what's going with D3D9 though - I haven't looked into that one and I need an early night ;D
Just checked with D3D9Max2DDriver, and, works... I had to check as it's been that long I wasnt sure what BlitzMax defaulted to when you just use Graphics()
Dabz
GlShareContexts(). That's it, thanks col! But the text only works with my modified Begin2D() / End2D() functions - but that's ok.
SuperStrict
Framework openb3d.b3dglgraphics
Import MaxGui.Drivers
Import brl.Timer
Import brl.EventQueue
Import BRL.freetypefont
SetGraphicsDriver GLMax2DDriver()
GLShareContexts()
' MAXGUI stuff
Global width:Int = 320
Global Height:Int = 240
Global wx:Int = (ClientWidth(Desktop()) - width) / 2
Global wy:Int = (ClientHeight(Desktop()) - Height) / 2
Global Window1:TGadget = CreateWindow("First Canvas", wx, wy, width, Height, Null, WINDOW_TITLEBAR | WINDOW_CLIENTCOORDS)
Global canvas1:TGadget = CreateCanvas(0, 0, 320, 240, Window1)
Global window2:TGadget = CreateWindow("Second Canvas", wx * 1.25, wy * 1.25, width, Height, Null, WINDOW_TITLEBAR | WINDOW_CLIENTCOORDS)
Global canvas2:TGadget = CreateCanvas(0, 0, 320, 240, window2)
ActivateGadget(canvas2)
' load font
Global Font:TImageFont = LoadImageFont(getenv_("WINDIR") + "/Fonts/Arial.ttf", 32)
Global switch:Int = 1
Global switchtext:String[] = ["MAX2D", "MAX2D fixed"]
' OpenB3D stuff
SetGraphics CanvasGraphics(canvas1)
Graphics3D width, Height, 0, 2, 60, -1, True
Global cam:TCamera = CreateCamera()
Global mesh:TMesh = CreateCube()
Global light:TLight = CreateLight(1)
AmbientLight 0, 0, 0
PositionEntity mesh, 0, 0, 3
CreateTimer 60
' hook
AddHook EmitEventHook, LoopHook
' main loop
Repeat
WaitEvent()
Forever
End
' ----------------------------------------------------------------------------
' Loop Hook
' ----------------------------------------------------------------------------
Function LoopHook:Object(id:Int, data:Object, context:Object)
Local Event:TEvent = TEvent(data)
If Event = Null Then Return Event
Select Event.id
Case EVENT_TIMERTICK
TurnEntity mesh, 0.5, 1, 0.5
RedrawGadget canvas1
RedrawGadget canvas2
Case EVENT_GADGETPAINT
Select Event.source
Case canvas1
SetGraphics CanvasGraphics(canvas1)
Cls
RenderWorld
If switch Then Begin2D() Else BeginMax2D()
SetBlend ALPHABLEND
SetColor(255, 0, 0)
SetImageFont Font
DrawText switchtext[switch], 0, 0
If switch Then End2D() Else EndMax2D()
Flip False
Case canvas2
SetGraphics CanvasGraphics(canvas2)
Cls
RenderWorld
If switch Then Begin2D() Else BeginMax2D()
SetBlend ALPHABLEND
SetColor(0, 255, 0)
SetImageFont Font
DrawText switchtext[switch], 0, 0
If switch Then End2D() Else EndMax2D()
Flip false
End Select
Case EVENT_KEYDOWN
Select Event.data
Case KEY_SPACE
switch = 1 - switch
End Select
Case EVENT_WINDOWCLOSE
FreeGadget canvas1
FreeGadget canvas2
End
Case EVENT_APPTERMINATE
End
End Select
End Function
' Fixed BeginMax2D()
Function Begin2D()
Local x:Int, y:Int, w:Int, h:Int
GetViewport(x, y, w, h)
glDisable(GL_LIGHTING)
glDisable(GL_DEPTH_TEST)
glDisable(GL_SCISSOR_TEST)
glDisable(GL_FOG)
glDisable(GL_CULL_FACE)
glMatrixMode GL_TEXTURE
glLoadIdentity
glMatrixMode GL_PROJECTION
glLoadIdentity
glOrtho 0, width, Height, 0, -1, 1
glMatrixMode GL_MODELVIEW
glLoadIdentity
SetViewport x, y, w, h
Local MaxTex:Int
glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))
For Local Layer:Int = 0 Until MaxTex
glActiveTexture(GL_TEXTURE0+Layer)
glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)
glDisable(GL_TEXTURE_2D)
Next
glActiveTexture(GL_TEXTURE0)
glViewport(0, 0, width, Height)
glScissor(0, 0, width, Height)
glEnable GL_BLEND
glEnable(GL_TEXTURE_2D)
End Function
' Fixed EndMax2D()
Function End2D()
glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)
glDisable(GL_TEXTURE_2D)
glDisable GL_BLEND
TGlobal.EnableStates()
TGlobal.alpha_enable[0] = 0 ' alpha blending was disabled by Max2d (GL_BLEND)
TGlobal.blend_mode[0] = 1 ' force alpha blending
TGlobal.fx1[0] = 0 ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
TGlobal.fx2[0] = 1 ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)
glClearDepth(1.0)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
glAlphaFunc(GL_GEQUAL, 0.5)
For Local cam:TCamera=EachIn TCamera.cam_list
' active camera - was if cam.hide[0]=0
If cam = TGlobal.camera_in_use
' fog with Max2d fix
cam.UpdateFog()
Exit
EndIf
Next
End Function
A question to Qube: the codebox in the forum here converts Tabs to Spaces, is it possible to fix this? See second screenshot.
Just convert your tabs to spaced before posting here. That way you can define how "deep" your tab-spaces should be (by default it should be 4 or 8).
Also: The line with "GLSharecontexts()" is having a "tab" at the beginning. Maybe it only removes the tabs when doing a code-paste in wysiwyg-mode.
bye
Ron
I've used this code as the basis for a multi-canvas example named maxgui2 (https://github.com/markcwm/openb3d.mod/blob/master/examples/minib3d/maxgui2.bmx), it works well now but it took me a few days. So thanks Krischan. Also thanks for the improved begin and endmax2d functions, I have replaced the old functions with them and renamed the old functions Begin and EndMini3D (so as not to conflict with your names).
There's a new commit for the wrapper which has a few other fixes; the Graphics3D command flags wouldn't let you override the default settings, LoadMesh now has a usenative=True parameter to choose between library or native loaders (which currently lack animation but are otherwise an improvement). And there's a few new examples. ;)