Explorar el Código

Add simple attribute animation system, and change StaticScene to test it.

aster2013 hace 11 años
padre
commit
b1b9c34c11

+ 107 - 0
Source/Engine/Scene/AttributeAnimation.cpp

@@ -0,0 +1,107 @@
+//
+// 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 "AttributeAnimation.h"
+
+#include "DebugNew.h"
+
+namespace Urho3D
+{
+
+AttributeAnimation::AttributeAnimation(Context* context) :
+    Serializable(context),
+    animationMode_(AM_LOOP)
+{
+}
+
+AttributeAnimation::~AttributeAnimation()
+{
+}
+
+void AttributeAnimation::SetAnimationMode(AnimationMode animationMode)
+{
+    animationMode_ = animationMode;
+}
+
+void AttributeAnimation::AddKeyFrame(float time, const Variant& value)
+{
+    KeyFrame keyFrame;
+    keyFrame.time_ = time;
+    keyFrame.value_ = value;
+
+    keyframes_.Push(keyFrame);
+}
+
+VariantType AttributeAnimation::GetValueType() const
+{
+    return keyframes_.Empty() ? VAR_NONE : keyframes_[0].value_.GetType();
+}
+
+void AttributeAnimation::GetValue(float animationTime, Variant& animationValue) const
+{
+    if (keyframes_.Empty())
+        return;
+
+    float keyTime = CalculateTime(animationTime, keyframes_.Back().time_);
+
+    for (unsigned i = 1; i < keyframes_.Size(); ++i)
+    {
+        if (keyframes_[i].time_ > keyTime)
+        {
+            // Hack here
+            if (GetValueType() == VAR_COLOR)
+            {
+                float t = (keyTime - keyframes_[i - 1].time_) / (keyframes_[i].time_ - keyframes_[i - 1].time_);
+                animationValue = keyframes_[i - 1].value_.GetColor().Lerp(keyframes_[i].value_.GetColor(), t);
+            }
+            else
+                animationValue = keyframes_[i - 1].value_;
+
+            break;
+        }
+    }
+}
+
+float AttributeAnimation::CalculateTime(float animationTime, float totalTime) const
+{
+    switch (animationMode_)
+    {
+    case AM_LOOP:
+        return fmodf(animationTime, totalTime);
+
+    case AM_CLAMP:
+        return Clamp(animationTime, 0.0f, totalTime);
+
+    case AM_PINGPONG:
+        {
+            float doubleTotalTime = totalTime * 2.0f;
+            float fract = fmodf(animationTime, doubleTotalTime);
+            return (fract < totalTime) ? fract : doubleTotalTime - fract;
+        }
+        break;
+    }
+
+    return animationTime;
+}
+
+}

+ 88 - 0
Source/Engine/Scene/AttributeAnimation.h

@@ -0,0 +1,88 @@
+//
+// 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 "Serializable.h"
+#include "Variant.h"
+
+namespace Urho3D
+{
+
+class SceneObject;
+
+/// Animation mode.
+enum AnimationMode
+{
+    /// Loop mode.
+    AM_LOOP = 0,
+    /// Clamp mode.
+    AM_CLAMP,
+    /// Pingpong Mode.
+    AM_PINGPONG,
+};
+
+/// Base class for attribute animation.
+class URHO3D_API AttributeAnimation : public Serializable
+{
+    OBJECT(AttributeAnimation);
+
+public:
+    /// Construct.
+    AttributeAnimation(Context* context);
+    /// Destruct.
+    virtual ~AttributeAnimation();
+
+    /// Set animation mode.
+    void SetAnimationMode(AnimationMode animationMode_);
+    /// Add key frame (please add in order).
+    void AddKeyFrame(float time, const Variant& value);
+
+    /// Return value type.
+    VariantType GetValueType() const;
+    /// Return Animation mode.
+    AnimationMode GetAnimationMode() const { return animationMode_; }
+    /// Get value by animation time.
+    void GetValue(float animationTime, Variant& animationValue) const;
+
+protected:
+    /// Calculate time according to the animation mode.
+    float CalculateTime(float animationTime, float totalTime) const;
+
+    /// Animation mode.
+    AnimationMode animationMode_;
+
+    /// Key frame
+    struct KeyFrame
+    {
+        /// Time.
+        float time_;
+        /// Value.
+        Variant value_;
+    };
+    /// Key frames.
+    Vector<KeyFrame> keyframes_;
+    
+
+};
+
+}

