Przeglądaj źródła

Add Sprite2D and Drawable2D.

aster2013 11 lat temu
rodzic
commit
232c096d9a

+ 1 - 1
Source/CMake/Modules/FindUrho3D.cmake

@@ -63,7 +63,7 @@ if (URHO3D_HOME)
     if (SOURCE_TREE_PATH)
     if (SOURCE_TREE_PATH)
         get_filename_component (SOURCE_TREE_PATH ${SOURCE_TREE_PATH} PATH)
         get_filename_component (SOURCE_TREE_PATH ${SOURCE_TREE_PATH} PATH)
         set (URHO3D_INCLUDE_DIRS ${SOURCE_TREE_PATH})
         set (URHO3D_INCLUDE_DIRS ${SOURCE_TREE_PATH})
-        foreach (DIR Audio Container Core Engine Graphics Input IO LuaScript Math Navigation Network Physics Resource Scene Script UI)
+        foreach (DIR Audio Container Core Engine Graphics Input IO LuaScript Math Navigation Network Physics Resource Scene Script UI Urho2D)
             list (APPEND URHO3D_INCLUDE_DIRS ${SOURCE_TREE_PATH}/${DIR})     # Note: variable change to list context after this
             list (APPEND URHO3D_INCLUDE_DIRS ${SOURCE_TREE_PATH}/${DIR})     # Note: variable change to list context after this
         endforeach ()
         endforeach ()
         set (DIRS Bullet/src kNet/include SDL/include)
         set (DIRS Bullet/src kNet/include SDL/include)

+ 295 - 0
Source/Engine/Urho2D/Drawable2D.cpp

