Browse Source

Add material shader animation.

aster 11 years ago
parent
commit
d0b1036001

+ 3 - 0
Source/Engine/Graphics/Batch.cpp

@@ -566,6 +566,9 @@ void Batch::Prepare(View* view, bool setModelTransform) const
     {
         if (graphics->NeedParameterUpdate(SP_MATERIAL, material_))
         {
+            // Update shader parameter animations
+            material_->UpdateShaderParameterAnimations();
+
             const HashMap<StringHash, MaterialShaderParameter>& parameters = material_->GetShaderParameters();
             for (HashMap<StringHash, MaterialShaderParameter>::ConstIterator i = parameters.Begin(); i != parameters.End(); ++i)
                 graphics->SetShaderParameter(i->first_, i->second_.value_);

+ 119 - 45
Source/Engine/Graphics/Material.cpp

@@ -26,6 +26,7 @@
 #include "Graphics.h"
 #include "Log.h"
 #include "Material.h"
+#include "MaterialShaderParameterAnimationInstance.h"
 #include "Matrix3x4.h"
 #include "Profiler.h"
 #include "ResourceCache.h"
@@ -68,7 +69,7 @@ static const char* cullModeNames[] =
 TextureUnit ParseTextureUnitName(String name)
 {
     name = name.ToLower().Trimmed();
-    
+
     TextureUnit unit = (TextureUnit)GetStringListIndex(name.CString(), textureUnitNames, MAX_TEXTURE_UNITS);
     if (unit == MAX_TEXTURE_UNITS)
     {
@@ -87,10 +88,10 @@ TextureUnit ParseTextureUnitName(String name)
         else if (name.Length() < 3)
             unit = (TextureUnit)Clamp(ToInt(name), 0, MAX_TEXTURE_UNITS);
     }
-    
+
     if (unit == MAX_TEXTURE_UNITS)
         LOGERROR("Unknown texture unit name " + name);
-    
+
     return unit;
 }
 
@@ -125,7 +126,8 @@ Material::Material(Context* context) :
     Resource(context),
     auxViewFrameNumber_(0),
     occlusion_(true),
-    specular_(false)
+    specular_(false),
+    frameNumber_(0)
 {
     ResetToDefaults();
 }
@@ -142,19 +144,19 @@ void Material::RegisterObject(Context* context)
 bool Material::Load(Deserializer& source)
 {
     PROFILE(LoadMaterial);
-    
+
     // In headless mode, do not actually load the material, just return success
     Graphics* graphics = GetSubsystem<Graphics>();
     if (!graphics)
         return true;
-    
+
     SharedPtr<XMLFile> xml(new XMLFile(context_));
     if (!xml->Load(source))
     {
         ResetToDefaults();
         return false;
     }
-    
+
     XMLElement rootElem = xml->GetRoot();
     return Load(rootElem);
 }
@@ -163,7 +165,7 @@ bool Material::Save(Serializer& dest) const
 {
     SharedPtr<XMLFile> xml(new XMLFile(context_));
     XMLElement materialElem = xml->CreateRoot("material");
-    
+
     Save(materialElem);
     return xml->Save(dest);
 }
@@ -171,15 +173,15 @@ bool Material::Save(Serializer& dest) const
 bool Material::Load(const XMLElement& source)
 {
     ResetToDefaults();
-    
+
     if (source.IsNull())
     {
         LOGERROR("Can not load material from null XML element");
         return false;
     }
-    
+
     ResourceCache* cache = GetSubsystem<ResourceCache>();
-    
+
     XMLElement techniqueElem = source.GetChild("technique");
     techniques_.Clear();
     while (techniqueElem)
@@ -197,9 +199,9 @@ bool Material::Load(const XMLElement& source)
         }
         techniqueElem = techniqueElem.GetNext("technique");
     }
-    
+
     SortTechniques();
-    
+
     XMLElement textureElem = source.GetChild("texture");
     while (textureElem)
     {
@@ -217,7 +219,7 @@ bool Material::Load(const XMLElement& source)
         }
         textureElem = textureElem.GetNext("texture");
     }
-    
+
     XMLElement parameterElem = source.GetChild("parameter");
     while (parameterElem)
     {
@@ -225,19 +227,19 @@ bool Material::Load(const XMLElement& source)
         SetShaderParameter(name, ParseShaderParameterValue(parameterElem.GetAttribute("value")));
         parameterElem = parameterElem.GetNext("parameter");
     }
