예제 #1
0
//! [font_translate]
void FontTranslator::translate(ScriptCompiler* compiler, const AbstractNodePtr& node)
{
    ObjectAbstractNode* obj = static_cast<ObjectAbstractNode*>(node.get());

    // Must have a name - unless we are in legacy mode. Then the class is the name.
    if (obj->name.empty() && obj->cls == "font")
    {
        compiler->addError(ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line,
                           "font must be given a name");
        return;
    }

    String& name = obj->cls == "font" ? obj->name : obj->cls;

    FontPtr font = FontManager::getSingleton().create(name, compiler->getResourceGroup());
    font->_notifyOrigin(obj->file);

    for (auto& c : obj->children)
    {
        if (c->type == ANT_PROPERTY)
        {
            parseAttribute(compiler, font, static_cast<PropertyAbstractNode*>(c.get()));
        }
    }
}
	//-----------------------------------------------------------------------
	bool VortexAffectorTranslator::translateChildObject(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		ObjectAbstractNode* child = reinterpret_cast<ObjectAbstractNode*>(node.get());
		ParticleAffector* af = any_cast<ParticleAffector*>(child->parent->context);
		VortexAffector* affector = static_cast<VortexAffector*>(af);

		DynamicAttributeTranslator dynamicAttributeTranslator;
		if (child->cls == token[TOKEN_ROTATION_SPEED])
		{
			// Property: rotation_speed
			dynamicAttributeTranslator.translate(compiler, node);
			DynamicAttribute* dynamicAttribute = any_cast<DynamicAttribute*>(child->context);
			affector->setRotationSpeed(dynamicAttribute);
			return true;
		}
		else if (child->cls == token[TOKEN_VORTEX_ROTATION_SPEED])
		{
			// Property: vortex_aff_speed (deprecated and replaced by 'rotation_speed')
			dynamicAttributeTranslator.translate(compiler, node);
			DynamicAttribute* dynamicAttribute = any_cast<DynamicAttribute*>(child->context);
			affector->setRotationSpeed(dynamicAttribute);
			return true;
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool PositionEmitterTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleEmitter* em = 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))
			{
				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;
	}
	//-----------------------------------------------------------------------
	bool DoAffectorEventHandlerTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleEventHandler* evt = any_cast<ParticleEventHandler*>(prop->parent->context);
		DoAffectorEventHandler* handler = static_cast<DoAffectorEventHandler*>(evt);

		if (prop->name == token[TOKEN_FORCE_AFFECTOR])
		{
			// Property: force_affector
			if (passValidateProperty(compiler, prop, token[TOKEN_FORCE_AFFECTOR], VAL_STRING))
			{
				String val;
				if(getString(prop->values.front(), &val))
				{
					handler->setAffectorName(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_FORCE_AFFECTOR_PRE_POST])
		{
			// Property: pre_post
			if (passValidateProperty(compiler, prop, token[TOKEN_FORCE_AFFECTOR_PRE_POST], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					handler->setPrePost(val);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool JetAffectorTranslator::translateChildObject(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		ObjectAbstractNode* child = reinterpret_cast<ObjectAbstractNode*>(node.get());
		ParticleAffector* af = any_cast<ParticleAffector*>(child->parent->context);
		JetAffector* affector = static_cast<JetAffector*>(af);

		DynamicAttributeTranslator dynamicAttributeTranslator;
		if (child->cls == token[TOKEN_ACCELERATION])
		{
			// Property: acceleration
			dynamicAttributeTranslator.translate(compiler, node);
			DynamicAttribute* dynamicAttribute = any_cast<DynamicAttribute*>(child->context);
			affector->setDynAcceleration(dynamicAttribute);
			return true;
		}
		else if (child->cls == token[TOKEN_JET_ACCELERATION])
		{
			// Property: jet_aff_accel (deprecated and replaced by 'acceleration')
			dynamicAttributeTranslator.translate(compiler, node);
			DynamicAttribute* dynamicAttribute = any_cast<DynamicAttribute*>(child->context);
			affector->setDynAcceleration(dynamicAttribute);
			return true;
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool SlaveEmitterTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleEmitter* em = 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))
			{
				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))
			{
				String val;
				if(getString(prop->values.front(), &val))
				{
					emitter->setMasterEmitterName(val);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool VortexExternTranslator::translateChildObject(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		ObjectAbstractNode* child = reinterpret_cast<ObjectAbstractNode*>(node.get());
		Extern* ex = any_cast<Extern*>(child->parent->context);
		VortexExtern* externObject = static_cast<VortexExtern*>(ex);

		DynamicAttributeTranslator dynamicAttributeTranslator;
		if (child->cls == token[TOKEN_ROTATION_SPEED])
		{
			// Property: rotation_speed
			dynamicAttributeTranslator.translate(compiler, node);
			DynamicAttribute* dynamicAttribute = any_cast<DynamicAttribute*>(child->context);
			externObject->setRotationSpeed(dynamicAttribute);
			return true;
		}
		else if (child->cls == token[TOKEN_VORTEX_ROTATION_SPEED])
		{
			// Property: vortex_aff_speed
			dynamicAttributeTranslator.translate(compiler, node);
			DynamicAttribute* dynamicAttribute = any_cast<DynamicAttribute*>(child->context);
			externObject->setRotationSpeed(dynamicAttribute);
			return true;
		}

		return false;
	}
//-----------------------------------------------------------------------
bool LinearForceAffectorTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
{
    PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
    ParticleAffector* af = any_cast<ParticleAffector*>(prop->parent->context);
    (void)af;

    // No own properties. Parse the BaseForceAffector
    BaseForceAffectorTranslator BaseForceAffectorTranslator;
    return BaseForceAffectorTranslator.translateChildProperty(compiler, node);
}
	//-----------------------------------------------------------------------
	bool SphereColliderTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleAffector* af = any_cast<ParticleAffector*>(prop->parent->context);
		SphereCollider* affector = static_cast<SphereCollider*>(af);

		if (prop->name == token[TOKEN_RADIUS])
		{
			// Property: radius
			if (passValidateProperty(compiler, prop, token[TOKEN_RADIUS], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->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))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setRadius(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_INNER_COLLISION])
		{
			// Property: inner_collision
			if (passValidateProperty(compiler, prop, token[TOKEN_INNER_COLLISION], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					affector->setInnerCollision(val);
					return true;
				}
			}
		}
		else
		{
			// Parse the BaseCollider
			BaseColliderTranslator baseColliderTranslator;
			return baseColliderTranslator.translateChildProperty(compiler, node);
		}

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

	// Translate section within a pass context.
	if (parent->cls == "pass")
	{
		translatePass(compiler, node);
	}
}
	//-----------------------------------------------------------------------
	bool OnTimeObserverTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleObserver* ob = any_cast<ParticleObserver*>(prop->parent->context);
		OnTimeObserver* observer = static_cast<OnTimeObserver*>(ob);

		if (prop->name == token[TOKEN_ONTIME])
		{
			// Property: on_time
			if (passValidatePropertyNumberOfValues(compiler, prop, token[TOKEN_ONTIME], 2))
			{
				String compareType;
				Real val = 0.0f;
				AbstractNodeList::const_iterator i = prop->values.begin();
				if(getString(*i, &compareType))
				{
					if (compareType == token[TOKEN_LESS_THAN])
					{
						observer->setCompare(CO_LESS_THAN);
					}
					else if (compareType == token[TOKEN_GREATER_THAN])
					{
						observer->setCompare(CO_GREATER_THAN);
					}
					else if (compareType == token[TOKEN_EQUALS])
					{
						observer->setCompare(CO_EQUALS);
					}
					++i;
					if(getReal(*i, &val))
					{
						observer->setThreshold(val);
						return true;
					}
				}
			}
		}
		else if (prop->name == token[TOKEN_SINCE_START_SYSTEM])
		{
			// Property: since_start_system
			if (passValidateProperty(compiler, prop, token[TOKEN_SINCE_START_SYSTEM], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					observer->setSinceStartSystem(val);
					return true;
				}
			}
		}

		return false;
	}
//-------------------------------------------------------------------------
void AliasTranslator::translate(ScriptCompiler* compiler, const AbstractNodePtr &node)
{
    ObjectAbstractNode* obj = reinterpret_cast<ObjectAbstractNode*>(node.get());
    if(obj->name.empty())
        compiler->addError(ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line);

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

		if (prop->name == token[TOKEN_DOENABLE_COMPONENT])
		{
			// Property: enable_component
			if (passValidatePropertyNumberOfValues(compiler, prop, token[TOKEN_DOENABLE_COMPONENT], 3))
			{
				String componentType;
				String name;
				bool enabled = true;
				AbstractNodeList::const_iterator i = prop->values.begin();
				if(getString(*i, &componentType))
				{
					if (componentType == token[TOKEN_DOENABLE_EMITTER_COMPONENT])
					{
						handler->setComponentType(CT_EMITTER);
					}
					else if (componentType == token[TOKEN_DOENABLE_AFFECTOR_COMPONENT])
					{
						handler->setComponentType(CT_AFFECTOR);
					}
					else if (componentType == token[TOKEN_DOENABLE_OBSERVER_COMPONENT])
					{
						handler->setComponentType(CT_OBSERVER);
					}
					else if (componentType == token[TOKEN_DOENABLE_TECHNIQUE_COMPONENT])
					{
						handler->setComponentType(CT_TECHNIQUE);
					}
					++i;
					if(getString(*i, &name))
					{
						handler->setComponentName(name);
						++i;
						if (getBoolean(*i, &enabled))
						{
							handler->setComponentEnabled(enabled);
							return true;
						}
					}
				}
			}
		}

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

    // Translate section within a pass context.
    if (parent->cls == "pass")
    {
        translatePass(compiler, node);
    }
    if (parent->cls == "texture_unit")
    {
        translateTextureUnit(compiler, node);
    }
}
	//-----------------------------------------------------------------------
	bool CollisionAvoidanceAffectorTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleAffector* af = any_cast<ParticleAffector*>(prop->parent->context);
		CollisionAvoidanceAffector* affector = static_cast<CollisionAvoidanceAffector*>(af);

		if (prop->name == token[TOKEN_AVOIDANCE_RADIUS])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_AVOIDANCE_RADIUS], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setRadius(val);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool JetAffectorTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleAffector* af = any_cast<ParticleAffector*>(prop->parent->context);
		JetAffector* affector = static_cast<JetAffector*>(af);

		if (prop->name == token[TOKEN_ACCELERATION])
		{
			// Property: acceleration
			if (passValidateProperty(compiler, prop, token[TOKEN_ACCELERATION], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					DynamicAttributeFixed* dynamicAttributeFixed = PU_NEW_T(DynamicAttributeFixed, MEMCATEGORY_SCENE_OBJECTS)();
					dynamicAttributeFixed->setValue(val);
					affector->setDynAcceleration(dynamicAttributeFixed);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_JET_ACCELERATION])
		{
			// Property: jet_aff_accel (deprecated and replaced by 'acceleration')
			if (passValidateProperty(compiler, prop, token[TOKEN_JET_ACCELERATION], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					DynamicAttributeFixed* dynamicAttributeFixed = PU_NEW_T(DynamicAttributeFixed, MEMCATEGORY_SCENE_OBJECTS)();
					dynamicAttributeFixed->setValue(val);
					affector->setDynAcceleration(dynamicAttributeFixed);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool PathFollowerTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleAffector* af = any_cast<ParticleAffector*>(prop->parent->context);
		PathFollower* affector = static_cast<PathFollower*>(af);

		if (prop->name == token[TOKEN_PATH_POINT])
		{
			// Property: path_follower_point
			if (passValidateProperty(compiler, prop, token[TOKEN_PATH_POINT], VAL_VECTOR3))
			{
				Vector3 val;
				if(getVector3(prop->values.begin(), prop->values.end(), &val))
				{
					affector->addPoint(val);
					return true;
				}
			}
		}

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

		// The first value is the type
		String type = obj->name;

		if (type == token[TOKEN_DYN_RANDOM])
		{
			mDynamicAttribute = PU_NEW_T(DynamicAttributeRandom, MEMCATEGORY_SCENE_OBJECTS)();
		}
		else if (type == token[TOKEN_DYN_CURVED_LINEAR])
		{
			mDynamicAttribute = PU_NEW_T(DynamicAttributeCurved, MEMCATEGORY_SCENE_OBJECTS)(IT_LINEAR);
		}
		else if (type == token[TOKEN_DYN_CURVED_SPLINE])
		{
			mDynamicAttribute = PU_NEW_T(DynamicAttributeCurved, MEMCATEGORY_SCENE_OBJECTS)(IT_SPLINE);
		}
		else if (type == token[TOKEN_DYN_OSCILLATE])
		{
			mDynamicAttribute = PU_NEW_T(DynamicAttributeOscillate, MEMCATEGORY_SCENE_OBJECTS)();
		}
		else
		{
			// Create a fixed one.
			mDynamicAttribute = PU_NEW_T(DynamicAttributeFixed, MEMCATEGORY_SCENE_OBJECTS)();
		}

		// Run through properties
		for(AbstractNodeList::iterator i = obj->children.begin(); i != obj->children.end(); ++i)
		{
			if((*i)->type == ANT_PROPERTY)
			{
				PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>((*i).get());
				if (prop->name == token[TOKEN_DYN_MIN])
				{
					// Property: min
					if (mDynamicAttribute->getType() == DynamicAttribute::DAT_RANDOM)
					{
						if (passValidateProperty(compiler, prop, token[TOKEN_DYN_MIN], VAL_REAL))
						{
							Real val = 0.0f;
							if(getReal(prop->values.front(), &val))
							{
								(static_cast<DynamicAttributeRandom*>(mDynamicAttribute))->setMin(val);
							}
						}
					}
				}
				else if (prop->name == token[TOKEN_DYN_MAX])
				{
					// Property: max
					if (mDynamicAttribute->getType() == DynamicAttribute::DAT_RANDOM)
					{
						if (passValidateProperty(compiler, prop, token[TOKEN_DYN_MAX], VAL_REAL))
						{
							Real val = 0.0f;
							if(getReal(prop->values.front(), &val))
							{
								(static_cast<DynamicAttributeRandom*>(mDynamicAttribute))->setMax(val);
							}
						}
					}
				}
				else if (prop->name == token[TOKEN_DYN_CONTROL_POINT])
				{
					// Property: control_point
					if (mDynamicAttribute->getType() == DynamicAttribute::DAT_CURVED)
					{
						if (passValidateProperty(compiler, prop, token[TOKEN_DYN_CONTROL_POINT], VAL_VECTOR2))
						{
							Vector2 val;
							if(getVector2(prop->values.begin(), prop->values.end(), &val))
							{
								(static_cast<DynamicAttributeCurved*>(mDynamicAttribute))->addControlPoint(val.x, val.y);
							}
						}
					}
				}
				else if (prop->name == token[TOKEN_DYN_OSCILLATE_FREQUENCY])
				{
					// Property: oscillate_frequency
					if (mDynamicAttribute->getType() == DynamicAttribute::DAT_OSCILLATE)
					{
						if (passValidateProperty(compiler, prop, token[TOKEN_DYN_OSCILLATE_FREQUENCY], VAL_REAL))
						{
							Real val = 0.0f;
							if(getReal(prop->values.front(), &val))
							{
								(static_cast<DynamicAttributeOscillate*>(mDynamicAttribute))->setFrequency(val);
							}
						}
					}
				}
				else if (prop->name == token[TOKEN_DYN_OSCILLATE_PHASE])
				{
					// Property: oscillate_phase
					if (mDynamicAttribute->getType() == DynamicAttribute::DAT_OSCILLATE)
					{
						if (passValidateProperty(compiler, prop, token[TOKEN_DYN_OSCILLATE_PHASE], VAL_REAL))
						{
							Real val = 0.0f;
							if(getReal(prop->values.front(), &val))
							{
								(static_cast<DynamicAttributeOscillate*>(mDynamicAttribute))->setPhase(val);
							}
						}
					}
				}
				else if (prop->name == token[TOKEN_DYN_OSCILLATE_BASE])
				{
					// Property: oscillate_base
					if (mDynamicAttribute->getType() == DynamicAttribute::DAT_OSCILLATE)
					{
						if (passValidateProperty(compiler, prop, token[TOKEN_DYN_OSCILLATE_BASE], VAL_REAL))
						{
							Real val = 0.0f;
							if(getReal(prop->values.front(), &val))
							{
								(static_cast<DynamicAttributeOscillate*>(mDynamicAttribute))->setBase(val);
							}
						}
					}
				}
				else if (prop->name == token[TOKEN_DYN_OSCILLATE_AMPLITUDE])
				{
					// Property: oscillate_amplitude
					if (mDynamicAttribute->getType() == DynamicAttribute::DAT_OSCILLATE)
					{
						if (passValidateProperty(compiler, prop, token[TOKEN_DYN_OSCILLATE_AMPLITUDE], VAL_REAL))
						{
							Real val = 0.0f;
							if(getReal(prop->values.front(), &val))
							{
								(static_cast<DynamicAttributeOscillate*>(mDynamicAttribute))->setAmplitude(val);
							}
						}
					}
				}
				else if (prop->name == token[TOKEN_DYN_OSCILLATE_TYPE])
				{
					// Property: oscillate_type
					if (mDynamicAttribute->getType() == DynamicAttribute::DAT_OSCILLATE)
					{
						if (passValidateProperty(compiler, prop, token[TOKEN_DYN_OSCILLATE_TYPE], VAL_STRING))
						{
							String val;
							if(getString(prop->values.front(), &val))
							{
								if (val == token[TOKEN_DYN_SINE])
								{
									(static_cast<DynamicAttributeOscillate*>(mDynamicAttribute))->setOscillationType(
										DynamicAttributeOscillate::OSCT_SINE);
								}
								else if (val == token[TOKEN_DYN_SQUARE])
								{
									(static_cast<DynamicAttributeOscillate*>(mDynamicAttribute))->setOscillationType(
										DynamicAttributeOscillate::OSCT_SQUARE);
								}
							}
						}
					}
				}
				else
				{
					errorUnexpectedProperty(compiler, prop);
				}

			}
			else if((*i)->type == ANT_OBJECT)
			{
				processNode(compiler, *i);
			}
            else
			{
				errorUnexpectedToken(compiler, *i);
			}
		}

		// Set it in the context
		obj->context = Any(mDynamicAttribute);
	}
	//-----------------------------------------------------------------------
	bool ParticleFollowerTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleAffector* af = any_cast<ParticleAffector*>(prop->parent->context);
		ParticleFollower* affector = static_cast<ParticleFollower*>(af);

		if (prop->name == token[TOKEN_MIN_DISTANCE])
		{
			// Property: min_distance
			if (passValidateProperty(compiler, prop, token[TOKEN_MIN_DISTANCE], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setMinDistance(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_FOLLOW_MIN_DISTANCE])
		{
			// Property: follower_min_distance (deprecated and replaced by 'min_distance')
			if (passValidateProperty(compiler, prop, token[TOKEN_FOLLOW_MIN_DISTANCE], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setMinDistance(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_MAX_DISTANCE])
		{
			// Property: max_distance
			if (passValidateProperty(compiler, prop, token[TOKEN_MAX_DISTANCE], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setMaxDistance(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_FOLLOW_MAX_DISTANCE])
		{
			// Property: follower_max_distance (deprecated and replaced by 'TOKEN_MAX_DISTANCE')
			if (passValidateProperty(compiler, prop, token[TOKEN_FOLLOW_MAX_DISTANCE], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setMaxDistance(val);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool RandomiserTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleAffector* af = 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))
			{
				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))
			{
				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))
			{
				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))
			{
				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))
			{
				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))
			{
				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))
			{
				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))
			{
				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 BoxColliderTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleAffector* af = any_cast<ParticleAffector*>(prop->parent->context);
		BoxCollider* affector = static_cast<BoxCollider*>(af);
		if (prop->name == token[TOKEN_BOX_WIDTH])
		{
			if (passValidateProperty(compiler, prop, token[TOKEN_BOX_WIDTH], VAL_REAL))
			{
				// Property: box_width
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setWidth(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_BOXCOLL_WIDTH])
		{
			// Property: box_collider_width (deprecated and replaced by 'box_width')
			if (passValidateProperty(compiler, prop, token[TOKEN_BOXCOLL_WIDTH], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->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))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setHeight(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_BOXCOLL_HEIGHT])
		{
			// Property: box_collider_height (deprecated and replaced by 'box_height')
			if (passValidateProperty(compiler, prop, token[TOKEN_BOXCOLL_HEIGHT], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->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))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setDepth(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_BOXCOLL_DEPTH])
		{
			// Property: box_collider_depth (deprecated and replaced by 'box_depth')
			if (passValidateProperty(compiler, prop, token[TOKEN_BOXCOLL_DEPTH], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					affector->setDepth(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_INNER_COLLISION])
		{
			// Property: inner_collision
			if (passValidateProperty(compiler, prop, token[TOKEN_INNER_COLLISION], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					affector->setInnerCollision(val);
					return true;
				}
			}
		}
		else
		{
			// Parse the BaseCollider
			BaseColliderTranslator baseColliderTranslator;
			return baseColliderTranslator.translateChildProperty(compiler, node);
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool BaseColliderTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleAffector* af = 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))
			{
				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))
			{
				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))
			{
				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))
			{
				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))
			{
				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))
			{
				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;
	}
	//-----------------------------------------------------------------------
	bool RibbonTrailRendererTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleRenderer* ren = any_cast<ParticleRenderer*>(prop->parent->context);
		RibbonTrailRenderer* renderer = static_cast<RibbonTrailRenderer*>(ren);

		if (prop->name == token[TOKEN_USE_VERTEX_COLOURS])
		{
			// Property: use_vertex_colours
			if (passValidateProperty(compiler, prop, token[TOKEN_USE_VERTEX_COLOURS], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					renderer->setUseVertexColours(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RIBBONTRAIL_VERTEX_COLOURS])
		{
			// Property: ribbontrail_vertex_colours (deprecated and replaced by 'use_vertex_colours')
			if (passValidateProperty(compiler, prop, token[TOKEN_RIBBONTRAIL_VERTEX_COLOURS], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					renderer->setUseVertexColours(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_MAX_ELEMENTS])
		{
			// Property: max_elements
			if (passValidateProperty(compiler, prop, token[TOKEN_MAX_ELEMENTS], VAL_UINT))
			{
				uint val = 0;
				if(getUInt(prop->values.front(), &val))
				{
					renderer->setMaxChainElements(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RIBBONTRAIL_MAX_ELEMENTS])
		{
			// Property: ribbontrail_max_elements (deprecated and replaced by 'max_elements')
			if (passValidateProperty(compiler, prop, token[TOKEN_RIBBONTRAIL_MAX_ELEMENTS], VAL_UINT))
			{
				uint val = 0;
				if(getUInt(prop->values.front(), &val))
				{
					renderer->setMaxChainElements(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RIBBONTRAIL_LENGTH])
		{
			// Property: ribbontrail_length
			if (passValidateProperty(compiler, prop, token[TOKEN_RIBBONTRAIL_MAX_ELEMENTS], VAL_REAL))
			{
				Real val = 0;
				if(getReal(prop->values.front(), &val))
				{
					renderer->setTrailLength(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RIBBONTRAIL_WIDTH])
		{
			// Property: ribbontrail_width
			if (passValidateProperty(compiler, prop, token[TOKEN_RIBBONTRAIL_WIDTH], VAL_REAL))
			{
				Real val = 0;
				if(getReal(prop->values.front(), &val))
				{
					renderer->setTrailWidth(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RANDOM_INITIAL_COLOUR])
		{
			// Property: random_initial_colour
			if (passValidateProperty(compiler, prop, token[TOKEN_RANDOM_INITIAL_COLOUR], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					renderer->setRandomInitialColour(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RIBBONTRAIL_RANDOM_INITIAL_COLOUR])
		{
			// Property: ribbontrail_random_initial_colour (deprecated and replaced by 'random_initial_colour'))
			if (passValidateProperty(compiler, prop, token[TOKEN_RIBBONTRAIL_RANDOM_INITIAL_COLOUR], VAL_BOOL))
			{
				bool val;
				if(getBoolean(prop->values.front(), &val))
				{
					renderer->setRandomInitialColour(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_INITIAL_COLOUR])
		{
			// Property: initial_colour
			if (passValidateProperty(compiler, prop, token[TOKEN_INITIAL_COLOUR], VAL_COLOURVALUE))
			{
				ColourValue val;
				if(getColour(prop->values.begin(), prop->values.end(), &val))
				{
					renderer->setInitialColour(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RIBBONTRAIL_INITIAL_COLOUR])
		{
			// Property: ribbontrail_initial_colour (deprecated and replaced by 'initial_colour')
			if (passValidateProperty(compiler, prop, token[TOKEN_RIBBONTRAIL_INITIAL_COLOUR], VAL_COLOURVALUE))
			{
				ColourValue val;
				if(getColour(prop->values.begin(), prop->values.end(), &val))
				{
					renderer->setInitialColour(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_COLOUR_CHANGE])
		{
			// Property: colour_change
			if (passValidateProperty(compiler, prop, token[TOKEN_COLOUR_CHANGE], VAL_COLOURVALUE))
			{
				ColourValue val;
				if(getColour(prop->values.begin(), prop->values.end(), &val))
				{
					renderer->setColourChange(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_RIBBONTRAIL_COLOUR_CHANGE])
		{
			// Property: ribbontrail_colour_change (deprecated and replaced by 'colour_change')
			if (passValidateProperty(compiler, prop, token[TOKEN_RIBBONTRAIL_COLOUR_CHANGE], VAL_COLOURVALUE))
			{
				ColourValue val;
				if(getColour(prop->values.begin(), prop->values.end(), &val))
				{
					renderer->setColourChange(val);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool VortexAffectorTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleAffector* af = any_cast<ParticleAffector*>(prop->parent->context);
		VortexAffector* affector = static_cast<VortexAffector*>(af);

		if (prop->name == token[TOKEN_ROTATION_AXIS])
		{
			// Property: rotation_axis
			if (passValidateProperty(compiler, prop, token[TOKEN_ROTATION_AXIS], VAL_VECTOR3))
			{
				Vector3 val;
				if(getVector3(prop->values.begin(), prop->values.end(), &val))
				{
					affector->setRotationVector(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_VORTEX_ROTATION_VECTOR])
		{
			// Property: vortex_aff_vector (deprecated and replaced by 'rotation_axis')
			if (passValidateProperty(compiler, prop, token[TOKEN_VORTEX_ROTATION_VECTOR], VAL_VECTOR3))
			{
				Vector3 val;
				if(getVector3(prop->values.begin(), prop->values.end(), &val))
				{
					affector->setRotationVector(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_ROTATION_SPEED])
		{
			// Property: rotation_speed
			if (passValidateProperty(compiler, prop, token[TOKEN_ROTATION_SPEED], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					DynamicAttributeFixed* dynamicAttributeFixed = PU_NEW_T(DynamicAttributeFixed, MEMCATEGORY_SCENE_OBJECTS)();
					dynamicAttributeFixed->setValue(val);
					affector->setRotationSpeed(dynamicAttributeFixed);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_VORTEX_ROTATION_SPEED])
		{
			// Property: vortex_aff_speed (deprecated and replaced by 'rotation_speed')
			if (passValidateProperty(compiler, prop, token[TOKEN_VORTEX_ROTATION_SPEED], VAL_REAL))
			{
				Real val = 0.0f;
				if(getReal(prop->values.front(), &val))
				{
					DynamicAttributeFixed* dynamicAttributeFixed = PU_NEW_T(DynamicAttributeFixed, MEMCATEGORY_SCENE_OBJECTS)();
					dynamicAttributeFixed->setValue(val);
					affector->setRotationSpeed(dynamicAttributeFixed);
					return true;
				}
			}
		}

		return false;
	}
	//-----------------------------------------------------------------------
	bool SceneDecoratorExternTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		Extern* ex = 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))
			{
				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))
			{
				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))
			{
				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))
			{
				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))
			{
				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))
			{
				Vector3 val;
				if(getVector3(prop->values.begin(), prop->values.end(), &val))
				{
					externObject->setPosition(val);
					return true;
				}
			}
		}

		return false;
	}
/*
note: we can know the texture unit index by getting parent then finding it in the list of children
*/
void SGScriptTranslator::translateTextureUnit(ScriptCompiler* compiler, const AbstractNodePtr &node)
{
    ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());    
    TextureUnitState* texState = any_cast<TextureUnitState*>(obj->parent->context);
    Pass* pass = texState->getParent();
    Technique* technique = pass->getParent();
    Material* material = technique->getParent();
    ShaderGenerator* shaderGenerator = ShaderGenerator::getSingletonPtr();
    String dstTechniqueSchemeName = obj->name;
    bool techniqueCreated;

    // Make sure the scheme name is valid - use default if none exists.
    if (dstTechniqueSchemeName.empty()) 
        dstTechniqueSchemeName = ShaderGenerator::DEFAULT_SCHEME_NAME;  


    //check if technique already created
    techniqueCreated = shaderGenerator->hasShaderBasedTechnique(material->getName(), 
        material->getGroup(),
        technique->getSchemeName(), 
        dstTechniqueSchemeName);
    
    if (techniqueCreated == false)
    {
        // Create the shader based technique.
        techniqueCreated = shaderGenerator->createShaderBasedTechnique(material->getName(), 
            material->getGroup(),
            technique->getSchemeName(), 
            dstTechniqueSchemeName,
            shaderGenerator->getCreateShaderOverProgrammablePass());
    }


                    
    // Case technique successfully created.
    if (techniqueCreated)
    {
        //Attempt to get the render state which might have been created by the pass parsing
        mGeneratedRenderState = shaderGenerator->getRenderState(dstTechniqueSchemeName, 
                    material->getName(), material->getGroup(), pass->getIndex());
    
        // Go over all the render state properties.
        for(AbstractNodeList::iterator i = obj->children.begin(); i != obj->children.end(); ++i)
        {
            if((*i)->type == ANT_PROPERTY)
            {
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>((*i).get());
                SubRenderState* subRenderState = ShaderGenerator::getSingleton().createSubRenderState(compiler, prop, texState, this);
                
                if (subRenderState)
                {
                    addSubRenderState(subRenderState, dstTechniqueSchemeName, material->getName(), 
                        material->getGroup(), pass->getIndex());
                }
            }
            else
            {
                processNode(compiler, *i);
            }
        }

        mGeneratedRenderState = NULL;
    }   
}
	//-----------------------------------------------------------------------
	bool EntityRendererTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleRenderer* ren = any_cast<ParticleRenderer*>(prop->parent->context);
		EntityRenderer* renderer = static_cast<EntityRenderer*>(ren);

		if (prop->name == token[TOKEN_MESH_NAME])
		{
			// Property: mesh_name
			if (passValidateProperty(compiler, prop, token[TOKEN_MESH_NAME], VAL_STRING))
			{
				String val;
				if(getString(prop->values.front(), &val))
				{
					renderer->setMeshName(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_ENT_MESH_NAME])
		{
			// Property: entity_renderer_mesh_name (deprecated and replaced by mesh_name)
			if (passValidateProperty(compiler, prop, token[TOKEN_ENT_MESH_NAME], VAL_STRING))
			{
				String val;
				if(getString(prop->values.front(), &val))
				{
					renderer->setMeshName(val);
					return true;
				}
			}
		}
		else if (prop->name == token[TOKEN_ENT_ORIENTATION_TYPE])
		{
			// Property: entity_orientation_type
			if (passValidateProperty(compiler, prop, token[TOKEN_ENT_ORIENTATION_TYPE], VAL_STRING))
			{
				String val;
				if(getString(prop->values.front(), &val))
				{
					if (val == token[TOKEN_ENT_ORIENTED_SELF])
					{
						renderer->setEntityOrientationType(EntityRenderer::ENT_ORIENTED_SELF);
						return true;
					}
					else if (val == token[TOKEN_ENT_ORIENTED_SELF_MIRRORED])
					{
						renderer->setEntityOrientationType(EntityRenderer::ENT_ORIENTED_SELF_MIRRORED);
						return true;
					}
					else if (val == token[TOKEN_ENT_ORIENTED_SHAPE])
					{
						renderer->setEntityOrientationType(EntityRenderer::ENT_ORIENTED_SHAPE);
						return true;
					}
				}
			}
		}

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

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

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

		// Create the Extern
		mExtern = ParticleSystemManager::getSingletonPtr()->createExtern(type);
		if (!mExtern)
		{
			compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, obj->file, obj->line);
			return;
		}

		if (!obj->parent->context.isEmpty())
		{
			ParticleTechnique* technique = any_cast<ParticleTechnique*>(obj->parent->context);
			technique->addExtern(mExtern);
		}
		else
		{
			// It is an alias
			mExtern->setAliasName(parent->name);
			ParticleSystemManager::getSingletonPtr()->addAlias(mExtern);
		}

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

		// Set it in the context
		obj->context = Any(mExtern);

		// Run through properties
		for(AbstractNodeList::iterator i = obj->children.begin(); i != obj->children.end(); ++i)
		{
			// No properties of its own
			if((*i)->type == ANT_PROPERTY)
			{
				PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>((*i).get());
				if (externFactory->translateChildProperty(compiler, *i))
				{
					// Parsed the property by another translator; do nothing
				}
				else
				{
					errorUnexpectedProperty(compiler, prop);
				}
			}
			else if((*i)->type == ANT_OBJECT)
			{
				if (externFactory->translateChildObject(compiler, *i))
				{
					// Parsed the object by another translator; do nothing
				}
				else
				{
					processNode(compiler, *i);
				}
			}
            else
			{
				errorUnexpectedToken(compiler, *i);
			}
		}
	}
//-----------------------------------------------------------------------------
void SGScriptTranslator::translatePass(ScriptCompiler* compiler, const AbstractNodePtr &node)
{
    ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());    
    Pass* pass = any_cast<Pass*>(obj->parent->context);
    Technique* technique = pass->getParent();
    Material* material = technique->getParent();
    ShaderGenerator* shaderGenerator = ShaderGenerator::getSingletonPtr();
    String dstTechniqueSchemeName = obj->name;
    bool techniqueCreated;

    // Make sure the scheme name is valid - use default if none exists.
    if (dstTechniqueSchemeName.empty()) 
        dstTechniqueSchemeName = ShaderGenerator::DEFAULT_SCHEME_NAME;  


    // Create the shader based technique.
    techniqueCreated = shaderGenerator->createShaderBasedTechnique(material->getName(), 
        material->getGroup(), 
        technique->getSchemeName(), 
        dstTechniqueSchemeName,
        shaderGenerator->getCreateShaderOverProgrammablePass());


    // Case technique successfully created.
    if (techniqueCreated)
    {
        // Go over all the render state properties.
        for(AbstractNodeList::iterator i = obj->children.begin(); i != obj->children.end(); ++i)
        {
            if((*i)->type == ANT_PROPERTY)
            {
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>((*i).get());

                // Handle light count property.
                if (prop->name == "light_count")
                {
                    if (prop->values.size() != 3)
                    {
                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
                    }
                    else
                    {
                        int lightCount[3];

                        if (false == SGScriptTranslator::getInts(prop->values.begin(), prop->values.end(), lightCount, 3))
                        {
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
                        }
                        else
                        {
                            shaderGenerator->createScheme(dstTechniqueSchemeName);
                            RenderState* renderState = shaderGenerator->getRenderState(dstTechniqueSchemeName, 
                                material->getName(), material->getGroup(), pass->getIndex());

                            renderState->setLightCount(lightCount);
                            renderState->setLightCountAutoUpdate(false);
                        }
                    }                   
                }

                // Handle the rest of the custom properties.
                else
                {
                    SubRenderState* subRenderState = ShaderGenerator::getSingleton().createSubRenderState(compiler, prop, pass, this);
                    if (subRenderState)
                    {
                        addSubRenderState(subRenderState, dstTechniqueSchemeName, material->getName(), material->getGroup(), pass->getIndex());
                    }
                }               
            }
            else
            {
                processNode(compiler, *i);
            }
        }

        mGeneratedRenderState = NULL;
    }

}
	//-----------------------------------------------------------------------
	bool OnPositionObserverTranslator::translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node)
	{
		PropertyAbstractNode* prop = reinterpret_cast<PropertyAbstractNode*>(node.get());
		ParticleObserver* ob = any_cast<ParticleObserver*>(prop->parent->context);
		OnPositionObserver* observer = static_cast<OnPositionObserver*>(ob);

		if (prop->name == token[TOKEN_ONPOSITION_X])
		{
			// Property: position_x
			if (passValidatePropertyNumberOfValues(compiler, prop, token[TOKEN_ONPOSITION_X], 2))
			{
				String compareType;
				Real val = 0;
				AbstractNodeList::const_iterator i = prop->values.begin();
				if(getString(*i, &compareType))
				{
					if (compareType == token[TOKEN_LESS_THAN])
					{
						observer->setComparePositionX(CO_LESS_THAN);
					}
					else if (compareType == token[TOKEN_GREATER_THAN])
					{
						observer->setComparePositionX(CO_GREATER_THAN);
					}
					else if (compareType == token[TOKEN_EQUALS])
					{
						observer->setComparePositionX(CO_EQUALS);
					}
					++i;
					if(getReal(*i, &val))
					{
						observer->setPositionXThreshold(val);
						return true;
					}
				}
			}
		}
		else if (prop->name == token[TOKEN_ONPOSITION_Y])
		{
			// Property: position_y
			if (passValidatePropertyNumberOfValues(compiler, prop, token[TOKEN_ONPOSITION_Y], 2))
			{
				String compareType;
				Real val = 0;
				AbstractNodeList::const_iterator i = prop->values.begin();
				if(getString(*i, &compareType))
				{
					if (compareType == token[TOKEN_LESS_THAN])
					{
						observer->setComparePositionY(CO_LESS_THAN);
					}
					else if (compareType == token[TOKEN_GREATER_THAN])
					{
						observer->setComparePositionY(CO_GREATER_THAN);
					}
					else if (compareType == token[TOKEN_EQUALS])
					{
						observer->setComparePositionY(CO_EQUALS);
					}
					++i;
					if(getReal(*i, &val))
					{
						observer->setPositionYThreshold(val);
						return true;
					}
				}
			}
		}
		else if (prop->name == token[TOKEN_ONPOSITION_Z])
		{
			// Property: position_z
			if (passValidatePropertyNumberOfValues(compiler, prop, token[TOKEN_ONPOSITION_Z], 2))
			{
				String compareType;
				Real val = 0;
				AbstractNodeList::const_iterator i = prop->values.begin();
				if(getString(*i, &compareType))
				{
					if (compareType == token[TOKEN_LESS_THAN])
					{
						observer->setComparePositionZ(CO_LESS_THAN);
					}
					else if (compareType == token[TOKEN_GREATER_THAN])
					{
						observer->setComparePositionZ(CO_GREATER_THAN);
					}
					else if (compareType == token[TOKEN_EQUALS])
					{
						observer->setComparePositionZ(CO_EQUALS);
					}
					++i;
					if(getReal(*i, &val))
					{
						observer->setPositionZThreshold(val);
						return true;
					}
				}
			}
		}

		return false;
	}