@@ -0,0 +1,295 @@
+//
+// 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 "Camera.h"
+#include "Context.h"
+#include "Drawable2D.h"
+#include "Geometry.h"
+#include "Material.h"
+#include "Node.h"
+#include "ResourceCache.h"
+#include "Sprite2D.h"
+#include "SpriteSheet2D.h"
+#include "Technique.h"
+#include "Texture2D.h"
+#include "VertexBuffer.h"
+
+#include "DebugNew.h"
+#include "Log.h"
+
+namespace Urho3D
+{
+
+extern const char* blendModeNames[];
+
+Drawable2D::Drawable2D(Context* context) : Drawable(context, DRAWABLE_GEOMETRY),
+    unitPerPixel_(1.0f),
+    blendMode_(BLEND_REPLACE),
+    zValue_(0.0f),
+    vertexBuffer_(new VertexBuffer(context_)),
+    geometryDirty_(true),
+    materialDirty_(true)
+{
+    geometry_ = new Geometry(context);
+    batches_.Resize(1);
+    batches_[0].geometry_ = geometry_;
+}
+
+Drawable2D::~Drawable2D()
+{
+}
+
+void Drawable2D::RegisterObject(Context* context)
+{
+    ACCESSOR_ATTRIBUTE(Drawable2D, VAR_FLOAT, "Unit Per Pixel", GetUnitPerPixel, SetUnitPerPixel, float, 1.0f, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(Drawable2D, VAR_RESOURCEREF, "Sprite", GetSpriteAttr, SetSpriteAttr, ResourceRef, ResourceRef(Sprite2D::GetTypeStatic()), AM_FILE);
+    ACCESSOR_ATTRIBUTE(Drawable2D, VAR_RESOURCEREF, "Material", GetMaterialAttr, SetMaterialAttr, ResourceRef, ResourceRef(Material::GetTypeStatic()), AM_DEFAULT);
+    ENUM_ACCESSOR_ATTRIBUTE(Drawable2D, "Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, 0, AM_FILE);
+    COPY_BASE_ATTRIBUTES(Drawable2D, Drawable);
+}
+
+void Drawable2D::ApplyAttributes()
+{
+    UpdateVertices();
+    UpdateMaterial(true);
+}
+
+void Drawable2D::UpdateBatches(const FrameInfo& frame)
+{
+    if (materialDirty_)
+        UpdateMaterial();
+
+    const Matrix3x4& worldTransform = node_->GetWorldTransform();
+    distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());
+
+    batches_[0].distance_ = distance_;
+    batches_[0].worldTransform_ = &worldTransform;
+}
+
+void Drawable2D::UpdateGeometry(const FrameInfo& frame)
+{
+    if (!geometryDirty_)
+        return;
+
+    if (verticesDirty_)
+        UpdateVertices();
+
+    if (vertices_.Size() > 0)
+    {
+        unsigned vertexCount = vertices_.Size() / 4 * 6;
+        
+        vertexBuffer_->SetSize(vertexCount, MASK_VERTEX2D);
+        Vertex2D* dest = (Vertex2D*)vertexBuffer_->Lock(0, vertexCount, true);
+        if (dest)
+        {
+            for (unsigned i = 0; i < vertices_.Size(); i += 4)
+            {
+                *(dest++) = vertices_[i + 0];
+                *(dest++) = vertices_[i + 1];
+                *(dest++) = vertices_[i + 2];
+
+                *(dest++) = vertices_[i + 0];
+                *(dest++) = vertices_[i + 2];
+                *(dest++) = vertices_[i + 3];
+            }
+
+            vertexBuffer_->Unlock();
+        }
+        else
+            LOGERROR("Failed to lock vertex buffer");
+        
+        if (geometry_->GetVertexBuffer(0) != vertexBuffer_)
+            geometry_->SetVertexBuffer(0, vertexBuffer_, MASK_VERTEX2D);
+        geometry_->SetDrawRange(TRIANGLE_LIST, 0, 0, 0, vertexCount);
+    }
+    else
+    {
+        if (geometry_->GetVertexBuffer(0) != vertexBuffer_)
+            geometry_->SetVertexBuffer(0, vertexBuffer_, MASK_VERTEX2D);
+        geometry_->SetDrawRange(TRIANGLE_LIST, 0, 0, 0, 0);
+    }
+
+    vertexBuffer_->ClearDataLost();
+    geometryDirty_ = false;
+}
+
+UpdateGeometryType Drawable2D::GetUpdateGeometryType()
+{
+    if (geometryDirty_ || vertexBuffer_->IsDataLost())
+        return UPDATE_MAIN_THREAD;
+    else
+        return UPDATE_NONE;
+}
+
+void Drawable2D::SetUnitPerPixel(float unitPerPixel)
+{
+    unitPerPixel_ = Max(1.0f, unitPerPixel);
+    MarkVerticesDirty();
+    MarkGeometryDirty();
+}
+
+void Drawable2D::SetSprite(Sprite2D* sprite)
+{
+    if (sprite == sprite_)
+        return;
+
+    sprite_ = sprite;
+    MarkVerticesDirty();
+    MarkGeometryDirty();
+    MarkMaterialDirty();
+}
+
+void Drawable2D::SetMaterial(Material* material)
+{
+    if (material_ != material)
+    {
+        material_ = material;
+        MarkMaterialDirty();
+    }
+}
+
+void Drawable2D::SetBlendMode(BlendMode mode)
+{
+    if (blendMode_ != mode)
+    {
+        blendMode_ = mode;
+        MarkMaterialDirty();
+    }
+}
+
+void Drawable2D::SetZValue(float zValue)
+{
+    zValue_ = zValue;
+
+    MarkVerticesDirty();
+    MarkGeometryDirty();
+}
+
+Material* Drawable2D::GetMaterial() const
+{
+    return material_;
+}
+
+void Drawable2D::SetSpriteAttr(ResourceRef value)
+{
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+
+    if (value.type_ == Sprite2D::GetTypeStatic())
+    {
+        SetSprite(cache->GetResource<Sprite2D>(value.name_));
+        return;
+    }
+
+    if (value.type_ == SpriteSheet2D::GetTypeStatic())
+    {
+        // value.name_ include sprite speet name and sprite name.
+        Vector<String> names = value.name_.Split('@');
+        if (names.Size() != 2)
+            return;
+
+        const String& spriteSheetName = names[0];
+        const String& spriteName = names[1];
+
+        SpriteSheet2D* spriteSheet = cache->GetResource<SpriteSheet2D>(spriteSheetName);
+        if (!spriteSheet)
+            return;
+
+        SetSprite(spriteSheet->GetSprite(spriteName));
+    }
+}
+
+ResourceRef Drawable2D::GetSpriteAttr() const
+{
+    SpriteSheet2D* spriteSheet = 0;
+    if (sprite_)
+        spriteSheet = sprite_->GetSpriteSheet();
+
+    if (!spriteSheet)
+        return GetResourceRef(sprite_, Sprite2D::GetTypeStatic());
+
+    // Combine sprite sheet name and sprite name as resource name.
+    return ResourceRef(spriteSheet->GetType(), spriteSheet->GetName() + "@" + sprite_->GetName());
+}
+
+void Drawable2D::SetMaterialAttr(ResourceRef value)
+{
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    SetMaterial(cache->GetResource<Material>(value.name_));
+}
+
+ResourceRef Drawable2D::GetMaterialAttr() const
+{
+    return GetResourceRef(material_, Material::GetTypeStatic());
+}
+
+void Drawable2D::OnWorldBoundingBoxUpdate()
+{
+    if (verticesDirty_)
+    {
+        UpdateVertices();
+
+        boundingBox_.Clear();
+        for (unsigned i = 0; i < vertices_.Size(); ++i)
+            boundingBox_.Merge(vertices_[i].position_);
+    }
+
+    worldBoundingBox_ = boundingBox_.Transformed(node_->GetWorldTransform());
+}
+
+void Drawable2D::UpdateMaterial(bool forceUpdate)
+{
+    if (!materialDirty_ && !forceUpdate)
+        return;
+
+    SharedPtr<Material> material;
+    if (!material_)
+    {
+        material = new Material(context_);
+        Technique* tech = new Technique(context_);
+        Pass* pass = tech->CreatePass(PASS_ALPHA);
+        pass->SetVertexShader("Basic");
+        pass->SetVertexShaderDefines("DIFFMAP VERTEXCOLOR");
+
+        pass->SetPixelShader("Basic");
+        pass->SetPixelShaderDefines("DIFFMAP VERTEXCOLOR");
+        
+        pass->SetBlendMode(blendMode_);
+        pass->SetDepthWrite(false);
+
+        material->SetTechnique(0, tech);
+        material->SetCullMode(CULL_NONE);
+    }
+    else
+        material = material_->Clone();
+
+    if (sprite_)
+    {
+        Texture2D* texture = sprite_->GetTexture();
+        material->SetTexture(TU_DIFFUSE, texture);
+    }
+
+    batches_[0].material_ = material;
+    materialDirty_ = false;
+}
+
+}

+ 129 - 0
Source/Engine/Urho2D/Drawable2D.h

@@ -0,0 +1,129 @@
+//
+// 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 "Drawable.h"
+#include "Sprite2D.h"
+
+namespace Urho3D
+{
+
+class VertexBuffer;
+
+/// Base class for 2D visible components.
+class URHO3D_API Drawable2D : public Drawable
+{
+    OBJECT(Drawable2D);
+
+public:
+    /// Construct.
+    Drawable2D(Context* context);
+    /// Destruct.
+    ~Drawable2D();
+    /// Register object factory. Drawable must be registered first.
+    static void RegisterObject(Context* context);
+
+    /// Apply attribute changes that can not be applied immediately.
+    virtual void ApplyAttributes();
+    /// Calculate distance and prepare batches for rendering. May be called from worker thread(s), possibly re-entrantly.
+    virtual void UpdateBatches(const FrameInfo& frame);
+    /// Prepare geometry for rendering. Called from a worker thread if possible (no GPU update.)
+    virtual void UpdateGeometry(const FrameInfo& frame);
+    /// Return whether a geometry update is necessary, and if it can happen in a worker thread.
+    virtual UpdateGeometryType GetUpdateGeometryType();
+
+    /// Set Unit per pixel.
+    void SetUnitPerPixel(float unitPerPixel);
+    /// Set sprite.
+    void SetSprite(Sprite2D* sprite);
+    /// Set material.
+    void SetMaterial(Material* material);
+    /// Set blend mode.
+    void SetBlendMode(BlendMode mode);
+    /// Set Z value.
+    void SetZValue(float zValue);
+
+    /// Return unit per pixel.
+    float GetUnitPerPixel() const { return unitPerPixel_; }
+    /// Return sprite.
+    Sprite2D* GetSprite() const { return sprite_; }
+    /// Return material.
+    Material* GetMaterial() const;
+    /// Return blend mode.
+    BlendMode GetBlendMode() const { return blendMode_; }
+    /// Return Z value.
+    float GetZValue() const { return zValue_; }
+
+    /// Return all vertices.
+    const Vector<Vertex2D>& GetVertices() const { return vertices_; }
+
+    /// Set sprite attribute.
+    void SetSpriteAttr(ResourceRef value);
+    /// Return sprite attribute.
+    ResourceRef GetSpriteAttr() const;
+    /// Set material attribute.
+    void SetMaterialAttr(ResourceRef value);
+    /// Return material attribute.
+    ResourceRef GetMaterialAttr() const;
+
+protected:
+    /// Recalculate the world-space bounding box.
+    virtual void OnWorldBoundingBoxUpdate();
+    /// Update vertices.
+    virtual void UpdateVertices() = 0;
+    /// Update material.
+    virtual void UpdateMaterial(bool forceUpdate = false);    
+    /// Mark vertices dirty.
+    void MarkVerticesDirty() { verticesDirty_ = true; }
+    /// Mark geometry dirty.
+    void MarkGeometryDirty() { geometryDirty_ = true; }
+    /// Mark material dirty.
+    void MarkMaterialDirty() { materialDirty_ = true; }
+
+    /// Unit per pixel.
+    float unitPerPixel_;
+    /// Sprite.
+    SharedPtr<Sprite2D> sprite_;
+    /// Material.
+    SharedPtr<Material> material_;
+    /// Blend mode.
+    BlendMode blendMode_;
+    /// Z value.
+    float zValue_;
+
+    /// Vertices.
+    Vector<Vertex2D> vertices_;
+    /// Geometry.
+    SharedPtr<Geometry> geometry_;
+    /// Vertex buffer.
+    SharedPtr<VertexBuffer> vertexBuffer_;
+    /// Vertices dirty flag.
+    bool verticesDirty_;
+    /// Geometry dirty flag.
+    bool geometryDirty_;
+    /// Material dirty flag.
+    bool materialDirty_;
+};
+
+}
+

+ 84 - 0
Source/Engine/Urho2D/Sprite2D.cpp

@@ -0,0 +1,84 @@
+//
+// 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 "SpriteSheet2D.h"
+#include "Texture2D.h"
+
+#include "DebugNew.h"
+
+namespace Urho3D
+{
+
+Sprite2D::Sprite2D(Context* context) : Resource(context), 
+    hotSpot_(0.5f, 0.5f)
+{
+
+}
+
+Sprite2D::~Sprite2D()
+{
+
+}
+
+void Sprite2D::RegisterObject(Context* context)
+{
+    context->RegisterFactory<Sprite2D>();
+}
+
+bool Sprite2D::Load(Deserializer& source)
+{
+    SharedPtr<Texture2D> texture(new Texture2D(context_));
+    if (!texture->Load(source))
+        return false;
+
+    SetTexture(texture);
+
+    if (texture)
+        SetRectangle(IntRect(0, 0, texture->GetWidth(), texture->GetHeight()));
+
+    return true;
+}
+
+void Sprite2D::SetTexture(Texture2D* texture)
+{
+    texture_ = texture;
+}
+
+void Sprite2D::SetRectangle(const IntRect& rectangle)
+{
+    rectangle_ = rectangle;
+}
+
+void Sprite2D::SetHotSpot(const Vector2& hotSpot)
+{
+    hotSpot_ = hotSpot;
+}
+
+void Sprite2D::SetSpriteSheet(SpriteSheet2D* spriteSheet)
+{
+    spriteSheet_ = spriteSheet;
+}
+
+}

+ 92 - 0
Source/Engine/Urho2D/Sprite2D.h

@@ -0,0 +1,92 @@
+//
+// 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 "GraphicsDefs.h"
+#include "Resource.h"
+
+namespace Urho3D
+{
+
+class SpriteSheet2D;
+class Texture2D;
+
+/// 2D vertex.
+struct Vertex2D
+{
+    /// Position.
+    Vector3 position_;
+    /// Color.
+    unsigned color_;
+    /// UV.
+    Vector2 uv_;
+};
+
+static const unsigned MASK_VERTEX2D = MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1;
+
+/// Sprite.
+class URHO3D_API Sprite2D : public Resource
+{
+    OBJECT(Sprite2D);
+
+public:
+    /// Construct.
+    Sprite2D(Context* context);
+    /// Destruct.
+    virtual ~Sprite2D();
+    /// Register object factory.
+    static void RegisterObject(Context* context);
+
+    /// Load resource. Return true if successful.
+    virtual bool Load(Deserializer& source);
+
+    /// Set texture.
+    void SetTexture(Texture2D* texture);
+    /// Set rectangle.
+    void SetRectangle(const IntRect& rectangle);
+    /// Set hot spot.
+    void SetHotSpot(const Vector2& hotSpot);
+    /// Set sprite sheet.
+    void SetSpriteSheet(SpriteSheet2D* spriteSheet);
+
+    /// Return texture.
+    Texture2D* GetTexture() const { return texture_; }
+    /// Return rectangle.
+    const IntRect& GetRectangle() const { return rectangle_; }
+    /// Return hot spot.
+    const Vector2& GetHotSpot() const { return hotSpot_; }
+    /// Return sprite sheet.
+    SpriteSheet2D* GetSpriteSheet() const { return spriteSheet_; }
+
+private:
+    /// Texture.
+    SharedPtr<Texture2D> texture_;
+    /// Rectangle.
+    IntRect rectangle_;
+    /// Hot spot.
+    Vector2 hotSpot_;
+    /// Sprite sheet.
+    WeakPtr<SpriteSheet2D> spriteSheet_;
+};
+
+}