-    
+
     XMLElement cullElem = source.GetChild("cull");
     if (cullElem)
         SetCullMode((CullMode)GetStringListIndex(cullElem.GetAttribute("value").CString(), cullModeNames, CULL_CCW));
-    
+
     XMLElement shadowCullElem = source.GetChild("shadowcull");
     if (shadowCullElem)
         SetShadowCullMode((CullMode)GetStringListIndex(shadowCullElem.GetAttribute("value").CString(), cullModeNames, CULL_CCW));
-    
+
     XMLElement depthBiasElem = source.GetChild("depthbias");
     if (depthBiasElem)
         SetDepthBias(BiasParameters(depthBiasElem.GetFloat("constant"), depthBiasElem.GetFloat("slopescaled")));
-    
+
     // Calculate memory use
     RefreshMemoryUse();
     CheckOcclusion();
@@ -251,20 +253,20 @@ bool Material::Save(XMLElement& dest) const
         LOGERROR("Can not save material to null XML element");
         return false;
     }
-    
+
     // Write techniques
     for (unsigned i = 0; i < techniques_.Size(); ++i)
     {
         const TechniqueEntry& entry = techniques_[i];
         if (!entry.technique_)
             continue;
-        
+
         XMLElement techniqueElem = dest.CreateChild("technique");
         techniqueElem.SetString("name", entry.technique_->GetName());
         techniqueElem.SetInt("quality", entry.qualityLevel_);
         techniqueElem.SetFloat("loddistance", entry.lodDistance_);
     }
-    
+
     // Write texture units
     for (unsigned j = 0; j < MAX_MATERIAL_TEXTURE_UNITS; ++j)
     {
@@ -276,7 +278,7 @@ bool Material::Save(XMLElement& dest) const
             textureElem.SetString("name", texture->GetName());
         }
     }
-    
+
     // Write shader parameters
     for (HashMap<StringHash, MaterialShaderParameter>::ConstIterator j = shaderParameters_.Begin(); j != shaderParameters_.End(); ++j)
     {
@@ -284,19 +286,19 @@ bool Material::Save(XMLElement& dest) const
         parameterElem.SetString("name", j->second_.name_);
         parameterElem.SetVectorVariant("value", j->second_.value_);
     }
-    
+
     // Write culling modes
     XMLElement cullElem = dest.CreateChild("cull");
     cullElem.SetString("value", cullModeNames[cullMode_]);
-    
+
     XMLElement shadowCullElem = dest.CreateChild("shadowcull");
     shadowCullElem.SetString("value", cullModeNames[shadowCullMode_]);
-    
+
     // Write depth bias
     XMLElement depthBiasElem = dest.CreateChild("depthbias");
     depthBiasElem.SetFloat("constant", depthBias_.constantBias_);
     depthBiasElem.SetFloat("slopescaled", depthBias_.slopeScaledBias_);
-    
+
     return true;
 }
 
@@ -304,7 +306,7 @@ void Material::SetNumTechniques(unsigned num)
 {
     if (!num)
         return;
-    
+
     techniques_.Resize(num);
     RefreshMemoryUse();
 }
@@ -313,7 +315,7 @@ void Material::SetTechnique(unsigned index, Technique* tech, unsigned qualityLev
 {
     if (index >= techniques_.Size())
         return;
-    
+
     techniques_[index] = TechniqueEntry(tech, qualityLevel, lodDistance);
     CheckOcclusion();
 }
@@ -325,7 +327,7 @@ void Material::SetShaderParameter(const String& name, const Variant& value)
     newParam.value_ = value;
     StringHash nameHash(name);
     shaderParameters_[nameHash] = newParam;
-    
+
     if (nameHash == PSP_MATSPECCOLOR)
     {
         VariantType type = value.GetType();
@@ -340,10 +342,32 @@ void Material::SetShaderParameter(const String& name, const Variant& value)
             specular_ = vec.x_ > 0.0f || vec.y_ > 0.0f || vec.z_ > 0.0f;
         }
     }
-    
+
     RefreshMemoryUse();
 }
 
