Bläddra i källkod

Naming fixes, angelscript bindings, refactoring

Guschin Konstantin 8 år sedan
förälder
incheckning
5ebe92d6ee

+ 7 - 0
Source/Urho3D/AngelScript/Urho2DAPI.cpp

@@ -299,6 +299,12 @@ static void RegisterTileMapLayer2D(asIScriptEngine* engine)
     engine->RegisterObjectMethod("TileMapLayer2D", "Node@+ get_imageNode() const", asMETHOD(TileMapLayer2D, GetImageNode), asCALL_THISCALL);
     engine->RegisterObjectMethod("TileMapLayer2D", "Node@+ get_imageNode() const", asMETHOD(TileMapLayer2D, GetImageNode), asCALL_THISCALL);
 }
 }
 
 
+static CScriptArray* TileMap2DGetTileCollisionShapes(int gid, TileMap2D* tileMap)
+{
+    Vector<SharedPtr<TileMapObject2D> > result = tileMap->GetTileCollisionShapes(gid);
+    return VectorToArray<SharedPtr<TileMapObject2D> >(result, "Array<TileMapObject2D@>@");
+}
+
 static void RegisterTileMap2D(asIScriptEngine* engine)
 static void RegisterTileMap2D(asIScriptEngine* engine)
 {
 {
     engine->RegisterObjectMethod("TileMap2D", "void set_tmxFile(TmxFile2D@+)", asMETHOD(TileMap2D, SetTmxFile), asCALL_THISCALL);
     engine->RegisterObjectMethod("TileMap2D", "void set_tmxFile(TmxFile2D@+)", asMETHOD(TileMap2D, SetTmxFile), asCALL_THISCALL);
@@ -308,6 +314,7 @@ static void RegisterTileMap2D(asIScriptEngine* engine)
     engine->RegisterObjectMethod("TileMap2D", "TileMapLayer2D@+ GetLayer(uint) const", asMETHOD(TileMap2D, GetLayer), asCALL_THISCALL);
     engine->RegisterObjectMethod("TileMap2D", "TileMapLayer2D@+ GetLayer(uint) const", asMETHOD(TileMap2D, GetLayer), asCALL_THISCALL);
     engine->RegisterObjectMethod("TileMap2D", "Vector2 TileIndexToPosition(int, int) const", asMETHOD(TileMap2D, TileIndexToPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("TileMap2D", "Vector2 TileIndexToPosition(int, int) const", asMETHOD(TileMap2D, TileIndexToPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("TileMap2D", "bool PositionToTileIndex(int&out x, int &out y, const Vector2&in) const", asMETHOD(TileMap2D, PositionToTileIndex), asCALL_THISCALL);
     engine->RegisterObjectMethod("TileMap2D", "bool PositionToTileIndex(int&out x, int &out y, const Vector2&in) const", asMETHOD(TileMap2D, PositionToTileIndex), asCALL_THISCALL);
+    engine->RegisterObjectMethod("TileMap2D", "Array<TileMapObject2D@>@ GetTileCollisionShapes(int) const", asFUNCTION(TileMap2DGetTileCollisionShapes), asCALL_CDECL_OBJLAST);
 }
 }
 
 
 static void RegisterRigidBody2D(asIScriptEngine* engine)
 static void RegisterRigidBody2D(asIScriptEngine* engine)

+ 14 - 15
Source/Urho3D/Urho2D/TileMap2D.cpp

@@ -57,7 +57,12 @@ void TileMap2D::RegisterObject(Context* context)
         AM_DEFAULT);
         AM_DEFAULT);
 }
 }
 
 
