/*********************************************************************//**
*	BaseFunction
*	Abstraktni trida defije jeden typ entit->funkce, ktere maji polygonovy
*	model vykreslovany klasicky back-to-front.
*	
*	author: Michal Jirous
*	date: 23.04.2009
*	file: ent_basefunction.cpp
**********************************************************************/

#include "ent_basefunction.h"
#include "level_render.h"
#include "level_loader.h"
#include "level_decals.h"
CBaseFunction::CBaseFunction()
{
	m_bSwitched = false;
	m_iProperties = ENT_PARM_COLLIDING | ENT_PARM_RENDER;
	m_bRenderSelf = false;
}


bool CBaseFunction::renderCullTest(  RenderData &renderData )
{
	dmodel_t &model = levelLoader.m_LevelData.models[m_SolidModel];
	m_bRenderSelf = false;
	if( renderData.frustum->isBoundsInsideFrustum( model.bounds ) )
		m_bRenderSelf = true;
	return (m_bRenderSelf || decalSystem.containDecals(m_SolidModel));	//kdyz obsahuje decals, tak at se vykresli
}

void CBaseFunction::basicSolidRender( RenderData &renderData )
{	
	if(m_bRenderSelf)
		renderer.backToFrontRendering( renderData, m_SolidModel );
	decalSystem.renderDecalsForModel( m_SolidModel, renderData );		//vykreslime decals
}	

bool texturesPoolCreating( Face &face, CBaseFunction *initiator )
{
	if( initiator && face.pTexture && face.pTexture->m_pTextureElement )
	{
		if( face.pTexture->m_pTextureElement != face.pTexture->m_pTextureElement->switcher )	//pokud existuje nejaky switch
		{
			face.pTexture->unload();	//prestaneme pouzivat globalni pool
			face.pTexture = initiator->m_TexturesPool.Pool_applyTexture( face.pTexture->m_pTextureElement->key );
		}
	}
	return false;
}



void CBaseFunction::compile()
{
	CBaseEntity::compile();
	if( m_SolidModel == 0 )
		return;

	m_pSortBoundingBox = &levelLoader.m_LevelData.models[m_SolidModel].bounds;

	levelLoader.forEachFaceDo( m_SolidModel, (bool (*)(Face &,void*) )texturesPoolCreating, this );
}

void CBaseFunction::decompile()
{	
	m_TexturesPool.Pool_destroy();
}

void CBaseFunction::render( RenderData &renderData )
{ 
	if( renderData.frameTimes.texturesAnim )
		m_TexturesPool.Pool_animNextAll();

	setRenderMode();
	basicSolidRender( renderData );
	unsetRenderMode();
}


void CBaseFunction::onTarget( int target_type )
{
	switchTextures();
}

#include "game.h"

void CBaseFunction::switchTextures()
{
	m_TexturesPool.Pool_switchNextAll();
	m_bSwitched ^= true;
	
	m_BackTimeData.push_front( BackTimeData() );
	m_BackTimeData.front().event_time = game.getGameTime();
	m_BackTimeData.front().type = EVENT_TEXTURE_SWITCH;
}



void CBaseFunction::restart()
{
	CBaseEntity::restart();
	if( m_bSwitched )
		switchTextures();
}

void CBaseFunction::goBackInTime()
{
	CBaseEntity::goBackInTime();

	for( std::list<BackTimeData>::reverse_iterator riter = m_BackTimeData.rbegin(); riter != m_BackTimeData.rend(); ++riter )
	{
		if( (*riter).type == EVENT_BORDER )
			return;

		if( (*riter).type == EVENT_TEXTURE_SWITCH )
			switchTextures();
	}
}

void CBaseFunction::passStoredEvent( BackTimeData &backData )
{
	if( backData.type == EVENT_TEXTURE_SWITCH )
			switchTextures();
}
