float GetNodeWorldPositionY(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, bool firstPerson)
	{
		NiAVObject	* object = ResolveNode(obj, nodeName, firstPerson);

		return object ? object->m_worldTransform.pos.y : 0;
	}
	bool HasNode(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, bool firstPerson)
	{
		NiAVObject	* object = ResolveNode(obj, nodeName, firstPerson);

		return object != NULL;
	}
void CHuiFxEffectParser::ParseAnimationNodeL(CMDXMLNode* aNode, PARAM_TYPE& aParam, TIMELINE_TYPE& aTimeLine)
    {
#ifdef _HUI_FX_PARSER_LOGGING
    __ALFFXLOGSTRING1("CHuiFxEffectParser::ParseAnimationNodeL - 0x%x", this);
#endif
    switch( ResolveNode( aNode ) )
        {
        case ENodeTypeDuration:
            {
            aTimeLine.SetDuration(ParseFloatValueL(aNode->FirstChild()));
            }
            break;
        case ENodeTypeStyle:
            {
            CMDXMLNode* styleNode = aNode->FirstChild();
            if (styleNode->NodeType() != CMDXMLNode::ETextNode)
                {
                FAIL(KErrGeneral, _L("Text node expected while parsing an interpolation mode"));
                }
            TPtrC modePtr( ((CMDXMLText *)styleNode)->Data() );
            
            if( modePtr.Compare( KLitHold ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeHold);
                }
            else if( modePtr.Compare( KLitLinear ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeLinear);
                }
            else if( modePtr.Compare( KLitInQuad ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeInQuad);
                }
            else if( modePtr.Compare( KLitOutQuad ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeOutQuad);
                }
            else if( modePtr.Compare( KLitInOutQuad ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeInOutQuad);
                }
            else if( modePtr.Compare( KLitOutInQuad ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeOutInQuad);
                }
            else if( modePtr.Compare( KLitInBack ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeInBack);
                }
            else if( modePtr.Compare( KLitOutBack ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeOutBack);
                }
            else if( modePtr.Compare( KLitInOutBack ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeInOutBack);
                }
            else if( modePtr.Compare( KLitOutInBack ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeOutInBack);
                }
            else if( modePtr.Compare( KLitQuadraticBezier ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeQuadraticBezier);
                }
            else if( modePtr.Compare( KLitCubicBezier ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeCubicBezier);
                }
/*                
            else if( modePtr.Compare( KLitDeclerate ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeDecelerate);
                }
            else if( modePtr.Compare( KLitAccelerate ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeAccelerate);
                }
            else if( modePtr.Compare( KLitImpulse ) == 0 )
                {
                aTimeLine.SetInterpolationMode(EInterpolationModeImpulse);
                }
*/                
            else
                {
                // unknown (unsupported) interpolation modes default to linear
                // (at least during testing when we add modes)
                aTimeLine.SetInterpolationMode(EInterpolationModeLinear);
//                FAIL(KErrGeneral, _L("Unknown interpolation mode"));
                }
            break;
            }
        case ENodeTypeMarker:
            {
            TReal32 time = ParseFloatAttributeL(aNode, KLitAt);
            TInt typeIndex = ((CMDXMLElement*)aNode)->FindIndex( KLitType );
            
            if (typeIndex == KErrNotFound)
                {
                FAIL(KErrGeneral, _L("Marker name not found"));
                }

            TPtrC attributeValue;
            TPtrC attributeName;
            User::LeaveIfError(((CMDXMLElement*)aNode)->AttributeDetails( typeIndex, attributeName, attributeValue ));

            // TODO: Should this be controllable?
            aTimeLine.SetLoopingMode(ELoopingModeRepeat);

            if (attributeValue.Compare(KLitLoopStart) == 0)
                {
                aTimeLine.SetLoopStart(time);
                }
            else if (attributeValue.Compare(KLitLoopEnd) == 0)
                {
                aTimeLine.SetLoopEnd(time);
                }
            else
                {
                FAIL(KErrGeneral, _L("Unsupported marker type"));
                }
            break;
            }
        case ENodeTypeKeyFrame:
            {
            TReal32 time = ParseFloatAttributeL(aNode, KLitAt);
            TReal32 aux1 = ParseFloatAttributeL(aNode, KLitAux1, EFalse);
            TReal32 aux2 = ParseFloatAttributeL(aNode, KLitAux2, EFalse);
            VALUE_TYPE value = ParseAnimationKeyFrameValueL<PARAM_TYPE::ValueType, TIMELINE_TYPE>(aNode->FirstChild(), aTimeLine);
            TRAPD(err, aTimeLine.AppendKeyFrameL(time, value, aux1, aux2));
            if (err != KErrNone)
                {
                FAIL(KErrGeneral, _L("Unable to append new key frame to timeline"));
                }
            }
            break;
        case ENodeTypeStart:
            {
            TInt refIndex  = ((CMDXMLElement*)aNode)->FindIndex( KLitRef );
            TReal32 refValue = 0;
            TBool needRefValue = EFalse;
            THuiFxReferencePoint ref = EReferencePointUndefined;
            if ( refIndex != KErrNotFound )
                {
                ref = GetReferencePointL( aNode, refValue, needRefValue );
                }
            aParam.SetStartReference( ref );
            if ( needRefValue )
                {
                aParam.SetStartValue( refValue );
                }
            if ( aParam.StartReference() != EReferencePointUndefined &&
               aParam.EndReference() != EReferencePointUndefined )
                {
                aParam.SetReferencePoint( EReferencePointUndefined );
                }
	     float value = ParseFloatValueL(aNode->FirstChild());
	     aParam.SetStartMultiplier( value );

            }
            break;
        case ENodeTypeEnd:
            {
            TInt refIndex  = ((CMDXMLElement*)aNode)->FindIndex( KLitRef );
            TReal32 refValue = 0;
            TBool needRefValue = EFalse;
            THuiFxReferencePoint ref = EReferencePointUndefined;
            if ( refIndex != KErrNotFound )
                {
                ref = GetReferencePointL( aNode, refValue, needRefValue );
                }
            aParam.SetEndReference( ref );
            if ( needRefValue )
                {
                aParam.SetEndValue( refValue );
                }
            if ( aParam.StartReference() != EReferencePointUndefined &&
               aParam.EndReference() != EReferencePointUndefined )
                {
                aParam.SetReferencePoint( EReferencePointUndefined );
                }
            float value = ParseFloatValueL(aNode->FirstChild());
            aParam.SetEndMultiplier( value );

            }
            break;
        }
#ifdef _HUI_FX_PARSER_LOGGING
    __ALFFXLOGSTRING("CHuiFxEffectParser::ParseAnimationNodeL - out");
#endif
    }
	float GetNodeScale(StaticFunctionTag* base, TESObjectREFR * obj, BSFixedString nodeName, bool firstPerson)
	{
		NiAVObject	* object = ResolveNode(obj, nodeName, firstPerson);

		return object ? object->m_localTransform.scale : 0;
	}
