In my quest to create the greatest RPG of all time ;) I wanted to code a GUI. Well, maybe it isn't for the superRPG, I really am taking this on as a learning experience. I have gotten to a point where I can compile this bad boy and get pretty much want I wanted to get, but with memory leaks (I assume) everywhere, problems left and right, i am sure, and so on...as I said, a learning experience. So I have deceided to put this up, especially since I need to hear that I am doing something right (I hope) to keep my morale up. I figure who to show this to but people who know what they are doing and want to help someone learn.
I apologize for the size, basically these windows are, in order:
Main GUI Interface class interface
Main GUI Interface class implementation
Drawing class interface
Drawing class implementation
Button object interface
Button object implementation
The homemade linked list I whipped up to keep track of all the children.
I would be BEYOND grateful, near enough to pledge my firstborn (not quite though...maybe when someone reviews my 3-d super dooper engine). Seriously, I would be so helpful if someone could take a little time and give me a bit of guidance on what I do wrong, what I do right. I think the code is understandable...I hope it is anyways.
Also, I zipped up the whole damn thing and stuck it on my school site...
I hope my only html skills still are up to par...
GUI.zip
One thing, I am by no means asking anyone to debug my stuff or tell me how to program. This thing does work. I get a button a moving mouse, static text and an update of the mouse location. I just really am asking if someone can take a look and tell me where I am moving in the right direction and where I am moving in the wrong direction. Thanks again!
Much Obliged
DrMol
The Main GUI interface
class CWindow_GUI
{
public:
//////////////
//Boring stuff
//////////////
CWindow_GUI();
virtual ~CWindow_GUI();
virtual void Init( );
void SetDXSystem( CDXDraw *DXControl );
//static CDXDraw*
//CDXDraw *GetDXSystem( );
//////////////////////
//Subwindows and stuff
//////////////////////
CWindow_GUI *GetParentWindow( );
bool AddWindow( CWindow_GUI *window );
void DeleteWindow( CWindow_GUI *window );
void SetParentWindow( CWindow_GUI *window );
void BringToTop( );
bool CleanUp( );
// void SetText( CTextGrinder cTG );
/////////////
//Visibility
/////////////
void SetVisible( bool vis = true );
bool GetVisible( ) const;
void SetActive( bool Act = true );
void GetActive( );
/////////////
//Positioning
////////////
void SetPos( long x, long y );
void SetSize( long Width, long Height );
bool ClickInside( int x, int y);
int MouseWindow( int MouseX, int MouseY, short button, short prevstate );
//Call this is mouse polling indicates a change of state
int MouseStateChange( int MouseX, int MouseY, short button, short prevstate );
// int VirtXPixel( int virtx );
// int VirtYPixel( int virty );
virtual void Test( int a );
/////////////////////////////////////
//Window creation
////////////////////////////////////
int RenderAll( );
virtual int RenderWindow( );
////////////////////////////////////
//Messaging, mechanics
////////////////////////////////////
virtual void GM_MOUSEACTION( int MouseX, int MouseY, short Btn, short LastBtnState );
virtual void GM_CHILDCLICKED( );// const;
////////////////////////////////////
//Messaging, user defined
////////////////////////////////////
virtual void GM_USERACTION_MOUSE( int Btn );
// virtual void GM_ACTIVATED( );
ConvertXToMS( int X );
ConvertYToMS( int Y );
private:
bool GUIWindowVisible;
bool Visible;
int index;
CWindow_GUI *winParent;
ArrayPtrCtrl< CWindow_GUI* > subWins; //the array of pointers to subwindows
bool Act;
protected:
// CTextGrinder cText;
CDXDraw *DXControl;
SWindowCoord sCoord;
bool TWindow;
int ele;
bool CTE( );
};
The Main class implementation
CWindow_GUI::CWindow_GUI()
{
TWindow = false;
winParent = NULL;
index = 0;
sCoord.Height = 300;
sCoord.Width = 300;
sCoord.pos.top = 0;
sCoord.pos.left = 0;
}
CWindow_GUI::~CWindow_GUI()
{
winParent = NULL; //no parent.
subWins.~ArrayPtrCtrl( );//Delete all subwindows
}
CWindow_GUI *CWindow_GUI::GetParentWindow( )
{
return winParent;
};
bool CWindow_GUI::AddWindow( CWindow_GUI *window )
{
//Make sure window is valid
if ( window == NULL )
return false;
subWins.Add( window );//subWins
window->SetParentWindow( this );
if ( subWins.IsEmpty( ) == true )
return false;
return true;
}
void CWindow_GUI::SetParentWindow( CWindow_GUI *window)
{
winParent = window;
}
void CWindow_GUI::DeleteWindow( CWindow_GUI *window )
{
subWins.Delete( window );
window->SetParentWindow( NULL );
};
//////////////////////
void CWindow_GUI::SetVisible( bool vis )
{
Visible = vis;
};
bool CWindow_GUI::GetVisible( ) const
{
return Visible;
};
/////////////////////////
void CWindow_GUI::SetSize( long Width, long Height )
{
sCoord.Width = Width;
sCoord.Height = Height;
sCoord.pos.right = Width + sCoord.pos.left;
sCoord.pos.bottom = Height + sCoord.pos.top;
CWindow_GUI *cGW = NULL;
cGW = GetParentWindow( );
/* if( cGW != NULL )
{
if( cGW->sCoord.pos.bottom < sCoord.pos.bottom )
{
sCoord.pos.top = cGW->sCoord.pos.bottom - sCoord.Height; //translate up
sCoord.pos.bottom = cGW->sCoord.pos.bottom;
}
if( cGW->sCoord.pos.right < sCoord.pos.right )
{
sCoord.pos.left = cGW->sCoord.pos.right - sCoord.Width; //translate left
sCoord.pos.right = cGW->sCoord.pos.right;
}
};
*/
}
void CWindow_GUI::SetPos( long x, long y )
{
sCoord.pos.left = x;
sCoord.pos.top = y;
CWindow_GUI *cGW = NULL;
cGW = GetParentWindow( );
/*if( cGW != NULL )
{
if( cGW->sCoord.pos.left > sCoord.pos.left )
sCoord.pos.left = cGW->sCoord.pos.left;
if( cGW->sCoord.pos.top > sCoord.pos.top )
sCoord.pos.top = cGW->sCoord.pos.top;
};*/
sCoord.pos.right = sCoord.Width + sCoord.pos.left;
sCoord.pos.bottom = sCoord.Height + sCoord.pos.top;
}
//////////////////////////////////////////
void CWindow_GUI::BringToTop( )
{
winParent->DeleteWindow( this );
winParent->AddWindow( this );
}
/*
int CWindow_GUI::VirtXPixel( int virtx )
{
// int width = (cWindow_Parent) ? cWindow_Parent->getpos().getwidth() : getscreendims().getwidth();
// return((int)((double)virtx*(double)width/GUI_SCALEX));
}
*/
void CWindow_GUI::Init( )
{
// Font = "Arial";
// Point = 12;
// index = 0;
}
int CWindow_GUI::RenderWindow( )
{
return 0;
}
int CWindow_GUI::RenderAll( )
{
RenderWindow( );
int ind = subWins.GetCount( ); //Creates a starting spot for tree
CWindow_GUI *cPtr; //Create a basic window pointer
if( subWins.GetCount( ) < 0 ) return false; //error
if( ind == 0 ) //No more children
{
return 0;
};
while ( ind >= 0 ) //Go through rest of children
{
cPtr = subWins.GetDataBW( ind );
cPtr->RenderAll( );
ind--;
};
return -1;
};
void CWindow_GUI::SetDXSystem( CDXDraw *cDXDraw )
{
DXControl = cDXDraw;
};
/*
CDXDraw *CWindow_GUI::GetDXSystem( )
{
return DXControl;
}
*/
int CWindow_GUI::MouseWindow( int MouseX, int MouseY, short button, short prevstate )
{
int ind = subWins.GetCount( ); //Creates a starting sport for tree
CWindow_GUI *cPtr; //Create a basic window pointer
if( subWins.GetCount( ) < 0 ) return false; //error
if( subWins.GetCount( ) == 0 ) //No more children
{
GM_MOUSEACTION( MouseX, MouseY, button, prevstate );
return 0;
};
while ( ind > 0 ) //Go through rest of children
{
cPtr = subWins.GetDataBW( ind );
cPtr->MouseWindow( MouseX, MouseY, button, prevstate );
ind--;
};
return true;
}
bool CWindow_GUI::ClickInside( int x, int y )
{
bool xVal, yVal;
xVal = yVal = false;
if( x >= sCoord.pos.left && x <= sCoord.pos.right )
xVal = true;
if( y >=sCoord.pos.top && y <= sCoord.pos.bottom )
yVal = true;
if( xVal == true && yVal == true )
return true;
return false;
};
void CWindow_GUI::GM_CHILDCLICKED( ) //const
{
BringToTop( );
};
int CWindow_GUI::MouseStateChange( int MouseX, int MouseY, short button, short prevstate )
{
//Something has happened with the mouse
//if ( button is up ) and move = true, let windows handle it
//else, a button state has changed
//Get the window that it happened in, recusion here
MouseWindow( MouseX, MouseY, button, prevstate );
//Let that window know that it has been clicked and pass all mouse info, button, last button state etc, hand the problem off
return 0;
};
bool CWindow_GUI::CleanUp( )
{
CWindow_GUI *cPtr = NULL;
//Number of elements in the list
// MessageBox( hWnd, "Start Debug", "CLEANUP", MB_OK );
// if( index > subWins.GetCount( ) ) //error
// return false;
index++; //bump the thing
if ( subWins.IsValid( index - 1 ) == true &&
subWins.IsEmpty( ) == false )//this window has children
{
//get the pointer to the last element
//Bump the count since we dont start with index = 0
cPtr = subWins.GetData( index - 1 );
cPtr->CleanUp( );
}
else if ( subWins.IsEmpty( ) == false && subWins.IsValid( index -1 ) == false )
{
subWins.DeleteAll( );
cPtr = winParent;
if ( cPtr == NULL ) //this window has no parent
{
index = 0; //So reset the counter
return false; //End the function
};
// cPtr = winParent;
}
else //no children
{
cPtr = winParent;
// return 0;
if ( cPtr == NULL ) //this window has no parent
{
index = 0; //So reset the counter
return false; //End the function
};
};
cPtr->CleanUp( ); //Continue the parents render function
return true;
}
void CWindow_GUI::GM_MOUSEACTION( int MouseX, int MouseY, short Btn, short LastBtnState )
{
//Do nothing
}
void CWindow_GUI::Test( int a )
{
}
void CWindow_GUI::GM_USERACTION_MOUSE( int Btn )
{
}
The Drawing class interface, draws all the objects. Wrapped not inplemented seperatley
class CDXDraw
{
friend class CWindow;
public:
CDXDraw( );
virtual ~CDXDraw();
bool Init( IDirect3DDevice8 *GraphicSystem, HWND h_Wnd );
bool PrepareToDraw( );
///////////////////////////////////////////////
//Window Drawing functions
//////////////////////////////////////////////
bool DrawWindow( RECT Coord, struct SWinImages );
bool DrawStatic( RECT Coord, STxtInf sTextInf, char *Text );
bool DrawButton( RECT Coord, SButtonInf sBI );
int ScaleX( int x );
int ScaleY( int y );
void ScaleRect( RECT &r );
/*
bool DrawButton( RECT winRect, SButtonInf sBI, LPDIRECTDRAWSURFACE7 lpDDS );
bool ButtonBlit( RECT winRect, LPDIRECTDRAWSURFACE7 lpDDS );
*/
private:
///////////////////////////////////////////////
//Window Drawing functions
//////////////////////////////////////////////
IDirect3DDevice8 *DXDevice;
ID3DXFont *DXFont;
LOGFONT lf;
HWND hWnd;
CD3DFont *hFont;
bool Init2D( );
bool DrawButtonAuto( RECT Coord, SButtonInf sBI );
bool DrawBorderedBox( RECT Coord, SButtonInf sBI, bool NoBox = false );
int SysWidth, SysHeight;
RECT windowSize;
};
The Drawing class implementation, this needs the most work, i guess
CDXDraw::CDXDraw( )
{
SysWidth=800;
SysHeight =600;
DXFont = NULL;
}
CDXDraw::~CDXDraw()
{
if( hFont )
{
hFont->DeleteDeviceObjects( );
delete hFont;
hFont = NULL;
}
DXDevice->Release( );
}
bool CDXDraw::Init( IDirect3DDevice8 *GraphicsSystem, HWND h_Wnd )
{
if( ( DXDevice = GraphicsSystem ) == NULL )
return false;
hWnd = h_Wnd;
return true;
}
bool CDXDraw::DrawWindow( RECT Coord, SWinImages sWI)
{
bool BGFill = false;
LPDIRECT3DTEXTURE8 Tex = NULL;
//ERROR CHECKING
if( Coord.right < Coord.left )
return false;
if( Coord.bottom < Coord.top )
return false;
if( DXDevice == NULL )
return false;
SButtonInf sBI;
//DRAW THE BORDERS
if( sWI.BordersOn == true )
{
sBI.BorderWidth = 3;
sBI.DrawUp = true;
DrawBorderedBox( Coord, sBI, true );
}
else sBI.BorderWidth = 0;
Coord.bottom -= sBI.BorderWidth;
Coord.top += sBI.BorderWidth;
Coord.left += 2 * sBI.BorderWidth;
Coord.right -= sBI.BorderWidth;
//SEE IF WE ARE USING A BG COLOR OR AN IMAGE
if( sWI.BG == NULL )
BGFill = TRUE;
if( BGFill == FALSE )
{
if( FAILED ( D3DXCreateTextureFromFileEx( DXDevice, sWI.BG, 0, 0, 0, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT,
D3DX_DEFAULT, 0, NULL, NULL, &Tex ) ) )
BGFill = TRUE;
}
//SET THIS THING UP AS A BILLBOARD
D3DXMATRIX Mtrx2D;
D3DXMATRIX Identity;
D3DXMatrixOrthoLH( &Mtrx2D, (float) SysWidth, (float) SysHeight, 0.0f, 1.0f );
D3DXMatrixIdentity( &Identity );
DXDevice->SetTransform( D3DTS_PROJECTION, &Mtrx2D );
DXDevice->SetTransform( D3DTS_WORLD, &Identity );
DXDevice->SetTransform( D3DTS_VIEW, &Identity );
LPDIRECT3DVERTEXBUFFER8 Vertices = NULL;
//WORK OUT THE SIZES
float Width = (float) ( Coord.right ) - (float) ( Coord.left );
float Height = (float) ( Coord.bottom )- (float) ( Coord.top );
ScaleRect( Coord );
//SEND THE VERTICES TO THE BUFFER AND SET UP THE INFO
DXDevice->CreateVertexBuffer( 8 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &Vertices );
PARAMETERS *pVertices = NULL;
Vertices->Lock (0, 0, (BYTE**) &pVertices, 0 );
pVertices[0].color = pVertices[1].color = pVertices[2].color = pVertices[3].color = sWI.color;
pVertices[0].x = pVertices[3].x = -Width / 2.0f;
pVertices[1].x = pVertices[2].x = Width/2.0f ;
pVertices[0].y = pVertices[1].y = Height/2.0f;
pVertices[2].y = pVertices[3].y = -Height/2.0f;
pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;
pVertices[1].u = pVertices[2].u = 1.0f;
pVertices[0].u = pVertices[3].u = 0.0f;
pVertices[0].v = pVertices[1].v = 0.0f;
pVertices[2].v = pVertices[3].v = 1.0f;
///////////////////////////////////////////////////////
pVertices[4].x = pVertices[7].x = -Width / 2.0f ;
pVertices[5].x = pVertices[6].x = Width / 2.0f;
pVertices[4].y = pVertices[5].y = ( Height * .1 ) / 2 + ( Height / 2 ) - ( ( Height * .1) / 2 );
pVertices[6].y = pVertices[7].y = -( Height * .1 ) / 2 + ( Height / 2 ) - ( (Height * .1) / 2 );
pVertices[4].z = pVertices[5].z = pVertices[6].z = pVertices[7].z = 0.0f;
pVertices[4].color = pVertices[5].color = pVertices[6].color = pVertices[7].color = sWI.TitleColor;
Vertices->Unlock( );
//TODO: put lock and unlock only once in rendering sequence
//MOVE IT BASED ON ENTERED COORDS
D3DXMATRIX Position;
D3DXMatrixTranslation( &Position,
-( ( SysWidth / 2.0f ) - ( Width/2.0f ) ) + Coord.left,
( SysHeight / 2.0f ) - ( Height/2.0f ) - Coord.top ,
0.0f
);
DXDevice->SetTransform( D3DTS_WORLD, &Position );
//RENDER IT TO THE BACK BUFFER
if( BGFill == FALSE )
DXDevice->SetTexture( 0, Tex );
DXDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
DXDevice->SetVertexShader( FVF_WINDOWVERTEX );
DXDevice->SetStreamSource( 0, Vertices, sizeof( PARAMETERS ) );
DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
if( BGFill == TRUE )
{
DXDevice->SetTexture( 0, NULL );
if( Tex != NULL )
Tex->Release( );
}
//////////////////////////////////////////////////////////////
if( sWI.TitleBar == true )
{
if( sWI.TitleLoc != NULL )
{
D3DXCreateTextureFromFileEx( DXDevice, sWI.TitleLoc, 0, 0, 0, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT,
D3DX_DEFAULT, 0, NULL, NULL, &Tex );
DXDevice->SetTexture( 0, Tex );
};
DXDevice->SetStreamSource( 0, Vertices, sizeof( PARAMETERS ) );
DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 4, 2 );
sWI.TitleText = "Hello World";
if( sWI.TitleText != NULL )
{
STxtInf sTextInf;
sTextInf.Color = 0xff000000;
sTextInf.Font = "Arial"; //TODO:Make variable
sTextInf.Point = ( ( (int)( Height * .1 ) % 2 ) ? Height : ( Height - 1 ) );
sTextInf.Bold = 0;
sTextInf.Italic = false;
sTextInf.Underline = false;
sTextInf.Center = FALSE;
sTextInf.VCenter = FALSE;
Coord.left = Coord.left / 2; //+3 is a buffer from left
Coord.top = Coord.top / 2 + 11;// + ( 6 + 2 * sBI.BorderWidth );
sTextInf.Point = 12;
DrawStatic( Coord, sTextInf, sWI.TitleText );
};
}
return true;
}
bool CDXDraw::DrawStatic( RECT Coord, STxtInf sTextInf, char *Text )
{
DWORD Flag = 0L;
if( sTextInf.Bold == true )
Flag = 0x0001;
hFont = new CD3DFont( sTextInf.Font, sTextInf.Point, Flag );
hFont->InitDeviceObjects( DXDevice );
hFont->RestoreDeviceObjects( );
ScaleRect( Coord );
SIZE fExt;
hFont->GetTextExtent( Text, &fExt );
Coord.top += (Coord.bottom - Coord.top - fExt.cy )/2;
Coord.left += ( Coord.right - Coord.left - fExt.cx )/2 ;
hFont->DrawText( Coord.left, Coord.top, sTextInf.Color, Text );
return true;
}
bool CDXDraw::DrawButton( RECT Coord, SButtonInf sBI )
{
SWinImages sWI = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
char *txt;
if( sBI.DrawUp == true )
{
sWI.BG = sBI.UImage;
txt = sBI.UText;
}
else
{
sWI.BG = sBI.DImage;
txt = sBI.DText;
}
if( sBI.AutoDraw )
DrawBorderedBox( Coord, sBI );
else
{
sWI.color = 0xffffff; //Backup, but can't be black
sWI.TitleBar = false; //Make sure the thing doesn't draw a title bar
DrawWindow( Coord, sWI );
}
sBI.sTxtInf.Center = TRUE;
sBI.sTxtInf.VCenter = TRUE;
DrawStatic( Coord, sBI.sTxtInf, txt );
return true;
}
bool CDXDraw::DrawBorderedBox( RECT Coord, SButtonInf sBI, bool NoBox )
{
//Add in a texture handler later
LPDIRECT3DVERTEXBUFFER8 VtxLBox = NULL;
LPDIRECT3DVERTEXBUFFER8 VtxBBox = NULL;
if( DXDevice == NULL )
return false;
DWORD ColorDrkBase, ColorLtBase;
if( sBI.DrawUp == TRUE )
{
ColorDrkBase = 0xff000000;
ColorLtBase = 0xffffffff;
}
else
{
ColorDrkBase = 0xffffffff;
ColorLtBase = 0xff000000;
}
PARAMETERS *pVertices = NULL;
DXDevice->SetRenderState( D3DRS_AMBIENT,RGB(255,255,255) );
DXDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
DXDevice->SetVertexShader( FVF_WINDOWVERTEX );
//SET THIS THING UP AS A BILLBOARD
D3DXMATRIX Mtrx2D;
D3DXMATRIX Identity;
D3DXMatrixOrthoLH( &Mtrx2D, (float) SysWidth, (float) SysHeight, 0.0f, 1.0f );
D3DXMatrixIdentity( &Identity );
DXDevice->SetTransform( D3DTS_PROJECTION, &Mtrx2D );
DXDevice->SetTransform( D3DTS_WORLD, &Identity );
DXDevice->SetTransform( D3DTS_VIEW, &Identity );
//WORK OUT THE SIZES
float Width = (float) ( Coord.right ) - (float) ( Coord.left );
float Height = (float) ( Coord.bottom )- (float) ( Coord.top );
ScaleRect( Coord );
///////////////////////////////
//Draw big box
DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxBBox );
VtxBBox->Lock (0, 0, (BYTE**) &pVertices, 0 );
//Color of corners
pVertices[0].color = ColorLtBase ;
pVertices[1].color = 0xffb6b6b6; //Medium grey
pVertices[3].color = 0xffa0a0a0;
pVertices[2].color = ColorDrkBase;
//H/W of the big box
pVertices[0].x = pVertices[3].x = -Width / 2.0f;
pVertices[1].x = pVertices[2].x = Width/2.0f;
pVertices[0].y = pVertices[1].y = Height/2.0f;
pVertices[2].y = pVertices[3].y = -Height/2.0f;
//Stupid stuff
pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;
pVertices[1].u = pVertices[2].u = 1.0f;
pVertices[0].u = pVertices[3].u = 0.0f;
pVertices[0].v = pVertices[1].v = 0.0f;
pVertices[2].v = pVertices[3].v = 1.0f;
VtxBBox->Unlock();
/////////////////////////////////
//Draw little box (button itself)
// sBI.BorderWidth = ScaleY( sBI.BorderWidth );
if( NoBox == false )
{
DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxLBox );
VtxLBox->Lock (0, 0, (BYTE**) &pVertices, 0 );
//Color is all the same
pVertices[0].color = pVertices[1].color = pVertices[3].color = pVertices[2].color = sBI.color;
//W/H, this is modified
pVertices[0].x = pVertices[3].x = -Width / 2.0f + sBI.BorderWidth;
pVertices[1].x = pVertices[2].x = Width /2.0f - sBI.BorderWidth;
pVertices[0].y = pVertices[1].y = Height/2.0f - sBI.BorderWidth;
pVertices[2].y = pVertices[3].y = -Height/2.0f + sBI.BorderWidth;
//Useless crap
pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;
pVertices[1].u = pVertices[2].u = 1.0f;
pVertices[0].u = pVertices[3].u = 0.0f;
pVertices[0].v = pVertices[1].v = 0.0f;
pVertices[2].v = pVertices[3].v = 1.0f;
VtxLBox->Unlock();
};
/////////////////////////////////////////////////
//TRANSLATION
D3DXMATRIX Position;
D3DXMatrixTranslation( &Position,
-( ( SysWidth / 2.0f ) - ( Width/2.0f ) ) + Coord.left,
( SysHeight / 2.0f ) - ( Height/2.0f ) - Coord.top ,
0.0f);
//-( ( SysWidth / 2.0f ) - ( Width/2.0f ) ) + Coord.left,
// ( SysHeight / 2.0f ) - ( Height/2.0f ) - Coord.top ,
// 0.0f
// );
DXDevice->SetTransform( D3DTS_WORLD, &Position );
/////////////////////////////////////////////////
//RENDERING SEQUENCE
DXDevice->SetStreamSource( 0, VtxBBox, sizeof( PARAMETERS ) );
DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
if( NoBox == false )
{
DXDevice->SetStreamSource( 0, VtxLBox, sizeof( PARAMETERS ) );
DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
};
return true;
}
bool CDXDraw::DrawButtonAuto( RECT Coord, SButtonInf sBI )
{
LPDIRECT3DVERTEXBUFFER8 VtxLeft = NULL;
LPDIRECT3DVERTEXBUFFER8 VtxBottom = NULL;
LPDIRECT3DVERTEXBUFFER8 VtxTop = NULL;
LPDIRECT3DVERTEXBUFFER8 VtxRight = NULL;
LPDIRECT3DVERTEXBUFFER8 VtxBox = NULL;
DWORD ColorDrkFade, ColorDrkBase, ColorLtBase, ColorLtFade;
if( sBI.DrawUp == TRUE )
{
ColorDrkFade = 0xff7d7d7d;
ColorDrkBase = 0xff646464;
ColorLtBase = 0xffffffff;
ColorLtFade = 0xffd2d2d2;
}
else
{
ColorDrkFade = 0xffd2d2d2;
ColorDrkBase = 0xffffffff;
ColorLtBase = 0xff646464;
ColorLtFade = 0xff7d7d7d;
}
PARAMETERS *pVertices = NULL;
if( DXDevice == NULL )
return false;
DXDevice->SetRenderState( D3DRS_AMBIENT,RGB(255,255,255) );
DXDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
DXDevice->SetVertexShader( FVF_WINDOWVERTEX );
//SET THIS THING UP AS A BILLBOARD
D3DXMATRIX Mtrx2D;
D3DXMATRIX Identity;
D3DXMatrixOrthoLH( &Mtrx2D, (float) SysWidth, (float) SysHeight, 0.0f, 1.0f );
D3DXMatrixIdentity( &Identity );
DXDevice->SetTransform( D3DTS_PROJECTION, &Mtrx2D );
DXDevice->SetTransform( D3DTS_WORLD, &Identity );
DXDevice->SetTransform( D3DTS_VIEW, &Identity );
//WORK OUT THE SIZES
float Width = (float) ( Coord.right ) - (float) ( Coord.left );
float Height = (float) ( Coord.bottom )- (float) ( Coord.top );
float Buffer = 5;
ScaleRect( Coord );
////////////////////////////////////////////////////
//Left Square
DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxLeft );
VtxLeft->Lock (0, 0, (BYTE**) &pVertices, 0 );
pVertices[0].color = pVertices[3].color = ColorLtBase;
pVertices[1].color = pVertices[2].color = ColorLtFade;
pVertices[0].x = pVertices[3].x = -Width / 2.0f ;
pVertices[1].x = pVertices[2].x = -Width/2.0f +4;
pVertices[0].y = Height/2.0f; //The angled corner
pVertices[1].y = Height/2.0f;
pVertices[2].y = -Height/2.0f;
pVertices[3].y = -Height/2.0f - 2;
pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;
pVertices[1].u = pVertices[2].u = 1.0f;
pVertices[0].u = pVertices[3].u = 0.0f;
pVertices[0].v = pVertices[1].v = 0.0f;
pVertices[2].v = pVertices[3].v = 1.0f;
VtxLeft->Unlock();
////////////////////////////////////////////////////
//Right Square
DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxRight );
VtxRight->Lock (0, 0, (BYTE**) &pVertices, 0 );
pVertices[0].color = pVertices[3].color = ColorDrkBase;
pVertices[1].color = pVertices[2].color = ColorDrkFade;
pVertices[0].x = pVertices[3].x = Width / 2.0f ;
pVertices[1].x = pVertices[2].x = Width/2.0f -4;
pVertices[0].y = -Height/2.0f; //The angled corner
pVertices[1].y = -Height/2.0f +3;
pVertices[2].y = Height/2.0f -3;
pVertices[3].y = Height/2.0f +1;
pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;
pVertices[1].u = pVertices[2].u = 1.0f;
pVertices[0].u = pVertices[3].u = 0.0f;
pVertices[0].v = pVertices[1].v = 0.0f;
pVertices[2].v = pVertices[3].v = 1.0f;
VtxRight->Unlock();
///////////////////////////////////////////////////////
//Bottom Square
DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxBottom );
VtxBottom->Lock (0, 0, (BYTE**) &pVertices, 0 );
pVertices[0].color = pVertices[1].color = ColorDrkFade;
pVertices[3].color = pVertices[2].color = ColorDrkBase;
pVertices[0].x = -Width / 2.0f + 4.45;
pVertices[3].x = -Width / 2.0f - 1;
pVertices[1].x = pVertices[2].x = Width/2.0f;
pVertices[0].y = pVertices[1].y = -Height/2.0f +4 ;
pVertices[2].y = -Height/2.0f -1;
pVertices[3].y = -Height/2.0f -1;
pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;
pVertices[1].u = pVertices[2].u = 1.0f;
pVertices[0].u = pVertices[3].u = 0.0f;
pVertices[0].v = pVertices[1].v = 0.0f;
pVertices[2].v = pVertices[3].v = 1.0f;
VtxBottom->Unlock();
///////////////////////////////////////////////////////
//Top Square
DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxTop );
VtxTop->Lock (0, 0, (BYTE**) &pVertices, 0 );
pVertices[0].color = pVertices[1].color = ColorLtBase;
pVertices[3].color = pVertices[2].color = ColorLtFade;
pVertices[0].x = pVertices[3].x = -Width / 2.0f ;
pVertices[1].x = Width/2.0f ;
pVertices[2].x = Width/2.0f - 4;
pVertices[0].y = pVertices[1].y = Height/2.0f +1 ;
pVertices[2].y = pVertices[3].y = Height/2.0f -3;
pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;
pVertices[1].u = pVertices[2].u = 1.0f;
pVertices[0].u = pVertices[3].u = 0.0f;
pVertices[0].v = pVertices[1].v = 0.0f;
pVertices[2].v = pVertices[3].v = 1.0f;
VtxTop->Unlock();
///////////////////////////////////////////////////////
//Box
DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxBox );
VtxBox->Lock (0, 0, (BYTE**) &pVertices, 0 );
pVertices[0].color = pVertices[1].color = pVertices[3].color = pVertices[2].color = sBI.color;
pVertices[0].x = pVertices[3].x = -Width / 2.0f +4;
pVertices[1].x = pVertices[2].x = Width/2.0f -4;
pVertices[0].y = pVertices[1].y = Height/2.0f -2;
pVertices[2].y = pVertices[3].y = -Height/2.0f +4;
pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;
pVertices[1].u = pVertices[2].u = 1.0f;
pVertices[0].u = pVertices[3].u = 0.0f;
pVertices[0].v = pVertices[1].v = 0.0f;
pVertices[2].v = pVertices[3].v = 1.0f;
VtxBox->Unlock();
/////////////////////////////////////////////////
//TRANSLATION
D3DXMATRIX Position;
D3DXMatrixTranslation( &Position,
-( ( SysWidth / 2.0f ) - ( Width/2.0f ) ) + Coord.left,
( SysHeight / 2.0f ) - ( Height/2.0f ) - Coord.top ,
0.0f);
DXDevice->SetTransform( D3DTS_WORLD, &Position );
/////////////////////////////////////////////////
//RENDERING SEQUENCE
DXDevice->SetStreamSource( 0, VtxBox, sizeof( PARAMETERS ) );
DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
DXDevice->SetStreamSource( 0, VtxLeft, sizeof( PARAMETERS ) );
DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
DXDevice->SetStreamSource( 0, VtxBottom, sizeof( PARAMETERS ) );
DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
DXDevice->SetStreamSource( 0, VtxRight, sizeof( PARAMETERS ) );
DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
DXDevice->SetStreamSource( 0, VtxTop, sizeof( PARAMETERS ) );
DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
return true;
}
int CDXDraw::ScaleX( int X )
{
GetClientRect( hWnd, &windowSize);
return ( windowSize.right - 5.0 ) / (float) SysWidth * X;
}
int CDXDraw::ScaleY( int Y )
{
GetClientRect( hWnd, &windowSize);
return ( windowSize.bottom - 5.0 ) / (float) SysHeight * Y;
}
void CDXDraw::ScaleRect( RECT &r )
{
if( &r == NULL )
return;
GetWindowRect( hWnd, &windowSize);
r.left = ( ( windowSize.right ) / (float) SysWidth )* r.left;
r.right = ( ( windowSize.right ) / (float) SysWidth ) * r.right;
r.bottom = ( ( windowSize.bottom ) / (float) SysHeight ) * r.bottom;
r.top = ( (windowSize.bottom ) / (float)SysHeight ) * r.top;
}
Interface for a Button Object
class CButton : public CWindow_GUI
{
public:
CButton();
virtual ~CButton();
virtual int RenderWindow( );
virtual void Init( );
// virtual void Init( );
//these refer to the face
void SetImage( char *UpImage, char *DownImage = NULL );
void SetButtonText( char *UpText, char* DownText = NULL );
bool CreateSurface( );
void SetFont( char *FontType = NULL );
void SetPoint( int Point = 12 );
void SetColor( DWORD Color = 0 );
void SetMargins( short Vertical, short Horizontal );
void SetParams( bool Italic = false, bool Bold = false, bool Underline = false );
void SetAutoDraw( bool Auto = true, DWORD color = 0xffBCBCBC );
void SetCommandLeft( void *ComLMB );
// virtual void Test( int a );
//Messaging
virtual void GM_MOUSEACTION( int MouseX, int MouseY, short Btn, short LastBtnState );
protected:
SButtonInf sButtonInf;
// void *CommandLB();
};
#endif
CButton::CButton()
{
}
CButton::~CButton()
{
}
void CButton::Init( )
{
//TODO: Put this in initialize
sButtonInf.DrawUp = true;
sButtonInf.sTxtInf.Italic = false;
sButtonInf.sTxtInf.Bold = 0;
sButtonInf.sTxtInf.Underline = false;
sButtonInf.sTxtInf.Font = "Times New Roman";
sButtonInf.sTxtInf.Point = 10;
sButtonInf.sTxtInf.Color = 0xff000000;
sButtonInf.BorderWidth = 3;
sButtonInf.AutoDraw = true;
sButtonInf.color = 0xffBCBCBC;
sButtonInf.UText = "Hello World";
sButtonInf.DText = "Hello World";
sButtonInf.DrawUp = true;
sButtonInf.HMargin = 4;
sButtonInf.VMargin = 4;
SetPos( 0, 0 );
SetSize( 100, 100 );
}
void CButton::SetFont( char *FontType )
{
if( FontType != NULL )
sButtonInf.sTxtInf.Font = FontType;
else
sButtonInf.sTxtInf.Font = "Arial";
}
void CButton::SetPoint( int Point )
{
if( Point % 2 )
Point--;
if( Point > 24 )
Point = 24;
if( Point == 0 )
Point = 12;
if( Point < 8 )
Point = 8;
sButtonInf.sTxtInf.Point = Point;
}
void CButton::SetColor( DWORD Color )
{
sButtonInf.sTxtInf.Color = Color;
}
void CButton::SetParams( bool Italic, bool Bold, bool Underline )
{
if( Bold )
sButtonInf.sTxtInf.Bold = 700;
else
sButtonInf.sTxtInf.Bold = 0;
sButtonInf.sTxtInf.Italic = Italic;
sButtonInf.sTxtInf.Underline = Underline;
}
void CButton::SetImage( char *UpImage, char *DownImage )
{
sButtonInf.UImage = UpImage;
if( DownImage == NULL )
sButtonInf.DImage = sButtonInf.UImage;
else
sButtonInf.DImage = DownImage;
}
void CButton::SetButtonText( char *UpText, char* DownText )
{
sButtonInf.UText = UpText;
if ( DownText == NULL )
sButtonInf.DText = sButtonInf.UText;
else
sButtonInf.DText = DownText;
}
int CButton::RenderWindow( )
{
DXControl->DrawButton( sCoord.pos, sButtonInf );
return 0;
}
void CButton::SetMargins( short Vertical, short Horizontal )
{
sButtonInf.VMargin = Vertical;
sButtonInf.HMargin = Horizontal;
}
void CButton::GM_MOUSEACTION( int MouseX, int MouseY, short Btn, short LastBtnState )
{
bool inside = ClickInside( MouseX, MouseY );
bool up = sButtonInf.DrawUp;
//State machine
if( inside == true && up == true )//Button has been clicked on
sButtonInf.DrawUp = false;
if( inside == true && up == false )//Button has been activated
{
sButtonInf.DrawUp = true;
GM_USERACTION_MOUSE( Btn );
// (void)CommandLB( );
}
if( inside == false && up == false )//Button has been cancelled
sButtonInf.DrawUp = true;
}
void CButton::SetAutoDraw( bool Auto, DWORD color )
{
sButtonInf.AutoDraw = Auto;
sButtonInf.color = color;
}
/*
void CButton::Test( int a )
{
if( sButtonInf.DrawUp == false )
sButtonInf.DrawUp = true;
else
sButtonInf.DrawUp = false;
}*/
void CButton::SetCommandLeft( void *ComLMB )
{
// CommandLB() = ComLMB();
}
The likned list template, homemade I might say...
template< class NTYPE >
class ArrayPtrCtrl
{
public:
ArrayPtrCtrl( );
~ArrayPtrCtrl( );
//TODO: NEED DELETE ELEMENT NOT ITEM
//ALSO NEED TO ADD INSERT IN LINKS
//ALSO NEED TO REVIEW ALL ITERATION ROUTINES
int Add( NTYPE value ); //add pointer to back
int Delete( NTYPE value ); //delete a given pointer
NTYPE GetData( int ind ) const; //Give index # and get data
NTYPE GetDataBW( int index ) const;
bool IsValid( int ind );
bool IsEmpty( );
int GetCount( );
void DeleteAll( );
private:
APtrNode< NTYPE > * Search( NTYPE Data );
NTYPE GetDBW( int index, int dest, APtrNode< NTYPE > *ptr ) const;
int size;
APtrNode< NTYPE > *Start; //Pointer to start of list
APtrNode< NTYPE > *End; //pointer to end
APtrNode< NTYPE > *getNewNode( const NTYPE/*, APtrNode< NTYPE > last*/ );
NTYPE Value;
int count;
};
///////////////////////////////////////////////////////////////
/////////Implementaion
///////////////////////////////////////////////////////////////
template< class NTYPE >
ArrayPtrCtrl< NTYPE >::ArrayPtrCtrl( )
: Start( NULL ), End( NULL )
{
count = 0;
};
template< class NTYPE >
ArrayPtrCtrl< NTYPE >::~ArrayPtrCtrl( )
{
//List has stuff in it
if( !IsEmpty( ) )
{
APtrNode< NTYPE > *currentPtr = Start;
APtrNode< NTYPE > *tempPtr;
while ( currentPtr != NULL )
{
tempPtr = currentPtr; //make addy of temp be that of the current ptr
currentPtr = currentPtr->nextPtr;//change the current
tempPtr->data = NULL;
delete tempPtr; //delete the one that was previous
tempPtr = NULL;
}
}
}
template< class NTYPE >
ArrayPtrCtrl< NTYPE >::Add( NTYPE value )
{
//FOUL!!!!
// if ( value == NULL )
// return -1;
APtrNode< NTYPE > *nPtr = getNewNode( value );
if( nPtr == NULL )
MessageBox( NULL, "nPtr Null", "AptrNode", MB_YESNO );
if( value == NULL )
MessageBox( NULL, "value Null", "AptrNode", MB_YESNO );
if ( IsEmpty( ) ) //List is empty
{
Start = nPtr;
End = nPtr;
nPtr->lastPtr = Start;
}
else
{
End->nextPtr = nPtr; //Assign the last ptr's new ptr
nPtr->lastPtr = End;
End = nPtr; //Assign last pointer to the new ptr
};
count++;
return 1;
};
template< class NTYPE >
//This adds another point to the node
APtrNode< NTYPE > *ArrayPtrCtrl< NTYPE >::getNewNode ( NTYPE value/*, APtrNode< NTYPE > last*/ )
{
APtrNode< NTYPE > *ptr =
new APtrNode< NTYPE > ( value );
return ptr;
};
//This will return the address of data
template< class NTYPE >
APtrNode< NTYPE > *ArrayPtrCtrl< NTYPE >::Search( NTYPE data )
{
APtrNode< NTYPE > *currentPtr = Start;
while ( currentPtr != NULL )
{
//Check if the current node has the data being searched for
if ( currentPtr->GetData( ) == data )
{
//if so, return the node address
return currentPtr;
break;
};
//This sets the current pointer address to the address specified in
//currentpointer.NextPointer
currentPtr = currentPtr -> nextPtr;
};
return NULL;
};
template< class NTYPE >
int ArrayPtrCtrl< NTYPE >::Delete( NTYPE data )
{
//Pointer to delete
APtrNode< NTYPE > *delPtr = Search( data );
//See if the data is in the list
if( delPtr == NULL )
return NULL;
//Since it is, begin from 1st address
APtrNode< NTYPE > *currentPtr = Start;
if ( currentPtr == delPtr )
{
Start = currentPtr->nextPtr;
currentPtr->nextPtr = NULL;
delete delPtr;
return true;
};//just in case it is the first pointer
while( currentPtr->nextPtr != NULL )//until end of list
{
//if the next pointer address is equal to the address of
//the & of the node to be deleted, then set the next pointer
//to the one of the pointer to be deleted
if ( currentPtr->nextPtr == delPtr )
{
currentPtr->nextPtr = delPtr->nextPtr;
delPtr->nextPtr = NULL;
return true;
};
currentPtr = currentPtr->nextPtr;
//break;
};
return NULL;//Somethings wrong
};
template< class NTYPE >
bool ArrayPtrCtrl< NTYPE >::IsValid( int index )
{
int in; //index
APtrNode< NTYPE > *currentPtr; //
currentPtr = Start;
if ( currentPtr == NULL )
return false;
if( index == 0 )
return true; //since this is the first on the list and wont get tested
//loop through chain up to index
for( in = 0 ; in<index ; in++ )
{
//jump to next node
currentPtr = currentPtr->nextPtr; //take the current pointer,
//and assign it to the next on the list.
if ( currentPtr == NULL ) //if the pointer becomes invalid, then the
return false;//error //link does not exist
}//we have 1
return true;//since CurrentPtr does exist, return true
};
template< class NTYPE >
NTYPE ArrayPtrCtrl< NTYPE >::GetData( int index ) const
{
int in;
APtrNode< NTYPE > *currentPtr;
currentPtr = Start;
//loop through chain
for( in = 0 ; in<index ; in++ )
{
//jump to next node
currentPtr = currentPtr->nextPtr; //take the current pointer,
//and assign it to the next on the list.
if ( currentPtr == NULL )
return NULL;//error
}//we have 1
if ( index == 0 )
{
currentPtr = Start; //in case the current pointer
//is start and not a next ptr
//when point is reached, return the data
return currentPtr->GetData( );
}
else
return currentPtr->GetData( );
};
template< class NTYPE >
bool ArrayPtrCtrl< NTYPE >::IsEmpty( )
{
if ( Start == NULL )
return true;
else
return false;
};
template< class NTYPE >
NTYPE ArrayPtrCtrl< NTYPE >::GetDBW( int index, int dest, APtrNode< NTYPE > *ptr ) const
{
if( index == dest )
return ptr->GetData( );
GetDBW( index, (dest-1), ptr->lastPtr );
}
template< class NTYPE >
NTYPE ArrayPtrCtrl< NTYPE >::GetDataBW( int index ) const
{
if( index > count ) return 0;
if( index == count )
return End->GetData( );
if( index <= 0 )
return Start->GetData( );
GetDBW( index, count, End );
};
template< class NTYPE >
int ArrayPtrCtrl< NTYPE >::GetCount( )
{
return count;
}
template< class NTYPE >
void ArrayPtrCtrl< NTYPE >::DeleteAll( )
{
if( IsEmpty( ) == false )
{
APtrNode< NTYPE > *currentPtr = Start;
APtrNode< NTYPE > *tempPtr;
while ( currentPtr != NULL )
{
tempPtr = currentPtr; //make addy of temp be that of the current ptr
currentPtr = currentPtr->nextPtr;//change the current
tempPtr->data = NULL;
Start = NULL;
End = NULL;
delete tempPtr; //delete the one that was previous
//tempPtr = NULL;
}
}
}