Răsfoiți Sursa

refactor tile map code.

aster 11 ani în urmă
părinte
comite
7110a05c58

+ 1 - 1
Source/Engine/Urho2D/TileMap2D.cpp

@@ -76,7 +76,7 @@ void TileMap2D::SetTmxFile(TmxFile2D* tmxFile)
     {
         const TmxLayer2D* tmxLayer = tmxFile_->GetLayer(i);
 
-        SharedPtr<Node> layerNode(GetNode()->CreateChild(tmxLayer->name_, LOCAL));
+        SharedPtr<Node> layerNode(GetNode()->CreateChild(tmxLayer->GetName(), LOCAL));
         layerNode->SetTemporary(true);
 
         SharedPtr<TileMapLayer2D> layer(layerNode->CreateComponent<TileMapLayer2D>());

+ 44 - 71
Source/Engine/Urho2D/TileMapLayer2D.cpp

@@ -76,14 +76,25 @@ void TileMapLayer2D::SetTmxLayer(const TmxLayer2D* tmxLayer)
     if (!tmxLayer_)
         return;
 
-    if (tmxLayer_->type_ == LT_TILE_LAYER)
+    switch (tmxLayer_->GetType())
+    {
+    case LT_TILE_LAYER:
         SetTileLayer((const TmxTileLayer2D*)tmxLayer_);
-    else if (tmxLayer_->type_ == LT_OBJECT_GROUP)
+        break;
+
+    case LT_OBJECT_GROUP:
         SetObjectGroup((const TmxObjectGroup2D*)tmxLayer_);
-    else if (tmxLayer_->type_ == LT_IMAGE_LAYER)
+        break;
+
+    case LT_IMAGE_LAYER:
         SetImageLayer((const TmxImageLayer2D*)tmxLayer_);
+        break;
 
-    SetVisible(tmxLayer_->visible_);
+    default:
+        break;
+    }
+
+    SetVisible(tmxLayer_->IsVisible());
 }
 
 void TileMapLayer2D::SetDrawOrder(int drawOrder)
@@ -120,17 +131,17 @@ void TileMapLayer2D::SetVisible(bool visible)
 
 const String& TileMapLayer2D::GetName() const
 {
-    return tmxLayer_ ? tmxLayer_->name_ : String::EMPTY;
+    return tmxLayer_ ? tmxLayer_->GetName() : String::EMPTY;
 }
 
 int TileMapLayer2D::GetWidth() const
 {
-    return tmxLayer_ ? tmxLayer_->width_ : 0;
+    return tmxLayer_ ? tmxLayer_->GetWidth(): 0;
 }
 
 int TileMapLayer2D::GetHeight() const
 {
-    return tmxLayer_ ? tmxLayer_->height_ : 0;
+    return tmxLayer_ ? tmxLayer_->GetHeight(): 0;
 }
 
 bool TileMapLayer2D::HasProperty(const String& name) const
@@ -150,7 +161,7 @@ const String& TileMapLayer2D::GetProperty(const String& name) const
 
 TmxLayerType2D TileMapLayer2D::GetLayerType() const
 {
-    return tmxLayer_ ? tmxLayer_->type_ : LT_INVALID;
+    return tmxLayer_ ? tmxLayer_->GetType() : LT_INVALID;
 }
 
 Node* TileMapLayer2D::GetTileNode(int x, int y) const
@@ -158,37 +169,18 @@ Node* TileMapLayer2D::GetTileNode(int x, int y) const
     if (!tileLayer_)
         return 0;
     
-    if (x < 0 || x >= tileLayer_->width_ || y < 0 || y >= tileLayer_->height_)
+    if (x < 0 || x >= tileLayer_->GetWidth() || y < 0 || y >= tileLayer_->GetHeight())
         return 0;
     
-    return nodes_[y * tileLayer_->width_ + x];
+    return nodes_[y * tileLayer_->GetWidth() + x];
 }
 
-const TmxTile* TileMapLayer2D::GetTile(int x, int y) const
+const Tile2D* TileMapLayer2D::GetTile(int x, int y) const
 {
     if (!tileLayer_)
         return 0;
     
-    if (x < 0 || x >= tileLayer_->width_ || y < 0 || y >= tileLayer_->height_)
-        return 0;
-
-    const TmxTile& tile = tileLayer_->tileGids_[y * tileLayer_->width_ + x];
-    return tile.gid_ == 0 ? 0 : &tile;
-}
-
-bool TileMapLayer2D::HasTileProperty(int x, int y, const String& name) const
-{
-    const TmxTile* tile = GetTile(x, y);
-    return tile && tile->HasProperty(name);
-}
-
-const String& TileMapLayer2D::GetTileProperty(int x, int y, const String& name) const
-{
-    const TmxTile* tile = GetTile(x, y);
-    if (!tile)
-        return String::EMPTY;
-
-    return tile->GetProperty(name);
+    return tileLayer_->GetTile(x, y);
 }
 
 Node* TileMapLayer2D::GetObjectNode(unsigned index) const
@@ -207,39 +199,20 @@ unsigned TileMapLayer2D::GetNumObjects() const
     if (!objectGroup_)
         return 0;
 
