/** 
 * \file Button.cpp
 * \brief Various buttons implementation.
 * 
 * CButton class provides standard button functionality. User can make 2D and 3D buttons.
 * C2DButton can be initialized with selected picture, position, size, rotation, sound. 
 * C3DButton is initialized with 3D model instead of image.
 *
 * \author Petar Bajic, MPE (C) All Rights Reserved, Homepage: www.mystic-peanut.com
 * \date January, 16 2007.
 */

#include "Button.h"

#pragma warning( disable : 4996 ) // disable deprecated warning 
#include <strsafe.h>
#pragma warning( default : 4996 )

/**
 * \brief Basic button constructor.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
CButton::CButton()
{
	m_textColor = 0xFF000000;
	m_rcBoundingBox.bottom = m_rcBoundingBox.left = m_rcBoundingBox.right = m_rcBoundingBox.top = 0;
	m_rcTextBox.bottom = m_rcTextBox.left = m_rcTextBox.right = m_rcTextBox.top = 0;
	m_bEnabled = true;
	m_bVisible = true;
	WCHAR* m_caption = NULL;;
	m_focusIn = false;
	m_bPressed = false;
	m_localTime = 0.0;
	m_clickSound = NULL;
	m_focusSound = NULL;
}

/**
 * \brief Basic button destructor
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
CButton::~CButton()
{
}

/**
 * \brief Button press function.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CButton::OnButtonPress()
{
	if (CanHaveFocus())
	{
		m_clickSound->Stop();
		m_clickSound->Reset();
		m_clickSound->Play();
	}
}

/**
 * \brief This function sets focus on button.
 * \param focus true if button is selected.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CButton::SetFocus(bool focus)
{
	if (CanHaveFocus())
	{
		if (focus && !m_focusIn)
		{
			m_focusSound->Reset();
			m_focusSound->Play();
		}
		m_focusIn = focus;

		if (!focus)
			m_transOffset.x = 0;
	}
}

/**
 * \brief Initialize button object.
 * \param type MPE_BUTTON_TYPE enum variable.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
bool CButton::Init(RECT box, bool visible, bool enabled, WCHAR* caption, RECT textBox, 
				   IDirectSound8* pDS, LPWSTR clickSoundFilename, LPWSTR focusSoundFilename, int type)
{
	m_buttonType = type;
	return true;
}

/**
 * \brief OnEvent should handle events like mouse click and mouse over.
 * For button to handle these events, button class must contain info about button position, size, etc.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
bool CButton::OnEvent( UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	return true;
}

/**
 * \brief OnRender is stub for basic button class, it is implemented in classes who inherit CButton.
 * (Should be declared virutal)
 * \param pd3dDevice DirectX 3D device.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CButton::OnRender(LPDIRECT3DDEVICE9 pd3dDevice)
{
}

/**
 * \brief OnFrameMove is stub for basic button class, it is implemented in classes who inherit CButton.
 * (Should be declared virutal)
 * \param fElapsedTime time between two frames
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void CButton::OnFrameMove(LPDIRECT3DDEVICE9 pd3dDevice, float fElapsedTime)
{
}

/**
 * \brief Initialize button object.
 * \param type MPE_BUTTON_TYPE enum variable.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
bool C2DButton::Init(HWND hWnd, RECT box, bool visible, bool enabled, WCHAR* caption, RECT textBox, LPDIRECT3DTEXTURE9 tex, LPDIRECT3DTEXTURE9 texOver, 
					 IDirectSound8* pDS, LPWSTR clickSoundFilename, LPWSTR focusSoundFilename,int type)
{
	m_buttonType = type;
	m_rcBoundingBox = box;
	m_rcTextBox = textBox;
	m_bEnabled = enabled;
	m_bVisible = visible;
	m_caption = caption;
	m_buttonTexture = tex;
	m_buttonTextureOver = texOver;

	//private frame move animation parameters
	m_transOffset = D3DXVECTOR2(0.0f,0.0f);;
	m_scaleOffset = D3DXVECTOR2(0.0f,0.0f);;

	m_clickSound = new CSound();
	if (!m_clickSound->Init(pDS, clickSoundFilename))
	{
		MessageBox(hWnd,L"Could not load button sound file",L"Error",MB_OK);
		return false;
	}
	m_focusSound = new CSound();
	if (!m_focusSound->Init(pDS, focusSoundFilename))
	{
		MessageBox(hWnd,L"Could not load button sound file",L"Error",MB_OK);
		return false;
	}

	if ((m_buttonTexture == NULL) || (m_buttonTextureOver == NULL))
		return false;

	return true;
}

/**
 * \brief Standard constructor.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
C2DButton::C2DButton()
{
	m_buttonTexture = NULL;
	m_buttonTextureOver = NULL;
}

/**
 * \brief OnEvent should handle events like mouse click and mouse over.
 * For button to handle these events, button class must contain info about button position, size, etc.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
bool C2DButton::OnEvent( UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	return false;
}

/**
 * \brief Render button on the screen (d3ddevice).
 * 2D buttons are drawn on sprites. They have texture and caption.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void C2DButton::OnRender(LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXSPRITE pSprite, LPD3DXFONT pFont, 
						 D3DXVECTOR2* pScaling, D3DXVECTOR2* pTrans, D3DXVECTOR2* spriteCentre, float rotation)
{
	D3DXMATRIX mat;
	if(pTrans != NULL)
	{
		//button can be positioned by bounding box or translation matrix.if both are defined, position is calculated
		//as addition of both values. m_transOffset is added also: this is usefull for animating temporary small 
		//movement around basic position. Same effect can be made from outside by sending pTrans offsets.
		D3DXVECTOR2 trans=D3DXVECTOR2(0.0f,0.0f);
		trans.x = pTrans->x + m_rcBoundingBox.left + m_transOffset.x; 
		trans.y = pTrans->y + m_rcBoundingBox.top + m_transOffset.y;  
		if (m_bVisible)
		{
			switch (m_buttonType)
			{
			case MPE_BUTTON_TYPE_2DSTATIC:
				my_DrawSprite(&mat, pScaling, spriteCentre, rotation, &trans, m_buttonTexture, pSprite, m_bEnabled, 
								&m_rcTextBox, m_caption, pFont, m_textColor);
			case MPE_BUTTON_TYPE_2DSWITCH:
				my_DrawSprite(&mat, pScaling, spriteCentre, rotation, &trans, m_focusIn ? m_buttonTextureOver : m_buttonTexture,
								pSprite, m_bEnabled, &m_rcTextBox, m_caption, pFont, m_textColor);
			}
		}
	}
}

/**
 * \brief OnFrameMove defines button animation (if any).
 * In this case, buttons are shaken when in focus.
 * \author Petar Bajic 
 * \date January, 16 2007.
 */
void C2DButton::OnFrameMove(LPDIRECT3DDEVICE9 pd3dDevice, float fElapsedTime)
{
	static float tempTime = 0;

	if (m_focusIn)
	{
		tempTime += fElapsedTime*4;
		m_transOffset.x += fElapsedTime*30;
		if (tempTime > 0.3)
		{
			tempTime = 0;
			m_transOffset.x = 0;
		}
	}
}