+void Material::SetShaderParameterAnimation(const String& name, ValueAnimation* animation, WrapMode wrapMode, float speed)
+{
+    if (shaderParameters_.Find(name) == shaderParameters_.End())
+        return;
+
+    materialShaderParameterAnimationInstances_[name] = new MaterialShaderParameterAnimationInstance(this, name, animation, wrapMode, speed);
+}
+
+void Material::SetShaderParameterAnimationWrapMode(const String& name, WrapMode wrapMode)
+{
+    MaterialShaderParameterAnimationInstance* instance = GetMaterialShaderParameterAnimationInstance(name);
+    if (instance)
+        instance->SetWrapMode(wrapMode);
+}
+
+void Material::SetShaderParameterAnimationSpeed(const String& name, float speed)
+{
+    MaterialShaderParameterAnimationInstance* instance = GetMaterialShaderParameterAnimationInstance(name);
+    if (instance)
+        instance->SetSpeed(speed);
+}
+
 void Material::SetTexture(TextureUnit unit, Texture* texture)
 {
     if (unit < MAX_MATERIAL_TEXTURE_UNITS)
@@ -357,7 +381,7 @@ void Material::SetUVTransform(const Vector2& offset, float rotation, const Vecto
     transform.m11_ = repeat.y_;
     transform.m03_ = -0.5f * transform.m00_ + 0.5f;
     transform.m13_ = -0.5f * transform.m11_ + 0.5f;
-    
+
     Matrix3x4 rotationMatrix(Matrix3x4::IDENTITY);
     rotationMatrix.m00_ = Cos(rotation);
     rotationMatrix.m01_ = Sin(rotation);
@@ -365,15 +389,15 @@ void Material::SetUVTransform(const Vector2& offset, float rotation, const Vecto
     rotationMatrix.m11_ = rotationMatrix.m00_;
     rotationMatrix.m03_ = 0.5f - 0.5f * (rotationMatrix.m00_ + rotationMatrix.m01_);
     rotationMatrix.m13_ = 0.5f - 0.5f * (rotationMatrix.m10_ + rotationMatrix.m11_);
-    
+
     transform = rotationMatrix * transform;
-    
+
     Matrix3x4 offsetMatrix = Matrix3x4::IDENTITY;
     offsetMatrix.m03_ = offset.x_;
     offsetMatrix.m13_ = offset.y_;
-    
+
     transform = offsetMatrix * transform;
-    
+
     SetShaderParameter("UOffset", Vector4(transform.m00_, transform.m01_, transform.m02_, transform.m03_));
     SetShaderParameter("VOffset", Vector4(transform.m10_, transform.m11_, transform.m12_, transform.m13_));
 }
@@ -406,7 +430,7 @@ void Material::RemoveShaderParameter(const String& name)
 
     if (nameHash == PSP_MATSPECCOLOR)
         specular_ = false;
-    
+
     RefreshMemoryUse();
 }
 
@@ -423,7 +447,7 @@ void Material::ReleaseShaders()
 SharedPtr<Material> Material::Clone(const String& cloneName) const
 {
     SharedPtr<Material> ret(new Material(context_));
-    
+
     ret->SetName(cloneName);
     ret->techniques_ = techniques_;
     ret->shaderParameters_ = shaderParameters_;
@@ -434,7 +458,7 @@ SharedPtr<Material> Material::Clone(const String& cloneName) const
     ret->cullMode_ = cullMode_;
     ret->shadowCullMode_ = shadowCullMode_;
     ret->RefreshMemoryUse();
-    
+
     return ret;
 }
 
@@ -448,6 +472,30 @@ void Material::MarkForAuxView(unsigned frameNumber)
     auxViewFrameNumber_ = frameNumber;
 }
 