-Vector2 TransformNode2D(Matrix3x4 transform, Vector2 local);
+// Transform vector from node-local space to global space
+static Vector2 TransformNode2D(Matrix3x4 transform, Vector2 local)
+{
+    Vector3 transformed = transform * Vector4(local.x_, local.y_, 0.f, 1.f);
+    return Vector2(transformed.x_, transformed.y_);
+}
 
 
 void TileMap2D::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 void TileMap2D::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 {
 {
@@ -69,6 +74,8 @@ void TileMap2D::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
     switch (info_.orientation_)
     switch (info_.orientation_)
     {
     {
     case O_ORTHOGONAL:
     case O_ORTHOGONAL:
+    case O_STAGGERED:
+    case O_HEXAGONAL:
         debug->AddLine(TransformNode2D(transform, Vector2(0.0f, 0.0f)), TransformNode2D(transform, Vector2(mapW, 0.0f)), color);
         debug->AddLine(TransformNode2D(transform, Vector2(0.0f, 0.0f)), TransformNode2D(transform, Vector2(mapW, 0.0f)), color);
         debug->AddLine(TransformNode2D(transform, Vector2(mapW, 0.0f)), TransformNode2D(transform, Vector2(mapW, mapH)), color);
         debug->AddLine(TransformNode2D(transform, Vector2(mapW, 0.0f)), TransformNode2D(transform, Vector2(mapW, mapH)), color);
         debug->AddLine(TransformNode2D(transform, Vector2(mapW, mapH)), TransformNode2D(transform, Vector2(0.0f, mapH)), color);
         debug->AddLine(TransformNode2D(transform, Vector2(mapW, mapH)), TransformNode2D(transform, Vector2(0.0f, mapH)), color);
@@ -81,20 +88,6 @@ void TileMap2D::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
         debug->AddLine(TransformNode2D(transform, Vector2(mapW, mapH * 0.5f)), TransformNode2D(transform, Vector2(mapW * 0.5f, mapH)), color);
         debug->AddLine(TransformNode2D(transform, Vector2(mapW, mapH * 0.5f)), TransformNode2D(transform, Vector2(mapW * 0.5f, mapH)), color);
         debug->AddLine(TransformNode2D(transform, Vector2(mapW * 0.5f, mapH)), TransformNode2D(transform, Vector2(0.0f, mapH * 0.5f)), color);
         debug->AddLine(TransformNode2D(transform, Vector2(mapW * 0.5f, mapH)), TransformNode2D(transform, Vector2(0.0f, mapH * 0.5f)), color);
         break;
         break;
-
-    case O_STAGGERED:
-        debug->AddLine(TransformNode2D(transform, Vector2(0.0f, 0.0f)), TransformNode2D(transform, Vector2(mapW, 0.0f)), color);
-        debug->AddLine(TransformNode2D(transform, Vector2(mapW, 0.0f)), TransformNode2D(transform, Vector2(mapW, mapH)), color);
-        debug->AddLine(TransformNode2D(transform, Vector2(mapW, mapH)), TransformNode2D(transform, Vector2(0.0f, mapH)), color);
-        debug->AddLine(TransformNode2D(transform, Vector2(0.0f, mapH)), TransformNode2D(transform, Vector2(0.0f, 0.0f)), color);
-        break;
-
-    case O_HEXAGONAL:
-        debug->AddLine(TransformNode2D(transform, Vector2(0.0f, 0.0f)), TransformNode2D(transform, Vector2(mapW, 0.0f)), color);
-        debug->AddLine(TransformNode2D(transform, Vector2(mapW, 0.0f)), TransformNode2D(transform, Vector2(mapW, mapH)), color);
-        debug->AddLine(TransformNode2D(transform, Vector2(mapW, mapH)), TransformNode2D(transform, Vector2(0.0f, mapH)), color);
-        debug->AddLine(TransformNode2D(transform, Vector2(0.0f, mapH)), TransformNode2D(transform, Vector2(0.0f, 0.0f)), color);
-        break;
     }
     }
 
 
     for (unsigned i = 0; i < layers_.Size(); ++i)
     for (unsigned i = 0; i < layers_.Size(); ++i)
@@ -186,4 +179,10 @@ ResourceRef TileMap2D::GetTmxFileAttr() const
     return GetResourceRef(tmxFile_, TmxFile2D::GetTypeStatic());
     return GetResourceRef(tmxFile_, TmxFile2D::GetTypeStatic());
 }
 }
 
 
+Vector<SharedPtr<TileMapObject2D> > TileMap2D::GetTileCollisionShapes(int gid) const
+{
+    Vector<SharedPtr<TileMapObject2D> > shapes;
+    return tmxFile_ ? tmxFile_->GetTileCollisionShapes(gid) : shapes;
+}
+
 }
 }

+ 2 - 1
Source/Urho3D/Urho2D/TileMap2D.h

@@ -72,7 +72,8 @@ public:
     void SetTmxFileAttr(const ResourceRef& value);
     void SetTmxFileAttr(const ResourceRef& value);
     /// Return tile map file attribute.
     /// Return tile map file attribute.
     ResourceRef GetTmxFileAttr() const;
     ResourceRef GetTmxFileAttr() const;
