void TransitionTerrain::addTransitionOnMap(Tiled::Map &tiledMap)
{
    const unsigned int w=tiledMap.width();
    const unsigned int h=tiledMap.height();

    //list the layer name to parse
    QHash<QString,LoadMap::Terrain> transition;
    QStringList transitionList;
    for(int height=0;height<5;height++)
        for(int moisure=0;moisure<6;moisure++)
        {
            LoadMap::Terrain &terrain=LoadMap::terrainList[height][moisure];
            if(!terrain.tmp_layerString.isEmpty())
            {
                if(!transitionList.contains(terrain.terrainName))
                {
                    transition[terrain.terrainName]=terrain;
                    transitionList << terrain.terrainName;
                }
            }
        }

    {
        Tiled::TileLayer * transitionLayerMask=LoadMap::searchTileLayerByName(tiledMap,"OnGrass");
        Tiled::TileLayer * const colisionLayerMask=LoadMap::searchTileLayerByName(tiledMap,"Collisions");
        unsigned int index=0;
        while(index<(unsigned int)transitionList.size())
        {
            const LoadMap::Terrain &terrain=transition.value(transitionList.at(index));
            Tiled::TileLayer * terrainLayer=terrain.tileLayer;
            Tiled::TileLayer * transitionLayer=NULL;
            uint16_t XORop;
            if(terrain.outsideBorder)
            {
                transitionLayer=terrainLayer;
                XORop=0x01ff;
            }
            else
            {
                const unsigned int index=LoadMap::searchTileIndexByName(tiledMap,terrain.tmp_layerString);
                Tiled::Layer * rawLayer=tiledMap.layerAt(index+1);
                if(!rawLayer->isTileLayer())
                {
                    std::cerr << "Next layer after " << terrain.tmp_layerString.toStdString() << "is not tile layer (abort)" << std::endl;
                    abort();
                }
                transitionLayer=static_cast<Tiled::TileLayer *>(rawLayer);
                transitionLayerMask=transitionLayer;
                XORop=0x0000;
            }
            unsigned int y=0;
            while(y<h)
            {
                unsigned int x=0;
                while(x<w)
                {
                    const bool innerBool=!XORop && (terrainLayer->cellAt(x,y).tile==terrain.tile);
                    const unsigned int &bitMask=x+y*w;
                    const bool outerBool=XORop && terrainLayer->cellAt(x,y).tile!=terrain.tile && !(MapBrush::mapMask[bitMask/8] & (1<<(7-bitMask%8)));
                    if(
                            //inner
                            innerBool ||
                            //outer
                            outerBool
                            )
                    {
                        //check the near tile and determine what transition use
                        const uint16_t to_type_match=layerMask(terrainLayer,x,y,terrain.tile,XORop);
                        if(to_type_match>512)
                            abort();

                        if(to_type_match!=0 && to_type_match!=16)
                        {
                            unsigned int indexTile=0;
                            if(XORop)
                            {
                                const uint16_t to_type_match_collision=layerMask(colisionLayerMask,x,y,NULL,false);
                                const bool onGrass=transitionLayerMask->cellAt(x,y).tile!=NULL;
                                bool forceDisplay=false;
                                //outer border
                                if(to_type_match&2)
                                {
                                    if(to_type_match&8)
                                    {
                                        indexTile=8;
                                    }
                                    else if(to_type_match&32)
                                    {
                                        indexTile=9;
                                    }
                                    else
                                    {
                                        indexTile=5;
                                        if(to_type_match_collision&8 && to_type_match_collision&32)
                                            forceDisplay=true;
                                    }
                                }
                                else if(to_type_match&128)
                                {
                                    if(to_type_match&8)
                                    {
                                        indexTile=11;
                                    }
                                    else if(to_type_match&32)
                                    {
                                        indexTile=10;
                                    }
                                    else
                                    {
                                        indexTile=1;
                                        if(to_type_match_collision&8 && to_type_match_collision&32)
                                            forceDisplay=true;
                                    }
                                }
                                else if(to_type_match&8)
                                {
                                    indexTile=3;
                                    if(to_type_match_collision&2 && to_type_match_collision&128)
                                        forceDisplay=true;
                                }
                                else if(to_type_match&32)
                                {
                                    indexTile=7;
                                    if(to_type_match_collision&2 && to_type_match_collision&128)
                                        forceDisplay=true;
                                }
                                else if(to_type_match&256)
                                {
                                    indexTile=0;
                                    if(!(to_type_match_collision&256))
                                    {
                                        if(to_type_match_collision&32 && to_type_match_collision&128)
                                            forceDisplay=true;
                                        if(to_type_match_collision&8 && to_type_match_collision&32)
                                            forceDisplay=true;
                                        if(to_type_match_collision&2 && to_type_match_collision&128)
                                            forceDisplay=true;
                                    }
                                }
                                else if(to_type_match&64)
                                {
                                    indexTile=2;
                                    if(!(to_type_match_collision&64))
                                    {
                                        if(to_type_match_collision&8 && to_type_match_collision&128)
                                            forceDisplay=true;
                                        if(to_type_match_collision&8 && to_type_match_collision&32)
                                            forceDisplay=true;
                                        if(to_type_match_collision&2 && to_type_match_collision&128)
                                            forceDisplay=true;
                                    }
                                }
                                else if(to_type_match&1)
                                {
                                    indexTile=4;
                                    if(!(to_type_match_collision&1))
                                    {
                                        if(to_type_match_collision&2 && to_type_match_collision&8)
                                            forceDisplay=true;
                                        if(to_type_match_collision&8 && to_type_match_collision&32)
                                            forceDisplay=true;
                                        if(to_type_match_collision&2 && to_type_match_collision&128)
                                            forceDisplay=true;
                                    }
                                }
                                else if(to_type_match&4)
                                {
                                    indexTile=6;
                                    if(!(to_type_match_collision&4))
                                    {
                                        if(to_type_match_collision&2 && to_type_match_collision&32)
                                            forceDisplay=true;
                                        if(to_type_match_collision&8 && to_type_match_collision&32)
                                            forceDisplay=true;
                                        if(to_type_match_collision&2 && to_type_match_collision&128)
                                            forceDisplay=true;
                                    }
                                }

                                if(!onGrass || forceDisplay)
                                {
                                    Tiled::Cell cell;
                                    cell.tile=terrain.transition_tile.at(indexTile);
                                    cell.flippedHorizontally=false;
                                    cell.flippedVertically=false;
                                    cell.flippedAntiDiagonally=false;
                                    transitionLayer->setCell(x,y,cell);
                                }
                            }
                            else
                            {
                                //inner border
                                if(to_type_match&2)
                                {
                                    if(to_type_match&8)
                                        indexTile=0;
                                    else if(to_type_match&32)
                                        indexTile=2;
                                    else
                                        indexTile=1;
                                }
                                else if(to_type_match&128)
                                {
                                    if(to_type_match&8)
                                        indexTile=6;
                                    else if(to_type_match&32)
                                        indexTile=4;
                                    else
                                        indexTile=5;
                                }
                                else if(to_type_match&8)
                                    indexTile=7;
                                else if(to_type_match&32)
                                    indexTile=3;
                                else if(to_type_match&256)
                                    indexTile=8;
                                else if(to_type_match&64)
                                    indexTile=9;
                                else if(to_type_match&1)
                                    indexTile=10;
                                else if(to_type_match&4)
                                    indexTile=11;

                                Tiled::Cell cell;
                                cell.tile=terrain.transition_tile.at(indexTile);
                                cell.flippedHorizontally=false;
                                cell.flippedVertically=false;
                                cell.flippedAntiDiagonally=false;
                                transitionLayer->setCell(x,y,cell);
                            }
                        }
                    }
                    x++;
                }
                y++;
            }
            index++;
        }
    }
}
void TransitionTerrain::mergeDown(Tiled::Map &tiledMap)
{
    const unsigned int w=tiledMap.width();
    const unsigned int h=tiledMap.height();

    std::vector<Tiled::TileLayer *> layerToDelete;
    unsigned int terrainIndex=0;
    while(terrainIndex<(unsigned int)LoadMap::terrainFlatList.size())
    {
        const QString &terrainName=LoadMap::terrainFlatList.at(terrainIndex);
        LoadMap::Terrain * terrain=LoadMap::terrainNameToObject.value(terrainName);
        if(terrain->outsideBorder)
        {
            Tiled::TileLayer * const transitionLayerMask=LoadMap::searchTileLayerByName(tiledMap,"[T]"+terrainName);
            layerToDelete.push_back(transitionLayerMask);

            //search the layer
            int tileLayerIndex=0;
            while(true)
            {
                if(tiledMap.layerCount()<tileLayerIndex)
                {
                    std::cerr << "tiledMap.layerCount()<tileLayerIndexTemp (abort)" << std::endl;
                    abort();
                }
                Tiled::Layer * tempLayer=tiledMap.layerAt(tileLayerIndex);
                if(tempLayer->isTileLayer() &&
                        //tempLayer==transitionLayerMask
                        tempLayer->name()==terrain->tmp_layerString
                        )
                    break;
                else
                    tileLayerIndex++;
            }

            unsigned int y=0;
            while(y<h)
            {
                unsigned int x=0;
                while(x<w)
                {
                    const Tiled::Cell &cell=transitionLayerMask->cellAt(x,y);
                    if(cell.tile!=NULL)
                    {
                        int tileLayerIndexTemp=tileLayerIndex;
                        while(true)
                        {
                            if(tiledMap.layerCount()<tileLayerIndexTemp)
                            {
                                std::cerr << "tiledMap.layerCount()<tileLayerIndexTemp (abort)" << std::endl;
                                abort();
                            }
                            Tiled::Layer * tempLayer=tiledMap.layerAt(tileLayerIndexTemp);
                            if(!tempLayer->isTileLayer())
                            {
                                std::cerr << "!tempLayer->isTileLayer() (abort)" << std::endl;
                                abort();
                            }
                            if(static_cast<Tiled::TileLayer *>(tempLayer)->cellAt(x,y).tile!=NULL)
                            {
                                if(cell.tile!=terrain->tile)
                                    tileLayerIndexTemp++;
                                else
                                {
                                    tileLayerIndexTemp++;
                                    //clean the upper layer
                                    while(tileLayerIndexTemp<(tileLayerIndex+3))
                                    {
                                        Tiled::TileLayer * tileLayer=static_cast<Tiled::TileLayer *>(tiledMap.layerAt(tileLayerIndexTemp));
                                        Tiled::Cell cell;
                                        cell.tile=NULL;
                                        cell.flippedHorizontally=false;
                                        cell.flippedVertically=false;
                                        cell.flippedAntiDiagonally=false;
                                        tileLayer->setCell(x,y,cell);
                                        tileLayerIndexTemp++;
                                    }
                                    tileLayerIndexTemp=tileLayerIndex;
                                    break;
                                }
                            }
                            else
                                break;
                        }
                        Tiled::TileLayer * tileLayer=static_cast<Tiled::TileLayer *>(tiledMap.layerAt(tileLayerIndexTemp));
                        tileLayer->setCell(x,y,cell);
                    }
                    x++;
                }
                y++;
            }
        }
        terrainIndex++;
    }
    unsigned int index=0;
    while(index<layerToDelete.size())
    {
        Tiled::TileLayer * layer=layerToDelete.at(index);
        //layer->setVisible(false);
        const int indexOfLayer=tiledMap.indexOfLayer(layer->name());
        if(indexOfLayer>=0)
            delete tiledMap.takeLayerAt(indexOfLayer);
        index++;
    }
}