+void Material::UpdateShaderParameterAnimations()
+{
+    if (materialShaderParameterAnimationInstances_.Empty())
+        return;
+
+    Time* time = GetSubsystem<Time>();
+    if (time->GetFrameNumber() == frameNumber_)
+        return;
+
+    frameNumber_ = time->GetFrameNumber();
+    float timeStep = time->GetTimeStep();
+
+    Vector<String> finishedNames;
+    for (HashMap<StringHash, SharedPtr<MaterialShaderParameterAnimationInstance> >::ConstIterator i = materialShaderParameterAnimationInstances_.Begin(); i != materialShaderParameterAnimationInstances_.End(); ++i)
+    {
+        if (i->second_->Update(timeStep))
+            finishedNames.Push(i->second_->GetName());
+    }
+
+    // Remove finished animation
+    for (unsigned i = 0; i < finishedNames.Size(); ++i)
+        SetShaderParameterAnimation(finishedNames[i], 0);
+}
+
 const TechniqueEntry& Material::GetTechniqueEntry(unsigned index) const
 {
     return index < techniques_.Size() ? techniques_[index] : noEntry;
@@ -475,6 +523,24 @@ const Variant& Material::GetShaderParameter(const String& name) const
     return i != shaderParameters_.End() ? i->second_.value_ : Variant::EMPTY;
 }
 
+ValueAnimation* Material::GetShaderParameterAnimation(const String& name) const
+{
+    MaterialShaderParameterAnimationInstance* instance = GetMaterialShaderParameterAnimationInstance(name);
+    return instance == 0 ? 0 : instance->GetAnimation();
+}
+
+WrapMode Material::GetShaderParameterAnimationWrapMode(const String& name) const
+{
+    MaterialShaderParameterAnimationInstance* instance = GetMaterialShaderParameterAnimationInstance(name);
+    return instance == 0 ? WM_LOOP : instance->GetWrapMode();
+}
+
+float Material::GetShaderParameterAnimationSpeed(const String& name) const
+{
+    MaterialShaderParameterAnimationInstance* instance = GetMaterialShaderParameterAnimationInstance(name);
+    return instance == 0 ? 0 : instance->GetSpeed();
+}
+
 String Material::GetTextureUnitName(TextureUnit unit)
 {
     return textureUnitNames[unit];
@@ -509,35 +575,43 @@ void Material::ResetToDefaults()
 {
     SetNumTechniques(1);
     SetTechnique(0, GetSubsystem<ResourceCache>()->GetResource<Technique>("Techniques/NoTexture.xml"));
-    
+
     for (unsigned i = 0; i < MAX_MATERIAL_TEXTURE_UNITS; ++i)
         textures_[i] = 0;
-    
+
     shaderParameters_.Clear();
-    
+
     SetShaderParameter("UOffset", Vector4(1.0f, 0.0f, 0.0f, 0.0f));
     SetShaderParameter("VOffset", Vector4(0.0f, 1.0f, 0.0f, 0.0f));
     SetShaderParameter("MatDiffColor", Vector4::ONE);
     SetShaderParameter("MatEmissiveColor", Vector3::ZERO);
     SetShaderParameter("MatEnvMapColor", Vector3::ONE);
     SetShaderParameter("MatSpecColor", Vector4(0.0f, 0.0f, 0.0f, 1.0f));
-    
+
     cullMode_ = CULL_CCW;
     shadowCullMode_ = CULL_CCW;
     depthBias_ = BiasParameters(0.0f, 0.0f);
-    
+
     RefreshMemoryUse();
 }
 
 void Material::RefreshMemoryUse()
 {
     unsigned memoryUse = sizeof(Material);
-    
+
     memoryUse += techniques_.Size() * sizeof(TechniqueEntry);
     memoryUse += MAX_MATERIAL_TEXTURE_UNITS * sizeof(SharedPtr<Texture>);
     memoryUse += shaderParameters_.Size() * sizeof(MaterialShaderParameter);
-    
+
     SetMemoryUse(memoryUse);
 }
 
+MaterialShaderParameterAnimationInstance* Material::GetMaterialShaderParameterAnimationInstance(const String& name) const
+{
+    HashMap<StringHash, SharedPtr<MaterialShaderParameterAnimationInstance> >::ConstIterator i = materialShaderParameterAnimationInstances_.Find(name);
+    if (i == materialShaderParameterAnimationInstances_.End())
+        return 0;
+    return i->second_;
+}
+
 }

+ 32 - 8
Source/Engine/Graphics/Material.h

@@ -22,6 +22,7 @@
 
 #pragma once
 
+#include "AnimationDefs.h"
 #include "GraphicsDefs.h"
 #include "Light.h"
 #include "Resource.h"
