//-----------------------------------------------------------------------
	bool SlaveEmitterTranslator::translateChildProperty(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>(node.get());
		ParticleEmitter* em = Ogre::any_cast<ParticleEmitter*>(prop->parent->context);
		SlaveEmitter* emitter = static_cast<SlaveEmitter*>(em);

		if (prop->name == token[TOKEN_MASTER_TECHNIQUE])
		{
			// Property: master_technique_name
			if (passValidateProperty(compiler, prop, token[TOKEN_MASTER_TECHNIQUE], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					emitter->setMasterTechniqueName(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_MASTER_EMITTER])
		{
			// Property: master_emitter_name
			if (passValidateProperty(compiler, prop, token[TOKEN_MASTER_EMITTER], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					emitter->setMasterEmitterName(val);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool PositionEmitterTranslator::translateChildProperty(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>(node.get());
		ParticleEmitter* em = Ogre::any_cast<ParticleEmitter*>(prop->parent->context);
		PositionEmitter* emitter = static_cast<PositionEmitter*>(em);

		if (prop->name == token[TOKEN_POS_ADD_POSITION])
		{
			// Property: add_position
			if (passValidateProperty(compiler, prop, token[TOKEN_POS_ADD_POSITION], VAL_VECTOR3))
			{
				Ogre::Vector3 val;
				if(getVector3(prop->values.begin(), prop->values.end(), &val))
				{
					emitter->addPosition(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_POS_RANDOMIZE])
		{
			// Property: random_position
			if (passValidateProperty(compiler, prop, token[TOKEN_POS_RANDOMIZE], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					emitter->setRandomized(val);
					return true;
				}
			}
		}

		return false;
	}
//------------------------------------------------------------------------------
void
ParticleEmitterTranslator::translate(Ogre::ScriptCompiler *compiler, const Ogre::AbstractNodePtr &node)
{
    Ogre::ObjectAbstractNode *obj = reinterpret_cast<Ogre::ObjectAbstractNode*>(node.get());

    // name can't be empty because we get renderer type from it
    if(obj->name.empty())
    {
        compiler->addError(Ogre::ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line);
        return;
    }

    ParticleTechnique* tech = Ogre::any_cast<ParticleTechnique*>(obj->parent->context);

    ParticleEmitter* emitter = tech->CreateEmitter(obj->name);
    if (emitter == NULL)
    {
        compiler->addError(Ogre::ScriptCompiler::CE_OBJECTALLOCATIONERROR, obj->file, obj->line);
        return;
    }
    Ogre::LogManager::getSingletonPtr()->logMessage("ParticleEmitterTranslator: create emitter.");

    for (Ogre::AbstractNodeList::iterator i = obj->children.begin(); i != obj->children.end(); ++i)
    {
        if ((*i)->type == Ogre::ANT_PROPERTY)
        {
            Ogre::PropertyAbstractNode *prop = reinterpret_cast<Ogre::PropertyAbstractNode*>((*i).get());
            Ogre::String value = prop->getValue();
/*
            // Glob the values together
            for (Ogre::AbstractNodeList::iterator i = prop->values.begin(); i != prop->values.end(); ++i)
            {
                if((*i)->type == Ogre::ANT_ATOM)
                {
                    if (value.empty())
                    {
                        value = ((Ogre::AtomAbstractNode*)(*i).get())->value;
                    }
                    else
                    {
                        value = value + " " + ((Ogre::AtomAbstractNode*)(*i).get())->value;
                    }
                }
                else
                {
                    compiler->addError(Ogre::ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
                    break;
                }
            }
*/
            Ogre::LogManager::getSingletonPtr()->logMessage("ParticleEmitterTranslator: Set param '" + prop->name + "' to '" + value + "'.");
            if (!emitter->setParameter(prop->name, value))
            {
                compiler->addError(Ogre::ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
            }
        }
    }
}
	//-------------------------------------------------------------------------
	void AliasTranslator::translate(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::ObjectAbstractNode* obj = reinterpret_cast<Ogre::ObjectAbstractNode*>(node.get());
		if(obj->name.empty())
			compiler->addError(Ogre::ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line);

		for(Ogre::AbstractNodeList::iterator i = obj->children.begin(); i != obj->children.end(); ++i)
		{
			if((*i)->type == Ogre::ANT_OBJECT)
			{
				processNode(compiler, *i);
			}
		}
	}
	//-----------------------------------------------------------------------
	bool DoScaleEventHandlerTranslator::translateChildProperty(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>(node.get());
		ParticleEventHandler* evt = Ogre::any_cast<ParticleEventHandler*>(prop->parent->context);
		DoScaleEventHandler* handler = static_cast<DoScaleEventHandler*>(evt);

		if (prop->name == token[TOKEN_DOSCALE_FRACTION])
		{
			// Property: scale_fraction
			if (passValidateProperty(compiler, prop, token[TOKEN_DOSCALE_FRACTION], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					handler->setScaleFraction(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_DOSCALE_TYPE])
		{
			// Property: scale_type
			if (passValidateProperty(compiler, prop, token[TOKEN_DOSCALE_TYPE], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					if (val == token[TOKEN_TIME_TO_LIVE] || val == token[TOKEN_DOSCALE_TIME_TO_LIVE])
					{
						handler->setScaleType(DoScaleEventHandler::ST_TIME_TO_LIVE);
						return true;
					}
					else if (val == token[TOKEN_VELOCITY] || val == token[TOKEN_DOSCALE_VELOCITY])
					{
						handler->setScaleType(DoScaleEventHandler::ST_VELOCITY);
						return true;
					}
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool MeshSurfaceEmitterTranslator::translateChildProperty(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>(node.get());
		ParticleEmitter* em = Ogre::any_cast<ParticleEmitter*>(prop->parent->context);
		MeshSurfaceEmitter* emitter = static_cast<MeshSurfaceEmitter*>(em);

		if (prop->name == token[TOKEN_MESH_NAME])
		{
			// Property: mesh_name
			if (passValidateProperty(compiler, prop, token[TOKEN_MESH_NAME], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					emitter->setMeshName(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_MESH_SURFACE_NAME])
		{
			// Property: mesh_surface_mesh_name (deprecated and replaced by mesh_name)
			if (passValidateProperty(compiler, prop, token[TOKEN_MESH_SURFACE_NAME], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					emitter->setMeshName(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_MESH_SURFACE_DISTRIBUTION])
		{
			// Property: mesh_surface_distribution
			if (passValidateProperty(compiler, prop, token[TOKEN_MESH_SURFACE_DISTRIBUTION], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					if (val == token[TOKEN_MESH_SURFACE_EDGE])
					{
						emitter->setDistribution(MeshInfo::MSD_EDGE);
						return true;
					}
					else if (val == token[TOKEN_MESH_SURFACE_HETEROGENEOUS_1])
					{
						emitter->setDistribution(MeshInfo::MSD_HETEROGENEOUS_1);
						return true;
					}
					else if (val == token[TOKEN_MESH_SURFACE_HETEROGENEOUS_2])
					{
						emitter->setDistribution(MeshInfo::MSD_HETEROGENEOUS_2);
						return true;
					}
					else if (val == token[TOKEN_MESH_SURFACE_HOMOGENEOUS])
					{
						emitter->setDistribution(MeshInfo::MSD_HOMOGENEOUS);
						return true;
					}
					else if (val == token[TOKEN_MESH_SURFACE_HOMOGENEOUS])
					{
						emitter->setDistribution(MeshInfo::MSD_HOMOGENEOUS);
						return true;
					}
				}
			}
		}
		else if (prop->name == token[TOKEN_MESH_SURFACE_MESH_SCALE])
		{
			// Property: mesh_surface_scale
			if (passValidateProperty(compiler, prop, token[TOKEN_MESH_SURFACE_MESH_SCALE], VAL_VECTOR3))
			{
				Ogre::Vector3 val;
				if(getVector3(prop->values.begin(), prop->values.end(), &val))
				{
					emitter->setScale(val);
					return true;
				}
			}
		}

		return false;
	}
	//-------------------------------------------------------------------------
	void ScriptTranslator::errorUnexpectedToken(Ogre::ScriptCompiler* compiler, 
		Ogre::AbstractNodePtr token)
	{
		compiler->addError(Ogre::ScriptCompiler::CE_UNEXPECTEDTOKEN, token.getPointer()->file, token.getPointer()->line, 
			"PU Compiler: token is not recognized");
	}
	//-----------------------------------------------------------------------
	bool SphereColliderExternTranslator::translateChildProperty(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>(node.get());
		Extern* ex = Ogre::any_cast<Extern*>(prop->parent->context);
		SphereColliderExtern* externObject = static_cast<SphereColliderExtern*>(ex);
//		BaseColliderTranslator baseColliderTranslator;

		if (prop->name == token[TOKEN_RADIUS])
		{
			// Property: radius
			if (passValidateProperty(compiler, prop, token[TOKEN_RADIUS], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					externObject->setRadius(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_SPHERE_COLLIDER_RADIUS])
		{
			// Property: sphere_collider_radius (Deprecated; replaced by radius)
			if (passValidateProperty(compiler, prop, token[TOKEN_SPHERE_COLLIDER_RADIUS], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					externObject->setRadius(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_DISTANCE_THRESHOLD])
		{
			// Property: distance_threshold
			if (passValidateProperty(compiler, prop, token[TOKEN_DISTANCE_THRESHOLD], VAL_REAL))
			{
				Ogre::Real val;
				if(getReal(prop->values.front(), &val))
				{
					externObject->setDistanceThreshold(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_EXTERN_DISTANCE_THRESHOLD])
		{
			// Property: attachable_distance_threshold (deprecated and replaced by 'distance_threshold')
			if (passValidateProperty(compiler, prop, token[TOKEN_EXTERN_DISTANCE_THRESHOLD], VAL_REAL))
			{
				Ogre::Real val;
				if(getReal(prop->values.front(), &val))
				{
					externObject->setDistanceThreshold(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_FRICTION])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_FRICTION], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					externObject->setFriction(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_COLLIDER_FRICTION])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_COLLIDER_FRICTION], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					externObject->setFriction(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_BOUNCYNESS])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_BOUNCYNESS], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					externObject->setBouncyness(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_COLLIDER_BOUNCYNESS])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_COLLIDER_BOUNCYNESS], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					externObject->setBouncyness(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_INTERSECTION])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_INTERSECTION], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					if (val == token[TOKEN_COLLIDER_INTERSECTION_POINT])
					{
						externObject->setIntersectionType(BaseCollider::IT_POINT);
						return true;
					}
					else if (val == token[TOKEN_COLLIDER_INTERSECTION_BOX])
					{
						externObject->setIntersectionType(BaseCollider::IT_BOX);
						return true;
					}
				}
			}
		}
		else if (prop->name == token[TOKEN_COLLIDER_INTERSECTION])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_COLLIDER_INTERSECTION], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					if (val == token[TOKEN_COLLIDER_INTERSECTION_POINT])
					{
						externObject->setIntersectionType(BaseCollider::IT_POINT);
						return true;
					}
					else if (val == token[TOKEN_COLLIDER_INTERSECTION_BOX])
					{
						externObject->setIntersectionType(BaseCollider::IT_BOX);
						return true;
					}
				}
			}
		}
		else if (prop->name == token[TOKEN_COLLIDER_COLLISION_TYPE])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_COLLIDER_COLLISION_TYPE], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					if (val == token[TOKEN_COLLIDER_BOUNCE])
					{
						externObject->setCollisionType(BaseCollider::CT_BOUNCE);
						return true;
					}
					else if (val == token[TOKEN_COLLIDER_FLOW])
					{
						externObject->setCollisionType(BaseCollider::CT_FLOW);
						return true;
					}
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool SceneDecoratorExternTranslator::translateChildProperty(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>(node.get());
		Extern* ex = Ogre::any_cast<Extern*>(prop->parent->context);
		SceneDecoratorExtern* externObject = static_cast<SceneDecoratorExtern*>(ex);

		if (prop->name == token[TOKEN_MESH_NAME])
		{
			// Property: mesh_name
			if (passValidateProperty(compiler, prop, token[TOKEN_MESH_NAME], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					externObject->setMeshName(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_SCENE_MESH_NAME])
		{
			// Property: scene_mesh_name (deprecated and replaced by mesh_name)
			if (passValidateProperty(compiler, prop, token[TOKEN_SCENE_MESH_NAME], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					externObject->setMeshName(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_MATERIAL])
		{
			// Property: material
			if (passValidateProperty(compiler, prop, token[TOKEN_MATERIAL], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					externObject->setMaterialName(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_SCENE_MATERIAL_NAME])
		{
			// Property: scene_material_name (deprecated and replaced by 'material')
			if (passValidateProperty(compiler, prop, token[TOKEN_SCENE_MATERIAL_NAME], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					externObject->setMaterialName(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_SCENE_SCALE])
		{
			// Property: scene_node_scale
			if (passValidateProperty(compiler, prop, token[TOKEN_SCENE_SCALE], VAL_VECTOR3))
			{
				Ogre::Vector3 val;
				if(getVector3(prop->values.begin(), prop->values.end(), &val))
				{
					externObject->setScale(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_SCENE_POSITION])
		{
			// Property: scene_node_position
			if (passValidateProperty(compiler, prop, token[TOKEN_SCENE_POSITION], VAL_VECTOR3))
			{
				Ogre::Vector3 val;
				if(getVector3(prop->values.begin(), prop->values.end(), &val))
				{
					externObject->setPosition(val);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool BoxEmitterTranslator::translateChildProperty(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>(node.get());
		ParticleEmitter* em = Ogre::any_cast<ParticleEmitter*>(prop->parent->context);
		BoxEmitter* emitter = static_cast<BoxEmitter*>(em);

		if (prop->name == token[TOKEN_BOX_WIDTH])
		{
			// Property: box_width
			if (passValidateProperty(compiler, prop, token[TOKEN_BOX_WIDTH], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setWidth(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_EMITTER_BOX_WIDTH])
		{
			// Property: box_em_width (deprecated and replaced by 'box_width')
			if (passValidateProperty(compiler, prop, token[TOKEN_EMITTER_BOX_WIDTH], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setWidth(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_BOX_HEIGHT])
		{
			// Property: box_height
			if (passValidateProperty(compiler, prop, token[TOKEN_BOX_HEIGHT], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setHeight(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_EMITTER_BOX_HEIGHT])
		{
			// Property: box_em_height (deprecated and replaced by 'box_height')
			if (passValidateProperty(compiler, prop, token[TOKEN_EMITTER_BOX_HEIGHT], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setHeight(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_BOX_DEPTH])
		{
			// Property: box_depth
			if (passValidateProperty(compiler, prop, token[TOKEN_BOX_DEPTH], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setDepth(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_EMITTER_BOX_DEPTH])
		{
			// Property: box_em_depth (deprecated and replaced by 'box_depth')
			if (passValidateProperty(compiler, prop, token[TOKEN_EMITTER_BOX_DEPTH], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setDepth(val);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool BaseColliderTranslator::translateChildProperty(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>(node.get());
		ParticleAffector* af = Ogre::any_cast<ParticleAffector*>(prop->parent->context);
		BaseCollider* affector = static_cast<BaseCollider*>(af); // Do not check type; assume the type is correct.

		if (prop->name == token[TOKEN_FRICTION])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_FRICTION], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setFriction(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_COLLIDER_FRICTION])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_COLLIDER_FRICTION], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setFriction(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_BOUNCYNESS])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_BOUNCYNESS], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setBouncyness(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_COLLIDER_BOUNCYNESS])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_COLLIDER_BOUNCYNESS], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setBouncyness(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_INTERSECTION] || prop->name == token[TOKEN_COLLIDER_INTERSECTION])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_INTERSECTION], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					if (val == token[TOKEN_COLLIDER_INTERSECTION_POINT])
					{
						affector->setIntersectionType(BaseCollider::IT_POINT);
						return true;
					}
					else if (val == token[TOKEN_COLLIDER_INTERSECTION_BOX])
					{
						affector->setIntersectionType(BaseCollider::IT_BOX);
						return true;
					}
				}
			}
		}
		else if (prop->name == token[TOKEN_COLLIDER_COLLISION_TYPE])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_COLLIDER_COLLISION_TYPE], VAL_STRING))
			{
				Ogre::String val;
				if(getString(prop->values.front(), &val))
				{
					if (val == token[TOKEN_COLLIDER_BOUNCE])
					{
						affector->setCollisionType(BaseCollider::CT_BOUNCE);
						return true;
					}
					else if (val == token[TOKEN_COLLIDER_FLOW])
					{
						affector->setCollisionType(BaseCollider::CT_FLOW);
						return true;
					}
				}
			}
		}

		return false;
	}
	//-------------------------------------------------------------------------
	void ParticleEventHandlerTranslator::translate(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::ObjectAbstractNode* obj = reinterpret_cast<Ogre::ObjectAbstractNode*>(node.get());
		Ogre::ObjectAbstractNode* parent = obj->parent ? reinterpret_cast<Ogre::ObjectAbstractNode*>(obj->parent) : 0;

		// The name of the obj is the type of the ParticleEventHandler
		// Remark: This can be solved by using a listener, so that obj->values is filled with type + name. Something for later
		Ogre::String type;
		if(!obj->name.empty())
		{
			type = obj->name;
		}
		else
		{
			compiler->addError(Ogre::ScriptCompiler::CE_INVALIDPARAMETERS, obj->file, obj->line);
			return;
		}

		// Get the factory
		ParticleEventHandlerFactory* particleEventHandlerFactory = ParticleSystemManager::getSingletonPtr()->getEventHandlerFactory(type);
		if (!particleEventHandlerFactory)
		{
			compiler->addError(Ogre::ScriptCompiler::CE_INVALIDPARAMETERS, obj->file, obj->line);
			return;
		}

		// Create the ParticleEventHandler
		mParticleEventHandler = ParticleSystemManager::getSingletonPtr()->createEventHandler(type);
		if (!mParticleEventHandler)
		{
			compiler->addError(Ogre::ScriptCompiler::CE_INVALIDPARAMETERS, obj->file, obj->line);
			return;
		}

		if (!obj->parent->context.isEmpty())
		{
			ParticleObserver* observer = Ogre::any_cast<ParticleObserver*>(obj->parent->context);
			observer->addEventHandler(mParticleEventHandler);
		}
		else
		{
			// It is an alias
			mParticleEventHandler->setAliasName(parent->name);
			ParticleSystemManager::getSingletonPtr()->addAlias(mParticleEventHandler);
		}

		// The first value is the (optional) name
		Ogre::String name;
		if(!obj->values.empty())
		{
			getString(obj->values.front(), &name);
			mParticleEventHandler->setName(name);
		}

		// Set it in the context
		obj->context = Ogre::Any(mParticleEventHandler);

		// Run through properties
		for(Ogre::AbstractNodeList::iterator i = obj->children.begin(); i != obj->children.end(); ++i)
		{
			// No properties of its own
			if((*i)->type == Ogre::ANT_PROPERTY)
			{
				Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>((*i).get());
				if (particleEventHandlerFactory->translateChildProperty(compiler, *i))
				{
					// Parsed the property by another translator; do nothing
				}
				else
				{
					errorUnexpectedProperty(compiler, prop);
				}
			}
			else if((*i)->type == Ogre::ANT_OBJECT)
			{
				if (particleEventHandlerFactory->translateChildObject(compiler, *i))
				{
					// Parsed the object by another translator; do nothing
				}
				else
				{
					processNode(compiler, *i);
				}
			}
            else
			{
				errorUnexpectedToken(compiler, *i);
			}
		}
	}
	//-----------------------------------------------------------------------
	bool RandomiserTranslator::translateChildProperty(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>(node.get());
		ParticleAffector* af = Ogre::any_cast<ParticleAffector*>(prop->parent->context);
		Randomiser* affector = static_cast<Randomiser*>(af);

		if (prop->name == token[TOKEN_MAX_DEVIATION_X])
		{
			// Property: max_deviation_x
			if (passValidateProperty(compiler, prop, token[TOKEN_MAX_DEVIATION_X], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setMaxDeviationX(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RND_MAX_DEVIATION_X])
		{
			// Property: rand_aff_max_deviation_x (depreacted and replaced by 'max_deviation_x')
			if (passValidateProperty(compiler, prop, token[TOKEN_RND_MAX_DEVIATION_X], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setMaxDeviationX(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_MAX_DEVIATION_Y])
		{
			// Property: max_deviation_y
			if (passValidateProperty(compiler, prop, token[TOKEN_MAX_DEVIATION_Y], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setMaxDeviationY(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RND_MAX_DEVIATION_Y])
		{
			// Property: rand_aff_max_deviation_y (deprecated and replaced by 'max_deviation_y')
			if (passValidateProperty(compiler, prop, token[TOKEN_RND_MAX_DEVIATION_Y], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setMaxDeviationY(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_MAX_DEVIATION_Z])
		{
			// Property: max_deviation_z
			if (passValidateProperty(compiler, prop, token[TOKEN_MAX_DEVIATION_Z], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setMaxDeviationZ(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RND_MAX_DEVIATION_Z])
		{
			// Property: rand_aff_max_deviation_z (deprecated and replaced by 'max_deviation_z')
			if (passValidateProperty(compiler, prop, token[TOKEN_RND_MAX_DEVIATION_Z], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setMaxDeviationZ(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_TIME_STEP])
		{
			// Property: time_step
			if (passValidateProperty(compiler, prop, token[TOKEN_TIME_STEP], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setTimeStep(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RND_TIME_STEP])
		{
			// Property: rand_aff_time_step (deprecated and replaced by 'time_step')
			if (passValidateProperty(compiler, prop, token[TOKEN_RND_TIME_STEP], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setTimeStep(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_USE_DIRECTION])
		{
			// Property: use_direction
			if (passValidateProperty(compiler, prop, token[TOKEN_USE_DIRECTION], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					affector->setRandomDirection(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RND_DIRECTION])
		{
			// Property: rand_aff_direction (deprecated and replaced by 'use_direction')
			if (passValidateProperty(compiler, prop, token[TOKEN_RND_DIRECTION], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					affector->setRandomDirection(val);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool CircleEmitterTranslator::translateChildProperty(Ogre::ScriptCompiler* compiler, const Ogre::AbstractNodePtr &node)
	{
		Ogre::PropertyAbstractNode* prop = reinterpret_cast<Ogre::PropertyAbstractNode*>(node.get());
		ParticleEmitter* em = Ogre::any_cast<ParticleEmitter*>(prop->parent->context);
		CircleEmitter* emitter = static_cast<CircleEmitter*>(em);

		if (prop->name == token[TOKEN_RADIUS])
		{
			// Property: radius
			if (passValidateProperty(compiler, prop, token[TOKEN_RADIUS], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setRadius(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_CIRCLE_RADIUS])
		{
			// Property: circle_em_radius (deprecated and replaced by radius)
			if (passValidateProperty(compiler, prop, token[TOKEN_CIRCLE_RADIUS], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setRadius(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_STEP])
		{
			// Property: step
			if (passValidateProperty(compiler, prop, token[TOKEN_STEP], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setStep(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_CIRCLE_STEP])
		{
			// Property: circle_em_step (deprecated and replaced by 'step')
			if (passValidateProperty(compiler, prop, token[TOKEN_CIRCLE_STEP], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setStep(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_ANGLE])
		{
			// Property: angle
			if (passValidateProperty(compiler, prop, token[TOKEN_ANGLE], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setCircleAngle(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_CIRCLE_ANGLE])
		{
			// Property: circle_em_angle
			if (passValidateProperty(compiler, prop, token[TOKEN_CIRCLE_ANGLE], VAL_REAL))
			{
				Ogre::Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					emitter->setCircleAngle(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_EMIT_RANDOM])
		{
			// Property: emit_random
			if (passValidateProperty(compiler, prop, token[TOKEN_EMIT_RANDOM], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					emitter->setRandom(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_CIRCLE_RANDOM])
		{
			// Property: circle_em_random (deprecated and replaced by 'emit_random'))
			if (passValidateProperty(compiler, prop, token[TOKEN_CIRCLE_RANDOM], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					emitter->setRandom(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_NORMAL])
		{
			// Property: normal
			{
				Ogre::Vector3 val;
				if(getVector3(prop->values.begin(), prop->values.end(), &val))
				{
					emitter->setNormal(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_CIRCLE_NORMAL])
		{
			// Property: circle_em_normal (deprecated and replaced by 'normal')
			{
				Ogre::Vector3 val;
				if(getVector3(prop->values.begin(), prop->values.end(), &val))
				{
					emitter->setNormal(val);
					return true;
				}
			}
		}

		return false;
	}