Code archives/Graphics/MaxGUI graphics mode chooser
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| This is based on part of a series of modules that I use for my current game, but it should be useful as a stand-alone way for the player to select a graphics mode before starting any BlitzMax/MaxGUI program. I don't pretend that this is the best method, but since I didn't find a similar routine in the archives, I thought that I should perhaps offer this. Though it's a "module," it can be used just by having the .bmx file in the same folder as the calling program (or by including the code for the Type within another program). As written, it restricts resolutions from a minimum of 800 x 600 to a maximum of 1600 x 1200, though you can specify different ones. Its 'recommended' settings are those with >= 1024 x 768 resolution, with >= 24-bit color, and with an aspect ratio around 4:3 (allowing for "not exactly 4:3, but close" modes like 1360 x 1024). You can also change those 'recommended' criteria if desired. Sept. 5 '06 update: Defaults to OpenGL in OS X and Linux (thanks to Diordna for suggestion) and tweaks appearance on those platforms. Calling example in comments improved. Destroy function changed to work better. | |||||
Rem
PreGame module by WendellM - released September 1, 2006, updated Sept. 5, 2006
Allows choice of graphics driver, screen mode, and settings
Saves config file to preserve choices for future use, but works without one
Defaults to OpenGL without displaying choice in Linux & OS X
Example of use within a calling program:
Import "pregame.bmx"
Local pre:TPregame
' whenever you want to set graphics:
pre = TPregame.Create()
pre.UserChoice
If pre.driver = "OpenGL" Then SetGraphicsDriver GLMax2DDriver()
If pre.driver = "DirectX" Then SetGraphicsDriver D3D7Max2DDriver()
If pre.screen = "Windowed" Then
Graphics pre.width, pre.height
Else
Graphics pre.width, pre.height, pre.depth, pre.hertz
EndIf
' Save graphics settings here if desired.
TPreGame.Destroy pre
WaitKey
End Rem
Strict
TPreGame.Test ' <- Self-contained example of use. Uncomment to use, comment out to ignore.
Type TPreGame
Field driver$, screen$, mode$
Field width, height, depth, hertz
Field preGame:TGadget
Field pgPanelDriver:TGadget
Field pgDriverDX:TGadget, pgDriverGL:TGadget
Field pgPanelScreen:TGadget
Field pgScreenFull:TGadget, pgScreenWindowed:TGadget
Field pgPanelRes:TGadget
Field pgMode:TGadget
Field pgButtonOK:TGadget, pgButtonQuit:TGadget
Function Create:TPreGame()
Local t:TPreGame = New TPreGame
Local dw = GadgetWidth( Desktop() )
Local dh = GadgetHeight( Desktop() )
Local w = 220
Local h = 350
Local in:TStream = ReadFile("graphics.dat")
? MacOS
w = 250
?
? Linux
w = 250
?
If in Then
t.driver = ReadLine(in)
t.screen = ReadLine(in)
t.mode = ReadLine(in)
CloseFile in
Else
t.driver = "DirectX"
t.screen = "Fullscreen"
t.mode = "1024 x 768, 32-bit, 85 Hz *" ' try this as default if none other specified
EndIf
t.preGame = CreateWindow( "PreGame", (dw-w)/2,(dh-h)/2, w,h, Null, WINDOW_TITLEBAR )
t.pgPanelDriver = CreatePanel( 10,10, w-25,47, t.preGame,PANEL_GROUP, "Driver" )
t.pgDriverDX = CreateButton( "DirectX", 10,3, 80,19, t.pgPanelDriver, BUTTON_RADIO )
t.pgDriverGL = CreateButton( "OpenGL", 100,3, 80,19, t.pgPanelDriver, BUTTON_RADIO )
If t.Driver = "DirectX" Then
SetButtonState t.pgDriverDX, True
ElseIf t.Driver = "OpenGL" Then
SetButtonState t.pgDriverGL, True
Else
SetButtonState t.pgDriverDX, True
EndIf
? Linux
SetButtonState t.pgDriverGL, True
HideGadget t.pgPanelDriver
?
? MacOS
SetButtonState t.pgDriverGL, True
HideGadget t.pgPanelDriver
?
t.pgPanelScreen = CreatePanel( 10,65, w-25,47, t.preGame,PANEL_GROUP, "Screen Mode" )
t.pgScreenFull = CreateButton( "Fullscreen", 10,3, 80,19, t.pgPanelScreen, BUTTON_RADIO )
t.pgScreenWindowed = CreateButton( "Windowed", 100,3, 80,19, t.pgPanelScreen, BUTTON_RADIO )
If t.Screen = "Fullscreen" Then
SetButtonState t.pgScreenFull, True
ElseIf t.Screen = "Windowed" Then
SetButtonState t.pgScreenWindowed, True
Else
SetButtonState t.pgScreenFull, True
EndIf
Local PanelResY = 120
? Linux
PanelResY = 150
?
t.pgPanelRes = CreatePanel( 10,PanelResY, w-25,70, t.preGame,PANEL_GROUP,..
"Resolution, Color, Refresh" )
CreateLabel "( * = recommended )", 10,0, w-52,15, t.pgPanelRes
t.pgMode = CreateComboBox( 8,19, w-48, 23, t.pgPanelRes )
Local List:TList = New TList
Local numModes = CountGraphicsModes()
Local index = 0, setIndex
Local gw, ght, gd, ghz, rec$ ' graphic width, height, depth, hz, + recommended
Local spcW$, spcH$
Local selected = False
For Local x = 0 To numModes - 1
GetGraphicsMode( x, gw, ght, gd, ghz )
If gw < 1000 Then spcW = " " Else spcW = "" ' for nice columns
If ght < 1000 Then spcH = " " Else spcH = ""
' put recommendation asterisk if 1024x768 or better and near 4:3 (1.333) aspect ratio
If gw >= 1024 And ght >= 768 And Float(gw) / ght > 1.3 And Float(gw) / ght < 1.3667 And ..
gd >= 24 Then rec = " *" Else rec = ""
Local a$ = spcW + gw + " x " + spcH + ght + ", " + gd +"-bit, " + ghz + " Hz" + rec
' don't display resolutions below 800x600 or above 1600x1200
If gw >= 800 And gw <= 1600 And ght >= 600 And ght <= 1200 Then
ListAddLast List, a
AddGadgetItem t.pgMode, a
If a = t.mode Then setIndex = index
index :+ 1
EndIf
Next
If setIndex Then
SelectGadgetItem t.pgMode, setIndex
selected = True
EndIf
If Not selected Then SelectGadgetItem t.pgMode, 0
t.pgButtonOK = CreateButton( "OK", 20+(w-220)/2,289, 80,24, t.preGame, BUTTON_OK )
t.pgButtonQuit = CreateButton( "Quit", 110+(w-220),289, 80,24, t.preGame )
Return t
End Function
Function Destroy(t:TPreGame Var)
FreeGadget t.preGame
t = Null
GCCollect
End Function
Method UserChoice:Int() ' updates driver, screen, width, height, depth, and hertz fields
ActivateGadget pgButtonOK ' default focus
Repeat
WaitEvent
Until ( EventID() = EVENT_WINDOWCLOSE And EventSource() = preGame ) or..
( EventID() = EVENT_GADGETACTION And EventSource() = pgButtonOK ) or..
( EventID() = EVENT_GADGETACTION And EventSource() = pgButtonQuit )
If EventSource() = preGame Or EventSource() = pgButtonQuit Then End
If EventSource() = pgButtonOK Then
If ButtonState(pgDriverDX) Then Driver = "DirectX"
If ButtonState(pgDriverGL) Then Driver = "OpenGL"
If ButtonState(pgScreenFull) Then Screen = "Fullscreen"
If ButtonState(pgScreenWindowed) Then Screen = "Windowed"
mode = GadgetItemText( pgMode, SelectedGadgetItem(pgMode) ) ' same as: GadgetText(pgMode)
width = Int(mode[0..5])
height = Int(mode[7..13])
Local comma = mode.find(",")
depth = Int(mode[comma+2..comma+4])
comma = mode.find(",", comma+3)
hertz = Int(mode[comma+2..comma+4])
Local out:TStream = WriteFile("graphics.dat")
WriteLine out, driver
WriteLine out, screen
WriteLine out, mode
CloseFile out
Return True
EndIf
Notify "Event handling exception in PreGame:UserChoice", True; End
End Method
Function Test()
Local e:TPreGame = TPreGame.Create()
If e.UserChoice() Then Notify e.driver +", "+ e.screen +", "+ ..
e.width +","+ e.height +","+ e.depth +","+ e.hertz
TPreGame.Destroy e
End Function
End Type |
Comments
| ||
| I said it before and I'll say it again: This is a great little nugget of elegance and ease of use. Exactly what I was after! |
| ||
| Thanks buddy! I was thinking about making one of these for myself but no point in reinventing the wheel! |
Code Archives Forum