Browse Source

Add SpriteSheet2D and StaticSprite2D.

aster2013 11 years ago
parent
commit
6af6a5412a

+ 208 - 0
Source/Engine/Urho2D/SpriteSheet2D.cpp

@@ -0,0 +1,208 @@
+//
+// 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 "Context.h"
+#include "Deserializer.h"
+#include "Log.h"
+#include "ResourceCache.h"
+#include "Serializer.h"
+#include "Sprite2D.h"
+#include "SpriteSheet2D.h"
+#include "Texture2D.h"
+#include "XMLFile.h"
+
+#include "DebugNew.h"
+
+
+namespace Urho3D
+{
+
+SpriteSheet2D::SpriteSheet2D(Context* context) : Resource(context)
+{
+
+}
+
+SpriteSheet2D::~SpriteSheet2D()
+{
+
+}
+
+void SpriteSheet2D::RegisterObject(Context* context)
+{
+    context->RegisterFactory<SpriteSheet2D>();
+}
+
+bool SpriteSheet2D::Load(Deserializer& source)
+{
+    spriteMapping_.Clear();
+
+    SharedPtr<XMLFile> xmlFile(new XMLFile(context_));
+    if(!xmlFile->Load(source))
+    {
+        LOGERROR("Could not load sprite sheet");
+        return false;
+    }
+
+    SetMemoryUse(source.GetSize());
+
+    XMLElement rootElem = xmlFile->GetRoot();
+    if (!rootElem)
+    {
+        LOGERROR("Invalid sprite sheet");
+        return false;
+    }
+
+    if (rootElem.GetName() == "SpriteSheet")
+    {
+        ResourceCache* cache = GetSubsystem<ResourceCache>();
+        texture_ = cache->GetResource<Texture2D>(rootElem.GetAttribute("texture"));
+        if (!texture_)
+        {
+            LOGERROR("Cound not load texture");
+            return false;
+        }
+
+        XMLElement spriteElem = rootElem.GetChild("Sprite");
+        while (spriteElem)
+        {
+            String name = spriteElem.GetAttribute("name");
+            IntRect rectangle = spriteElem.GetIntRect("rectangle");
+            
+            Vector2 hotSpot(0.5f, 0.5f);
+            if (spriteElem.HasAttribute("hotSpot"))
+                hotSpot = spriteElem.GetVector2("hotSpot");
+
+            DefineSprite(name, rectangle, hotSpot);
+
+            spriteElem = spriteElem.GetNext("Sprite");
+        }
+    }
+    // Sparrow Starling texture atlas
+    else if (rootElem.GetName() == "TextureAtlas")
+    {    
+        ResourceCache* cache = GetSubsystem<ResourceCache>();
+        texture_ = cache->GetResource<Texture2D>(rootElem.GetAttribute("imagePath"));
+        if (!texture_)
+        {
+            LOGERROR("Cound not load texture");
+            return false;
+        }
+
+        XMLElement subTextureElem = rootElem.GetChild("SubTexture");
+        while (subTextureElem)
+        {
+            String name = subTextureElem.GetAttribute("name");
+
+            int x = subTextureElem.GetInt("x");
+            int y = subTextureElem.GetInt("y");
+            int width = subTextureElem.GetInt("width");
+            int height = subTextureElem.GetInt("height");
+            IntRect rectangle(x, y, x + width, y + height);
+
+            Vector2 hotSpot(0.5f, 0.5f);
+            if (subTextureElem.HasAttribute("frameWidth") && subTextureElem.HasAttribute("frameHeight"))
+            {
+                int frameX = subTextureElem.GetInt("frameX");
+                int frameY = subTextureElem.GetInt("frameY");
+                int frameWidth = subTextureElem.GetInt("frameWidth");
+                int frameHeight = subTextureElem.GetInt("frameHeight");
+                hotSpot.x_ = ((float)frameX + frameWidth / 2) / width;
+                hotSpot.y_ = ((float)frameY + frameHeight / 2) / height;
+            }
+
+            DefineSprite(name, rectangle, hotSpot);
+
+            subTextureElem = subTextureElem.GetNext("SubTexture");
+        }
+    }
+    else
+    {
+        LOGERROR("Invalid sprite sheet file");
+        return false;
+    }
+
+    return true;
+}
+
+bool SpriteSheet2D::Save(Serializer& dest) const
+{
+    if (!texture_)
+        return false;
+    
+    SharedPtr<XMLFile> xmlFile(new XMLFile(context_));    
+    XMLElement rootElem = xmlFile->CreateRoot("SpriteSheet");
+    rootElem.SetAttribute("texture", texture_->GetName());
+
+    for (HashMap<String, SharedPtr<Sprite2D> >::ConstIterator i = spriteMapping_.Begin(); i != spriteMapping_.End(); ++i)
+    {
+        XMLElement spriteElem = rootElem.CreateChild("Sprite");
+        spriteElem.SetAttribute("name", i->first_);
+        Sprite2D* sprite = i->second_;
+        spriteElem.SetIntRect("rectangle", sprite->GetRectangle());
+        spriteElem.SetVector2("hotSpot", sprite->GetHotSpot());
+    }
+
+    return xmlFile->Save(dest);
+}
+
+Sprite2D* SpriteSheet2D::GetSprite(const String& name) const
+{
+    HashMap<String, SharedPtr<Sprite2D> >::ConstIterator i = spriteMapping_.Find(name);
+    if (i == spriteMapping_.End())
+        return 0;
+
+    return i->second_;
+}
+
+void SpriteSheet2D::DefineSprite(const String& name, const IntRect& rectangle, const Vector2& hotSpot)
+{
+    if (!texture_)
+        return;
+
+    if (GetSprite(name))
+        return;
+
+    SharedPtr<Sprite2D> sprite(new Sprite2D(context_));
+    sprite->SetName(name);
+    sprite->SetTexture(texture_);
+    sprite->SetRectangle(rectangle);
+    sprite->SetHotSpot(hotSpot);
+    sprite->SetSpriteSheet(this);
+
+    spriteMapping_[name] = sprite;
+}
+
+void SpriteSheet2D::UpdateSprite(const String& name, const IntRect& rectangle, const Vector2& hotSpot)
+{
+    if (!texture_)
+        return;
+
+    Sprite2D* sprite = GetSprite(name);
+    if (sprite)
+    {
+        sprite->SetRectangle(rectangle);
+        sprite->SetHotSpot(hotSpot);
+    }
+}
+
+}