-
+    ///
+    Vector<SharedPtr<TileMapObject2D> > GetTileCollisionShapes(int gid) const;
 private:
 private:
     /// Tmx file.
     /// Tmx file.
     SharedPtr<TmxFile2D> tmxFile_;
     SharedPtr<TmxFile2D> tmxFile_;

+ 51 - 60
Source/Urho3D/Urho2D/TileMapLayer2D.cpp

@@ -53,14 +53,8 @@ void TileMapLayer2D::RegisterObject(Context* context)
     context->RegisterFactory<TileMapLayer2D>();
     context->RegisterFactory<TileMapLayer2D>();
 }
 }
 
 
-// Transform vector from tiled isometric space to Urho3d node-local space
-static Vector2 TransformIsometricVector(Vector2 vec)
-{
-    return Vector2(vec.x_ - vec.y_, - (vec.x_ + vec.y_) / 2);
-}
-
 // Transform vector from node-local space to global space
 // Transform vector from node-local space to global space
-Vector2 TransformNode2D(Matrix3x4 transform, Vector2 local)
+static Vector2 TransformNode2D(Matrix3x4 transform, Vector2 local)
 {
 {
     Vector3 transformed = transform * Vector4(local.x_, local.y_, 0.f, 1.f);
     Vector3 transformed = transform * Vector4(local.x_, local.y_, 0.f, 1.f);
     return Vector2(transformed.x_, transformed.y_);
     return Vector2(transformed.x_, transformed.y_);
@@ -78,80 +72,77 @@ void TileMapLayer2D::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
         {
         {
             TileMapObject2D* object = objectGroup_->GetObject(i);
             TileMapObject2D* object = objectGroup_->GetObject(i);
             const Color& color = Color::YELLOW;
             const Color& color = Color::YELLOW;
+            const Vector2& size = object->GetSize();
+            const TileMapInfo2D& info = tileMap_->GetInfo();
+
 
 
             switch (object->GetObjectType())
             switch (object->GetObjectType())
             {
             {
             case OT_RECTANGLE:
             case OT_RECTANGLE:
                 {
                 {
-                    switch (GetTileMap()->GetInfo().orientation_)
+                    Vector<Vector2> points;
+
+                    switch (info.orientation_)
                     {
                     {
                     case O_ORTHOGONAL:
                     case O_ORTHOGONAL:
                     case O_HEXAGONAL:
                     case O_HEXAGONAL:
                     case O_STAGGERED:
                     case O_STAGGERED:
                         {
                         {
-                            const Vector2& lb = object->GetPosition();
-                            const Vector2& rt = lb + object->GetSize();
-                            debug->AddLine(TransformNode2D(transform, Vector2(lb.x_, lb.y_)), TransformNode2D(transform, Vector2(rt.x_, lb.y_)), color, depthTest);
-                            debug->AddLine(TransformNode2D(transform, Vector2(rt.x_, lb.y_)), TransformNode2D(transform, Vector2(rt.x_, rt.y_)), color, depthTest);
-                            debug->AddLine(TransformNode2D(transform, Vector2(rt.x_, rt.y_)), TransformNode2D(transform, Vector2(lb.x_, rt.y_)), color, depthTest);
-                            debug->AddLine(TransformNode2D(transform, Vector2(lb.x_, rt.y_)), TransformNode2D(transform, Vector2(lb.x_, lb.y_)), color, depthTest);
+                            points.Push(Vector2::ZERO);
+                            points.Push(Vector2(size.x_, 0.0f));
+                            points.Push(Vector2(size.x_, -size.y_));
+                            points.Push(Vector2(0.0f, -size.y_));
                             break;
                             break;
                         }
                         }
                     case O_ISOMETRIC:
                     case O_ISOMETRIC:
                         {
                         {
-                            const Vector2& size = object->GetSize();
-                            const Vector2 lt = object->GetPosition();
-                            const Vector2 lb = lt - TransformIsometricVector(Vector2(0, size.y_));
-                            const Vector2 rb = lb + TransformIsometricVector(Vector2(size.x_, 0));
-                            const Vector2 rt = lb + TransformIsometricVector(Vector2(size.x_, size.y_));
-                            debug->AddLine(TransformNode2D(transform, lt), TransformNode2D(transform, lb), color, depthTest);
-                            debug->AddLine(TransformNode2D(transform, lb), TransformNode2D(transform, rb), color, depthTest);
-                            debug->AddLine(TransformNode2D(transform, rb), TransformNode2D(transform, rt), color, depthTest);
-                            debug->AddLine(TransformNode2D(transform, rt), TransformNode2D(transform, lt), color, depthTest);
+                            float ratio = (info.tileWidth_ / info.tileHeight_) * 0.5f;
+                            points.Push(Vector2::ZERO);
+                            points.Push(Vector2(size.y_ * ratio, size.y_ * 0.5f));
+                            points.Push(Vector2((size.x_ + size.y_) * ratio, (-size.x_ + size.y_) * 0.5f));
+                            points.Push(Vector2(size.x_ * ratio, -size.x_ * 0.5f));
                             break;
                             break;
                         }
                         }
                     }
                     }
+
+                    for (unsigned j = 0; j < points.Size(); ++j)
+                        debug->AddLine(TransformNode2D(transform, points[j] + object->GetPosition()),
+                                       TransformNode2D(transform, points[(j + 1) % points.Size()] + object->GetPosition()), color, depthTest);
                 }
                 }
                 break;
                 break;
 
 
             case OT_ELLIPSE:
             case OT_ELLIPSE:
                 {
                 {
-                    switch (GetTileMap()->GetInfo().orientation_)
+                    const Vector2 halfSize = object->GetSize() * 0.5f;
+                    float ratio = (info.tileWidth_ / info.tileHeight_) * 0.5f; // For isometric only
+
+                    Vector2 pivot = object->GetPosition();
+                    if (info.orientation_ == O_ISOMETRIC)
                     {
                     {
-                    case O_ORTHOGONAL:
-                    case O_HEXAGONAL:
-                    case O_STAGGERED:
-                        {
-                            const Vector2 halfSize = object->GetSize() * 0.5f;
-                            const Vector2 center = object->GetPosition() + halfSize;
-                            for (unsigned i = 0; i < 360; i += 30)
-                            {
-                                unsigned j = i + 30;
-                                float x1 = halfSize.x_ * Cos((float)i);
-                                float y1 = halfSize.y_ * Sin((float)i);
-                                float x2 = halfSize.x_ * Cos((float)j);
-                                float y2 = halfSize.y_ * Sin((float)j);
-                                debug->AddLine(TransformNode2D(transform, center + Vector2(x1, y1)),
-                                               TransformNode2D(transform, center + Vector2(x2, y2)), color, depthTest);
-                            }
-                            break;
-                        }
-                    case O_ISOMETRIC:
+                        pivot += Vector2((halfSize.x_ + halfSize.y_) * ratio, (-halfSize.x_ + halfSize.y_) * 0.5f);
+                    }
+                    else
+                    {
+                        pivot += halfSize;
+                    }
+
+                    for (unsigned i = 0; i < 360; i += 30)
+                    {
+                        unsigned j = i + 30;
+                        float x1 = halfSize.x_ * Cos((float)i);
+                        float y1 = halfSize.y_ * Sin((float)i);
+                        float x2 = halfSize.x_ * Cos((float)j);
+                        float y2 = halfSize.y_ * Sin((float)j);
+                        Vector2 point1 = Vector2(x1, - y1);
+                        Vector2 point2 = Vector2(x2, - y2);
+
+                        if (info.orientation_ == O_ISOMETRIC)
                         {
                         {
-                            const Vector2 halfSize = object->GetSize() * 0.5f;
-                            const Vector2 center = object->GetPosition() + TransformIsometricVector(Vector2(halfSize.x_, -halfSize.y_));
-                            for (unsigned i = 0; i < 360; i += 30)
-                            {
-                                unsigned j = i + 30;
-                                float x1 = halfSize.x_ * Cos((float)i);
-                                float y1 = halfSize.y_ * Sin((float)i);
-                                float x2 = halfSize.x_ * Cos((float)j);
-                                float y2 = halfSize.y_ * Sin((float)j);
-                                debug->AddLine(TransformNode2D(transform, center + TransformIsometricVector(Vector2(x1, y1))),
-                                               TransformNode2D(transform, center + TransformIsometricVector(Vector2(x2, y2))), color, depthTest);
-                            }
-                            break;
+                            point1 = Vector2((point1.x_ + point1.y_) * ratio, (point1.y_ - point1.x_) * 0.5f);
+                            point2 = Vector2((point2.x_ + point2.y_) * ratio, (point2.y_ - point2.x_) * 0.5f);
                         }
                         }
+
+                        debug->AddLine(TransformNode2D(transform, pivot + point1), TransformNode2D(transform, pivot + point2), color, depthTest);
                     }
                     }
                 }
                 }
                 break;
                 break;
@@ -166,6 +157,9 @@ void TileMapLayer2D::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
                     if (object->GetObjectType() == OT_POLYGON)
                     if (object->GetObjectType() == OT_POLYGON)
                         debug->AddLine(TransformNode2D(transform, object->GetPoint(0)),
                         debug->AddLine(TransformNode2D(transform, object->GetPoint(0)),
                                        TransformNode2D(transform, object->GetPoint(object->GetNumPoints() - 1)), color, depthTest);
                                        TransformNode2D(transform, object->GetPoint(object->GetNumPoints() - 1)), color, depthTest);
+                    // Also draw a circle at origin to indicate direction
+                    else
+                        debug->AddCircle(TransformNode2D(transform, object->GetPoint(0)), Vector3::FORWARD, 0.05f, color, 64, depthTest);
                 }
                 }
                 break;
                 break;
 
 
@@ -337,10 +331,7 @@ Node* TileMapLayer2D::GetObjectNode(unsigned index) const
 
 
 Node* TileMapLayer2D::GetImageNode() const
 Node* TileMapLayer2D::GetImageNode() const
 {
 {
-    if (!imageLayer_)
-        return 0;
-
-    if (nodes_.Empty())
+    if (!imageLayer_ || nodes_.Empty())
         return 0;
         return 0;
 
 
     return nodes_[0];
     return nodes_[0];

+ 50 - 46
Source/Urho3D/Urho2D/TmxFile2D.cpp

@@ -240,7 +240,18 @@ bool TmxObjectGroup2D::Load(const XMLElement& element, const TileMapInfo2D& info
     for (XMLElement objectElem = element.GetChild("object"); objectElem; objectElem = objectElem.GetNext("object"))
     for (XMLElement objectElem = element.GetChild("object"); objectElem; objectElem = objectElem.GetNext("object"))
     {
     {
         SharedPtr<TileMapObject2D> object(new TileMapObject2D());
         SharedPtr<TileMapObject2D> object(new TileMapObject2D());
+        StoreObject(objectElem, object, info);
+        objects_.Push(object);
+    }
+
+    if (element.HasChild("properties"))
+        LoadPropertySet(element.GetChild("properties"));
 
 
+    return true;
+}
+
+void TmxObjectGroup2D::StoreObject(XMLElement objectElem, SharedPtr<TileMapObject2D> object, const TileMapInfo2D& info, bool isTile)
+{
         if (objectElem.HasAttribute("name"))
         if (objectElem.HasAttribute("name"))
             object->name_ = objectElem.GetAttribute("name");
             object->name_ = objectElem.GetAttribute("name");
         if (objectElem.HasAttribute("type"))
         if (objectElem.HasAttribute("type"))
@@ -294,7 +305,7 @@ bool TmxObjectGroup2D::Load(const XMLElement& element, const TileMapInfo2D& info
                 points = polygonElem.GetAttribute("points").Split(' ');
                 points = polygonElem.GetAttribute("points").Split(' ');
 
 
                 if (points.Size() <= 1)
                 if (points.Size() <= 1)
-                    continue;
+                    return;
 
 
                 object->points_.Resize(points.Size());
                 object->points_.Resize(points.Size());
 
 
@@ -315,14 +326,6 @@ bool TmxObjectGroup2D::Load(const XMLElement& element, const TileMapInfo2D& info
             object->propertySet_ = new PropertySet2D();
             object->propertySet_ = new PropertySet2D();
             object->propertySet_->Load(objectElem.GetChild("properties"));
             object->propertySet_->Load(objectElem.GetChild("properties"));
         }
         }
-
-        objects_.Push(object);
-    }
-
-    if (element.HasChild("properties"))
-        LoadPropertySet(element.GetChild("properties"));
-
-    return true;
 }
 }
 
 
 TileMapObject2D* TmxObjectGroup2D::GetObject(unsigned index) const
 TileMapObject2D* TmxObjectGroup2D::GetObject(unsigned index) const
@@ -561,18 +564,20 @@ Sprite2D* TmxFile2D::GetTileSprite(int gid) const
     return i->second_;
     return i->second_;
 }
 }
 
 
-PropertySet2D* TmxFile2D::GetTilePropertySet(int gid) const
+Vector<SharedPtr<TileMapObject2D> > TmxFile2D::GetTileCollisionShapes(int gid) const
 {
 {
-    HashMap<int, SharedPtr<PropertySet2D> >::ConstIterator i = gidToPropertySetMapping_.Find(gid);
-    if (i == gidToPropertySetMapping_.End())
-        return 0;
+    Vector<SharedPtr<TileMapObject2D> > tileShapes;
+    HashMap<int, Vector<SharedPtr<TileMapObject2D> > >::ConstIterator i = gidToCollisionShapeMapping_.Find(gid);
+    if (i == gidToCollisionShapeMapping_.End())
+        return tileShapes;
+
     return i->second_;
     return i->second_;
 }
 }
 
 
-TmxObjectGroup2D* TmxFile2D::GetCollisionObjectGroup(int gid) const
+PropertySet2D* TmxFile2D::GetTilePropertySet(int gid) const
 {
 {
-    HashMap<int, SharedPtr<TmxObjectGroup2D> >::ConstIterator i = gidToCollisionObjectGroupMapping_.Find(gid);
-    if (i == gidToCollisionObjectGroupMapping_.End())
+    HashMap<int, SharedPtr<PropertySet2D> >::ConstIterator i = gidToPropertySetMapping_.Find(gid);
+    if (i == gidToPropertySetMapping_.End())
         return 0;
         return 0;
     return i->second_;
     return i->second_;
 }
 }
@@ -623,7 +628,7 @@ bool TmxFile2D::LoadTileSet(const XMLElement& element)
             if (!tsxXMLFile)
             if (!tsxXMLFile)
                 return false;
                 return false;
 
 
-            // Add to napping to avoid release
+            // Add to mapping to avoid release
             tsxXMLFiles_[source] = tsxXMLFile;
             tsxXMLFiles_[source] = tsxXMLFile;
 
 
             tileSetElem = tsxXMLFile->GetRoot("tileset");
             tileSetElem = tsxXMLFile->GetRoot("tileset");
@@ -634,26 +639,13 @@ bool TmxFile2D::LoadTileSet(const XMLElement& element)
     else
     else
         tileSetElem = element;
         tileSetElem = element;
 
 
-    bool isIsometricGrid = tileSetElem.HasChild("grid") && tileSetElem.GetChild("grid").GetAttribute("orientation") == "isometric";
     int tileWidth = tileSetElem.GetInt("tilewidth");
     int tileWidth = tileSetElem.GetInt("tilewidth");
     int tileHeight = tileSetElem.GetInt("tileheight");
     int tileHeight = tileSetElem.GetInt("tileheight");
     int spacing = tileSetElem.GetInt("spacing");
     int spacing = tileSetElem.GetInt("spacing");
     int margin = tileSetElem.GetInt("margin");
     int margin = tileSetElem.GetInt("margin");
-    bool isSingleTileSet = false;
     int imageWidth;
     int imageWidth;
     int imageHeight;
     int imageHeight;
-
-    if (isIsometricGrid)
-        URHO3D_LOGWARNING("Tilesets with isometric orientation are not supported yet");
-
-    // Set hot spot at left bottom
-    Vector2 hotSpot(0.0f, 0.0f);
-    if (tileSetElem.HasChild("tileoffset"))
-    {
-        XMLElement offsetElem = tileSetElem.GetChild("tileoffset");
-        hotSpot.x_ += offsetElem.GetFloat("x") / (float)tileWidth;
-        hotSpot.y_ += offsetElem.GetFloat("y") / (float)tileHeight;
-    }
+    bool isSingleTileSet = false;
 
 
     ResourceCache* cache = GetSubsystem<ResourceCache>();
     ResourceCache* cache = GetSubsystem<ResourceCache>();
     {
     {
@@ -669,7 +661,14 @@ bool TmxFile2D::LoadTileSet(const XMLElement& element)
                 return false;
                 return false;
             }
             }
 
 
-            tileSetTextures_.Push(texture);
+            // Set hot spot at left bottom
+            Vector2 hotSpot(0.0f, 0.0f);
+            if (tileSetElem.HasChild("tileoffset"))
+            {
+                XMLElement offsetElem = tileSetElem.GetChild("tileoffset");
+                hotSpot.x_ += offsetElem.GetFloat("x") / (float)tileWidth;
+                hotSpot.y_ += offsetElem.GetFloat("y") / (float)tileHeight;
+            }
 
 
             imageWidth = imageElem.GetInt("width");
             imageWidth = imageElem.GetInt("width");
             imageHeight = imageElem.GetInt("height");
             imageHeight = imageElem.GetInt("height");
@@ -712,24 +711,29 @@ bool TmxFile2D::LoadTileSet(const XMLElement& element)
                 tileImageInfos.Push(info);
                 tileImageInfos.Push(info);
             }
             }
         }
         }