@@ -30,11 +31,13 @@
 namespace Urho3D
 {
 
+class MaterialShaderParameterAnimationInstance;
 class Pass;
 class Technique;
 class Texture;
 class Texture2D;
 class TextureCube;
+class ValueAnimationInfo;
 
 /// %Material's shader parameter definition.
 struct MaterialShaderParameter
@@ -54,7 +57,7 @@ struct TechniqueEntry
     TechniqueEntry(Technique* tech, unsigned qualityLevel, float lodDistance);
     /// Destruct.
     ~TechniqueEntry();
-    
+
     /// Technique.
     SharedPtr<Technique> technique_;
     /// Quality level.
@@ -67,7 +70,7 @@ struct TechniqueEntry
 class URHO3D_API Material : public Resource
 {
     OBJECT(Material);
-    
+
 public:
     /// Construct.
     Material(Context* context);
@@ -75,12 +78,12 @@ public:
     ~Material();
     /// Register object factory.
     static void RegisterObject(Context* context);
-    
+
     /// Load resource. Return true if successful.
     virtual bool Load(Deserializer& source);
     /// Save resource. Return true if successful.
     virtual bool Save(Serializer& dest) const;
-    
+
     /// Load from an XML element. Return true if successful.
     bool Load(const XMLElement& source);
     /// Save to an XML element. Return true if successful.
@@ -91,6 +94,12 @@ public:
     void SetTechnique(unsigned index, Technique* tech, unsigned qualityLevel = 0, float lodDistance = 0.0f);
     /// Set shader parameter.
     void SetShaderParameter(const String& name, const Variant& value);
+    /// Set shader paramter animation.
+    void SetShaderParameterAnimation(const String& name, ValueAnimation* animation, WrapMode wrapMode = WM_LOOP, float speed = 1.0f);
+    /// Set shader paramter animation.
+    void SetShaderParameterAnimationWrapMode(const String& name, WrapMode wrapMode);
+    /// Set shader paramter animation.
+    void SetShaderParameterAnimationSpeed(const String& name, float speed);
     /// Set texture.
     void SetTexture(TextureUnit unit, Texture* texture);
     /// Set texture coordinate transform.
@@ -113,7 +122,9 @@ public:
     void SortTechniques();
     /// Mark material for auxiliary view rendering.
     void MarkForAuxView(unsigned frameNumber);
-    
+    /// Update shader parameter animations.
+    void UpdateShaderParameterAnimations();
+
     /// Return number of techniques.
     unsigned GetNumTechniques() const { return techniques_.Size(); }
     /// Return all techniques.
@@ -130,6 +141,12 @@ public:
     const SharedPtr<Texture>* GetTextures() const { return &textures_[0]; }
     /// Return shader parameter.
     const Variant& GetShaderParameter(const String& name) const;
+    /// Return shader parameter animation.
+    ValueAnimation* GetShaderParameterAnimation(const String& name) const;
+    /// Return shader parameter animation wrap mode.
+    WrapMode GetShaderParameterAnimationWrapMode(const String& name) const;
+    /// Return shader parameter animation speed.
+    float GetShaderParameterAnimationSpeed(const String& name) const;
     /// Return all shader parameters.
     const HashMap<StringHash, MaterialShaderParameter>& GetShaderParameters() const { return shaderParameters_; }
     /// Return normal culling mode.
@@ -144,12 +161,12 @@ public:
     bool GetOcclusion() const { return occlusion_; }
     /// Return whether should render specular.
     bool GetSpecular() const { return specular_; }
-    
+
     /// Return name for texture unit.
     static String GetTextureUnitName(TextureUnit unit);
     /// Parse a shader parameter value from a string. Retunrs either a bool, a float, or a 2 to 4-component vector.
     static Variant ParseShaderParameterValue(const String& value);
-    
+
 private:
     /// Re-evaluate occlusion rendering.
     void CheckOcclusion();
@@ -157,13 +174,17 @@ private:
     void ResetToDefaults();
     /// Recalculate the memory used by the material.
     void RefreshMemoryUse();
-    
+    /// Return shader parameter animation instance.
+    MaterialShaderParameterAnimationInstance* GetMaterialShaderParameterAnimationInstance(const String& name) const;
+
     /// Techniques.
     Vector<TechniqueEntry> techniques_;
     /// Textures.
     SharedPtr<Texture> textures_[MAX_MATERIAL_TEXTURE_UNITS];
     /// %Shader parameters.
     HashMap<StringHash, MaterialShaderParameter> shaderParameters_;
+    /// %Shader parameters animation infos.
+    HashMap<StringHash, SharedPtr<MaterialShaderParameterAnimationInstance> > materialShaderParameterAnimationInstances_;
     /// Normal culling mode.
     CullMode cullMode_;
     /// Culling mode for shadow rendering.
@@ -176,6 +197,9 @@ private:
     bool occlusion_;
     /// Specular lighting flag.
     bool specular_;
+    /// Material update frame number.
+    unsigned frameNumber_;
+
 };
 
 }