void CHuiFxEffectParser::ParseNodeL( CMDXMLNode* aNode, CHuiFxLayer* aLayer)
    {
    switch( ResolveNode( aNode ) )
        {
        case ENodeTypeUnknown:
            {
#ifdef _HUI_FX_PARSER_LOGGING
            __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeUnknown");
#endif
            __ALFFXLOGSTRING1("CHuiFxEffectParser::ParseNodeL : WARNING - Node tag <%S> is not supported.", &(aNode->NodeName()));
            break;
            }
            
        case ENodeTypeGroup:
            {
#ifdef _HUI_FX_PARSER_LOGGING
            __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeGroup");
#endif
            // can't have group layers inside group layer
            if (aLayer && aLayer->Type() == ELayerTypeGroup)
                {
                FAIL(KErrGeneral, _L("Nested group layers not supported"));
                }
            
            CHuiFxGroupLayer* group = CHuiFxGroupLayer::NewL();
            CleanupStack::PushL( group );
            for (CMDXMLNode* node = aNode->FirstChild(); node; node = node->NextSibling())
                {
                ParseNodeL( node, group );
                }
            iEffect->AddLayerL( group ); // ownership transferred
            CleanupStack::Pop( group );
            break;
            }
            
        case ENodeTypeFilter:
            {
#ifdef _HUI_FX_PARSER_LOGGING
            __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeFilter");
#endif
            THuiFxFilterType filterType = GetFilterTypeL( aNode );
            CHuiFxFilter* filter = iEngine.CreateFilterL( filterType );
            CleanupStack::PushL( filter );
            CHuiFxFilterLayer* filterLayer = CHuiFxFilterLayer::NewL( filter );
            CleanupStack::Pop( filter );
            CleanupStack::PushL( filterLayer );
            if (aLayer && aLayer->Type() == ELayerTypeGroup)
                {
                CHuiFxGroupLayer* group = reinterpret_cast<CHuiFxGroupLayer*>(aLayer);
                group->AddLayerL( filterLayer ); // ownership transferred
                }
            else
                {
                iEffect->AddLayerL( filterLayer ); // ownership transferred
                }
            CleanupStack::Pop( filterLayer );
            
            if (filterType == EFilterTypeTransform)
                {
                filterLayer->SetTransformed(ETrue);
                }
            
            for (CMDXMLNode* node = aNode->FirstChild(); node; node = node->NextSibling())
                {
                ParseNodeL( node, filterLayer );
                }
            break;
            }
            
        case ENodeTypeVisual:
            {
#ifdef _HUI_FX_PARSER_LOGGING
            __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeVisual");
#endif
            TPtrC16 extBitmap;
            THuiFxVisualSrcType srcType = GetSrcTypeL( aNode, extBitmap );
            TBool opaqueHint = GetOpaqueHintL(aNode);
            CHuiFxVisualLayer* visual = CHuiFxVisualLayer::NewL( iVisual );
            CleanupStack::PushL( visual );
            visual->SetSourceType( srcType );
            visual->SetFxmlUsesOpaqueHint( opaqueHint );
            if ( srcType == EVisualSrcBitmap && extBitmap.Length() > 0 )
                {
                visual->SetExtBitmapFileL( extBitmap );
                }
            if (aLayer && aLayer->Type() == ELayerTypeGroup)
                {
                CHuiFxGroupLayer* group = reinterpret_cast<CHuiFxGroupLayer*>(aLayer);
                group->AddLayerL( visual ); // ownership transferred
                }
            else
                {
                iEffect->AddLayerL( visual ); // ownership transferred
                }
            for (CMDXMLNode* node = aNode->FirstChild(); node; node = node->NextSibling())
                {
                ParseNodeL( node, visual );
                }
            CleanupStack::Pop( visual );
            break;
            }
         
         case ENodeTypeBlending:
            {
#ifdef _HUI_FX_PARSER_LOGGING
            __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeBlending");
#endif
            CMDXMLNode* blendingNode = aNode->FirstChild();
            if( blendingNode->NodeType() != CMDXMLNode::ETextNode )
                {
                FAIL(KErrGeneral, _L("Bad blending mode"));
                }
            TPtrC modePtr( ((CMDXMLText *)blendingNode)->Data() );
            
            // set replace as default blending mode
            THuiFxBlendingMode blendingMode = EBlendingModeReplace;
            if( modePtr.Compare( KLitReplace ) == 0 )
                {
                blendingMode = EBlendingModeReplace;
                }
            else if( modePtr.Compare( KLitOver ) == 0 )
                {
                blendingMode = EBlendingModeOver;
                }
            else if( modePtr.Compare( KLitMultiply ) == 0 )
                {
                blendingMode = EBlendingModeMultiply;
                }
            else if( modePtr.Compare( KLitAdditive ) == 0 )
                {
                blendingMode = EBlendingModeAdditive;
                }
            else if( modePtr.Compare( KLitDarken ) == 0 )
                {
                blendingMode = EBlendingModeDarken;
                }
            else if( modePtr.Compare( KLitLighten ) == 0 )
                {
                blendingMode = EBlendingModeLighten;
                }
            else
                {
                FAIL(KErrGeneral, _L("Bad blending mode"));
                }
                
            if (aLayer && aLayer->Type() == ELayerTypeGroup)
                {
                aLayer->SetBlendingMode( blendingMode );
                }
            else
                {
                // TODO: should other layers have a blending mode?
                FAIL(KErrGeneral, _L("Blending mode can only be set for a group layer"));
                }            
            break;
            }
            
         case  ENodeTypeParam:
            {
#ifdef _HUI_FX_PARSER_LOGGING
            __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeParam");
#endif
            ResolveParamL(aNode, aLayer);
            break;
            }
            
        default:
            __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - default??");
            break;
        }
    
    }