+        // Tile collision shape(s)
+        TmxObjectGroup2D objectGroup(this);
+        for (XMLElement collisionElem = tileElem.GetChild("objectgroup"); collisionElem; collisionElem = collisionElem.GetNext("objectgroup"))
+        {
+            Vector<SharedPtr<TileMapObject2D> > objects;
+            for (XMLElement objectElem = collisionElem.GetChild("object"); objectElem; objectElem = objectElem.GetNext("object"))
+            {
+                SharedPtr<TileMapObject2D> object(new TileMapObject2D());
+
+                // Convert Tiled local position (left top) to Urho3D local position (left bottom)
+                objectElem.SetAttribute("y", String(info_.GetMapHeight() / PIXEL_SIZE - (tileHeight - objectElem.GetFloat("y"))));
+
+                objectGroup.StoreObject(objectElem, object, info_, true);
+                objects.Push(object);
+            }
+            gidToCollisionShapeMapping_[gid] = objects;
+        }
         if (tileElem.HasChild("properties"))
         if (tileElem.HasChild("properties"))
         {
         {
             SharedPtr<PropertySet2D> propertySet(new PropertySet2D());
             SharedPtr<PropertySet2D> propertySet(new PropertySet2D());
             propertySet->Load(tileElem.GetChild("properties"));
             propertySet->Load(tileElem.GetChild("properties"));
             gidToPropertySetMapping_[gid] = propertySet;
             gidToPropertySetMapping_[gid] = propertySet;
         }
         }