+ 86 - 0
Source/Engine/Graphics/MaterialShaderParameterAnimationInstance.cpp

@@ -0,0 +1,86 @@
+//
+// Copyright (c) 2008-2014 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "Precompiled.h"
+#include "Material.h"
+#include "ValueAnimation.h"
+#include "MaterialShaderParameterAnimationInstance.h"
+
+#include "DebugNew.h"
+
+namespace Urho3D
+{
+
+MaterialShaderParameterAnimationInstance::MaterialShaderParameterAnimationInstance(Material* material, const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode, float speed) :
+    ValueAnimationInfo(attributeAnimation, wrapMode, speed),
+    material_(material),
+    name_(name),
+    currentTime_(0.0f),
+    lastScaledTime_(0.0f)
+{
+}
+
+MaterialShaderParameterAnimationInstance::MaterialShaderParameterAnimationInstance(const MaterialShaderParameterAnimationInstance& other) :
+    ValueAnimationInfo(other),
+    material_(other.material_),
+    name_(other.name_),
+    currentTime_(0.0f),
+    lastScaledTime_(0.0f)
+{
+}
+
+MaterialShaderParameterAnimationInstance::~MaterialShaderParameterAnimationInstance()
+{
+}
+
+bool MaterialShaderParameterAnimationInstance::Update(float timeStep)
+{
+    if (!animation_)
+        return true;
+
+    currentTime_ += timeStep * speed_;
+
+    if (!animation_->IsValid())
+        return true;
+
+    bool finished = false;
+
+    // Calculate scale time by wrap mode
+    float scaledTime = CalculateScaledTime(currentTime_, finished);
+
+    material_->SetShaderParameter(name_, animation_->GetAnimationValue(scaledTime));
+
+    if (animation_->HasEventFrames())
+    {
+        PODVector<const VAnimEventFrame*> eventFrames;
+        GetEventFrames(lastScaledTime_, scaledTime, eventFrames);
+
+        for (unsigned i = 0; i < eventFrames.Size(); ++i)
+            material_->SendEvent(eventFrames[i]->eventType_, const_cast<VariantMap&>(eventFrames[i]->eventData_));
+    }
+
+    lastScaledTime_ = scaledTime;
+
+    return finished;
+}
+
+}

+ 64 - 0
Source/Engine/Graphics/MaterialShaderParameterAnimationInstance.h

@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2008-2014 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "ValueAnimationInfo.h"
+
+namespace Urho3D
+{
+
+class Material;
+
+/// Material shader parameter animation instance.
+class URHO3D_API MaterialShaderParameterAnimationInstance : public ValueAnimationInfo
+{
+public:
+    /// Construct.
+    MaterialShaderParameterAnimationInstance(Material* material, const String& name, ValueAnimation* attributeAnimation, WrapMode wrapMode, float speed);
+    /// Copy construct.
+    MaterialShaderParameterAnimationInstance(const MaterialShaderParameterAnimationInstance& other);
+    /// Destruct.
+    ~MaterialShaderParameterAnimationInstance();
+
+    /// Update. Return true when the animation is finished.
+    bool Update(float timeStep);
+
+    /// Return material.
+    Material* GetMaterial() const { return material_; }
+    /// Return shader parameter name.
+    const String& GetName() const { return name_; }
+    /// Return current time.
+    float GetCurrentTime() const { return currentTime_; }
+
+private:
+    /// Material.
+    WeakPtr<Material> material_;
+    /// Shader parameter name.
+    String name_;
+    /// Current time.
+    float currentTime_;
+    /// Last scaled time.
+    float lastScaledTime_;
+};
+
+}