+ 4 - 4
Source/Engine/Scene/Component.cpp

@@ -33,7 +33,7 @@ namespace Urho3D
 {
 
 Component::Component(Context* context) :
-    Serializable(context),
+    SceneObject(context),
     node_(0),
     id_(0),
     networkUpdate_(false),
@@ -47,7 +47,7 @@ Component::~Component()
 
 void Component::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
-    Serializable::OnSetAttribute(attr, src);
+    SceneObject::OnSetAttribute(attr, src);
     MarkNetworkUpdate();
 }
 
@@ -60,7 +60,7 @@ bool Component::Save(Serializer& dest) const
         return false;
 
     // Write attributes
-    return Serializable::Save(dest);
+    return SceneObject::Save(dest);
 }
 
 bool Component::SaveXML(XMLElement& dest) const
@@ -72,7 +72,7 @@ bool Component::SaveXML(XMLElement& dest) const
         return false;
 
     // Write attributes
-    return Serializable::SaveXML(dest);
+    return SceneObject::SaveXML(dest);
 }
 
 void Component::SetEnabled(bool enable)

+ 2 - 2
Source/Engine/Scene/Component.h

@@ -22,7 +22,7 @@
 
 #pragma once
 
-#include "Serializable.h"
+#include "SceneObject.h"
 
 namespace Urho3D
 {
@@ -34,7 +34,7 @@ class Scene;
 struct ComponentReplicationState;
 
 /// Base class for components. Components can be created to scene nodes.
-class URHO3D_API Component : public Serializable
+class URHO3D_API Component : public SceneObject
 {
     OBJECT(Component);
     BASEOBJECT(Component);

+ 6 - 6
Source/Engine/Scene/Node.cpp

@@ -39,7 +39,7 @@ namespace Urho3D
 {
 
 Node::Node(Context* context) :
-    Serializable(context),
+    SceneObject(context),
     worldTransform_(Matrix3x4::IDENTITY),
     dirty_(false),
     networkUpdate_(false),
@@ -82,7 +82,7 @@ void Node::RegisterObject(Context* context)
 
 void Node::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
 {
-    Serializable::OnSetAttribute(attr, src);
+    SceneObject::OnSetAttribute(attr, src);
     MarkNetworkUpdate();
 }
 
@@ -112,7 +112,7 @@ bool Node::Save(Serializer& dest) const
         return false;
 
     // Write attributes
-    if (!Serializable::Save(dest))
+    if (!SceneObject::Save(dest))
         return false;
 
     // Write components
@@ -172,7 +172,7 @@ bool Node::SaveXML(XMLElement& dest) const
         return false;
 
     // Write attributes
-    if (!Serializable::SaveXML(dest))
+    if (!SceneObject::SaveXML(dest))
         return false;
 
     // Write components
@@ -1055,7 +1055,7 @@ bool Node::Load(Deserializer& source, SceneResolver& resolver, bool readChildren
     RemoveAllComponents();
 
     // ID has been read at the parent level
-    if (!Serializable::Load(source))
+    if (!SceneObject::Load(source))
         return false;
 
     unsigned numComponents = source.ReadVLE();
@@ -1098,7 +1098,7 @@ bool Node::LoadXML(const XMLElement& source, SceneResolver& resolver, bool readC
     RemoveAllChildren();
     RemoveAllComponents();
 
-    if (!Serializable::LoadXML(source))
+    if (!SceneObject::LoadXML(source))
         return false;
 
     XMLElement compElem = source.GetChild("component");

+ 4 - 4
Source/Engine/Scene/Node.h

@@ -23,7 +23,7 @@
 #pragma once
 
 #include "Matrix3x4.h"
-#include "Serializable.h"
+#include "SceneObject.h"
 #include "VectorBuffer.h"
 
 namespace Urho3D
@@ -44,7 +44,7 @@ enum CreateMode
 };
 
 /// %Scene node that may contain components and child nodes.
-class URHO3D_API Node : public Serializable
+class URHO3D_API Node : public SceneObject
 {
     OBJECT(Node);
     BASEOBJECT(Node);
@@ -75,6 +75,8 @@ public:
     virtual bool SaveDefaultAttributes() const { return true; }
     /// Add a replication state that is tracking this node.
     virtual void AddReplicationState(NodeReplicationState* state);
+    /// Return scene.
+    virtual Scene* GetScene() const { return scene_; }
 
     /// Save to an XML file. Return true if successful.
     bool SaveXML(Serializer& dest) const;
@@ -187,8 +189,6 @@ public:
     StringHash GetNameHash() const { return nameHash_; }
     /// Return parent scene node.
     Node* GetParent() const { return parent_; }
-    /// Return scene.
-    Scene* GetScene() const { return scene_; }
     /// Return whether is enabled. Disables nodes effectively disable all their components.
     bool IsEnabled() const { return enabled_; }
     /// Return owner connection in networking.

+ 127 - 0
Source/Engine/Scene/SceneObject.cpp

@@ -0,0 +1,127 @@
+//
+// 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 "AttributeAnimation.h"
+#include "Log.h"
+#include "Scene.h"
+#include "SceneEvents.h"
+#include "SceneObject.h"
+
+#include "DebugNew.h"
+
+namespace Urho3D
+{
+
+SceneObject::SceneObject(Context* context) :
+    Serializable(context),
+    animationTime_(0.0f)
+{
+}
+
+SceneObject::~SceneObject()
+{
+}
+
+void SceneObject::SetAttributeAnimation(const String& name, AttributeAnimation* animation)
+{
+    if (!animation)
+    {
+        for (HashMap<const AttributeInfo*, SharedPtr<AttributeAnimation> >::Iterator i = attributeAnimations_.Begin(); i != attributeAnimations_.End(); ++i)
+        {
+            if (i->first_->name_.Contains(name, true))
+            {
+                attributeAnimations_.Erase(i);
+                break;
+            }
+        }
+
+        if (attributeAnimations_.Empty())
+            UnsubscribeFromEvent(GetScene(), E_SCENEPOSTUPDATE);
+    }
+    else
+    {
+        const Vector<AttributeInfo>* attributes = GetAttributes();
+        if (!attributes)
+        {
+            LOGERROR(GetTypeName() + " has no attributes");
+            return;
+        }
+
+        for (Vector<AttributeInfo>::ConstIterator i = attributes->Begin(); i != attributes->End(); ++i)
+        {
+            const AttributeInfo* attributeInfo = &(*i);
+            if (!attributeInfo->name_.Compare(name, true))
+            {
+                // Check that the new value's type matches the attribute type
+                if (animation->GetValueType() == attributeInfo->type_)
+                {
+                    if (attributeAnimations_.Empty())
+                    {
+                        // Reset anmation time
+                        animationTime_ = 0.0f;
+
+                        SubscribeToEvent(GetScene(), E_SCENEPOSTUPDATE, HANDLER(SceneObject, HandleScenePostUpdate));
+                    }
+
+                    attributeAnimations_[attributeInfo] = SharedPtr<AttributeAnimation>(animation);
+                    return;
+                }
+            }
+        }
+
+        LOGERROR("Could not find attribute " + name + " in " + GetTypeName());
+    }
+}
+
+AttributeAnimation* SceneObject::GetAttributeAnimation(const String& name) const
+{
+    for (HashMap<const AttributeInfo*, SharedPtr<AttributeAnimation> >::ConstIterator i = attributeAnimations_.Begin(); i != attributeAnimations_.End(); ++i)
+    {
+        if (i->first_->name_.Contains(name, true))
+            return i->second_;
+    }
+
+    return 0;
+}
+
+void SceneObject::UpdateAttributeAnimations(float timeStep)
+{
+    animationTime_ += timeStep;
+
+    for (HashMap<const AttributeInfo*, SharedPtr<AttributeAnimation> >::Iterator i = attributeAnimations_.Begin(); i != attributeAnimations_.End(); ++i)
+    {
+        Variant animationValue;
+        i->second_->GetValue(animationTime_, animationValue);
+
+        OnSetAttribute(*i->first_, animationValue);
+    }
+}
+
+void SceneObject::HandleScenePostUpdate(StringHash eventType, VariantMap& eventData)
+{
+    using namespace ScenePostUpdate;
+    
+    UpdateAttributeAnimations(eventData[P_TIMESTEP].GetFloat());
+}
+
+}

+ 65 - 0
Source/Engine/Scene/SceneObject.h

@@ -0,0 +1,65 @@
+//
+// 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 "Serializable.h"
+
+namespace Urho3D
+{
+
+class AttributeAnimation;
+class Scene;
+
+/// Base class for scene objects.
+class URHO3D_API SceneObject : public Serializable
+{
+    OBJECT(SceneObject);
+
+public:
+    /// Construct.
+    SceneObject(Context* context);
+    /// Destruct.
+    virtual ~SceneObject();
+
+    /// Return scene.
+    virtual Scene* GetScene() const = 0;
+
+    /// Add attribute animation.
+    void SetAttributeAnimation(const String& name, AttributeAnimation* animation);
+    /// Get attribute animation.
+    AttributeAnimation* GetAttributeAnimation(const String& name) const;
+
+private:
+    /// Update attribute animations.
+    void UpdateAttributeAnimations(float timeStep);
+    /// Handle scene post-update event.
+    void HandleScenePostUpdate(StringHash eventType, VariantMap& eventData);
+
+    /// Animation time.
+    float animationTime_;
+    /// Attribute animations.
+    HashMap<const AttributeInfo*, SharedPtr<AttributeAnimation> > attributeAnimations_;
+
+};
+
+}

+ 9 - 1
Source/Samples/04_StaticScene/StaticScene.cpp

@@ -20,6 +20,7 @@
 // THE SOFTWARE.
 //
 
+#include "AttributeAnimation.h"
 #include "Camera.h"
 #include "CoreEvents.h"
 #include "Engine.h"
@@ -95,7 +96,14 @@ void StaticScene::CreateScene()
     lightNode->SetDirection(Vector3(0.6f, -1.0f, 0.8f)); // The direction vector does not need to be normalized
     Light* light = lightNode->CreateComponent<Light>();
     light->SetLightType(LIGHT_DIRECTIONAL);
-    
+
+    AttributeAnimation* lightColorAnimation = new AttributeAnimation(context_);
+    lightColorAnimation->AddKeyFrame(0.0f, Color(1.0f, 1.0f, 1.0f, 1.0f));
+    lightColorAnimation->AddKeyFrame(1.0f, Color(1.0f, 0.0f, 0.0f, 1.0f));
+    lightColorAnimation->AddKeyFrame(2.0f, Color(0.0f, 0.0f, 1.0f, 1.0f));
+    lightColorAnimation->AddKeyFrame(3.0f, Color(1.0f, 1.0f, 1.0f, 1.0f));    
+    light->SetAttributeAnimation("Color", lightColorAnimation);
+
     // Create more StaticModel objects to the scene, randomly positioned, rotated and scaled. For rotation, we construct a
     // quaternion from Euler angles where the Y angle (rotation about the Y axis) is randomized. The mushroom model contains
     // LOD levels, so the StaticModel component will automatically select the LOD level according to the view distance (you'll