-        if (tileElem.HasChild("objectgroup"))
-        {
-            if (!isIsometricGrid)
-            {
-                TmxObjectGroup2D* objectGroup = new TmxObjectGroup2D(this);
-                TileMapInfo2D info = info_;
-                info.width_ = tileWidth * PIXEL_SIZE / info.tileWidth_;
-                info.height_ = tileHeight * PIXEL_SIZE / info.tileHeight_;
-                objectGroup->Load(tileElem.GetChild("objectgroup"), info);
-                gidToCollisionObjectGroupMapping_[gid] = SharedPtr<TmxObjectGroup2D>(objectGroup);
-            }
-        }
     }
     }
 
 
     if (!isSingleTileSet)
     if (!isSingleTileSet)
@@ -748,6 +752,7 @@ bool TmxFile2D::LoadTileSet(const XMLElement& element)
                 return false;
                 return false;
             }
             }
         }
         }
+
         SharedPtr<Texture2D> texture(new Texture2D(context_));
         SharedPtr<Texture2D> texture(new Texture2D(context_));
         texture->SetMipsToSkip(QUALITY_LOW, 0);
         texture->SetMipsToSkip(QUALITY_LOW, 0);
         texture->SetNumLevels(1);
         texture->SetNumLevels(1);
@@ -771,11 +776,10 @@ bool TmxFile2D::LoadTileSet(const XMLElement& element)
             SharedPtr<Sprite2D> sprite(new Sprite2D(context_));
             SharedPtr<Sprite2D> sprite(new Sprite2D(context_));
             sprite->SetTexture(texture);
             sprite->SetTexture(texture);
             sprite->SetRectangle(IntRect(info.x, info.y, info.x + info.imageWidth, info.y +  + info.imageHeight));
             sprite->SetRectangle(IntRect(info.x, info.y, info.x + info.imageWidth, info.y +  + info.imageHeight));
