// This file is part of ThriceBall.
//
// Author: Kai Hillenbrand (AnTeevY)
// © Copyright, 2009 by Kai Hillenbrand, http://www.anteevy.de

// --------------------------------------------------

#include "gate.h"

CGate::CGate(CRenderer *renderer, CLevel *level, NxOgre::Scene *scene, OGRE3DRenderSystem *rendersys)
	: m_pRenderer(renderer), m_pLevel(level), m_pScene(scene), m_pRenderSystem(rendersys), m_iColor(1),
	m_fXPos(0), m_fYPos(0), m_fZPos(0)
{
	m_pSceneMgr = m_pRenderer->getSceneManager();
	m_pPlayer = m_pRenderer->getPlayer();
}

void CGate::create(float x, float y, float z, int color)
{
	// apply the variables
	m_iColor = color;
	m_fXPos = x;
	m_fYPos = y;
	m_fZPos = z;	

	// load the .nxs file
	NxOgre::ResourceSystem::getSingleton()->openArchive("models", "file:media/models");
	NxOgre::ArchiveResourceIdentifier nxs("models:gate.nxs");
	NxOgre::Mesh* triangleMesh = NxOgre::MeshManager::getSingleton()->load(nxs);
	NxOgre::TriangleGeometry* triangleGeometry = new NxOgre::TriangleGeometry(triangleMesh);
	m_pScene->createSceneGeometry(triangleGeometry, NxOgre::Matrix44(NxOgre::Real3(m_fXPos, m_fYPos, m_fZPos)));
	
	// avoid twice the same entity name
	String entName = "";
	bool entExists = true;

	while (entExists)
	{
		entName = "Gate_" + StringConverter::toString(Ogre::Math::RangeRandom(0,10000));
		entExists = m_pSceneMgr->hasEntity(entName);
	}	

	// create the visible mesh
	Ogre::Entity* triangleEntity = m_pSceneMgr->createEntity(entName, "gate.mesh");
	triangleEntity->setCastShadows(m_pRenderer->shadowsEnabled());
	Ogre::SceneNode* triangleNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode();
	triangleNode->attachObject(triangleEntity);
	triangleNode->setPosition(Vector3(m_fXPos, m_fYPos, m_fZPos));
	
	createParticles();	// create the red/green/blue particles in the door
	setupVolume();		// create the volume and trigger
}

void CGate::setupVolume()
{
	m_pVolume = m_pScene->createVolume(new NxOgre::Box(NxOgre::Vec3(3.5, 2, 3.5)), 
		NxOgre::Matrix44(NxOgre::Real3(m_fXPos, m_fYPos + 1, m_fZPos)),	this, NxOgre::Enums::VolumeCollisionType_All);
}

void CGate::onVolumeEvent(NxOgre::Volume* volume, NxOgre::Shape* volumeShape, NxOgre::RigidBody* rigidBody, 
		NxOgre::Shape* rigidBodyShape, unsigned int collisionEvent)
{
	NxOgre::Actor* actor = static_cast<NxOgre::Actor*>(rigidBody);

	if ((volume == m_pVolume) && (actor == m_pPlayer->getCurBall()))
	{
		// if ball enters the volume
		if(collisionEvent == NxOgre::Enums::VolumeCollisionType_OnEnter)
		{
			Vector3 direction = Vector3(actor->getLinearVelocity().x, actor->getLinearVelocity().y,
				actor->getLinearVelocity().z);
			direction.normalise();
			
			// if player ball has not the same color as the gate, push it back
			if (m_pPlayer->getCurBallNum() != m_iColor)
			{
				// reset the speed of the ball and add a force in the reversed direction
				actor->setLinearVelocity(NxOgre::Vec3(0,0,0));
				actor->addForce(-direction * 150 * m_pPlayer->getCurPowerMult());
				m_pRenderer->getAudio()->playSound(3);	// play "no way" sound
			}
		}
	}
}

void CGate::createParticles()
{
	ParticleSystem* pSys = 0;
	String partName = "";
	bool partExists = true;

	// avoid twice the same particle (and later particle node) name
	while (partExists)
	{
		partName = "GateParticles_" + StringConverter::toString(Ogre::Math::RangeRandom(0,10000));
		partExists = m_pSceneMgr->hasParticleSystem(partName);
	}

	// create particle system based on color
	pSys = m_pSceneMgr->createParticleSystem(partName, "GateParticles");

	switch (m_iColor)	// change to appropiate color
	{
	case 1: // red
		pSys->getEmitter(0)->setColourRangeStart(ColourValue(1,0,0));
		pSys->getEmitter(0)->setColourRangeEnd(ColourValue(0.7,0,0));
		break;
	case 2: // green
		pSys->getEmitter(0)->setColourRangeStart(ColourValue(0,1,0));
		pSys->getEmitter(0)->setColourRangeEnd(ColourValue(0,0.7,0));
		break;
	case 3: // blue
		pSys->getEmitter(0)->setColourRangeStart(ColourValue(0,0,1));
		pSys->getEmitter(0)->setColourRangeEnd(ColourValue(0,0,0.7));
		break;
	default: 
		break;
	}
	
	// adjust its position
    SceneNode *partNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("Node_" + partName);
    partNode->attachObject(pSys);
	partNode->setPosition(Vector3(m_fXPos, m_fYPos + 1.8, m_fZPos));
}