-    return nodes_.Size();
+    return objectGroup_->GetNumObjects();
 }
 
-
-const TmxObject2D* TileMapLayer2D::GetObject(unsigned index) const
+const TileObject2D* TileMapLayer2D::GetObject(unsigned index) const
 {
     if (objectGroup_)
         return 0;
 
-    return &objectGroup_->objects_[index];
-}
-
-bool TileMapLayer2D::HasObjectProperty(unsigned index, const String& name) const
-{
-    const TmxObject2D* object = GetObject(index);
-    if (!object)
-        return false;
-
-    return object->HasProperty(name);
-}
-
-const String& TileMapLayer2D::GetObjectProperty(unsigned index, const String& name) const
-{
-    const TmxObject2D* object = GetObject(index);
-    if (!object)
-        return String::EMPTY;
-
-    return object->GetProperty(name);
+    return objectGroup_->GetObject(index);
 }
 
 Node* TileMapLayer2D::GetImageNode() const
 {
-    if (!tmxLayer_ || tmxLayer_->type_ != LT_IMAGE_LAYER)
+    if (!imageLayer_)
         return 0;
 
     if (nodes_.Empty())
@@ -252,11 +225,11 @@ void TileMapLayer2D::SetTileLayer(const TmxTileLayer2D* tileLayer)
 {
     tmxLayer_ = tileLayer;
 
-    int width = tileLayer->width_;
-    int height = tileLayer->height_;
+    int width = tileLayer->GetWidth();
+    int height = tileLayer->GetHeight();
     nodes_.Resize(width * height);
 
-    TmxFile2D* tmxFile = tileLayer->tmxFile_;
+    TmxFile2D* tmxFile = tileLayer->GetTmxFile();
     float tileWidth = tmxFile->GetTileWidth();
     float tileHeight = tmxFile->GetTileHeight();
 
@@ -264,8 +237,8 @@ void TileMapLayer2D::SetTileLayer(const TmxTileLayer2D* tileLayer)
     {
         for (int x = 0; x < width; ++x)
         {
-            const TmxTile& tile = tileLayer->tileGids_[y * width + x];
-            if (tile.gid_ == 0 || !tile.sprite_)
+            const Tile2D* tile = tileLayer->GetTile(x, y);
+            if (!tile)
                 continue;
 
             SharedPtr<Node> tileNode(GetNode()->CreateChild("Tile"));
@@ -273,7 +246,7 @@ void TileMapLayer2D::SetTileLayer(const TmxTileLayer2D* tileLayer)
             tileNode->SetPosition(Vector3(x * tileWidth, y * tileHeight, 0.0f));
 
             StaticSprite2D* staticSprite = tileNode->CreateComponent<StaticSprite2D>();
-            staticSprite->SetSprite(tile.sprite_);
+            staticSprite->SetSprite(tile->GetSprite());
             staticSprite->SetLayer(drawOrder_);
             staticSprite->SetOrderInLayer((height - 1 - y) * width + x);
 
@@ -286,27 +259,27 @@ void TileMapLayer2D::SetObjectGroup(const TmxObjectGroup2D* objectGroup)
 {
     objectGroup_ = objectGroup;
 
-    TmxFile2D* tmxFile = objectGroup->tmxFile_;
+    TmxFile2D* tmxFile = objectGroup->GetTmxFile();
 
-    for (unsigned i = 0; i < objectGroup->objects_.Size(); ++i)
+    for (unsigned i = 0; i < objectGroup->GetNumObjects(); ++i)
     {
-        const TmxObject2D& object = objectGroup->objects_[i];
+        const TileObject2D* object = objectGroup->GetObject(i);
 
         SharedPtr<Node> objectNode(GetNode()->CreateChild("Object"));
         objectNode->SetTemporary(true);
-        objectNode->SetPosition(Vector3(object.x_, object.y_, 0.0f));
+        objectNode->SetPosition(object->GetPosition());
 
         // Set object data
         objectNode->SetVar("ObjectData", (void*)&object);
 
-        if (object.type_ == OT_TILE)
+        if (object->GetType() == OT_TILE)
         {
-            if (object.gid_ && object.sprite_)
+            if (object->GetTileGid() && object->GetTileSprite())
             {
                 StaticSprite2D* staticSprite = objectNode->CreateComponent<StaticSprite2D>();
-                staticSprite->SetSprite(object.sprite_);
+                staticSprite->SetSprite(object->GetTileSprite());
                 staticSprite->SetLayer(drawOrder_);
-                staticSprite->SetOrderInLayer((int)((10.0f - object.y_) * 100.0f));
+                staticSprite->SetOrderInLayer((int)((10.0f - object->GetPosition().y_) * 100.0f));
             }
         }
         
@@ -318,10 +291,10 @@ void TileMapLayer2D::SetImageLayer(const TmxImageLayer2D* imageLayer)
 {
     imageLayer_ = imageLayer;
 
-    if (!imageLayer->sprite_)
+    if (!imageLayer->GetSprite())
         return;
 
-    TmxFile2D* tmxFile = imageLayer->tmxFile_;
+    TmxFile2D* tmxFile = imageLayer->GetTmxFile();
     int height = tmxFile->GetHeight();
     float tileHeight = tmxFile->GetTileHeight();
 
@@ -330,7 +303,7 @@ void TileMapLayer2D::SetImageLayer(const TmxImageLayer2D* imageLayer)
     imageNode->SetPosition(Vector3(0.0f, height * tileHeight, 0.0f));
 
     StaticSprite2D* staticSprite = imageNode->CreateComponent<StaticSprite2D>();
-    staticSprite->SetSprite(imageLayer->sprite_);
+    staticSprite->SetSprite(imageLayer->GetSprite());
     staticSprite->SetOrderInLayer(0);
 
     nodes_.Push(imageNode);

+ 2 - 10
Source/Engine/Urho2D/TileMapLayer2D.h

@@ -73,22 +73,14 @@ public:
     /// Return tile node (for tile layer only).
     Node* GetTileNode(int x, int y) const;
     /// Return tile (for tile layer only).
-    const TmxTile* GetTile(int x, int y) const;
-    /// Return tile has property.
-    bool HasTileProperty(int x, int y, const String& name) const;
-    /// Return tile property.
-    const String& GetTileProperty(int x, int y, const String& name) const;
+    const Tile2D* GetTile(int x, int y) const;
     
     /// Return tile node (for object group only).
     Node* GetObjectNode(unsigned index) const;
     /// Return number of tile nodes (for object group only).
     unsigned GetNumObjects() const;
     /// Return object (for object group only).
-    const TmxObject2D* GetObject(unsigned index) const;
-    /// Return object has property.
-    bool HasObjectProperty(unsigned index, const String& name) const;
-    /// Return object property.
-    const String& GetObjectProperty(unsigned index, const String& name) const;
+    const TileObject2D* GetObject(unsigned index) const;
 
     /// Return image node (for image layer only).
     Node* GetImageNode() const;

+ 277 - 186
Source/Engine/Urho2D/TmxFile2D.cpp

@@ -38,45 +38,54 @@ namespace Urho3D
 
 extern const float PIXEL_SIZE;
 
-bool TmxProperties2D::HasProperty(const String& name) const
+Properties2D::Properties2D()
 {
-    return properties_.Find(name) != properties_.End();
 }
 
-const String& TmxProperties2D::GetProperty(const String& name) const
+Properties2D::~Properties2D()
 {
-    HashMap<String, String>::ConstIterator i = properties_.Find(name);
-    if (i == properties_.End())
-        return String::EMPTY;
-    return i->second_;
 }
 
-TmxLayer2D::TmxLayer2D(TmxFile2D* tmxFile, TmxLayerType2D type) :
-    tmxFile_(tmxFile),
-    type_(type)
+void Properties2D::Load(const XMLElement& element)
 {
+    assert(element.GetName() == "properties");
+    for (XMLElement propertyElem = element.GetChild("property"); propertyElem; propertyElem = propertyElem.GetNext("property"))
+        properties_[propertyElem.GetAttribute("name")] = propertyElem.GetAttribute("value");
+}
 
+bool Properties2D::HasProperty(const String& name) const
+{
+    return properties_.Find(name) != properties_.End();
 }
 
-TmxLayer2D::~TmxLayer2D()
+const String& Properties2D::GetProperty(const String& name) const
 {
+    HashMap<String, String>::ConstIterator i = properties_.Find(name);
+    if (i == properties_.End())
+        return String::EMPTY;
+
+    return i->second_;
 }
 
-TmxTile::TmxTile() : 
+Tile2D::Tile2D() : 
     gid_(0), 
     properties_(0)
 {
+}
 
+Sprite2D* Tile2D::GetSprite() const
+{
+    return sprite_;
 }
 
-bool TmxTile::HasProperty(const String& name) const
+bool Tile2D::HasProperty(const String& name) const
 {
     if (!properties_)
         return false;
     return properties_->HasProperty(name);
 }
 
-const String& TmxTile::GetProperty(const String& name) const
+const String& Tile2D::GetProperty(const String& name) const
 {
     if (!properties_)
         return String::EMPTY;
@@ -84,18 +93,18 @@ const String& TmxTile::GetProperty(const String& name) const
     return properties_->GetProperty(name);
 }
 
-TmxTileLayer2D::TmxTileLayer2D(TmxFile2D* tmxFile) :
-    TmxLayer2D(tmxFile, LT_TILE_LAYER)
+
+TileObject2D::TileObject2D()
 {
-}
 
+}
 
-unsigned TmxObject2D::GetNumPoints() const
+unsigned TileObject2D::GetNumPoints() const
 {
     return points_.Size();
 }
 
-const Vector2& TmxObject2D::GetPoint(unsigned index) const
+const Vector2& TileObject2D::GetPoint(unsigned index) const
 {
     if (index >= points_.Size())
         return Vector2::ZERO;
@@ -103,17 +112,242 @@ const Vector2& TmxObject2D::GetPoint(unsigned index) const
     return points_[index];
 }
 
+Sprite2D* TileObject2D::GetTileSprite() const
+{
+    return sprite_;
+}
+
+bool TileObject2D::HasProperty(const String& name) const
+{
+    return properties_.HasProperty(name);
+}
+
+const String& TileObject2D::GetProperty(const String& name) const
+{
+    return properties_.GetProperty(name);
+}
+
+TmxLayer2D::TmxLayer2D(TmxFile2D* tmxFile, TmxLayerType2D type) :
+    tmxFile_(tmxFile),
+    type_(type)
+{
+
+}
+
+TmxLayer2D::~TmxLayer2D()
+{
+}
+
+TmxFile2D* TmxLayer2D::GetTmxFile() const
+{
+    return tmxFile_;
+}
+
+bool TmxLayer2D::HasProperty(const String& name) const
+{
+    return properties_.HasProperty(name);
+}
+
+const String& TmxLayer2D::GetProperty(const String& name) const
+{
+    return properties_.GetProperty(name);
+}
+
+void TmxLayer2D::LoadInfo(const XMLElement& element)
+{
+    name_ = element.GetAttribute("name");
+    width_ = element.GetInt("width");
+    height_ = element.GetInt("height");
+    if (element.HasAttribute("visible"))
+        visible_ = element.GetInt("visible") != 0;
+    else
+        visible_ = true;
+}
+
+void TmxLayer2D::LoadProperties(const XMLElement& element)
+{
+    properties_.Load(element);
+}
+
+TmxTileLayer2D::TmxTileLayer2D(TmxFile2D* tmxFile) :
+    TmxLayer2D(tmxFile, LT_TILE_LAYER)
+{
+}
+
+bool TmxTileLayer2D::Load(const XMLElement& element)
+{
+    LoadInfo(element);
+
+    XMLElement dataElem = element.GetChild("data");
+    if (!dataElem)
+    {
+        LOGERROR("Could not find data in layer");
+        return false;
+    }
+
+    if (dataElem.HasAttribute("encoding") && dataElem.GetAttribute("encoding") != "xml")
+    {
+        LOGERROR("Encoding not support now");
+        return false;
+    }
+
+    XMLElement tileElem = dataElem.GetChild("tile");
+    tileGids_.Resize(width_ * height_);
+
+    // Flip y
+    for (int y = height_ - 1; y >= 0; --y)
+    {
+        for (int x = 0; x < width_; ++x)
+        {
+            if (!tileElem)
+                return false;
+
+            int gid = tileElem.GetInt("gid");
+            if (gid > 0)
+            {
+                SharedPtr<Tile2D> tile(new Tile2D());
+                tile->gid_ = gid;
+                tile->sprite_ = tmxFile_->GetTileSprite(gid);
+                tile->properties_ = tmxFile_->GetTileProperties(gid);
+                tileGids_[y * width_ + x] = tile;
+            }
+
+            tileElem = tileElem.GetNext("tile");
+        }
+    }
+
+    if (element.HasChild("properties"))
+        LoadProperties(element.GetChild("properties"));
+    
+    return true;
+}
+
+Tile2D* TmxTileLayer2D::GetTile(int x, int y) const
+{
+    if (x < 0 || x > width_ || y < 0 || y > height_)
+        return 0;
+
+    return tileGids_[y * width_ + x];
+}
+
+
+
+
 TmxObjectGroup2D::TmxObjectGroup2D(TmxFile2D* tmxFile) :
     TmxLayer2D(tmxFile, LT_OBJECT_GROUP)
 {
 }
 
 
+bool TmxObjectGroup2D::Load(const XMLElement& element)
+{
+    LoadInfo(element);
+   
+    const float mapHeight = height_ * tmxFile_->GetTileHeight();
+
+    for (XMLElement objectElem = element.GetChild("object"); objectElem; objectElem = objectElem.GetNext("object"))
+    {
+        SharedPtr<TileObject2D> object(new TileObject2D());
+        
+        object->position_ = Vector2(objectElem.GetInt("x") * PIXEL_SIZE, mapHeight - objectElem.GetInt("y") * PIXEL_SIZE);
+        if (objectElem.HasAttribute("width") || objectElem.HasAttribute("height"))
+        {
+            if (!objectElem.HasChild("ellipse"))
+                object->type_ = OT_RECTANGLE;
+            else
+                object->type_ = OT_ELLIPSE;
+
+            object->size_ = Vector2(objectElem.GetInt("width") * PIXEL_SIZE, objectElem.GetInt("height") * PIXEL_SIZE);
+            object->position_.y_ -= object->size_.y_;
+        }
+        else if (objectElem.HasAttribute("gid"))
+        {
+            object->type_ = OT_TILE;
+            object->gid_ = objectElem.GetInt("gid");
+            object->sprite_ = tmxFile_->GetTileSprite(object->gid_);
+        }
+        else
+        {
+            XMLElement childElem = objectElem.GetChild();
+            if (childElem.GetName() == "polygon")
+                object->type_ = OT_POLYGON;
+            else if (childElem.GetName() == "polyline")
+                object->type_ = OT_POLYLINE;
+            else
+                return false;
+
+            Vector<String> points = childElem.GetAttribute("points").Split(' ');
+            object->points_.Resize(points.Size());
+
+            for (unsigned i = 0; i < points.Size(); ++i)
+            {
+                points[i].Replace(',', ' ');
+                Vector2 point = ToVector2(points[i]) * PIXEL_SIZE;
+                point.y_ = mapHeight - point.y_;
+                object->points_[i] = point;
+            }
+        }
+
+        if (objectElem.HasChild("properties"))
+            object->properties_.Load(objectElem.GetChild("properties"));
+
+        objects_.Push(object);
+    }
+
+    if (element.HasChild("properties"))
+        LoadProperties(element.GetChild("properties"));
+
+    return true;
+}
+
+
+TileObject2D* TmxObjectGroup2D::GetObject(unsigned index) const
+{
+    if (index >= objects_.Size())
+        return 0;
+    return objects_[index];
+}
+
+
 TmxImageLayer2D::TmxImageLayer2D(TmxFile2D* tmxFile) :
     TmxLayer2D(tmxFile, LT_IMAGE_LAYER)
 {
 }
 
+bool TmxImageLayer2D::Load(const XMLElement& element)
+{
+    LoadInfo(element);
+
+    XMLElement imageElem = element.GetChild("image");
+    if (!imageElem)
+        return false;
+
+    String textureFilePath = GetParentPath(GetName()) + imageElem.GetAttribute("source");
+    ResourceCache* cache = tmxFile_->GetSubsystem<ResourceCache>();
+    SharedPtr<Texture2D> texture(cache->GetResource<Texture2D>(textureFilePath));
+    if (!texture)
+    {
+        LOGERROR("Could not load texture " + textureFilePath);
+        return false;
+    }
+
+    sprite_ = new Sprite2D(tmxFile_->GetContext());
+    sprite_->SetTexture(texture);
+    sprite_->SetRectangle(IntRect(0, 0, texture->GetWidth(), texture->GetHeight()));
+    // Left top
+    sprite_->SetHotSpot(Vector2(0.0f, 1.0f));
+
+    if (element.HasChild("properties"))
+        LoadProperties(element.GetChild("properties"));
+
+    return true;
+}
+
+Sprite2D* TmxImageLayer2D::GetSprite() const
+{
+    return sprite_;
+}
+
 TmxFile2D::TmxFile2D(Context* context) :
     Resource(context),
     width_(0),
@@ -224,6 +458,23 @@ bool TmxFile2D::EndLoad()
     return true;
 }
 
+Sprite2D* TmxFile2D::GetTileSprite(int gid) const
+{
+    HashMap<int, SharedPtr<Sprite2D> >::ConstIterator i = tileSprites_.Find(gid);
+    if (i == tileSprites_.End())
+        return 0;
+
+    return i->second_;
+}
+
+const Properties2D* TmxFile2D::GetTileProperties(int gid) const
+{
+    HashMap<int, Properties2D>::ConstIterator i = tileProperties_.Find(gid);
+    if (i == tileProperties_.End())
+        return 0;
+    return &(i->second_);
+}
+
 const TmxLayer2D* TmxFile2D::GetLayer(unsigned index) const
 {
     if (index >= layers_.Size())
@@ -236,7 +487,7 @@ const TmxLayer2D* TmxFile2D::GetLayerByName(const String& name) const
 {
     for (unsigned i = 0; i < layers_.Size(); ++i)
     {
-        if (name == layers_[i]->name_)
+        if (name == layers_[i]->GetName())
             return layers_[i];
     }
 
@@ -284,8 +535,8 @@ bool TmxFile2D::LoadTileSet(const XMLElement& element)
     {
         if (tileElem.HasChild("properties"))
         {
-            TmxProperties2D properties;
-            LoadProperties(tileElem.GetChild("properties"), properties);
+            Properties2D properties;
+            properties.Load(tileElem.GetChild("properties"));
             tileProperties_[firstgid + tileElem.GetInt("id")] = properties;
         }
     }
@@ -293,68 +544,13 @@ bool TmxFile2D::LoadTileSet(const XMLElement& element)
     return true;
 }
 
+
 bool TmxFile2D::LoadLayer(const XMLElement& element)
 {
     TmxTileLayer2D* tileLayer = new TmxTileLayer2D(this);
     layers_.Push(tileLayer);
 
-    LoadLayerInfo(element, tileLayer);
-
-    XMLElement dataElem = element.GetChild("data");
-    if (!dataElem)
-    {
-        LOGERROR("Could not find data in layer");
-        return false;
-    }
-
-    if (dataElem.HasAttribute("encoding") && dataElem.GetAttribute("encoding") != "xml")
-    {
-        LOGERROR("Encoding not support now");
-        return false;
-    }
-
-    XMLElement tileElem = dataElem.GetChild("tile");
-    tileLayer->tileGids_.Resize(tileLayer->width_ * tileLayer->height_);
-    
-    // Flip y
-    for (int y = tileLayer->height_ - 1; y >= 0; --y)
-    {
-        for (int x = 0; x < tileLayer->width_; ++x)
-        {
-            if (!tileElem)
-                return false;
-
-            int gid = tileElem.GetInt("gid");
-            tileElem = tileElem.GetNext("tile");
-            TmxTile tile;
-            tile.gid_ = gid;
-            tile.sprite_ = GetTileSprite(gid);
-            tile.properties_ = GetTileProperties(gid);
-            tileLayer->tileGids_[y * tileLayer->width_ + x] = tile;
-        }
-    }
-
-    if (element.HasChild("properties"))
-        LoadProperties(element.GetChild("properties"), *tileLayer);
-
-    return true;
-}
-
-Sprite2D* TmxFile2D::GetTileSprite(int gid) const
-{
-    HashMap<int, SharedPtr<Sprite2D> >::ConstIterator i = tileSprites_.Find(gid);
-    if (i == tileSprites_.End())
-        return 0;
-
-    return i->second_;
-}
-
-const TmxProperties2D* TmxFile2D::GetTileProperties(int gid) const
-{
-    HashMap<int, TmxProperties2D>::ConstIterator i = tileProperties_.Find(gid);
-    if (i == tileProperties_.End())
-        return 0;
-    return &(i->second_);
+    return tileLayer->Load(element);
 }
 
 bool TmxFile2D::LoadObjectGroup(const XMLElement& element)
@@ -362,67 +558,7 @@ bool TmxFile2D::LoadObjectGroup(const XMLElement& element)
     TmxObjectGroup2D* objectGroup = new TmxObjectGroup2D(this);
     layers_.Push(objectGroup);
 
-    LoadLayerInfo(element, objectGroup);
-
-    const float mapHeight = height_ * tileHeight_;
-
-    for (XMLElement objectElem = element.GetChild("object"); objectElem; objectElem = objectElem.GetNext("object"))
-    {
-        objectGroup->objects_.Push(TmxObject2D());
-        TmxObject2D& object = objectGroup->objects_.Back();
-
-        object.x_ = objectElem.GetInt("x") * PIXEL_SIZE;
-        // Flip y
-        object.y_ = mapHeight - objectElem.GetInt("y") * PIXEL_SIZE;
-
-        if (objectElem.HasAttribute("width") || objectElem.HasAttribute("height"))
-        {
-            if (!objectElem.HasChild("ellipse"))
-                object.type_ = OT_RECTANGLE;
-            else
-                object.type_ = OT_ELLIPSE;
-
-            object.width_ = objectElem.GetInt("width") * PIXEL_SIZE;
-            object.height_ = objectElem.GetInt("height") * PIXEL_SIZE;
-
-            object.y_ -= object.height_;
-        }
-        else if (objectElem.HasAttribute("gid"))
-        {
-            object.type_ = OT_TILE;
-            object.gid_ = objectElem.GetInt("gid");
-            object.sprite_ = GetTileSprite(object.gid_);
-        }
-        else
-        {
-            XMLElement childElem = objectElem.GetChild();
-            if (childElem.GetName() == "polygon")
-                object.type_ = OT_POLYGON;
-            else if (childElem.GetName() == "polyline")
-                object.type_ = OT_POLYLINE;
-            else
-                return false;
-
-            Vector<String> points = childElem.GetAttribute("points").Split(' ');
-            object.points_.Resize(points.Size());
-            
-            for (unsigned i = 0; i < points.Size(); ++i)
-            {
-                points[i].Replace(',', ' ');
-                Vector2 point = ToVector2(points[i]) * PIXEL_SIZE;
-                point.y_ = mapHeight - point.y_;
-                object.points_[i] = point;
-            }
-        }
-
-        if (objectElem.HasChild("properties"))
-            LoadProperties(objectElem.GetChild("properties"), object);
-    }
-
-    if (element.HasChild("properties"))
-        LoadProperties(element.GetChild("properties"), *objectGroup);
-
-    return true;
+    return objectGroup->Load(element);
 }
 
 bool TmxFile2D::LoadImageLayer(const XMLElement& element)
@@ -430,51 +566,6 @@ bool TmxFile2D::LoadImageLayer(const XMLElement& element)
     TmxImageLayer2D* imageLayer = new TmxImageLayer2D(this);
     layers_.Push(imageLayer);
 
-    LoadLayerInfo(element, imageLayer);
-
-    XMLElement imageElem = element.GetChild("image");
-    if (!imageElem)
-        return false;
-
-    String textureFilePath = GetParentPath(GetName()) + imageElem.GetAttribute("source");
-    ResourceCache* cache = GetSubsystem<ResourceCache>();
-    SharedPtr<Texture2D> texture(cache->GetResource<Texture2D>(textureFilePath));
-    if (!texture)
-    {
-        LOGERROR("Could not load texture " + textureFilePath);
-        return false;
-    }
-
-    SharedPtr<Sprite2D> sprite(new Sprite2D(context_));
-    sprite->SetTexture(texture);
-    sprite->SetRectangle(IntRect(0, 0, texture->GetWidth(), texture->GetHeight()));
-    // Left top
-    sprite->SetHotSpot(Vector2(0.0f, 1.0f));
-    
-    imageLayer->sprite_ = sprite;
-
-    if (element.HasChild("properties"))
-        LoadProperties(element.GetChild("properties"), *imageLayer);
-
-    return true;
+    return imageLayer->Load(element);
 }
-
-void TmxFile2D::LoadLayerInfo(const XMLElement& element, TmxLayer2D* layer)
-{
-    layer->name_ = element.GetAttribute("name");
-    layer->width_ = element.GetInt("width");
-    layer->height_ = element.GetInt("height");
-    if (element.HasAttribute("visible"))
-        layer->visible_ = element.GetInt("visible") != 0;
-    else
-        layer->visible_ = true;
-}
-
-void TmxFile2D::LoadProperties(const XMLElement& element, TmxProperties2D& properties)
-{
-    for (XMLElement propertyElem = element.GetChild("property"); propertyElem; propertyElem = propertyElem.GetNext("property"))
-        properties.properties_[propertyElem.GetAttribute("name")] = propertyElem.GetAttribute("value");
-}
-
-
 }

+ 148 - 69
Source/Engine/Urho2D/TmxFile2D.h

@@ -35,80 +35,53 @@ class TmxFile2D;
 class XMLElement;
 class XMLFile;
 
-/// Tmx peroperies.
-struct URHO3D_API TmxProperties2D
+/// Peroperies.
+class URHO3D_API Properties2D
 {
+public:
+    Properties2D();
+    virtual ~Properties2D();
+
+    /// Load from XML element.
+    void Load(const XMLElement& element);
     /// Return has property (use for script).
     bool HasProperty(const String& name) const;
     /// Return property value (use for script).
     const String& GetProperty(const String& name) const;
 
+protected:
     /// Properties.
     HashMap<String, String> properties_;
 };
 
-/// Tmx layer type.
-enum TmxLayerType2D
-{
-    /// Tile layer.
-    LT_TILE_LAYER = 0,
-    /// Object group.
-    LT_OBJECT_GROUP,
-    /// Image layer.
-    LT_IMAGE_LAYER,
-    /// Invalid.
-    LT_INVALID,
-};
-
-/// Tmx layer.
-struct URHO3D_API TmxLayer2D : TmxProperties2D
+/// Tile.
+class URHO3D_API Tile2D : public RefCounted
 {
-    TmxLayer2D(TmxFile2D* tmxFile, TmxLayerType2D type);
-    virtual ~TmxLayer2D();
-
-    /// Tmx file.
-    WeakPtr<TmxFile2D> tmxFile_;
-    /// Layer type.
-    TmxLayerType2D type_;
-    /// Name.
-    String name_;
-    /// Width.
-    int width_;
-    /// Height.
-    int height_;
-    /// Visible.
-    bool visible_;
-};
-
-/// Tmx tile.
-struct URHO3D_API TmxTile
-{
-    TmxTile();
+public:
+    /// Construct.
+    Tile2D();
 
+    /// Return gid.
+    int GetGid() const { return gid_; }
+    /// Return sprite.
+    Sprite2D* GetSprite() const;
     /// Return has property.
     bool HasProperty(const String& name) const;
     /// Return property.
     const String& GetProperty(const String& name) const;
 
+private:
+    friend class TmxTileLayer2D;
     /// Gid.
     int gid_;
     /// Sprite.
     SharedPtr<Sprite2D> sprite_;
     /// Properties.
-    const TmxProperties2D* properties_;
+    const Properties2D* properties_;
 };
 
-/// Tmx tile layer.
-struct URHO3D_API TmxTileLayer2D : TmxLayer2D
-{
-    TmxTileLayer2D(TmxFile2D* tmxFile);
-
-    /// Tile.
-    Vector<TmxTile> tileGids_;
-};
-
-/// Object type.
-enum TmxObjectType
+/// Tile object type.
+enum TileObjectType2D
 {
     /// Rectangle.
     OT_RECTANGLE = 0,
@@ -122,43 +95,153 @@ enum TmxObjectType
     OT_TILE,
 };
 
-/// Tmx object.
-struct URHO3D_API TmxObject2D : TmxProperties2D
+/// Tile map object.
+class URHO3D_API TileObject2D : public RefCounted
 {
+public:
+    TileObject2D();;
+    /// Return type.
+    TileObjectType2D GetType() const { return type_; }
+    /// Return position.
+    const Vector2& GetPosition() const { return position_; }
+    /// Return size (for rectangle and ellipse).
+    const Vector2& GetSize() const { return size_; }
     /// Return number of points (use for script).
     unsigned GetNumPoints() const;
     /// Return point at index (use for script).
     const Vector2& GetPoint(unsigned index) const;
-    
+    /// Return tile Gid.
+    int GetTileGid() const { return gid_; }
+    /// Return tile sprite.
+    Sprite2D* GetTileSprite() const;
+    /// Return has property.
+    bool HasProperty(const String& name) const;
+    /// Return property value.
+    const String& GetProperty(const String& name) const;
+
+private:
+    friend class TmxObjectGroup2D;
     /// Object type.
-    TmxObjectType type_;
+    TileObjectType2D type_;
     /// Position.
-    float x_, y_;
+    Vector2 position_;
     /// Size (for rectangle and ellipse).
-    float width_, height_;
+    Vector2 size_;
     /// Points(for polygon and polyline).
     Vector<Vector2> points_;
-
     /// Gid (for tile).
     int gid_;
     /// Sprite (for tile).
     SharedPtr<Sprite2D> sprite_;
+    /// Properties.
+    Properties2D  properties_;
+};
+
+/// Tmx layer type.
+enum TmxLayerType2D
+{
+    /// Tile layer.
+    LT_TILE_LAYER = 0,
+    /// Object group.
+    LT_OBJECT_GROUP,
+    /// Image layer.
+    LT_IMAGE_LAYER,
+    /// Invalid.
+    LT_INVALID,
+};
+
+/// Tmx layer.
+class TmxLayer2D : public RefCounted
+{
+public:
+    TmxLayer2D(TmxFile2D* tmxFile, TmxLayerType2D type);
+    virtual ~TmxLayer2D();
+
+    /// Return tmx file.
+    TmxFile2D* GetTmxFile() const;
+    /// Return type.
+    TmxLayerType2D GetType() const { return type_; }
+    /// Return name.
+    const String& GetName() const { return name_; }
+    /// Return width.
+    int GetWidth() const { return width_; }
+    /// Return height.
+    int GetHeight() const { return height_; }
+    /// Return is visible.
+    bool IsVisible() const { return visible_; }
+    /// Return has property (use for script).
+    bool HasProperty(const String& name) const;
+    /// Return property value (use for script).
+    const String& GetProperty(const String& name) const;
+
+
+protected:
+    /// Load layer info.
+    void LoadInfo(const XMLElement& element);
+    /// Load properties.
+    void LoadProperties(const XMLElement& element);
+
+    /// Tmx file.
+    WeakPtr<TmxFile2D> tmxFile_;
+    /// Layer type.
+    TmxLayerType2D type_;
+    /// Name.
+    String name_;
+    /// Width.
+    int width_;
+    /// Height.
+    int height_;
+    /// Visible.
+    bool visible_;
+    /// Properties.
+    Properties2D properties_;
+};
+
+/// Tmx tile layer.
+class TmxTileLayer2D : public TmxLayer2D
+{
+public:
+    TmxTileLayer2D(TmxFile2D* tmxFile);
+
+    /// Load from xml element.
+    bool Load(const XMLElement& element);
+    /// Return tile.
+    Tile2D* GetTile(int x, int y) const;
+protected:
+    /// Tile.
+    Vector<SharedPtr<Tile2D> > tileGids_;
 };
 
 /// Tmx image layer.
-struct URHO3D_API TmxObjectGroup2D : TmxLayer2D
+class TmxObjectGroup2D : public TmxLayer2D
 {
+public:
     TmxObjectGroup2D(TmxFile2D* tmxFile);
 
+    /// Load from XML element.
+    bool Load(const XMLElement& element);
+    /// Return number of objects.
+    unsigned GetNumObjects() const { return objects_.Size(); }
+    /// Return object at index.
+    TileObject2D* GetObject(unsigned index) const;
+
+private:
     /// Objects.
-    Vector<TmxObject2D> objects_;
+    Vector<SharedPtr<TileObject2D> > objects_;
 };
 
 /// Tmx image layer.
-struct URHO3D_API TmxImageLayer2D : TmxLayer2D
+class TmxImageLayer2D : public TmxLayer2D
 {
+public:
     TmxImageLayer2D(TmxFile2D* tmxFile);
 
+    /// Load from XML element.
+    bool Load(const XMLElement& element);
+    /// Return sprite.
+    Sprite2D* GetSprite() const;
+    
+private:
     /// Sprite.
     SharedPtr<Sprite2D> sprite_;
 };
@@ -189,6 +272,10 @@ public:
     float GetTileWidth() const { return tileWidth_; }
     /// Return tile height.
     float GetTileHeight() const { return tileHeight_; }
+    /// Return tile sprite by gid.
+    Sprite2D* GetTileSprite(int gid) const;
+    /// Return tile properties by gid.
+    const Properties2D* GetTileProperties(int gid) const;
     /// Return number of layers.
     unsigned GetNumLayers() const { return layers_.Size(); }
     /// Return layer at index.
@@ -201,18 +288,10 @@ private:
     bool LoadTileSet(const XMLElement& element);
     /// Load layer.
     bool LoadLayer(const XMLElement& element);
-    /// Return tile sprite by gid.
-    Sprite2D* GetTileSprite(int gid) const;
-    /// Return tile properties by gid.
-    const TmxProperties2D* GetTileProperties(int gid) const;
     /// Load object group.
     bool LoadObjectGroup(const XMLElement& element);
     /// Load image layer.
     bool LoadImageLayer(const XMLElement& element);
-    /// Load layer info.
-    void LoadLayerInfo(const XMLElement& element, TmxLayer2D* layer);
-    /// Load properties.
-    void LoadProperties(const XMLElement& element, TmxProperties2D& peoperties);
 
     /// XML file used during loading.
     SharedPtr<XMLFile> loadXMLFile_;
@@ -229,7 +308,7 @@ private:
     /// Gid to tile sprite mapping.
     HashMap<int, SharedPtr<Sprite2D> > tileSprites_;
     /// Gid to tile properties mapping.
-    HashMap<int, TmxProperties2D> tileProperties_;
+    HashMap<int, Properties2D> tileProperties_;
     /// Layers.
     Vector<TmxLayer2D*> layers_;
 };