BRL.DXGraphics Modification

BlitzMax Forums/BlitzMax Module Tweaks/BRL.DXGraphics Modification

Moogles(Posted 2006) [#1]
Hi, If you have maxgui you can add this code to your d3d7graphics.bmx

At the imports at the top add
Import BRL.Win32MaxGUI


then click on your navbar and click the function
CreateHWND and then inside the function add
Local xpos,ypos ' Added by Moogle
Local style,ex_style,hwnd
xpos = ((GadgetWidth(Desktop())/2)-(width/2))
ypos = ((GadgetHeight(Desktop())/2)-(height/2))


scroll down a bit more and find the style variable inside the function and change it to
style=WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX

only if you want to have a minimize button on your app put this, otherwise leave it.

then finally find hwnd and change it to
hwnd=CreateWindowExA( 0,DX_CLASS_NAME,wndTitle,style,xPos,yPos,width,height,0,0,hinst,Null )

Build modules and compile your game/app and this should hopefully make your game/app using Graphics with DirectX be centered on screen. I dont know how to retrieve desktop width and height without maxgui im afraid. if anyone else knows please post. :)
also i dont know how to modify the open gl one for mac or linux so someone else might be able to help here. :)
hope you like this.


Moogles(Posted 2006) [#2]
i found another way to do it using eikons code.

here is my whole code for d3d7graphics.bmx
now graphics command will create a centered window, with the icon working without the requirement of maxgui. i have indiepaths dxrendertype function already set into this. all you have to do is follow the instructions to modify d3d7.bmx file and you can have it working. go here
http://www.blitzbasic.com/Community/posts.php?topic=51795
and just do the first step. this code already has the rest.

[edit] ive been playing with OpenGl and i was reading the source file. i cant seem to make opengl windows centered tho. i tried but the variables rect.top and the like seem to be off. If anyone could help that would be great.
Strict

Import BRL.Graphics
Import BRL.LinkedList
Import BRL.KeyCodes

Import PUB.Win32
Import PUB.DirectX

Global DXRenderType:Byte
Const RGB = 1
Const MMX = 2
Const TnL = 3

Private

Extern "win32"
   Function GetActiveWindow%()
   Function GetDesktopWindow%()
   Function GetWindowRect%(hWnd%, lpRect:Byte Ptr)
   Function SetWindowText%(hWnd%, lpString$z) = "SetWindowTextA@8"
   Function SetWindowPos%(hWnd%, after%, x%, y%, w%, h%, flags%)
End Extern

Type lpRECT
   Field l%, t%, r%, b%
End Type

Global DDDevices:TList=New TList

Global DX_CLASS_NAME:Byte Ptr="BBDX7Device Window Class".ToCString()

Function WndProc( hwnd,message,wp,lp ) "win32"

	bbSystemEmitOSEvent hwnd,message,wp,lp,Null
	
	Select message
	Case WM_CLOSE
		Return
	Case WM_KEYDOWN
		Return
	Case WM_SYSKEYDOWN
		If wp<>KEY_F4 Return
	Case WM_SETFOCUS
		PrimaryDevice.SetFocus
		Return		
	Case WM_KILLFOCUS
		PrimaryDevice.KillFocus
		Return
	Case WM_DESTROY
		Return
	Case WM_LBUTTONDOWN,WM_RBUTTONDOWN,WM_MBUTTONDOWN
		If Not (PrimaryDevice.state & PrimaryDevice.DX7FULLSCREEN)
			SetCapture hwnd
		EndIf
		Return
	Case WM_LBUTTONUP,WM_RBUTTONUP,WM_MBUTTONUP
		If Not (PrimaryDevice.state & PrimaryDevice.DX7FULLSCREEN)
			ReleaseCapture
		EndIf
		Return
	End Select
	Return DefWindowProcA( hwnd,message,wp,lp )
End Function

Function CreateHWND(width,height,fullscreen)

    Local style,ex_style,hwnd
    Local hinst=GetModuleHandleA(0)

    


    Global wndClas
    
    If Not wndClas
        Local wc:WNDCLASS=New WNDCLASS
        wc.hIcon=LoadIconA(hinst,Byte Ptr(101)) ' Added by yan
        wc.hInstance=hinst
        wc.lpfnWndProc=WndProc
        wc.hCursor=LoadCursorA( Null,Byte Ptr IDC_ARROW )
        wc.lpszClassName=DX_CLASS_NAME
        wndClas=RegisterClassA( wc )
        If Not wndClas
            Throw "Failed to register window class"
        EndIf
    EndIf

    Local wndTitle:Byte Ptr=AppTitle.ToCString()

    If fullscreen
        style=WS_VISIBLE|WS_POPUP
        hwnd=CreateWindowExA( 0,DX_CLASS_NAME,wndTitle,style,0,0,width,height,0,0,hinst,Null )
    Else
	Local xpos,ypos ' Added by Moogle
	Local desk_hWnd = GetDesktopWindow(), l:lpRect = New lpRECT
        GetWindowRect(desk_hWnd, l:lpRECT) ' Get Desktop Dimensions
	xpos = ((l.r/2)-(width/2)) ' Added by Moogle
	ypos = ((l.b/2)-(height/2)) ' Added by Moogle
        style=WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX  ' Added by Moogle
        Local rect[]=[0,0,width,height]
        AdjustWindowRect rect,style,0
        width = rect[2] - rect[0]
        height = rect[3] - rect[1]
        hwnd=CreateWindowExA( 0,DX_CLASS_NAME,wndTitle,style,xPos,yPos,width,height,0,0,hinst,Null )
    EndIf
    MemFree wndTitle
    If Not hwnd Throw "Failed to create window"
    Return hwnd
End Function

Function enum_devices_callback(guid Ptr,desc:Byte Ptr,name:Byte Ptr,context Ptr) "win32"
	Local		device:TD3D7Device
	Local		devicedesc:Int Ptr,caps	
	
	devicedesc=Int Ptr(desc)
	caps=devicedesc[0]	
	If (caps&D3DDEVCAPS_HWRASTERIZATION)=0 Return
	device=New TD3D7Device
	device.guid=guid
	device.name=String.FromCString(name)	
	device.description=String.FromCString(desc)
	If Not primarydevice primarydevice=device
	DDDevices.AddLast device
	Return True
End Function

'Type TDDFormat
'	Field	width,height,depth,frequency
'End Type

Public

Global PrimaryDevice:TD3D7Device

Type TD3D7Device
	Field		guid Ptr
	Field		name$
	Field		description$
	Field		ddraw:IDirectDraw7
	Field		d3d:IDirect3D7
	Field		device:IDirect3DDevice7
	Field		primarysurface:IDirectDrawSurface7
	Field		backbuffer:IDirectDrawSurface7
	Field		clipper:IDirectDrawClipper
	Field		reslist:TList=New TList
	Field		displaymodes:TGraphicsMode[]
	Field		state
	Field		width,height,depth,freq,hwnd
	Field		flipflags
	Field		painter:Object
	Field		devicecount

	Const DX7FULLSCREEN=1
	Const DX7WINDOWED=2
	Const DX7DESKTOP=4
	Const DX7EXCLUSIVE=8
	Const DX7LOST=16
	
	Function enum_modes_callback(surfdesc:Byte Ptr,context:Object) "win32"
		Local		device:TD3D7Device
		Local		surf Ptr
		device=TD3D7Device(context)
		surf=Int Ptr(surfdesc)		
		device.AddFormat(surf[3],surf[2],surf[21],surf[6])
		Return DDENUMRET_OK 
	End Function
	
	Function enum_d3d_callback(desc:Byte Ptr,name:Byte Ptr,d3ddevice:Byte Ptr,context:Object) "win32"
		Local		device:TD3D7Device
		Local		dev Ptr
		dev=Int Ptr(d3ddevice)
		device=TD3D7Device(context)
		device.AddD3DDevice(String.FromCString(desc),String.FromCString(name))
		Return D3DENUMRET_OK 
	End Function

	Method GetDevice:IDirect3DDevice7(user:Object)
		If (state&DX7LOST)=False And device
			painter=user
			Return device
		EndIf
	End Method

	Method AddD3DDevice(desc$,name$)
'		Print "desc="+desc+" name="+name
		devicecount:+1
	End Method

	Method AddFormat(w,h,d,f)
		If d<16 Return
		Local		pf:TGraphicsMode	'TDDFormat
'		Print "w="+w+" h="+h+" d="+d+" f="+f
		pf=New TGraphicsMode'TDDFormat
		pf.width=w
		pf.height=h
		pf.depth=d
		pf.hertz=f
		ResList.AddLast pf	
	End Method

	Method Init()
		Local		res
		res=DirectDrawCreateEx( guid,Varptr ddraw,IID_IDirectDraw7,Null )
		If res RuntimeError "DirectDrawCreateEx failed:"+res
		res=DDraw.QueryInterface( IID_IDirect3D7,Byte Ptr Ptr(Varptr D3D) )
		If res RuntimeError "Direct3D7 Interface Failed:"+res
		D3D.EnumDevices enum_d3d_callback,Self
		If Not primarydevice Return
		ddraw.EnumDisplayModes DDEDM_REFRESHRATES,Null,Self,enum_modes_callback		
		Local i
		displaymodes=New TGraphicsMode[reslist.count()]
		For Local mode:TGraphicsMode=EachIn reslist
			displaymodes[i]=mode
			i:+1
		Next
	End Method

	Method SetFocus()
		Local		res
		If state&DX7FULLSCREEN And state&DX7EXCLUSIVE And state&DX7LOST
			Restore			
		EndIf			
	End Method

	Method KillFocus()
		Local		res
		If state&DX7FULLSCREEN And state&DX7EXCLUSIVE
			res=ddraw.SetCooperativeLevel(hwnd,DDSCL_NORMAL|DDSCL_FPUPRESERVE)
			ShowWindow( hwnd,SW_MINIMIZE )
			state:|DX7LOST
			If painter painter.SendMessage("DEVICELOST",Self)
		EndIf			
	End Method
			
	Method Restore()
		Local	res	
		If state&DX7FULLSCREEN And state&DX7EXCLUSIVE
			res=ddraw.SetDisplayMode(width,height,depth,freq,0)
			Assert Not res,"Restore:SetDisplayMode Failed result="+res
			res=ddraw.SetCooperativeLevel(hwnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_FPUPRESERVE)	
			Assert Not res,"Restore:SetCooperativeLevel Failed result="+res
		EndIf
		res=PrimarySurface.Restore()
		Assert Not res,"PrimarySurface Restore Failed result="+res
		res=BackBuffer.Restore()
		Assert Not res,"BackBuffer Restore Failed result="+res
		state:&~DX7LOST
		Device.BeginScene()	'simon was here
		If painter painter.SendMessage("DEVICERESTORED",Self)
	End Method
	
	Method OpenDesktop()
		Local	rect[4],res
		If state=DX7DESKTOP Return
		hwnd=GetDesktopWindow()
		GetWindowRect(hwnd,rect)
		hwnd=0
		width=rect[2]
		height=rect[3]
		depth=0
		freq=0
		res=ddraw.SetCooperativeLevel(0,DDSCL_NORMAL|DDSCL_FPUPRESERVE)	
		Assert Not res,"SetCooperativeLevel Failed result="+res
		state=DX7DESKTOP
		Reset()
		device.BeginScene()
	End Method
	
	Method OpenWindowed(w,h)
		Local 	res
		width=w
		height=h
		depth=0
		freq=0
		hwnd=CreateHWND(width,height,False)
		res=ddraw.SetCooperativeLevel(hwnd,DDSCL_NORMAL|DDSCL_FPUPRESERVE)	
		Assert Not res,"SetCooperativeLevel Failed result="+res
		state=DX7WINDOWED
		Reset()
		device.BeginScene()
	End Method
		
	Method OpenFullScreen(w,h,d,f)
		Local		res				
		width=w
		height=h
		depth=d
		freq=f
		hwnd=CreateHWND(width,height,True)
		res=ddraw.SetCooperativeLevel(hwnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_FPUPRESERVE)	
		Assert Not res,"SetCooperativeLevel Failed result="+res
		res=ddraw.SetDisplayMode(width,height,depth,freq,0)
		If res And freq
			freq=0
			res=ddraw.SetDisplayMode(width,height,depth,freq,0)
		EndIf
		If res And depth<>32
			depth=32
			res=ddraw.SetDisplayMode(width,height,depth,freq,0)
		EndIf
		If res
			If depth=24 depth=32
			res=ddraw.SetDisplayMode(width,height,depth,freq,0)
		EndIf
		Assert Not res,"SetDisplayMode Failed result="+res
'		res=ddraw.SetCooperativeLevel(hwnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_FPUPRESERVE)	
'		Assert Not res,"SetCooperativeLevel Failed result="+res
		state=DX7FULLSCREEN|DX7EXCLUSIVE
		Reset()
		device.BeginScene()
	End Method
	
	Method Reset()
		Local		ddsd:DDSURFACEDESC2
		Local		ddsc:DDSCAPS2
		Local		res
		Local		fullscreen
		
		ddsd=New DDSURFACEDESC2
		ddsd.dwSize=SizeOf(ddsd)
		fullscreen=state&DX7FULLSCREEN
		flipflags=DDFLIP_WAIT
		If fullscreen
			ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT
			ddsd.ddsCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_3DDEVICE
			ddsd.dwBackBufferCount=1
		Else
			ddsd.dwFlags=DDSD_CAPS
			ddsd.ddsCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_3DDEVICE
		EndIf

		res=ddraw.CreateSurface( ddsd,Varptr primarysurface,Null )
		Assert Not res,"CreateSurface Failed result="+res
		
		Select DXRenderType
			Case RGB
				res=d3d.CreateDevice(IID_IDirect3DRGBDevice,primarysurface,Varptr device)
			Case MMX
				res=d3d.CreateDevice(IID_IDirect3DMMXDevice,primarysurface,Varptr device)
			Case TnL
				res=d3d.CreateDevice(IID_IDirect3DTnLHalDevice,primarysurface,Varptr device)
			Default
				res=d3d.CreateDevice(IID_IDirect3DHALDevice,primarysurface,Varptr device)
		End Select
		
		If res res=d3d.CreateDevice(IID_IDirect3DHALDevice,primarysurface,Varptr device)
		Assert Not res,"CreateDevice Failed result="+res		

		If fullscreen
			ddsc=New DDSCAPS2
			ddsc.dwCaps=DDSCAPS_BACKBUFFER
			res=primarysurface.GetAttachedSurface( ddsc,Varptr BackBuffer )
			Assert Not res,"GetAttachedSurface Failed result="+res
		Else
			ddsd.ddsCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_3DDEVICE
			ddsd.dwFlags=DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS
			ddsd.dwWidth=width
			ddsd.dwHeight=height
			res=ddraw.CreateSurface( ddsd,Varptr BackBuffer,Null )
			Assert Not res,"CreateSurface Failed result="+res
			res=ddraw.CreateClipper( 0,Varptr Clipper,Null )
			Assert Not res,"CreateClipper Failed result="+res
			res=primarysurface.SetClipper(Clipper)
			Assert Not res,"SetClipper Failed result="+res
			res=clipper.SetHWnd( 0,hwnd )
			Assert Not res,"Clipper.SetHWND Failed result="+res			
		EndIf
		device.SetRenderTarget BackBuffer,0
		device.SetRenderState D3DRS_LIGHTING,False
	End Method

	Method _Release()
		Local	res		
		res=BackBuffer.Release_()
		BackBuffer=Null
'		Print "backbuffer release res="+res
		res=device.Release_()		
		device=Null
'		Print "D3D.Release res="+res		
		res=PrimarySurface.Release_()
		PrimarySurface=Null
'		Print "primarybuffer release res="+res			
		If Clipper
			res=Clipper.Release_()
			Clipper=Null
'			Print "clipper release res="+res			
		EndIf		
	End Method
				
	Method Close()
		device.EndScene()
		device.SetRenderTarget(Null,0)
		If state&DX7FULLSCREEN 
			Local res=ddraw.SetCooperativeLevel(hwnd,DDSCL_NORMAL|DDSCL_FPUPRESERVE)
		EndIf
		_Release		
		If state&DX7WINDOWED Or state&DX7FULLSCREEN DestroyWindow(hwnd);
		state=0
	End Method

	Method Flip()
		Device.EndScene()
		If state&DX7FULLSCREEN
			PrimarySurface.Flip Null,flipflags
		Else
			Local src[]=[0,0,width,height]
			Local dest[]=[0,0,width,height]
			ClientToScreen hwnd,dest
			dest[2]:+dest[0]
			dest[3]:+dest[1]
			PrimarySurface.Blt dest,BackBuffer,src,0,Null
		EndIf
		Device.BeginScene()
	End Method

	Method SetSwapInterval( interval )
		If state&DX7FULLSCREEN=0 Return
		Select interval
			Case 0
				flipflags=DDFLIP_NOVSYNC
			Case 2
				flipflags=DDFLIP_WAIT|DDFLIP_INTERVAL2
			Case 3
				flipflags=DDFLIP_WAIT|DDFLIP_INTERVAL3
			Case 4
				flipflags=DDFLIP_WAIT|DDFLIP_INTERVAL4
			Default
				flipflags=DDFLIP_WAIT
		End Select
	End Method
	
End Type

Type TD3D7Graphics Extends TGraphics

	Field	hwnd
	
	Method Driver:TD3D7GraphicsDriver()
		Return D3D7GraphicsDriver()
	End Method

	Method GetSettings( width Var,height Var,depth Var,hertz Var,flags Var )
		If hwnd
			Local dest[4]
			GetClientRect hwnd,dest
			width=dest[2]
			height=dest[3]
		Else
			width=PrimaryDevice.width
			height=PrimaryDevice.height
		EndIf
		depth=0
		hertz=0
		flags=0
	End Method

	Method Close()
		PrimaryDevice.Close
	End Method
	
	Method GetDevice:IDirect3DDevice7(user:Object)
		Return PrimaryDevice.GetDevice(user)
	End Method

End Type

Type TD3D7GraphicsDriver Extends TGraphicsDriver

	Global _graphics:TD3D7Graphics
	
	Field islost

	Method GraphicsModes:TGraphicsMode[]()
		Return PrimaryDevice.displaymodes
	End Method
	
	Method AttachGraphics:TD3D7Graphics( widget,flags )
		Local	g:TD3D7Graphics		
		PrimaryDevice.OpenDesktop
		g=New TD3D7Graphics
		g.hwnd=widget
		Return g		
	End Method
	
	Method CreateGraphics:TD3D7Graphics( width,height,depth,hertz,flags )
		Local	g:TD3D7Graphics		
		If depth
			PrimaryDevice.OpenFullScreen width,height,depth,hertz
		Else
			PrimaryDevice.OpenWindowed width,height
		EndIf		
		g=New TD3D7Graphics
		Return g		
	End Method
	
	Method SetGraphics( g:TGraphics )
		_graphics=TD3D7Graphics( g )
		If Not _graphics Return
		If _graphics.hwnd
		
			If islost 
				Print "device lost!" 
				PrimaryDevice._Release
				PrimaryDevice.Reset
				PrimaryDevice.device.BeginScene()
				Print "device restored!" 
			EndIf
			
			PrimaryDevice.clipper.SetHWnd( 0,_graphics.hwnd )
		EndIf			
	End Method
	
	Method Flip( sync )
		If Not _graphics Return
		
		Local interval
		If sync interval=1
		PrimaryDevice.SetSwapInterval interval
		
		If _graphics.hwnd
			islost=PrimaryDevice.device.EndScene()
			Local src[4]
			Local dest[4]
			GetClientRect _graphics.hwnd,dest
			GetClientRect _graphics.hwnd,src
			ClientToScreen _graphics.hwnd,dest
			dest[2]:+dest[0]
			dest[3]:+dest[1]
			PrimaryDevice.primarysurface.Blt dest,PrimaryDevice.backbuffer,src,0,Null
			PrimaryDevice.device.BeginScene()
		Else
			PrimaryDevice.Flip		
		EndIf
	End Method
	
End Type

Function D3D7GraphicsDriver:TD3D7GraphicsDriver()

	Global _done
	Global _driver:TD3D7GraphicsDriver
	
	If _done Return _driver
	If DirectDrawCreateEx
		DirectDrawEnumerate enum_devices_callback,Null
'		Print "DirectDraw found "+DDDevices.Count()+" devices."
		If PrimaryDevice
			PrimaryDevice.Init
'			Print "PrimaryDevice reslist.count()="+PrimaryDevice.reslist.Count()
			If PrimaryDevice.reslist.Count()	
				 _driver=New TD3D7GraphicsDriver
			EndIf
		EndIf
	EndIf
	_done=True
	Return _driver
End Function



Grisu(Posted 2006) [#3]
The problem with Eikon's code is that the blitz app will still display a window at the wrong position for a sec, before it is moved to the center of the screen... You can see this... and it looks ugly! :/


Moogles(Posted 2006) [#4]
yea i know that. but this one doesnt. :P you havent even tried it. i remember trying eikons code and i didnt like it either. thats why i resorted to this method.


Moogles(Posted 2006) [#5]
found a new one. if you dont like how your mouse moves to the center of the screen when you call graphics then open BRL.Graphics module and search for
MoveMouse width/2,height/2
and comment that out. Ie replace it with
'MoveMouse width/2,height/2

and then when you turn graphics into fullscreen you can position the mouse yourself. :) now just a build mods will do and all will be fine :D


Moogles(Posted 2006) [#6]
does anyone read these topics? coz if no one does its a waste of my time. i might as well keep this info to myself.


tonyg(Posted 2006) [#7]
Just read it. Sounds interesting but I don't mind how my mouse moves to the centre and no longer change the supplied modules. If/when I need this I'll see if it can be done in a pub module.


Moogles(Posted 2006) [#8]
thanks. its nice to know people appreciate it. i thought everyone would want their apps to start in the center of every users screen.


Dreamora(Posted 2006) [#9]
Normally it does not make a difference for me, where it starts, as non-gui applications are started in fullscreen for performance reasons.
But a nice "hack" anyway :-)


Moogles(Posted 2006) [#10]
thanks ;)
i though everyone made games with BMax? Thats why I got it. :P


xlsior(Posted 2006) [#11]
How do these window-centering mods affect people who run a dual-screen setup?


Moogles(Posted 2006) [#12]
i dont know. it will probably center it on the first screen.
ive never seen a dual screen setup or know how it works. But by default the window is created at the default position of windows. its usually random.


Dreamora(Posted 2006) [#13]
If the screens are set to span across then you won't know where the window appears ;-) but I think you already know it ... :D


Moogles(Posted 2006) [#14]
:O, oh well ill have an option to... erm. ill edit my graphics function so i can specify where it appears. :P


Grisu(Posted 2006) [#15]
Unknown, can you put up an updated code version for bmx 1.20?