SA-MP/saco/d3d9/common/DXUTgui.cpp

539 lines
15 KiB
C++

//--------------------------------------------------------------------------------------
// File: DXUTgui.cpp
//
// Desc:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include "dxstdafx.h"
#include "DXUTgui.h"
#include "DXUTsettingsDlg.h"
#undef min // use __min instead
#undef max // use __max instead
double CDXUTDialog::s_fTimeRefresh = 0.0f;
CDXUTControl* CDXUTDialog::s_pControlFocus = NULL; // The control which has focus
CDXUTControl* CDXUTDialog::s_pControlPressed = NULL; // The control currently pressed
//--------------------------------------------------------------------------------------
// CDXUTDialog class
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
CDXUTDialog::CDXUTDialog()
{
m_x = 0;
m_y = 0;
m_width = 0;
m_height = 0;
m_pManager = NULL;
m_bVisible = true;
m_bCaption = false;
m_bMinimized = false;
m_wszCaption[0] = L'\0';
m_nCaptionHeight = 18;
m_colorTopLeft = 0;
m_colorTopRight = 0;
m_colorBottomLeft = 0;
m_colorBottomRight = 0;
m_pCallbackEvent = NULL;
m_pCallbackEventUserContext = NULL;
m_fTimeLastRefresh = 0;
m_pControlMouseOver = NULL;
m_pNextDialog = this;
m_pPrevDialog = this;
m_nDefaultControlID = 0xffff;
m_bNonUserEvents = false;
m_bKeyboardInput = false;
m_bMouseInput = true;
}
//--------------------------------------------------------------------------------------
CDXUTDialog::~CDXUTDialog()
{
int i=0;
RemoveAllControls();
m_Fonts.RemoveAll();
m_Textures.RemoveAll();
for( i=0; i < m_DefaultElements.GetSize(); i++ )
{
DXUTElementHolder* pElementHolder = m_DefaultElements.GetAt( i );
SAFE_DELETE( pElementHolder );
}
m_DefaultElements.RemoveAll();
}
//--------------------------------------------------------------------------------------
void CDXUTDialog::SetCallback( PCALLBACKDXUTGUIEVENT pCallback, void* pUserContext )
{
// If this assert triggers, you need to call CDXUTDialog::Init() first. This change
// was made so that the DXUT's GUI could become seperate and optional from DXUT's core. The
// creation and interfacing with CDXUTDialogResourceManager is now the responsibility
// of the application if it wishes to use DXUT's GUI.
assert( m_pManager != NULL && "To fix call CDXUTDialog::Init() first. See comments for details." );
m_pCallbackEvent = pCallback;
m_pCallbackEventUserContext = pUserContext;
}
//--------------------------------------------------------------------------------------
void CDXUTDialog::RemoveAllControls()
{
if( s_pControlFocus && s_pControlFocus->m_pDialog == this )
s_pControlFocus = NULL;
if( s_pControlPressed && s_pControlPressed->m_pDialog == this )
s_pControlPressed = NULL;
m_pControlMouseOver = NULL;
for( int i=0; i < m_Controls.GetSize(); i++ )
{
CDXUTControl* pControl = m_Controls.GetAt( i );
SAFE_DELETE( pControl );
}
m_Controls.RemoveAll();
}
//--------------------------------------------------------------------------------------
CDXUTDialogResourceManager::CDXUTDialogResourceManager()
{
m_pd3dDevice = NULL;
m_pStateBlock = NULL;
m_pSprite = NULL;
}
//--------------------------------------------------------------------------------------
HRESULT CDXUTDialogResourceManager::OnResetDevice()
{
HRESULT hr = S_OK;
for( int i=0; i < m_FontCache.GetSize(); i++ )
{
DXUTFontNode* pFontNode = m_FontCache.GetAt( i );
if( pFontNode->pFont )
pFontNode->pFont->OnResetDevice();
}
if( m_pSprite )
m_pSprite->OnResetDevice();
m_pd3dDevice->CreateStateBlock( D3DSBT_ALL, &m_pStateBlock );
return S_OK;
}
//--------------------------------------------------------------------------------------
void CDXUTDialogResourceManager::OnLostDevice()
{
for( int i=0; i < m_FontCache.GetSize(); i++ )
{
DXUTFontNode* pFontNode = m_FontCache.GetAt( i );
if( pFontNode->pFont )
pFontNode->pFont->OnLostDevice();
}
if( m_pSprite )
m_pSprite->OnLostDevice();
SAFE_RELEASE( m_pStateBlock );
}
//--------------------------------------------------------------------------------------
void CDXUTDialogResourceManager::OnDestroyDevice()
{
int i=0;
//m_pd3dDevice = NULL;
// Release the resources but don't clear the cache, as these will need to be
// recreated if the device is recreated
for( i=0; i < m_FontCache.GetSize(); i++ )
{
DXUTFontNode* pFontNode = m_FontCache.GetAt( i );
SAFE_RELEASE( pFontNode->pFont );
}
for( i=0; i < m_TextureCache.GetSize(); i++ )
{
DXUTTextureNode* pTextureNode = m_TextureCache.GetAt( i );
SAFE_RELEASE( pTextureNode->pTexture );
}
SAFE_RELEASE( m_pSprite );
}
//--------------------------------------------------------------------------------------
void CDXUTDialog::Refresh()
{
if( s_pControlFocus )
s_pControlFocus->OnFocusOut();
if( m_pControlMouseOver )
m_pControlMouseOver->OnMouseLeave();
s_pControlFocus = NULL;
s_pControlPressed = NULL;
m_pControlMouseOver = NULL;
for( int i=0; i < m_Controls.GetSize(); i++ )
{
CDXUTControl* pControl = m_Controls.GetAt(i);
pControl->Refresh();
}
if( m_bKeyboardInput )
FocusDefaultControl();
}
//--------------------------------------------------------------------------------------
VOID CDXUTDialog::SendEvent( UINT nEvent, bool bTriggeredByUser, CDXUTControl* pControl )
{
// If no callback has been registered there's nowhere to send the event to
if( m_pCallbackEvent == NULL )
return;
// Discard events triggered programatically if these types of events haven't been
// enabled
if( !bTriggeredByUser && !m_bNonUserEvents )
return;
m_pCallbackEvent( nEvent, pControl->GetID(), pControl, m_pCallbackEventUserContext );
}
//--------------------------------------------------------------------------------------
int CDXUTDialogResourceManager::AddFont( LPCTSTR strFaceName, LONG height, LONG weight )
{
// See if this font already exists
for( int i=0; i < m_FontCache.GetSize(); i++ )
{
DXUTFontNode* pFontNode = m_FontCache.GetAt(i);
if( 0 == _strnicmp( pFontNode->strFace, strFaceName, MAX_PATH-1 ) &&
pFontNode->nHeight == height &&
pFontNode->nWeight == weight )
{
return i;
}
}
// Add a new font and try to create it
DXUTFontNode* pNewFontNode = new DXUTFontNode();
if( pNewFontNode == NULL )
return -1;
ZeroMemory( pNewFontNode, sizeof(DXUTFontNode) );
StringCchCopy( pNewFontNode->strFace, MAX_PATH, strFaceName );
pNewFontNode->nHeight = height;
pNewFontNode->nWeight = weight;
m_FontCache.Add( pNewFontNode );
int iFont = m_FontCache.GetSize()-1;
// If a device is available, try to create immediately
if( m_pd3dDevice )
CreateFont( iFont );
return iFont;
}
//--------------------------------------------------------------------------------------
HRESULT CDXUTDialog::SetFont( UINT index, LPCTSTR strFaceName, LONG height, LONG weight )
{
// If this assert triggers, you need to call CDXUTDialog::Init() first. This change
// was made so that the DXUT's GUI could become seperate and optional from DXUT's core. The
// creation and interfacing with CDXUTDialogResourceManager is now the responsibility
// of the application if it wishes to use DXUT's GUI.
assert( m_pManager != NULL && "To fix call CDXUTDialog::Init() first. See comments for details." );
// Make sure the list is at least as large as the index being set
UINT i;
for( i=m_Fonts.GetSize(); i <= index; i++ )
{
m_Fonts.Add( -1 );
}
int iFont = m_pManager->AddFont( strFaceName, height, weight );
m_Fonts.SetAt( index, iFont );
return S_OK;
}
//--------------------------------------------------------------------------------------
DXUTFontNode* CDXUTDialog::GetFont( UINT index )
{
if( NULL == m_pManager )
return NULL;
return m_pManager->GetFontNode( m_Fonts.GetAt( index ) );
}
//--------------------------------------------------------------------------------------
HRESULT CDXUTDialog::InitControl( CDXUTControl* pControl )
{
HRESULT hr;
if( pControl == NULL )
return E_INVALIDARG;
pControl->m_Index = m_Controls.GetSize();
// Look for a default Element entries
for( int i=0; i < m_DefaultElements.GetSize(); i++ )
{
DXUTElementHolder* pElementHolder = m_DefaultElements.GetAt( i );
if( pElementHolder->nControlType == pControl->GetType() )
pControl->SetElement( pElementHolder->iElement, &pElementHolder->Element );
}
V_RETURN( pControl->OnInit() );
return S_OK;
}
//--------------------------------------------------------------------------------------
HRESULT CDXUTDialog::AddControl( CDXUTControl* pControl )
{
HRESULT hr = S_OK;
hr = InitControl( pControl );
if( FAILED(hr) )
return DXTRACE_ERR( "CDXUTDialog::InitControl", hr );
// Add to the list
hr = m_Controls.Add( pControl );
if( FAILED(hr) )
{
return DXTRACE_ERR( "CGrowableArray::Add", hr );
}
return S_OK;
}
//--------------------------------------------------------------------------------------
CDXUTControl* CDXUTDialog::GetControl( int ID )
{
// Try to find the control with the given ID
for( int i=0; i < m_Controls.GetSize(); i++ )
{
CDXUTControl* pControl = m_Controls.GetAt( i );
if( pControl->GetID() == ID )
{
return pControl;
}
}
// Not found
return NULL;
}
//--------------------------------------------------------------------------------------
CDXUTControl* CDXUTDialog::GetControl( int ID, UINT nControlType )
{
// Try to find the control with the given ID
for( int i=0; i < m_Controls.GetSize(); i++ )
{
CDXUTControl* pControl = m_Controls.GetAt( i );
if( pControl->GetID() == ID && pControl->GetType() == nControlType )
{
return pControl;
}
}
// Not found
return NULL;
}
//--------------------------------------------------------------------------------------
CDXUTControl* CDXUTDialog::GetNextControl( CDXUTControl* pControl )
{
int index = pControl->m_Index + 1;
CDXUTDialog* pDialog = pControl->m_pDialog;
// Cycle through dialogs in the loop to find the next control. Note
// that if only one control exists in all looped dialogs it will
// be the returned 'next' control.
while( index >= (int) pDialog->m_Controls.GetSize() )
{
pDialog = pDialog->m_pNextDialog;
index = 0;
}
return pDialog->m_Controls.GetAt( index );
}
//--------------------------------------------------------------------------------------
CDXUTControl* CDXUTDialog::GetPrevControl( CDXUTControl* pControl )
{
int index = pControl->m_Index - 1;
CDXUTDialog* pDialog = pControl->m_pDialog;
// Cycle through dialogs in the loop to find the next control. Note
// that if only one control exists in all looped dialogs it will
// be the returned 'previous' control.
while( index < 0 )
{
pDialog = pDialog->m_pPrevDialog;
if( pDialog == NULL )
pDialog = pControl->m_pDialog;
index = pDialog->m_Controls.GetSize() - 1;
}
return pDialog->m_Controls.GetAt( index );
}
//--------------------------------------------------------------------------------------
// CDXUTControl class
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
CDXUTControl::CDXUTControl( CDXUTDialog *pDialog )
{
m_Type = DXUT_CONTROL_BUTTON;
m_pDialog = pDialog;
m_ID = 0;
m_Index = 0;
m_pUserData = NULL;
m_bEnabled = true;
m_bVisible = true;
m_bMouseOver = false;
m_bHasFocus = false;
m_bIsDefault = false;
m_pDialog = NULL;
m_x = 0;
m_y = 0;
m_width = 0;
m_height = 0;
ZeroMemory( &m_rcBoundingBox, sizeof( m_rcBoundingBox ) );
}
//--------------------------------------------------------------------------------------
// CDXUTStatic class
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
HRESULT CDXUTStatic::GetTextCopy( PCHAR strDest, UINT bufferCount )
{
// Validate incoming parameters
if( strDest == NULL || bufferCount == 0 )
{
return E_INVALIDARG;
}
// Copy the window text
StringCchCopy( strDest, bufferCount, m_strText );
return S_OK;
}
//--------------------------------------------------------------------------------------
// CDXUTIMEEditBox class
//--------------------------------------------------------------------------------------
bool CDXUTIMEEditBox::s_bEnableImeSystem; // Whether the IME system is active
//--------------------------------------------------------------------------------------
// Enable/disable the entire IME system. When disabled, the default IME handling
// kicks in.
void CDXUTIMEEditBox::EnableImeSystem( bool bEnable )
{
s_bEnableImeSystem = bEnable;
}
//--------------------------------------------------------------------------------------
void DXUTBlendColor::Init( D3DCOLOR defaultColor, D3DCOLOR disabledColor, D3DCOLOR hiddenColor )
{
for( int i=0; i < MAX_CONTROL_STATES; i++ )
{
States[ i ] = defaultColor;
}
States[ DXUT_STATE_DISABLED ] = disabledColor;
States[ DXUT_STATE_HIDDEN ] = hiddenColor;
Current = hiddenColor;
}
//--------------------------------------------------------------------------------------
void DXUTBlendColor::Blend( UINT iState, float fElapsedTime, float fRate )
{
D3DXCOLOR destColor = States[ iState ];
D3DXColorLerp( &Current, &Current, &destColor, 1.0f - powf( fRate, 30 * fElapsedTime ) );
}
//--------------------------------------------------------------------------------------
void CDXUTElement::SetTexture( UINT iTexture, RECT* prcTexture, D3DCOLOR defaultTextureColor )
{
this->iTexture = iTexture;
if( prcTexture )
rcTexture = *prcTexture;
else
SetRectEmpty( &rcTexture );
TextureColor.Init( defaultTextureColor );
}
//--------------------------------------------------------------------------------------
void CDXUTElement::SetFont( UINT iFont, D3DCOLOR defaultFontColor, DWORD dwTextFormat )
{
this->iFont = iFont;
this->dwTextFormat = dwTextFormat;
FontColor.Init( defaultFontColor );
}
//--------------------------------------------------------------------------------------
void CDXUTElement::Refresh()
{
TextureColor.Current = TextureColor.States[ DXUT_STATE_HIDDEN ];
FontColor.Current = FontColor.States[ DXUT_STATE_HIDDEN ];
}