-            sprite->SetHotSpot(hotSpot);
+            sprite->SetHotSpot(Vector2::ZERO);
             gidToSpriteMapping_[info.tileGid] = sprite;
             gidToSpriteMapping_[info.tileGid] = sprite;
         }
         }
         texture->SetData(0, 0, 0, allocator.GetWidth(), allocator.GetHeight(), textureData.Get());
         texture->SetData(0, 0, 0, allocator.GetWidth(), allocator.GetHeight(), textureData.Get());
-        tileSetTextures_.Push(texture);
     }
     }
 
 
     return true;
     return true;

+ 10 - 10
Source/Urho3D/Urho2D/TmxFile2D.h

@@ -99,11 +99,11 @@ public:
     Tile2D* GetTile(int x, int y) const;
     Tile2D* GetTile(int x, int y) const;
 
 
 protected:
 protected:
-    /// Tile.
+    /// Tiles.
     Vector<SharedPtr<Tile2D> > tiles_;
     Vector<SharedPtr<Tile2D> > tiles_;
 };
 };
 
 
-/// Tmx image layer.
+/// Tmx objects layer.
 class TmxObjectGroup2D : public TmxLayer2D
 class TmxObjectGroup2D : public TmxLayer2D
 {
 {
 public:
 public:
@@ -112,6 +112,9 @@ public:
     /// Load from XML element.
     /// Load from XML element.
     bool Load(const XMLElement& element, const TileMapInfo2D& info);
     bool Load(const XMLElement& element, const TileMapInfo2D& info);
 
 
+    /// Store object.
+    void StoreObject(XMLElement objectElem, SharedPtr<TileMapObject2D> object, const TileMapInfo2D& info, bool isTile = false);
+
     /// Return number of objects.
     /// Return number of objects.
     unsigned GetNumObjects() const { return objects_.Size(); }
     unsigned GetNumObjects() const { return objects_.Size(); }
 
 
@@ -183,12 +186,12 @@ public:
     /// Return tile sprite by gid, if not exist return 0.
     /// Return tile sprite by gid, if not exist return 0.
     Sprite2D* GetTileSprite(int gid) const;
     Sprite2D* GetTileSprite(int gid) const;
 
 
+    /// Return tile collision shapes for a given gid.
+    Vector<SharedPtr<TileMapObject2D> > GetTileCollisionShapes(int gid) const;
+
     /// Return tile property set by gid, if not exist return 0.
     /// Return tile property set by gid, if not exist return 0.
     PropertySet2D* GetTilePropertySet(int gid) const;
     PropertySet2D* GetTilePropertySet(int gid) const;
 
 
-    /// Return collision object group by gid, if not exist return 0.
-    TmxObjectGroup2D* GetCollisionObjectGroup(int gid) const;
-
     /// Return number of layers.
     /// Return number of layers.
     unsigned GetNumLayers() const { return layers_.Size(); }
     unsigned GetNumLayers() const { return layers_.Size(); }
 
 
@@ -207,17 +210,14 @@ private:
     HashMap<String, SharedPtr<XMLFile> > tsxXMLFiles_;
     HashMap<String, SharedPtr<XMLFile> > tsxXMLFiles_;
     /// Tile map information.
     /// Tile map information.
     TileMapInfo2D info_;
     TileMapInfo2D info_;
-    /// Tile set textures.
-    Vector<SharedPtr<Texture2D> > tileSetTextures_;
     /// Gid to tile sprite mapping.
     /// Gid to tile sprite mapping.
     HashMap<int, SharedPtr<Sprite2D> > gidToSpriteMapping_;
     HashMap<int, SharedPtr<Sprite2D> > gidToSpriteMapping_;
     /// Gid to tile property set mapping.
     /// Gid to tile property set mapping.
     HashMap<int, SharedPtr<PropertySet2D> > gidToPropertySetMapping_;
     HashMap<int, SharedPtr<PropertySet2D> > gidToPropertySetMapping_;
-    /// Gid to collision object group mapping.
-    HashMap<int, SharedPtr<TmxObjectGroup2D> > gidToCollisionObjectGroupMapping_;
+    /// Gid to tile collision shape mapping.
+    HashMap<int, Vector<SharedPtr<TileMapObject2D> > > gidToCollisionShapeMapping_;
     /// Layers.
     /// Layers.
     Vector<TmxLayer2D*> layers_;
     Vector<TmxLayer2D*> layers_;
 };
 };
 
 
 }
 }
-