//-------------------------------------------------------------------------------------- // 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 ]; }