#include "SampleActorsGame.h"

SampleActorsGame::SampleActorsGame()
{
	this->preferAntialising(4);
}

void SampleActorsGame::initialize()
{
	SampleGame::initialize();

	planeMaterial = Material(Color::Black);

	camera->lookAt(PxVec3(40, 50, 40), PxVec3(0, 0, 0));

	//aktor statyczny - plaszczyzna
	PxRigidStatic* staticActor = this->createStaticActor(PxTransformFromPlaneEquation(PxPlane(0,1,0,0)),PxPlaneGeometry(),defaultPhysicsMaterial,&planeMaterial);
	scene->addActor(*staticActor);

	//aktor statyczny - sciana
	PxRigidStatic* wallActor=this->createStaticActor(PxTransform(PxVec3(0,4,-30)),PxBoxGeometry(10,4,2),defaultPhysicsMaterial,&Material::PolishedSilver);
	scene->addActor(*wallActor);

	//aktor dynamiczny - spadajaca kostka
	PxRigidDynamic* dynamicActor = this->createDynamicActor(PxTransform(PxVec3(0,20,0)),PxBoxGeometry(1,1,1),defaultPhysicsMaterial,&Material::Ruby);
	scene->addActor(*dynamicActor);

	//aktor kinetyczny - slupek
	kineticActor=this->createDynamicActor(PxTransform(PxVec3(0,4,20)),PxBoxGeometry(2,4,2),defaultPhysicsMaterial,&Material::Emerald);
	kineticActor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC,true);\
	scene->addActor(*kineticActor);

	kineticVelocity = 15.0f;
	kineticAngle=PxPi;

	//oszustwo
	this->addStackedBoxesAt(PxVec3(0,0,5),15,defaultPhysicsMaterial,&Material::Ruby);
	this->addPiramidBoxesAt(PxVec3(0,0,-5),7,defaultPhysicsMaterial,&Material::Gold);
	this->addWallBoxesAt(PxVec3(0,0,-15),5,4,defaultPhysicsMaterial,&Material::Chrome);

	this->addWallBoxesAt(PxVec3(0,0,25),5,4,defaultPhysicsMaterial,&Material::Chrome);
	this->addWallBoxesAt(PxVec3(0,0,35),5,4,defaultPhysicsMaterial,&Material::Chrome);
	this->addWallBoxesAt(PxVec3(0,0,45),5,4,defaultPhysicsMaterial,&Material::Chrome);
	this->addWallBoxesAt(PxVec3(0,0,55),5,4,defaultPhysicsMaterial,&Material::Chrome);
	this->addWallBoxesAt(PxVec3(0,0,65),5,4,defaultPhysicsMaterial,&Material::Chrome);
}

void SampleActorsGame::release()
{
	SampleGame::release();
}

void SampleActorsGame::rzucPudelkiem(const PxVec3& position,GxF32 halfExtents, const PxVec3& initialVelocity,const PxMaterial* physicsMaterial, Gx::Material* graphicsMaterial, PxReal density)
{
	PxTransform pose(position);
	//if(pose.p.y<halfExtents) pose.p.y=halfExtents+0.02f;

	PxRigidDynamic* actor=this->createDynamicActor(pose,PxBoxGeometry(halfExtents,halfExtents,halfExtents),physicsMaterial,graphicsMaterial,density);
	actor->setLinearVelocity(initialVelocity);
	actor->setLinearDamping(0.2f);

	scene->addActor(*actor);
}

void SampleActorsGame::input(GxF32 elapsedTime)
{
	SampleGame::input(elapsedTime);

	if(getKeyboard().isKeyPressed(Keys::Space))
	{
		PxVec3 velocity=camera->getViewDir();
		velocity*=150.0f;
		this->rzucPudelkiem(camera->getPosition(),2.0f,velocity,defaultPhysicsMaterial);
	}


	static bool kineticControl = false;
	if(getKeyboard().isKeyPressed(Keys::K))
	{
		kineticControl=!kineticControl;
	}

	if(kineticControl)
	{
		PxTransform pose = kineticActor->getGlobalPose();
		if(getKeyboard().isKeyDown(Keys::Up)) pose.p+=pose.rotate(PxVec3(0,0,-1)) * kineticVelocity * elapsedTime; //nie wiem
		if(getKeyboard().isKeyDown(Keys::Down)) pose.p-=pose.rotate(PxVec3(0,0,-1)) * kineticVelocity * elapsedTime;
		if(getKeyboard().isKeyDown(Keys::Left)) pose.q*=PxQuat(kineticAngle * elapsedTime, PxVec3(0,1,0));
		if(getKeyboard().isKeyDown(Keys::Right)) pose.q*=PxQuat(-kineticAngle * elapsedTime, PxVec3(0,1,0));
		pose.q*=PxQuat(-getMouse().getRelativePositionX()*elapsedTime*0.5f,PxVec3(0,1,0));
		kineticActor->setKinematicTarget(pose);

		//FPP
		const static GxF32 cameraDistance = -20;
		static GxF32 cameraHeight = 10;
		cameraHeight += -getMouse().getRelativePositionY()*elapsedTime;

		PxVec3 cameraOffset = pose.rotate(PxVec3(0,0,-1))*cameraDistance;
		cameraOffset.y=cameraHeight;
		camera->lookAt(pose.p+cameraOffset,pose.p);
	}


	const GxF32 fps = getStepper().getFps();
	std::stringstream stream;
	stream << "Sample Actors | Fps: " << std::fixed << std::setprecision(1) << fps 
		<< " | Dynamic actors: " << scene->getNbActors(PxActorTypeSelectionFlag::eRIGID_DYNAMIC)
		<< " | Static actors: " << scene->getNbActors(PxActorTypeSelectionFlag::eRIGID_STATIC)
		<< " | Camera position: " << camera->getPosition().x << " ; " << camera->getPosition().y << " ; " << camera->getPosition().z;

	this->setTitle(stream.str());
}

void SampleActorsGame::update(GxF32 elapsedTime)
{
	SampleGame::update(elapsedTime);
}

void SampleActorsGame::render(GxF32 elapsedTime)
{
	SampleGame::render(elapsedTime);

	graphics->clear(Color::CornflowerBlue);

	effect->bind();
	effect->setProjMatrix(projectionMtx);
	effect->setViewMatrix(camera->getViewMatrix());

	this->renderScene(scene);

	effect->unbind();
}

void SampleActorsGame::printHelp()
{
	SampleGame::printHelp();

	std::cout << "Spacja - rzucenie pudelkiem w kierunku patrzenia" << std::endl
		<< "K - przelaczenie miedzy trybami kamery FPP - TPP" << std::endl << std::endl
		<< "# Sterowanie aktorem kinetycznym" << std::endl
		<< "Aktorem kinetycznym sterujemy za pomoca klawiszy strzalek oraz myszki." << std::endl;
}
