void SceneSerializer::SerializeGameObject(XMLWriter& writer, const SharedGameObject gameObject)
{
	Ogre::Vector3 position = gameObject->GetWorldPosition();
	Ogre::Vector3 scale = gameObject->GetWorldScale();
	Ogre::Quaternion rotation = gameObject->GetWorldOrientation();
	
	writer.CreateNode(GameObjectNode, std::string(""), true); writer.AddAttribute(ObjectName, gameObject->GetName());
	writer.AddAttribute(ObjectTag, gameObject->tag, false, false);

		//game object Transform
		writer.CreateNode(Position);
			AddVector3Attribute(writer, position);
		writer.PopNode();

		writer.CreateNode(Rotation, gameObject->GetInheritOrientation());
			AddVector4Attribute(writer, rotation.x, rotation.y, rotation.z, rotation.w);
		writer.PopNode();

		writer.CreateNode(Scale, gameObject->GetInheritScale());
			AddVector3Attribute(writer, scale);
		writer.PopNode();

	for (auto compIter = gameObject->components.begin(); compIter != gameObject->components.end(); ++compIter)
	{
		switch (compIter->second->GetComponentType())
		{
		case Component::AUDIO_COMPONENT:
			break;

		case Component::MESH_RENDER_COMPONENT:
			SerializeMeshRenderComponent(writer, (MeshRenderComponent*)compIter->second);
			break;

		case Component::PARTICLE_COMPONENT:
			SerializeParticleComponent(writer, (ParticleComponent*)compIter->second);
			break;

		case Component::RIGID_BODY_COMPONENT:
			SerializeRigidBodyComponent(writer, (RigidBodyComponent*)compIter->second);
			break;

		default:
			break;
		}
	}

	//Serialize Child Game Objects
	for (auto childStart = gameObject->children.begin();
		childStart != gameObject->children.end(); ++childStart)
	{
		SerializeGameObject(writer, *childStart);
	}

	writer.PopNode();
}
bool SceneSerializer::SerializeRigidBodyComponent(XMLWriter& writer, const RigidBodyComponent* rigidBody)
{
	using namespace physx;

	RigidBodyComponent::RigidBodyType rigidType = rigidBody->GetBodyType();

	if(rigidType == RigidBodyComponent::NONE)
		return false;

	//if rigid body node created
	if(writer.CreateNode(RigidBodyComponen))
	{
		//write enabled state
		writer.AddAttribute(Enabled, rigidBody->IsEnabled());
		writer.AddAttribute(DynamicBodyType, rigidBody->GetBodyType() == RigidBodyComponent::DYNAMIC);

		physx::PxRigidActor* actor = NULL;
		if(rigidBody->GetBodyType() == RigidBodyComponent::DYNAMIC)
			actor = rigidBody->GetDynamicActor();
		else if(rigidBody->GetBodyType() == RigidBodyComponent::STATIC)
			actor = rigidBody->GetStaticActor();

		//if no actor, pop off the rigid body component
		if(!actor)
			writer.PopNode();

		std::string shapeName = "";
		PxU32 numShapes = actor->getNbShapes();
		PxShape** shapes = new physx::PxShape*[numShapes];
		actor->getShapes(shapes, numShapes);

		//loop through the shapes
		for (PxU32 i = 0; i < numShapes; i++)
		{
			//if the shape can't be found, move next iteration
			if(!PhysXDataManager::GetSingletonPtr()->FindShapeName(shapes[i], shapeName))
				continue;
			
			//Create the shape node and store its reference
			writer.CreateNode(RigidShape);
			writer.AddAttribute(ShapeName, shapeName);
			writer.PopNode();
		}

		delete[] shapes;
	}
		
	writer.PopNode();

	return true;
}
bool SceneSerializer::SerializeParticleEmitter(XMLWriter& writer, const ParticleComponent* particles)
{
	std::shared_ptr<AbstractParticleEmitter> emitter = particles->particleSystem->GetEmitter();

	//Next add emitter
	AbstractParticleEmitter::ParticleEmitterType emitterType = emitter->GetEmitterType();

	bool emitterNodeCreated = false;

	//Create node and add any type specific attributes required
	switch (emitterType)
	{
	case AbstractParticleEmitter::POINT_EMITTER:
		emitterNodeCreated = writer.CreateNode(PointEmitter);
		break;
	case AbstractParticleEmitter::LINE_EMITTER:
		emitterNodeCreated = writer.CreateNode(LineEmitter);
		break;
	case AbstractParticleEmitter::MESH_EMITTER:
		emitterNodeCreated = writer.CreateNode(MeshEmitter);
		break;
	}

	//write abstract emitter properties
	if(emitterNodeCreated)
	{
		writer.AddAttribute(PPS, emitter->particlesPerSecond);
		writer.AddAttribute(MinEmitSpeed, emitter->minSpeed);
		writer.AddAttribute(MaxEmitSpeed, emitter->maxSpeed);
		writer.AddAttribute(Duration, emitter->duration);
		writer.CreateNode(Position);
		AddVector3Attribute(writer, emitter->position);
		writer.PopNode();

		writer.CreateNode(MinEmitDirection);
		AddVector3Attribute(writer, emitter->minimumDirection);
		writer.PopNode();

		writer.CreateNode(MaxEmitDirection);
		AddVector3Attribute(writer, emitter->maximumDirection);
		writer.PopNode();

		writer.PopNode();//Pop off emitter node
		return true;
	}

	return false;
}
bool SceneSerializer::SerializeMeshRenderComponent(XMLWriter& writer, const MeshRenderComponent* renderer)
{
	//create render component node, setting enabled as its value
	if(writer.CreateNode(MeshRenderComponen))
	{
		writer.AddAttribute(Enabled, renderer->IsEnabled());
		writer.AddAttribute(EntityName, renderer->GetMeshName(), false, false);

		long long numSubmesh = renderer->entity->getNumSubEntities();

		for (long long i = 0; i < numSubmesh; i++)
		{
			writer.CreateNode(Subentity);
				writer.AddAttribute(SubentityID, i);
				writer.AddAttribute(SubentityMaterial, renderer->entity->getSubEntity(i)->getMaterialName());
			writer.PopNode();
		}

		writer.PopNode();
		return true;
	}

	return false;
}
bool SceneSerializer::SerializeParticleComponent(XMLWriter& writer, const ParticleComponent* particles)
{
	if(writer.CreateNode(ParticleComponen))
	{
		writer.AddAttribute(Enabled, particles->IsEnabled());
		writer.AddAttribute(ParticleSpace, particles->GetTransformationSpace(), false);//Store transformation space
		
		FluidAndParticleBase* particleSystem = particles->particleSystem;
		particleSystem->particleBase->releaseParticles();

		//Add particle system actor to the collection and store the ID in our format
		if(PhysXSerializerWrapper::AddToWorkingCollection(*particleSystem->particleBase))
		{
			PhysXSerializerWrapper::CreateIDs(ActorCollection, StartID);
			long long systemID = PhysXSerializerWrapper::GetID(ActorCollection, 
				*particleSystem->particleBase);

			if(systemID > PX_SERIAL_OBJECT_ID_INVALID)
				writer.AddAttribute(ParticleActorID, systemID);
		}
		//Particle system attributes
		writer.AddAttribute(MaxParticles, (long long)particleSystem->maximumParticles);
		writer.AddAttribute(OnGPU, particleSystem->onGPU);
		writer.AddAttribute(InitialLifetime, particleSystem->initialLifetime);

		bool emitterSerialized = SerializeParticleEmitter(writer, particles);

		bool affectorsSerialized = SerializeParticleAffectors(writer, particles);

		writer.PopNode();
		
		return emitterSerialized && affectorsSerialized;
	}

	return false;
}
bool SceneSerializer::SerializeParticleAffectors(XMLWriter& writer, const ParticleComponent* particles)
{
	ParticleSystemBase* particleSystem = (ParticleSystemBase*)particles->particleSystem;

	if(particleSystem->affectors.affectorMap.size() > 0)
		writer.CreateNode(ParticleAffectors);
	else
		return true;//if none to process, return as if successful

	for (auto affectIter = particleSystem->affectors.GetMapBegin();
		affectIter != particleSystem->affectors.GetMapEnd(); ++affectIter)
	{
		ParticleAffectorType::ParticleAffectorType affectType = 
			affectIter->second->GetAffectorType();

		switch (affectType)
		{
		case ParticleAffectorType::Scale:
			{
				if(writer.CreateNode(ScaleAffector))
				{
					GPUScaleAffectorParams* params = 
						(GPUScaleAffectorParams*)affectIter->second->GetGPUParamaters();

					writer.AddAttribute(OnGPU, affectIter->second->GetOnGPU());
					writer.AddAttribute(Enlarge,params->enlarge);
					writer.AddAttribute(MinScale, params->minScale);
					writer.AddAttribute(MaxScale, params->maxScale);

					writer.PopNode();
				}
			}
			
			break;
		case ParticleAffectorType::AlphaFade:
			break;
		case ParticleAffectorType::ColourToColour:
			{
				if(writer.CreateNode(ColourFaderAffector))
				{
					GPUColourFaderAffectorParams* params =
						(GPUColourFaderAffectorParams*)affectIter->second->GetGPUParamaters();

					writer.AddAttribute(OnGPU, affectIter->second->GetOnGPU());
					//Add start colour
					writer.CreateNode(StartColour);
					AddVector4Attribute(writer, params->startColour);
					writer.PopNode();

					//Add end colour
					writer.CreateNode(EndColour);
					AddVector4Attribute(writer, params->endColour);
					writer.PopNode();

					//pop off scale affector
					writer.PopNode();
				}
			}
			break;
		}
	}

	writer.PopNode();
	return true;
}