+ 70 - 0
Source/Engine/Urho2D/SpriteSheet2D.h

@@ -0,0 +1,70 @@
+//
+// 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 "Resource.h"
+
+namespace Urho3D
+{
+
+class Sprite2D;
+class Texture2D;
+
+/// Sprite sheet.
+class URHO3D_API SpriteSheet2D : public Resource
+{
+    OBJECT(SpriteSheet2D);
+
+public:
+    /// Construct.
+    SpriteSheet2D(Context* context);
+    /// Destruct.
+    virtual ~SpriteSheet2D();
+    /// 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;
+
+    /// Return texture.
+    Texture2D* GetTexture() const { return texture_; }
+    /// Return sprite.
+    Sprite2D* GetSprite(const String& name) const;
+    /// Define sprite.
+    void DefineSprite(const String& name, const IntRect& rectangle, const Vector2& hotSpot = Vector2(0.5f, 0.5f));
+    /// Update sprite.
+    void UpdateSprite(const String& name, const IntRect& rectangle, const Vector2& hotSpot = Vector2(0.5f, 0.5f));
+
+    /// Return sprite mapping.
+    const HashMap<String, SharedPtr<Sprite2D> >& GetSpriteMapping() const { return spriteMapping_; }
+
+private:
+    /// Texture.
+    SharedPtr<Texture2D> texture_;
+    /// Sprite mapping.
+    HashMap<String, SharedPtr<Sprite2D> > spriteMapping_;
+};
+
+}

+ 170 - 0
Source/Engine/Urho2D/StaticSprite2D.cpp

