Original Post
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 The Main class implementation The Drawing class interface, draws all the objects. Wrapped not inplemented seperatley The Drawing class implementation, this needs the most work, i guess Interface for a Button Object The likned list template, homemade I might say...
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( );
};
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 )
{
}
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;
};
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;
}
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();
}
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;
}
}
}