bool PhyTileEngine::IsRectCollidesTile(core::recti rect_, video::SColor blockType_, int tileX, int tileY)
{
	const LayerTile* layerTile = m_physicLayerTile->GetLayerTile(tileX, tileY);

	if (layerTile->GetTilesetId() >= 0)
    {
		Tileset* tileset = m_tilemap->GetTileset( layerTile->GetTilesetId() );
		video::ITexture* tilesetText = tileset->GetTexture( m_driver );

		// Get intersection with physic layer image to be in bounds
		core::recti srcRect = rect_;
		core::recti tileRect( tileX * m_tilemap->GetTileWidth(), tileY * m_tilemap->GetTileHeight(), (tileX + 1) * m_tilemap->GetTileWidth(), (tileY + 1) * m_tilemap->GetTileHeight() );
		//srcRect.clipAgainst(tileRect);
		srcRect.UpperLeftCorner.X =  core::max_( rect_.UpperLeftCorner.X, tileRect.UpperLeftCorner.X);
		srcRect.LowerRightCorner.X =  core::min_( rect_.LowerRightCorner.X, tileRect.LowerRightCorner.X);
		srcRect.UpperLeftCorner.Y =  core::max_( rect_.UpperLeftCorner.Y, tileRect.UpperLeftCorner.Y);
		srcRect.LowerRightCorner.Y =  core::min_( rect_.LowerRightCorner.Y, tileRect.LowerRightCorner.Y);

        // move to tileset coords
		s32 rectWidth = srcRect.getWidth();
		s32 rectHeight = srcRect.getHeight();
		srcRect.UpperLeftCorner.X = (srcRect.UpperLeftCorner.X % m_tilemap->GetTileWidth()) + tileset->GetTileX(layerTile->GetTileId()) * m_tilemap->GetTileWidth();
		srcRect.UpperLeftCorner.Y = (srcRect.UpperLeftCorner.Y % m_tilemap->GetTileHeight()) + tileset->GetTileY(layerTile->GetTileId()) * m_tilemap->GetTileHeight();

		srcRect.LowerRightCorner.X = srcRect.UpperLeftCorner.X + rectWidth;
		srcRect.LowerRightCorner.Y = srcRect.UpperLeftCorner.Y + rectHeight;

		u8* pixelData = static_cast<u8 *>( tilesetText->lock(true) );
		core::dimension2du textSize = tilesetText->getSize();
		u32 pixelSize = tilesetText->getPitch() / textSize.Width;
		
		bool isCollision = false;

		//!!!NOTE: suppose format video::ECOLOR_FORMAT::ECF_A8R8G8B8
		for( s32 x = srcRect.UpperLeftCorner.X; x < srcRect.LowerRightCorner.X && !isCollision; ++x )
		for( s32 y = srcRect.UpperLeftCorner.Y; y < srcRect.LowerRightCorner.Y && !isCollision; ++y )
		{
			s32 index = y * tilesetText->getPitch() + x * pixelSize;

			video::SColor color( *((u32*)(pixelData + index)) );

			if( color == blockType_ )
			{
				isCollision = true;
			}
		}

		tilesetText->unlock();
        
        return isCollision;
    }

    return false;
}
void TileLayer::parseElement(tinyxml2::XMLElement* layerElement, Map* map)
{
	// Get properties
	auto properties = layerElement->FirstChildElement("properties");
	if(properties != 0)
		parseProperties(properties);

	m_name = layerElement->Attribute("name");
	m_width = layerElement->UnsignedAttribute("width");
	m_height = layerElement->UnsignedAttribute("height");

	// Parse data
	unsigned int x = 0;
	unsigned int y = 0;
	auto tile = layerElement->FirstChildElement("data")->FirstChildElement("tile");
	while(tile != 0)
	{
		unsigned int gid = tile->UnsignedAttribute("gid");

		// Read out the flags
		bool flipped_horizontally = (gid & FLIPPED_HORIZONTALLY_FLAG) != 0;
		bool flipped_vertically = (gid & FLIPPED_VERTICALLY_FLAG) != 0;
        // TODO: implement this
		//bool flipped_diagonally = (gid & FLIPPED_DIAGONALLY_FLAG) != 0;

		// Clear the flags
		gid &= ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG
			| FLIPPED_DIAGONALLY_FLAG);

		// Find correct tileset
		for(int i = map->tilesets.size() - 1; i >= 0; --i)
		{
			Tileset* tileset = map->tilesets[i];

			if(tileset->GetFirstGID() <= gid)
			{
				if(x >= map->GetWidth())
				{
					x = 0;
					y++;
				}

				const pmath::Rect t(static_cast<float>(x * tileset->GetTileWidth()), static_cast<float>(y * tileset->GetTileHeight()),
					static_cast<float>(tileset->GetTileWidth()), static_cast<float>(tileset->GetTileHeight()));

				auto tile = new Tile(t);

				if(flipped_horizontally)
					tile->transform.SetScale(-1, tile->transform.GetScale().y);
				if(flipped_vertically)
                    tile->transform.SetScale(tile->transform.GetScale().x, -1);

				tile->parent = static_cast<GameObject*>(map);
				const pmath::Rect texCoords = tileset->GetTile(gid - tileset->GetFirstGID());

				m_tiles.push_back(tile);
				m_spriteBatches.at(tileset->GetTexture())->AddSprite(&tile->transform, "", pmath::Vec4(1,1,1,1),  texCoords);
				x++;
				break;
			}
		}
		tile = tile->NextSiblingElement("tile");
	}
}
void TileLayer::parseElement(tinyxml2::XMLElement* layerElement, Map* map)
{
	// Get properties
	auto properties = layerElement->FirstChildElement("properties");
	if(properties != 0)
		parseProperties(properties);

	m_name = layerElement->Attribute("name");
	m_width = layerElement->UnsignedAttribute("width");
	m_height = layerElement->UnsignedAttribute("height");
    if (layerElement->Attribute("visible") != 0)
    {
        m_active = layerElement->IntAttribute("visible") == 0 ? false : true;
    }
    else
        m_active = true;

	// Parse data
	unsigned int x = 0;
	unsigned int y = 0;
	auto tile = layerElement->FirstChildElement("data")->FirstChildElement("tile");
	while(tile != 0)
	{
		unsigned int gid = tile->UnsignedAttribute("gid");

        // Go to the next "line"
        if (x >= map->GetWidth())
        {
            x = 0;
            y++;
        }

        // Tile is "empty space"
        if (gid == 0)
        {
            x++;
            tile = tile->NextSiblingElement("tile");
            continue;
        }

		// Read out the flags
		const bool flipped_horizontally = (gid & FLIPPED_HORIZONTALLY_FLAG) != 0;
		const bool flipped_vertically = (gid & FLIPPED_VERTICALLY_FLAG) != 0;
		const bool flipped_diagonally = (gid & FLIPPED_DIAGONALLY_FLAG) != 0;

		// Clear the flags
		gid &= ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG
			| FLIPPED_DIAGONALLY_FLAG);

		// Find correct tileset
		for(int i = map->tilesets.size() - 1; i >= 0; --i)
		{
			Tileset* tileset = map->tilesets[i].get();

            if (tileset->GetFirstGID() <= gid)
            {
                const pmath::Rect t(static_cast<float>(x * tileset->GetTileWidth()), static_cast<float>(y * tileset->GetTileHeight()),
                    static_cast<float>(tileset->GetTileWidth()), static_cast<float>(tileset->GetTileHeight()));

                auto tile = new Tile(t);

                if (flipped_diagonally)
                {
                    if (flipped_horizontally && flipped_vertically)
                    {
                        tile->transform.Rotate(90);
                        tile->transform.SetScale(-1, tile->transform.GetScale().y);
                    }
                    else if (flipped_horizontally)
                    {
                        tile->transform.Rotate(90);
                    }
                    else if (flipped_vertically)
                    {
                        tile->transform.Rotate(-90);
                    }
                    else
                    {
                        tile->transform.Rotate(-90);
                        tile->transform.SetScale(-1, tile->transform.GetScale().y);
                    }
                        
                }
                else
                {
                    if (flipped_horizontally)
                        tile->transform.SetScale(-1, tile->transform.GetScale().y);
                    if (flipped_vertically)
                        tile->transform.SetScale(tile->transform.GetScale().x, -1);
                }

				map->AddChild(tile);
                const pmath::Rect texCoords = tileset->GetTile(gid - tileset->GetFirstGID());

                m_tiles.push_back(tile);
                m_spriteBatches.at(tileset->GetTexture())->AddSprite(&tile->transform, "", pmath::Vec4(1, 1, 1, 1), texCoords);
                x++;
                break;
            }
		}
		tile = tile->NextSiblingElement("tile");
	}
}