@@ -0,0 +1,170 @@
+//
+// 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 "Context.h"
+#include "Sprite2D.h"
+#include "StaticSprite2D.h"
+#include "Texture2D.h"
+
+#include "DebugNew.h"
+
+namespace Urho3D
+{
+
+extern const char* URHO2D_CATEGORY;
+
+StaticSprite2D::StaticSprite2D(Context* context) : Drawable2D(context),
+    flipX_(false),
+    flipY_(false),
+    color_(Color::WHITE)
+{
+    vertices_.Reserve(6);
+}
+
+StaticSprite2D::~StaticSprite2D()
+{
+}
+
+void StaticSprite2D::RegisterObject(Context* context)
+{
+    context->RegisterFactory<StaticSprite2D>(URHO2D_CATEGORY);
+    ACCESSOR_ATTRIBUTE(StaticSprite2D, VAR_BOOL, "Flip X", GetFlipX, SetFlipX, bool, false, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(StaticSprite2D, VAR_BOOL, "Flip Y", GetFlipY, SetFlipY, bool, false, AM_DEFAULT);
+    REF_ACCESSOR_ATTRIBUTE(StaticSprite2D, VAR_COLOR, "Color", GetColor, SetColor, Color, Color::WHITE, AM_DEFAULT);
+    COPY_BASE_ATTRIBUTES(StaticSprite2D, Drawable2D);
+}
+
+void StaticSprite2D::SetFlip(bool flipX, bool flipY)
+{
+    if (flipX_ == flipX && flipY_ == flipY)
+        return;
+
+    flipX_ = flipX;
+    flipY_ = flipY;
+    MarkVerticesDirty();
+    MarkGeometryDirty();
+}
+
+void StaticSprite2D::SetFlipX(bool flipX)
+{
+    SetFlip(flipX, flipY_);
+}
+
+void StaticSprite2D::SetFlipY(bool flipY)
+{
+    SetFlip(flipX_, flipY);
+}
+
+void StaticSprite2D::SetColor(const Color& color)
+{
+    color_ = color;
+    MarkVerticesDirty();
+    MarkGeometryDirty();
+}
+
+void StaticSprite2D::UpdateVertices()
+{
+    if (!verticesDirty_)
+        return;
+
+    vertices_.Clear();
+
+    if (!sprite_)
+        return;
+
+    Texture2D* texture = sprite_->GetTexture();
+    if (!texture)
+        return;
+
+    const IntRect& rectangle_ = sprite_->GetRectangle();
+    if (rectangle_.Width() == 0 || rectangle_.Height() == 0)
+        return;
+
+    /*
+    V1 --------V2
+    |         / |
+    |       /   |
+    |     /     |
+    |   /       |
+    | /         |
+    V0 --------V3
+    */
+    Vertex2D vertex0;
+    Vertex2D vertex1;
+    Vertex2D vertex2;
+    Vertex2D vertex3;
+
+    float pixelPerUnit = 1.0f / unitPerPixel_;
+    float width = (float)rectangle_.Width() * pixelPerUnit;
+    float height = (float)rectangle_.Height() * pixelPerUnit;
+
+    const Vector2& hotSpot = sprite_->GetHotSpot();
+    float hotSpotX = flipX_ ? (1.0f - hotSpot.x_) : hotSpot.x_;
+    float hotSpotY = flipY_ ? (1.0f - hotSpot.y_) : hotSpot.y_;
+
+    float leftX = -width * hotSpotX;
+    float rightX = width * (1.0f - hotSpotX);
+    float bottomY = -height * hotSpotY;
+    float topY = height * (1.0f - hotSpotY);
+    vertex0.position_ = Vector3(leftX, bottomY, zValue_);
+    vertex1.position_ = Vector3(leftX, topY, zValue_);
+    vertex2.position_ = Vector3(rightX, topY, zValue_);
+    vertex3.position_ = Vector3(rightX, bottomY, zValue_);
+
+    float invTexW = 1.0f / (float)texture->GetWidth();
+    float invTexH = 1.0f / (float)texture->GetHeight();
+
+    float leftU = rectangle_.left_ * invTexW;
+    float rightU = rectangle_.right_ * invTexW;
+    float topV = rectangle_.top_ * invTexH;    
+    float bottomV = rectangle_.bottom_ * invTexH;
+    vertex0.uv_ = Vector2(leftU, bottomV);
+    vertex1.uv_ = Vector2(leftU, topV);
+    vertex2.uv_ = Vector2(rightU, topV);
+    vertex3.uv_ = Vector2(rightU, bottomV);
+
+    if (flipX_)
+    {
+        Swap(vertex0.uv_.x_, vertex3.uv_.x_);
+        Swap(vertex1.uv_.x_, vertex2.uv_.x_);
+    }
+    
+    if (flipY_)
+    {
+        Swap(vertex0.uv_.y_, vertex1.uv_.y_);
+        Swap(vertex2.uv_.y_, vertex3.uv_.y_);
+    }
+
+    vertex0.color_ = vertex1.color_ = vertex2.color_  = vertex3.color_ = color_.ToUInt();
+
+    vertices_.Push(vertex0);
+    vertices_.Push(vertex1);
+    vertices_.Push(vertex2);
+    vertices_.Push(vertex3);
+
+    MarkGeometryDirty();
+
+    verticesDirty_ = false;
+}
+
+}

+ 72 - 0
Source/Engine/Urho2D/StaticSprite2D.h

@@ -0,0 +1,72 @@
+//
+// 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 "Drawable2D.h"
+
+namespace Urho3D
+{
+
+/// Static sprite component.
+class URHO3D_API StaticSprite2D : public Drawable2D
+{
+    OBJECT(StaticSprite2D);
+
+public:
+    /// Construct.
+    StaticSprite2D(Context* context);
+    /// Destruct.
+    ~StaticSprite2D();
+    /// Register object factory. Drawable2D must be registered first.
+    static void RegisterObject(Context* context);
+
+    /// Set flip.
+    void SetFlip(bool flipX, bool flipY);
+    /// Set flip X.
+    void SetFlipX(bool flipX);
+    /// Set flip Y.
+    void SetFlipY(bool flipY);
+    /// Set color.
+    void SetColor(const Color& color);
+
+    /// Return flip X.
+    bool GetFlipX() const { return flipX_; }
+    /// Return flip Y.
+    bool GetFlipY() const { return flipY_; }
+    /// Return color.
+    const Color& GetColor() const { return color_; }
+
+protected:
+    /// Update vertices.
+    virtual void UpdateVertices();
+
+    /// Flip X.
+    bool flipX_;
+    /// Flip Y.
+    bool flipY_;
+    /// Color.
+    Color color_;
+};
+
+}
+