Ticket #1109: 1109_Recenter_Undo.patch

File 1109_Recenter_Undo.patch, 65.8 KB (added by Stephen Imhoff, 8 years ago)

Patch with true undo.

  • source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp

    From 75012b00bd27005072c392c868cf66161a4ca0d0 Mon Sep 17 00:00:00 2001
    From: "Stephen A. Imhoff" <clockwork-muse@outlook.com>
    Date: Wed, 28 Sep 2016 12:25:45 -0700
    Subject: [PATCH] True undo
    
    ---
     .../MapResizeDialog/MapResizeDialog.cpp            |  2 +-
     .../atlas/GameInterface/Handlers/MapHandlers.cpp   | 45 +++++++++++++++++++++-
     2 files changed, 45 insertions(+), 2 deletions(-)
    
    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp
    index 778d0ff..69cf276 100644
    a b MapResizeDialog::MapResizeDialog(wxWindow* parent)  
    3636
    3737    SetTitle(_("Resize map"));
    3838    wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
    39     wxStaticText* label = new wxStaticText(this, wxID_ANY, _("Select new map size. WARNING: This probably only works reliably on blank maps."), wxDefaultPosition, wxDefaultSize);
     39    wxStaticText* label = new wxStaticText(this, wxID_ANY, _("Select new map size."), wxDefaultPosition, wxDefaultSize);
    4040    sizer->Add(label, wxSizerFlags().Align(wxALIGN_CENTER_HORIZONTAL).Border(wxALL, 10));
    4141
    4242    wxBoxSizer* listAndMap = new wxBoxSizer(wxHORIZONTAL);
  • source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp

    diff --git a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
    index 84fc124..c079001 100644
    a b BEGIN_COMMAND(ResizeMap)  
    430430    int m_OldPatches, m_NewPatches;
    431431    int m_OffsetX, m_OffsetY;
    432432
     433    u16* m_Heightmap;
     434    CPatch* m_Patches;
     435
    433436    std::vector<DeletedObject> m_DeletedObjects;
    434437
    435438    std::vector<std::pair<entity_id_t, CFixedVector3D>> m_OldPositions;
    BEGIN_COMMAND(ResizeMap)  
    439442    {
    440443    }
    441444
     445    ~cResizeMap()
     446    {
     447        delete m_Heightmap;
     448        delete m_Patches;
     449    }
     450
    442451    void MakeDirty()
    443452    {
    444453        CmpPtr<ICmpTerrain> cmpTerrain(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
    BEGIN_COMMAND(ResizeMap)  
    524533            m_OffsetX = msg->offsetX / PATCH_SIZE;
    525534            // Need to flip direction of vertical offset, due to screen mapping order.
    526535            m_OffsetY = -(msg->offsetY / PATCH_SIZE);
     536
     537            CTerrain* terrain = cmpTerrain->GetCTerrain();
     538            m_Heightmap = new u16[(m_OldPatches * PATCH_SIZE + 1) * (m_OldPatches * PATCH_SIZE + 1)];
     539            std::copy_n(terrain->GetHeightMap(), (m_OldPatches * PATCH_SIZE + 1) * (m_OldPatches * PATCH_SIZE + 1), m_Heightmap);
     540            m_Patches = new CPatch[m_OldPatches * m_OldPatches];
     541            for (ssize_t j = 0; j < m_OldPatches; ++j) {
     542                for (ssize_t i = 0; i < m_OldPatches; ++i)
     543                {
     544                    CPatch& src = *(terrain->GetPatch(i, j));
     545                    CPatch& dst = m_Patches[j * m_OldPatches + i];
     546                    std::copy_n(&(src.m_MiniPatches[0][0]), PATCH_SIZE * PATCH_SIZE, &(dst.m_MiniPatches[0][0]));
     547                }
     548            }
    527549        }
    528550
    529551        const int radiusInTerrainUnits = m_NewPatches * PATCH_SIZE * TERRAIN_TILE_SIZE / 2 * (1.f - 1e-6f);
    BEGIN_COMMAND(ResizeMap)  
    579601
    580602    void Undo()
    581603    {
    582         ResizeTerrain(m_OldPatches, -m_OffsetX, -m_OffsetY);
     604        if (m_Heightmap == nullptr || m_Patches == nullptr)
     605        {   
     606            // If there previously was no data, just resize to old (probably not originally valid).
     607            ResizeTerrain(m_OldPatches, -m_OffsetX, -m_OffsetY);
     608        }
     609        else
     610        {
     611            CSimulation2& sim = *g_Game->GetSimulation2();
     612            CmpPtr<ICmpTerrain> cmpTerrain(sim, SYSTEM_ENTITY);
     613            CTerrain* terrain = cmpTerrain->GetCTerrain();
     614           
     615            terrain->Initialize(m_OldPatches, m_Heightmap);
     616            // Copy terrain data back.
     617            for (ssize_t j = 0; j < m_OldPatches; ++j) {
     618                for (ssize_t i = 0; i < m_OldPatches; ++i)
     619                {
     620                    CPatch& src = m_Patches[j * m_OldPatches + i];
     621                    CPatch& dst = *(terrain->GetPatch(i, j));
     622                    std::copy_n(&(src.m_MiniPatches[0][0]), PATCH_SIZE * PATCH_SIZE, &(dst.m_MiniPatches[0][0]));
     623                }
     624            }
     625        }
    583626        UndeleteAll(m_DeletedObjects);
    584627        SetPosition(m_OldPositions);
    585628        MakeDirty();
  • source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp

    -- 
    2.8.1.windows.1
    
    From 4e555b16d391305d0b5785b80fe47a1e5ef03c65 Mon Sep 17 00:00:00 2001
    From: "Stephen A. Imhoff" <clockwork-muse@outlook.com>
    Date: Fri, 16 Sep 2016 12:11:40 -0700
    Subject: [PATCH] Switch maps to vectors
    
    ---
     source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp | 10 +++++-----
     1 file changed, 5 insertions(+), 5 deletions(-)
    
    diff --git a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
    index ea01c82..84fc124 100644
    a b BEGIN_COMMAND(ResizeMap)  
    432432
    433433    std::vector<DeletedObject> m_DeletedObjects;
    434434
    435     std::map<entity_id_t, CFixedVector3D> m_OldPositions;
    436     std::map<entity_id_t, CFixedVector3D> m_NewPositions;
     435    std::vector<std::pair<entity_id_t, CFixedVector3D>> m_OldPositions;
     436    std::vector<std::pair<entity_id_t, CFixedVector3D>> m_NewPositions;
    437437
    438438    cResizeMap()
    439439    {
    BEGIN_COMMAND(ResizeMap)  
    493493        }
    494494    }
    495495
    496     void SetPosition(const std::map<entity_id_t, CFixedVector3D>& movedObjects)
     496    void SetPosition(const std::vector<std::pair<entity_id_t, CFixedVector3D>>& movedObjects)
    497497    {
    498498        for (auto const& kv : movedObjects)
    499499        {
    BEGIN_COMMAND(ResizeMap)  
    547547            {
    548548                CFixedVector3D position = cmpPosition->GetPosition();
    549549
    550                 m_NewPositions[entityId] = position + offset;
    551                 m_OldPositions[entityId] = position;
     550                m_NewPositions.emplace_back(entityId, position + offset);
     551                m_OldPositions.emplace_back(entityId, position);
    552552            }
    553553            else
    554554            {
  • source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp

    -- 
    2.8.1.windows.1
    
    From 5d470dc1ebe5ce16b490a2d731776b2f1211eee2 Mon Sep 17 00:00:00 2001
    From: "Stephen A. Imhoff" <clockwork-muse@outlook.com>
    Date: Tue, 13 Sep 2016 11:05:55 -0700
    Subject: [PATCH] Delete or move entities as appropriate.
    
    ---
     .../atlas/GameInterface/Handlers/MapHandlers.cpp   | 162 +++++++++++++++++++--
     1 file changed, 148 insertions(+), 14 deletions(-)
    
    diff --git a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
    index 8d8e070..ea01c82 100644
    a b  
    1818#include "precompiled.h"
    1919
    2020#include "MessageHandler.h"
     21#include "../MessagePasser.h"
    2122#include "../GameLoop.h"
    2223#include "../CommandProc.h"
    2324
     
    4243#include "renderer/WaterManager.h"
    4344#include "scriptinterface/ScriptInterface.h"
    4445#include "simulation2/Simulation2.h"
     46#include "simulation2/components/ICmpOwnership.h"
    4547#include "simulation2/components/ICmpPlayer.h"
    4648#include "simulation2/components/ICmpPlayerManager.h"
    4749#include "simulation2/components/ICmpPosition.h"
    4850#include "simulation2/components/ICmpRangeManager.h"
     51#include "simulation2/components/ICmpTemplateManager.h"
    4952#include "simulation2/components/ICmpTerrain.h"
    5053#include "simulation2/system/ParamNode.h"
    5154
    QUERYHANDLER(GetCurrentMapSize)  
    402405
    403406BEGIN_COMMAND(ResizeMap)
    404407{
    405     int m_OldTiles, m_NewTiles;
     408    bool Within(const CFixedVector3D& test, const int centerX, const int centerZ, const int radius)
     409    {
     410        int dx = abs(test.X.ToInt_RoundToZero() - centerX);
     411        if (dx > radius)
     412            return false;
     413        int dz = abs(test.Z.ToInt_RoundToZero() - centerZ);
     414        if (dz > radius)
     415            return false;
     416        if (dx + dz <= radius)
     417            return true;
     418        return (dx * dx + dz * dz <= radius * radius);
     419    }
     420
     421    struct DeletedObject
     422    {
     423        entity_id_t entityId;
     424        CStr templateName;
     425        int32_t owner;
     426        CFixedVector3D pos;
     427        CFixedVector3D rot;
     428    };
     429
     430    int m_OldPatches, m_NewPatches;
    406431    int m_OffsetX, m_OffsetY;
    407432
     433    std::vector<DeletedObject> m_DeletedObjects;
     434
     435    std::map<entity_id_t, CFixedVector3D> m_OldPositions;
     436    std::map<entity_id_t, CFixedVector3D> m_NewPositions;
     437
    408438    cResizeMap()
    409439    {
    410440    }
    BEGIN_COMMAND(ResizeMap)  
    420450        g_Game->GetView()->GetLOSTexture().MakeDirty();
    421451    }
    422452
    423     void ResizeTerrain(int tiles, int offsetX, int offsetY)
     453    void ResizeTerrain(int patches, int offsetX, int offsetY)
    424454    {
    425455        CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
     456        terrain->ResizeRecenter(patches, offsetX, offsetY);
     457    }
     458   
     459    void DeleteAll(const std::vector<DeletedObject>& deletedObjects)
     460    {
     461        for (const DeletedObject& deleted : deletedObjects) {
     462            g_Game->GetSimulation2()->DestroyEntity(deleted.entityId);
     463        }
     464
     465        g_Game->GetSimulation2()->FlushDestroyedEntities();
     466    }
    426467
    427         // Need to flip offset of vertical offset, due to screen mapping order.
    428         terrain->ResizeRecenter(tiles / PATCH_SIZE, offsetX / PATCH_SIZE, -offsetY / PATCH_SIZE);
     468    void UndeleteAll(const std::vector<DeletedObject>& deletedObjects)
     469    {
     470        CSimulation2& sim = *g_Game->GetSimulation2();
    429471
    430         MakeDirty();
     472        for (const DeletedObject& deleted : deletedObjects)
     473        {
     474            entity_id_t ent = sim.AddEntity(deleted.templateName.FromUTF8(), deleted.entityId);
     475            if (ent == INVALID_ENTITY)
     476            {
     477                LOGERROR("Failed to load entity template '%s'", deleted.templateName.c_str());
     478            }
     479            else
     480            {
     481                CmpPtr<ICmpPosition> cmpPosition(sim, deleted.entityId);
     482                if (cmpPosition)
     483                {
     484                    cmpPosition->JumpTo(deleted.pos.X, deleted.pos.Z);
     485                    cmpPosition->SetXZRotation(deleted.rot.X, deleted.rot.Z);
     486                    cmpPosition->SetYRotation(deleted.rot.Y);
     487                }
     488
     489                CmpPtr<ICmpOwnership> cmpOwnership(sim, deleted.entityId);
     490                if (cmpOwnership)
     491                    cmpOwnership->SetOwner(deleted.owner);
     492            }
     493        }
     494    }
     495
     496    void SetPosition(const std::map<entity_id_t, CFixedVector3D>& movedObjects)
     497    {
     498        for (auto const& kv : movedObjects)
     499        {
     500            entity_id_t id = kv.first;
     501            CFixedVector3D position = kv.second;
     502            CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
     503            ENSURE(cmpPosition);
     504            cmpPosition->JumpTo(position.X, position.Z);
     505        }
    431506    }
    432507
    433508    void Do()
    434509    {
    435         CmpPtr<ICmpTerrain> cmpTerrain(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
     510        CSimulation2& sim = *g_Game->GetSimulation2();
     511        CmpPtr<ICmpTemplateManager> cmpTemplateManager(sim, SYSTEM_ENTITY);
     512        ENSURE(cmpTemplateManager);
     513
     514        CmpPtr<ICmpTerrain> cmpTerrain(sim, SYSTEM_ENTITY);
    436515        if (!cmpTerrain)
    437516        {
    438             m_OldTiles = m_NewTiles = 0;
     517            m_OldPatches = m_NewPatches = 0;
    439518            m_OffsetX = m_OffsetY = 0;
    440519        }
    441520        else
    442521        {
    443             m_OldTiles = (int)cmpTerrain->GetTilesPerSide();
    444             m_NewTiles = msg->tiles;
    445             m_OffsetX = msg->offsetX;
    446             m_OffsetY = msg->offsetY;
     522            m_OldPatches = (int)cmpTerrain->GetTilesPerSide() / PATCH_SIZE;
     523            m_NewPatches = msg->tiles / PATCH_SIZE;
     524            m_OffsetX = msg->offsetX / PATCH_SIZE;
     525            // Need to flip direction of vertical offset, due to screen mapping order.
     526            m_OffsetY = -(msg->offsetY / PATCH_SIZE);
     527        }
     528
     529        const int radiusInTerrainUnits = m_NewPatches * PATCH_SIZE * TERRAIN_TILE_SIZE / 2 * (1.f - 1e-6f);
     530        // Opposite direction offset, as we move the destination onto the source, not the source into the destination.
     531        const int mapCenterX = (m_OldPatches / 2 - m_OffsetX) * PATCH_SIZE * TERRAIN_TILE_SIZE;
     532        const int mapCenterZ = (m_OldPatches / 2 - m_OffsetY) * PATCH_SIZE * TERRAIN_TILE_SIZE;
     533        // The offset to move units by is opposite the direction the map is moved, and from the corner.
     534        const int offsetX = ((m_NewPatches - m_OldPatches) / 2 + m_OffsetX) * PATCH_SIZE * TERRAIN_TILE_SIZE;
     535        const int offsetZ = ((m_NewPatches - m_OldPatches) / 2 + m_OffsetY) * PATCH_SIZE * TERRAIN_TILE_SIZE;
     536        const CFixedVector3D offset = CFixedVector3D(fixed::FromInt(offsetX), fixed::FromInt(0), fixed::FromInt(offsetZ));
     537
     538        const CSimulation2::InterfaceListUnordered& ents = sim.GetEntitiesWithInterfaceUnordered(IID_Selectable);
     539
     540        for (auto const& kv : ents) {
     541
     542            const entity_id_t entityId = kv.first;
     543
     544            CmpPtr<ICmpPosition> cmpPosition(sim, entityId);
     545
     546            if (cmpPosition && cmpPosition->IsInWorld() && Within(cmpPosition->GetPosition(), mapCenterX, mapCenterZ, radiusInTerrainUnits))
     547            {
     548                CFixedVector3D position = cmpPosition->GetPosition();
     549
     550                m_NewPositions[entityId] = position + offset;
     551                m_OldPositions[entityId] = position;
     552            }
     553            else
     554            {
     555                DeletedObject deleted;
     556                deleted.entityId = entityId;
     557                deleted.templateName = cmpTemplateManager->GetCurrentTemplateName(entityId);
     558
     559                // If the entity has a position, but the ending position is not valid;
     560                if (cmpPosition)
     561                {
     562                    deleted.pos = cmpPosition->GetPosition();
     563                    deleted.rot = cmpPosition->GetRotation();
     564                }
     565
     566                CmpPtr<ICmpOwnership> cmpOwnership(sim, entityId);
     567                if (cmpOwnership)
     568                    deleted.owner = cmpOwnership->GetOwner();
     569
     570                m_DeletedObjects.push_back(deleted);
     571            }
    447572        }
    448573
    449         ResizeTerrain(m_NewTiles, m_OffsetX, m_OffsetY);
     574        DeleteAll(m_DeletedObjects);
     575        ResizeTerrain(m_NewPatches, m_OffsetX, m_OffsetY);
     576        SetPosition(m_NewPositions);
     577        MakeDirty();
    450578    }
    451579
    452580    void Undo()
    453581    {
    454         ResizeTerrain(m_OldTiles, -m_OffsetX, -m_OffsetY);
     582        ResizeTerrain(m_OldPatches, -m_OffsetX, -m_OffsetY);
     583        UndeleteAll(m_DeletedObjects);
     584        SetPosition(m_OldPositions);
     585        MakeDirty();
    455586    }
    456587
    457588    void Redo()
    458589    {
    459         ResizeTerrain(m_NewTiles, m_OffsetX, m_OffsetY);
     590        DeleteAll(m_DeletedObjects);
     591        ResizeTerrain(m_NewPatches, m_OffsetX, m_OffsetY);
     592        SetPosition(m_NewPositions);
     593        MakeDirty();
    460594    }
    461595};
    462596END_COMMAND(ResizeMap)
  • source/graphics/Terrain.cpp

    -- 
    2.8.1.windows.1
    
    From 3115e5ee9f55010af227daebf8bdc8b771e3c71c Mon Sep 17 00:00:00 2001
    From: "Stephen A. Imhoff" <clockwork-muse@outlook.com>
    Date: Thu, 14 Jul 2016 18:37:11 +0900
    Subject: [PATCH] Modify Resize to move the center of the map.
    
    ---
     source/graphics/Terrain.cpp                        | 173 ++++++++++++---------
     source/graphics/Terrain.h                          |   5 +-
     .../MapResizeDialog/MapResizeDialog.cpp            |  20 +--
     .../MapResizeDialog/MapResizeDialog.h              |   6 +
     .../MapResizeDialog/PsuedoMiniMapPanel.cpp         |  25 ++-
     .../MapResizeDialog/PsuedoMiniMapPanel.h           |  10 +-
     .../ScenarioEditor/Sections/Terrain/Terrain.cpp    |   4 +-
     .../atlas/GameInterface/Handlers/MapHandlers.cpp   |  17 +-
     source/tools/atlas/GameInterface/Messages.h        |   2 +
     9 files changed, 162 insertions(+), 100 deletions(-)
    
    diff --git a/source/graphics/Terrain.cpp b/source/graphics/Terrain.cpp
    index 8f7919a..98b5065 100644
    a b bool CTerrain::GetTriangulationDir(ssize_t i, ssize_t j) const  
    497497}
    498498
    499499///////////////////////////////////////////////////////////////////////////////
    500 // Resize: resize this terrain to the given size (in patches per side)
    501 void CTerrain::Resize(ssize_t size)
     500// Resize/Recenter: resize this terrain to the given size (in patches per side).
     501// The offset is in patches from the center of the source.
     502void CTerrain::ResizeRecenter(ssize_t size, int horizontalOffset, int verticalOffset)
    502503{
    503     if (size==m_MapSizePatches) {
    504         // inexplicable request to resize terrain to the same size .. ignore it
     504    if (size == m_MapSizePatches &&
     505        horizontalOffset == 0 &&
     506        verticalOffset == 0) {
     507        // inexplicable request to resize terrain to the same size and location .. ignore it
    505508        return;
    506509    }
    507510
    508     if (!m_Heightmap) {
    509         // not yet created a terrain; build a default terrain of the given size now
    510         Initialize(size,0);
     511    if (!m_Heightmap ||
     512        std::abs(horizontalOffset) > std::max(size, m_MapSizePatches) / 2 ||
     513        std::abs(verticalOffset) > std::max(size, m_MapSizePatches) / 2) {
     514        // not yet created a terrain, or offsetting outside the current source;
     515        // build a default terrain of the given size now
     516        Initialize(size, 0);
    511517        return;
    512518    }
    513519
    514520    // allocate data for new terrain
    515     ssize_t newMapSize=size*PATCH_SIZE+1;
    516     u16* newHeightmap=new u16[newMapSize*newMapSize];
    517     CPatch* newPatches=new CPatch[size*size];
    518 
    519     if (size>m_MapSizePatches) {
    520         // new map is bigger than old one - zero the heightmap so we don't get uninitialised
    521         // height data along the expanded edges
    522         memset(newHeightmap,0,newMapSize*newMapSize*sizeof(u16));
    523     }
     521    ssize_t newMapSize = size * PATCH_SIZE + 1;
     522    u16* newHeightmap = new u16[newMapSize * newMapSize];
     523    CPatch* newPatches = new CPatch[size * size];
    524524
    525     // now copy over rows of data
    526     u16* src=m_Heightmap;
    527     u16* dst=newHeightmap;
    528     ssize_t copysize=std::min(newMapSize, m_MapSize);
    529     for (ssize_t j=0;j<copysize;j++) {
    530         memcpy(dst,src,copysize*sizeof(u16));
    531         dst+=copysize;
    532         src+=m_MapSize;
    533         if (newMapSize>m_MapSize) {
    534             // extend the last height to the end of the row
    535             for (size_t i=0;i<newMapSize-(size_t)m_MapSize;i++) {
    536                 *dst++=*(src-1);
    537             }
    538         }
    539     }
     525    // Restate center offset as a window over destination.
     526    // This has the effect of always considering the source to be the same size or smaller.
     527    const ssize_t upperLeftX = std::max(0, (int(size) - int(m_MapSizePatches)) / 2 + horizontalOffset);
     528    const ssize_t upperLeftZ = std::max(0, (int(size) - int(m_MapSizePatches)) / 2 + verticalOffset);
     529    const ssize_t width = std::min(size, (int(size) - int(m_MapSizePatches)) / 2 + horizontalOffset + m_MapSizePatches) - upperLeftX;
     530    const ssize_t height = std::min(size, (int(size) - int(m_MapSizePatches)) / 2 + verticalOffset + m_MapSizePatches) - upperLeftZ;
    540531
     532    const ssize_t upperLeftXSource = std::max(0, (int(m_MapSizePatches) - int(size)) / 2 - horizontalOffset);
     533    const ssize_t upperLeftZSource = std::max(0, (int(m_MapSizePatches) - int(size)) / 2 - verticalOffset);
    541534
    542     if (newMapSize>m_MapSize) {
    543         // copy over heights of the last row to any remaining rows
    544         src=newHeightmap+((m_MapSize-1)*newMapSize);
    545         dst=src+newMapSize;
    546         for (ssize_t i=0;i<newMapSize-m_MapSize;i++) {
    547             memcpy(dst,src,newMapSize*sizeof(u16));
    548             dst+=newMapSize;
    549         }
     535    for (ssize_t j = upperLeftZ * PATCH_SIZE; j < (upperLeftZ + height) * PATCH_SIZE + 1; ++j)
     536    {
     537        u16* dst = newHeightmap + j * newMapSize;
     538        u16* src = m_Heightmap + (upperLeftZSource * PATCH_SIZE + (j - upperLeftZ * PATCH_SIZE)) * m_MapSize + upperLeftXSource * PATCH_SIZE;
     539
     540        dst = std::fill_n(dst, upperLeftX * PATCH_SIZE, *src);
     541        dst = std::copy_n(src, width * PATCH_SIZE + 1, dst);
     542        std::fill_n(dst, newMapSize - (upperLeftX + width) * PATCH_SIZE, *(src + (width * PATCH_SIZE + 1) - 1));
     543    }
     544    // Copy over heights from preceding/succeeding rows
     545    for (ssize_t j = 0; j < upperLeftZ * PATCH_SIZE; ++j)
     546    {
     547        u16* dst = newHeightmap + j * newMapSize;
     548        u16* src = newHeightmap + upperLeftZ * PATCH_SIZE * newMapSize;
     549        std::copy_n(src, newMapSize, dst);
     550    }
     551    for (ssize_t j = (upperLeftZ + height)*PATCH_SIZE + 1; j < newMapSize; ++j)
     552    {
     553        u16* dst = newHeightmap + j * newMapSize;
     554        u16* src = newHeightmap + (upperLeftZ + height) * PATCH_SIZE * newMapSize;
     555        std::copy_n(src, newMapSize, dst);
    550556    }
    551557
    552558    // now build new patches
    553     for (ssize_t j=0;j<size;j++) {
    554         for (ssize_t i=0;i<size;i++) {
     559    for (ssize_t j = upperLeftZ; j < upperLeftZ + height; ++j) {
     560        for (ssize_t i = upperLeftX; i < upperLeftX + width; ++i)
     561        {
    555562            // copy over texture data from existing tiles, if possible
    556             if (i<m_MapSizePatches && j<m_MapSizePatches) {
    557                 memcpy(newPatches[j*size+i].m_MiniPatches,m_Patches[j*m_MapSizePatches+i].m_MiniPatches,sizeof(CMiniPatch)*PATCH_SIZE*PATCH_SIZE);
     563            // Incrementing offsets in source need to be adjusted to 0-based, since the X/ZSource variables are the new "0"
     564            CPatch& src = m_Patches[(upperLeftZSource + (j - upperLeftZ)) * m_MapSizePatches + upperLeftXSource + (i - upperLeftX)];
     565            CPatch& dst = newPatches[j * size + i];
     566            std::copy_n(&(src.m_MiniPatches[0][0]), PATCH_SIZE * PATCH_SIZE, &(dst.m_MiniPatches[0][0]));
     567        }
     568        for (ssize_t i = 0; i < upperLeftX; ++i)
     569        {
     570            for (ssize_t patch_j = 0; patch_j < PATCH_SIZE; ++patch_j) {
     571                CMiniPatch& src = newPatches[j * size + upperLeftX].m_MiniPatches[patch_j][0];
     572                for (ssize_t patch_i = 0; patch_i < PATCH_SIZE; ++patch_i) {
     573                    CMiniPatch& dst = newPatches[j * size + i].m_MiniPatches[patch_j][patch_i];
     574                    dst = src;
     575                }
    558576            }
    559577        }
    560 
    561         if (j<m_MapSizePatches && size>m_MapSizePatches) {
    562             // copy over the last tile from each column
    563             for (ssize_t n=0;n<size-m_MapSizePatches;n++) {
    564                 for (ssize_t m=0;m<PATCH_SIZE;m++) {
    565                     CMiniPatch& src=m_Patches[j*m_MapSizePatches+m_MapSizePatches-1].m_MiniPatches[m][15];
    566                     for (ssize_t k=0;k<PATCH_SIZE;k++) {
    567                         CMiniPatch& dst=newPatches[j*size+m_MapSizePatches+n].m_MiniPatches[m][k];
    568                         dst = src;
    569                     }
     578        for (ssize_t i = upperLeftX + width; i < size; ++i)
     579        {
     580            for (ssize_t patch_j = 0; patch_j < PATCH_SIZE; ++patch_j) {
     581                CMiniPatch& src = newPatches[j * size + upperLeftX + width - 1].m_MiniPatches[patch_j][PATCH_SIZE - 1];
     582                for (ssize_t patch_i = 0; patch_i < PATCH_SIZE; ++patch_i) {
     583                    CMiniPatch& dst = newPatches[j * size + i].m_MiniPatches[patch_j][patch_i];
     584                    dst = src;
    570585                }
    571586            }
    572587        }
    573588    }
    574 
    575     if (size>m_MapSizePatches) {
    576         // copy over the last tile from each column
    577         CPatch* srcpatch=&newPatches[(m_MapSizePatches-1)*size];
    578         CPatch* dstpatch=srcpatch+size;
    579         for (ssize_t p=0;p<(ssize_t)size-m_MapSizePatches;p++) {
    580             for (ssize_t n=0;n<(ssize_t)size;n++) {
    581                 for (ssize_t m=0;m<PATCH_SIZE;m++) {
    582                     for (ssize_t k=0;k<PATCH_SIZE;k++) {
    583                         CMiniPatch& src=srcpatch->m_MiniPatches[15][k];
    584                         CMiniPatch& dst=dstpatch->m_MiniPatches[m][k];
    585                         dst = src;
    586                     }
     589    for (ssize_t j = 0; j < upperLeftZ; ++j) {
     590        CPatch* srcpatch = newPatches + (upperLeftZ * size);
     591        CPatch* dstpatch = newPatches + j * size;
     592        for (ssize_t i = 0; i < size; ++i){
     593            for (ssize_t patch_j = 0; patch_j < PATCH_SIZE; ++patch_j) {
     594                for (ssize_t patch_i = 0; patch_i < PATCH_SIZE; ++patch_i) {
     595                    CMiniPatch& src = srcpatch->m_MiniPatches[0][patch_i];
     596                    CMiniPatch& dst = dstpatch->m_MiniPatches[patch_j][patch_i];
     597                    dst = src;
    587598                }
    588                 srcpatch++;
    589                 dstpatch++;
    590599            }
     600            ++srcpatch;
     601            ++dstpatch;
     602        }
     603    }
     604    for (ssize_t j = upperLeftZ + height; j < size; ++j) {
     605        CPatch* srcpatch = newPatches + ((upperLeftZ + height - 1) * size);
     606        CPatch* dstpatch = newPatches + j * size;
     607        for (ssize_t i = 0; i < size; ++i){
     608            for (ssize_t patch_j = 0; patch_j < PATCH_SIZE; ++patch_j) {
     609                for (ssize_t patch_i = 0; patch_i < PATCH_SIZE; ++patch_i) {
     610                    CMiniPatch& src = srcpatch->m_MiniPatches[PATCH_SIZE - 1][patch_i];
     611                    CMiniPatch& dst = dstpatch->m_MiniPatches[patch_j][patch_i];
     612                    dst = src;
     613                }
     614            }
     615            ++srcpatch;
     616            ++dstpatch;
    591617        }
    592618    }
    593 
    594619
    595620    // release all the original data
    596621    ReleaseData();
    597622
    598623    // store new data
    599     m_Heightmap=newHeightmap;
    600     m_Patches=newPatches;
    601     m_MapSize=(ssize_t)newMapSize;
    602     m_MapSizePatches=(ssize_t)size;
     624    m_Heightmap = newHeightmap;
     625    m_Patches = newPatches;
     626    m_MapSize = (ssize_t)newMapSize;
     627    m_MapSizePatches = (ssize_t)size;
    603628
    604629    // initialise all the new patches
    605630    InitialisePatches();
    606631
    607632    // initialise mipmap
    608     m_HeightMipmap.Initialize(m_MapSize,m_Heightmap);
     633    m_HeightMipmap.Initialize(m_MapSize, m_Heightmap);
    609634}
    610635
    611636///////////////////////////////////////////////////////////////////////////////
  • source/graphics/Terrain.h

    diff --git a/source/graphics/Terrain.h b/source/graphics/Terrain.h
    index a2073d6..a99f846 100644
    a b public:  
    9898    // should be in the direction (1,-1); false if it should be (1,1)
    9999    bool GetTriangulationDir(ssize_t i, ssize_t j) const;
    100100
    101     // resize this terrain such that each side has given number of patches
    102     void Resize(ssize_t size);
     101    // resize this terrain such that each side has given number of patches,
     102    // with the center offset in patches from the larger of the two sizes.
     103    void ResizeRecenter(ssize_t size, int horizontalOffset = 0, int verticalOffset = 0);
    103104
    104105    // set up a new heightmap from 16 bit data; assumes heightmap matches current terrain size
    105106    void SetHeightMap(u16* heightmap);
  • source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp

    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp
    index 17ded82..778d0ff 100644
    a b  
    2424#include "GameInterface/Messages.h"
    2525
    2626#include <wx/statline.h>
    27 #include "PsuedoMiniMapPanel.h"
    2827
    2928MapResizeDialog::MapResizeDialog(wxWindow* parent)
    30     : wxDialog(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxCAPTION | wxRESIZE_BORDER),
    31     m_NewSize(0)
     29    : wxDialog(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxCAPTION | wxRESIZE_BORDER)
    3230{
    3331    Freeze();
    3432
    3533    AtlasMessage::qGetCurrentMapSize qrySize;
    3634    qrySize.Post();
    37     int currentSize = qrySize.size;
     35    m_NewSize = qrySize.size;
    3836
    3937    SetTitle(_("Resize map"));
    4038    wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
    MapResizeDialog::MapResizeDialog(wxWindow* parent)  
    5250    {   
    5351        wxString size(s["Tiles"]);
    5452        listBox->Append(wxString(s["Name"]), new wxStringClientData(size));
    55         if (currentSize == wxAtoi(size))
     53        if (m_NewSize == wxAtoi(size))
    5654            listBox->SetSelection(listBox->GetCount() - 1);
    5755    }
    5856    listAndMap->Add(listBox, wxSizerFlags().Align(wxALIGN_LEFT).Proportion(1).Expand());
    5957    listAndMap->AddSpacer(10);
    6058
    61     PsuedoMiniMapPanel* miniMap = new PsuedoMiniMapPanel(this, currentSize);
    62     listBox->Bind(wxEVT_LISTBOX, &PsuedoMiniMapPanel::OnNewSize, miniMap);
     59    m_MiniMap = new PsuedoMiniMapPanel(this, m_NewSize);
     60    listBox->Bind(wxEVT_LISTBOX, &PsuedoMiniMapPanel::OnNewSize, m_MiniMap);
    6361
    64     listAndMap->Add(miniMap, wxSizerFlags());
     62    listAndMap->Add(m_MiniMap, wxSizerFlags());
    6563    sizer->Add(listAndMap, wxSizerFlags().Proportion(1).Expand().Border(wxLEFT | wxRIGHT, 10));
    6664
    6765    sizer->AddSpacer(5);
    size_t MapResizeDialog::GetNewSize() const  
    8583    return m_NewSize;
    8684}
    8785
     86wxPoint MapResizeDialog::GetOffset() const
     87{
     88    return m_MiniMap->GetOffset();
     89}
     90
    8891void MapResizeDialog::OnListBox(wxCommandEvent& evt)
    8992{
    9093    if (!evt.IsSelection())
    9194        return;
    9295
    9396    m_NewSize = wxAtoi(static_cast<wxStringClientData*>(evt.GetClientObject())->GetData());
    94    
    9597    if (evt.GetEventType() == wxEVT_COMMAND_LISTBOX_DOUBLECLICKED)
    9698    {
    9799        EndModal(wxID_OK);
  • source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h

    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h
    index cc07341..a790591 100644
    a b  
    1919#define INCLUDED_MAPRESIZEDIALOG
    2020
    2121#include <wx/dialog.h>
     22#include "PsuedoMiniMapPanel.h"
    2223
    2324class MapResizeDialog : public wxDialog
    2425{
    public:  
    2930     * Returns selected new size.
    3031     */
    3132    size_t GetNewSize() const;
     33    /**
     34     * Returns the offset from center.
     35     */
     36    wxPoint GetOffset() const;
    3237
    3338private:
    3439    void OnCancel(wxCommandEvent& evt);
    private:  
    3641    void OnListBox(wxCommandEvent& evt);
    3742
    3843    size_t m_NewSize;
     44    PsuedoMiniMapPanel* m_MiniMap;
    3945
    4046    DECLARE_EVENT_TABLE();
    4147};
  • source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.cpp

    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.cpp b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.cpp
    index 39e7b4d..ce6277c 100644
    a b PsuedoMiniMapPanel::PsuedoMiniMapPanel(wxWindow* parent, int currentSize)  
    6666    : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(PanelRadius * 2 + 1, PanelRadius * 2 + 1)),
    6767    m_CurrentSize(currentSize), m_ScreenTones(),
    6868    m_LastMousePos(-1, -1), m_Dragging(false),
    69     m_SelectionRadius(PanelRadius), m_SelectionCenter(PanelCenter), m_SameOrGrowing(true)
     69    m_SelectionRadius(PanelRadius), m_SelectionCenter(PanelCenter), m_SameOrGrowing(true), m_NewSize(currentSize)
    7070{
    7171
    7272    AtlasMessage::qGetMiniMapDisplay qryBackground;
    PsuedoMiniMapPanel::PsuedoMiniMapPanel(wxWindow* parent, int currentSize)  
    8181    SetBackgroundStyle(wxBG_STYLE_PAINT);
    8282}
    8383
     84wxPoint PsuedoMiniMapPanel::GetOffset() const
     85{
     86    // Since offset is from center, amplitude is (at most) half the largest size.
     87    int size = std::max(m_CurrentSize, m_NewSize) / 2;
     88    // If the map is growing, the display is opposite what the actual offset is.
     89    float scalar = (m_SameOrGrowing ? 1.0 : -1.0) / PanelRadius * size;
     90    // Rebase offsets to center.
     91    int hOffset = m_SelectionCenter.x - PanelCenter.x;
     92    int vOffset = m_SelectionCenter.y - PanelCenter.y;
     93    return wxPoint(scalar * hOffset, scalar * vOffset);
     94}
     95
    8496void PsuedoMiniMapPanel::OnNewSize(wxCommandEvent& evt)
    8597{
    8698    if (!evt.IsSelection())
    8799        return;
    88100
    89     int newSize = wxAtoi(static_cast<wxStringClientData*>(evt.GetClientObject())->GetData());
     101    evt.Skip();
    90102
    91     m_SameOrGrowing = newSize >= m_CurrentSize;
    92     m_SelectionRadius = double(std::min(newSize, m_CurrentSize)) / std::max(newSize, m_CurrentSize) * PanelRadius;
     103    m_NewSize = wxAtoi(static_cast<wxStringClientData*>(evt.GetClientObject())->GetData());
    93104
     105    m_SameOrGrowing = m_NewSize >= m_CurrentSize;
     106    m_SelectionRadius = double(std::min(m_NewSize, m_CurrentSize)) / std::max(m_NewSize, m_CurrentSize) * PanelRadius;
    94107    if (!m_SameOrGrowing && m_ScreenTones.find(m_SelectionRadius) == m_ScreenTones.cend())
    95108    {
    96109        wxImage overlay = wxImage(PanelRadius * 4, PanelRadius * 4);
    void PsuedoMiniMapPanel::PaintEvent(wxPaintEvent& WXUNUSED(evt))  
    177190
    178191        const wxPen BorderPen(*wxWHITE, 2);
    179192        dc.SetPen(BorderPen);
    180         dc.DrawCircle(m_SelectionCenter, m_SelectionRadius);
    181        
     193        dc.DrawCircle(m_SelectionCenter, m_SelectionRadius);       
    182194    }
    183195    else
    184196    {
    void PsuedoMiniMapPanel::EraseBackground(wxEraseEvent& WXUNUSED(evt))  
    210222}
    211223
    212224BEGIN_EVENT_TABLE(PsuedoMiniMapPanel, wxPanel)
     225EVT_LEAVE_WINDOW(PsuedoMiniMapPanel::OnMouseUp)
    213226EVT_LEFT_DOWN(PsuedoMiniMapPanel::OnMouseDown)
    214227EVT_LEFT_UP(PsuedoMiniMapPanel::OnMouseUp)
    215228EVT_RIGHT_DOWN(PsuedoMiniMapPanel::OnMouseDown)
  • source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.h

    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.h b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.h
    index 215a177..331a431 100644
    a b  
    1515* along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
    1616*/
    1717
     18
     19#ifndef INCLUDED_PSUEDOMINIMAPPANEL
     20#define INCLUDED_PSUEDOMINIMAPPANEL
     21
    1822#include <wx/panel.h>
    1923
    2024class PsuedoMiniMapPanel : public wxPanel
    public:  
    2630    void EraseBackground(wxEraseEvent& evt);
    2731
    2832    void OnNewSize(wxCommandEvent& evt);
     33
     34    wxPoint GetOffset() const;
    2935private:
    3036    void OnMouseDown(wxMouseEvent& evt);
    3137    void OnMouseUp(wxMouseEvent& evt);
    private:  
    3844
    3945    wxPoint m_LastMousePos;
    4046    bool m_Dragging;
    41 
    4247    wxPoint m_SelectionCenter;
    4348    int m_SelectionRadius;
    4449    bool m_SameOrGrowing;
     50    int m_NewSize;
    4551
    4652    DECLARE_EVENT_TABLE();
    4753};
     54
     55#endif // INCLUDED_PSUEDOMINIMAPPANEL
     56 No newline at end of file
  • source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp

    diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp
    index b67d275..fa06d14 100644
    a b void TerrainSidebar::OnResizeMap(wxCommandEvent& WXUNUSED(evt))  
    284284
    285285    if (dlg.ShowModal() != wxID_OK)
    286286        return;
    287    
    288     POST_COMMAND(ResizeMap, (dlg.GetNewSize()));
     287    wxPoint offset = dlg.GetOffset();
     288    POST_COMMAND(ResizeMap, (dlg.GetNewSize(), offset.x, offset.y));
    289289}
    290290
    291291BEGIN_EVENT_TABLE(TerrainSidebar, Sidebar)
  • source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp

    diff --git a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
    index a142f5e..8d8e070 100644
    a b MESSAGEHANDLER(ImportHeightmap)  
    218218
    219219    // resize terrain to heightmap size
    220220    CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
    221     terrain->Resize(terrainSize / PATCH_SIZE);
     221    terrain->ResizeRecenter(terrainSize / PATCH_SIZE);
    222222
    223223    // copy heightmap data into map
    224224    u16* heightmap = g_Game->GetWorld()->GetTerrain()->GetHeightMap();
    QUERYHANDLER(GetCurrentMapSize)  
    403403BEGIN_COMMAND(ResizeMap)
    404404{
    405405    int m_OldTiles, m_NewTiles;
     406    int m_OffsetX, m_OffsetY;
    406407
    407408    cResizeMap()
    408409    {
    BEGIN_COMMAND(ResizeMap)  
    419420        g_Game->GetView()->GetLOSTexture().MakeDirty();
    420421    }
    421422
    422     void ResizeTerrain(int tiles)
     423    void ResizeTerrain(int tiles, int offsetX, int offsetY)
    423424    {
    424425        CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
    425426
    426         terrain->Resize(tiles / PATCH_SIZE);
     427        // Need to flip offset of vertical offset, due to screen mapping order.
     428        terrain->ResizeRecenter(tiles / PATCH_SIZE, offsetX / PATCH_SIZE, -offsetY / PATCH_SIZE);
    427429
    428430        MakeDirty();
    429431    }
    BEGIN_COMMAND(ResizeMap)  
    434436        if (!cmpTerrain)
    435437        {
    436438            m_OldTiles = m_NewTiles = 0;
     439            m_OffsetX = m_OffsetY = 0;
    437440        }
    438441        else
    439442        {
    440443            m_OldTiles = (int)cmpTerrain->GetTilesPerSide();
    441444            m_NewTiles = msg->tiles;
     445            m_OffsetX = msg->offsetX;
     446            m_OffsetY = msg->offsetY;
    442447        }
    443448
    444         ResizeTerrain(m_NewTiles);
     449        ResizeTerrain(m_NewTiles, m_OffsetX, m_OffsetY);
    445450    }
    446451
    447452    void Undo()
    448453    {
    449         ResizeTerrain(m_OldTiles);
     454        ResizeTerrain(m_OldTiles, -m_OffsetX, -m_OffsetY);
    450455    }
    451456
    452457    void Redo()
    453458    {
    454         ResizeTerrain(m_NewTiles);
     459        ResizeTerrain(m_NewTiles, m_OffsetX, m_OffsetY);
    455460    }
    456461};
    457462END_COMMAND(ResizeMap)
  • source/tools/atlas/GameInterface/Messages.h

    diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h
    index 3b1368f..8ba714f 100644
    a b QUERY(GetRMSData,  
    211211
    212212COMMAND(ResizeMap, NOMERGE,
    213213        ((int, tiles))
     214        ((int, offsetX))
     215        ((int, offsetY))
    214216        );
    215217
    216218QUERY(VFSFileExists,
  • source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.cpp

    -- 
    2.8.1.windows.1
    
    From 0cc33841fa8599f5b178ebe7c2c94b2ba91e76ee Mon Sep 17 00:00:00 2001
    From: "Stephen A. Imhoff" <clockwork-muse@outlook.com>
    Date: Sat, 9 Jul 2016 13:34:07 +0900
    Subject: [PATCH] Switch to actual map display.
    
    ---
     .../MapResizeDialog/PsuedoMiniMapPanel.cpp         | 42 ++++++++---
     .../MapResizeDialog/PsuedoMiniMapPanel.h           |  2 +
     .../atlas/GameInterface/Handlers/MapHandlers.cpp   | 83 ++++++++++++++++++++++
     source/tools/atlas/GameInterface/Messages.h        |  6 ++
     4 files changed, 122 insertions(+), 11 deletions(-)
    
    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.cpp b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.cpp
    index 020faee..39e7b4d 100644
    a b  
    2020#include "PsuedoMiniMapPanel.h"
    2121
    2222#include "GameInterface/Messages.h"
     23#include "GameInterface/MessagePasser.h"
    2324#include "ScenarioEditor/Tools/Common/Tools.h"
    2425
    2526#include <math.h>
     
    2930
    3031namespace
    3132{
    32     const int PanelRadius = 75;
     33    const int PanelRadius = 64 + 1;
    3334    const wxPoint PanelCenter = wxPoint(PanelRadius + 1, PanelRadius + 1);
    3435    const char* ScreenToneMask[] =
    3536    {
    namespace  
    4546    };
    4647    const wxPoint ScreenToneOffset(-2 * PanelRadius, -2 * PanelRadius);
    4748    const wxPen Rim(*wxBLACK, 3);
     49    const wxPen BackgroundMask(*wxBLACK, 2 * PanelRadius);
    4850
    4951    bool Within(const wxPoint& test, const wxPoint& center, int radius)
    5052    {
    PsuedoMiniMapPanel::PsuedoMiniMapPanel(wxWindow* parent, int currentSize)  
    6668    m_LastMousePos(-1, -1), m_Dragging(false),
    6769    m_SelectionRadius(PanelRadius), m_SelectionCenter(PanelCenter), m_SameOrGrowing(true)
    6870{
     71
     72    AtlasMessage::qGetMiniMapDisplay qryBackground;
     73    qryBackground.Post();
     74    int dim = qryBackground.dimension;
     75    unsigned char* data = static_cast<unsigned char*>((void*)qryBackground.imageBytes);
     76   
     77    m_Background = wxImage(dim, dim, data);
     78    m_Background.Rescale(PanelRadius * 2, PanelRadius * 2, wxIMAGE_QUALITY_BOX_AVERAGE);
     79    m_Backgrounds[PanelRadius] = wxBitmap(m_Background);
     80
    6981    SetBackgroundStyle(wxBG_STYLE_PAINT);
    7082}
    7183
    void PsuedoMiniMapPanel::OnNewSize(wxCommandEvent& evt)  
    96108        overlay.ConvertColourToAlpha(0, 0, 0);
    97109
    98110        m_ScreenTones[m_SelectionRadius] = wxBitmap(overlay);
     111    }
     112    else if (m_SameOrGrowing && m_Backgrounds.find(m_SelectionRadius) == m_Backgrounds.cend())
     113    {
     114        wxImage rescaled = wxImage(m_Background);
     115        rescaled.Rescale(2 * m_SelectionRadius, 2 * m_SelectionRadius, wxIMAGE_QUALITY_BOX_AVERAGE);
     116        m_Backgrounds[m_SelectionRadius] = wxBitmap(rescaled);
    99117    }
    100118
    101119    Refresh();
    void PsuedoMiniMapPanel::PaintEvent(wxPaintEvent& WXUNUSED(evt))  
    151169    wxGCDC dc(dca);
    152170    if (m_SameOrGrowing)
    153171    {
    154         dc.SetBrush(*wxBLACK_BRUSH);
    155         dc.DrawRectangle(0, 0, 2 * PanelRadius, 2 * PanelRadius);
    156         dc.SetBrush(*wxWHITE_BRUSH);
    157         dc.DrawCircle(m_SelectionCenter, m_SelectionRadius + 1);
    158         dc.SetBrush(*wxGREEN_BRUSH);
     172        dc.DrawBitmap(m_Backgrounds[m_SelectionRadius], m_SelectionCenter - wxSize(m_SelectionRadius, m_SelectionRadius));
     173       
     174        dc.SetBrush(*wxTRANSPARENT_BRUSH);
     175        dc.SetPen(BackgroundMask);
     176        dc.DrawCircle(m_SelectionCenter, PanelRadius + m_SelectionRadius);
     177
     178        const wxPen BorderPen(*wxWHITE, 2);
     179        dc.SetPen(BorderPen);
    159180        dc.DrawCircle(m_SelectionCenter, m_SelectionRadius);
     181       
    160182    }
    161183    else
    162184    {
    163         dc.SetBrush(*wxGREEN_BRUSH);
    164         dc.DrawRectangle(0, 0, 2 * PanelRadius, 2 * PanelRadius);
    165        
     185        dc.DrawBitmap(m_Backgrounds[PanelRadius], 0, 0);       
    166186        // "fade out" trimmed areas by drawing a screentone ring ring.
    167187        dc.DrawBitmap(m_ScreenTones[m_SelectionRadius], ScreenToneOffset + m_SelectionCenter);
    168188    }
    169189
    170190    // Centering markers.
    171191    dc.SetBrush(*wxBLACK_BRUSH);
    172     dc.DrawCircle(m_SelectionCenter, 3);
     192    dc.SetPen(*wxBLACK_PEN);
     193    dc.DrawCircle(m_SelectionCenter, 2);
    173194    dc.SetPen(*wxWHITE_PEN);
    174195    dc.DrawLine(PanelRadius - 10, PanelRadius, PanelRadius + 10, PanelRadius);
    175196    dc.DrawLine(PanelRadius, PanelRadius + 10, PanelRadius, PanelRadius - 10);
    EVT_MIDDLE_DOWN(PsuedoMiniMapPanel::OnMouseDown)  
    197218EVT_MIDDLE_UP(PsuedoMiniMapPanel::OnMouseUp)
    198219EVT_MOTION(PsuedoMiniMapPanel::OnMouseMove)
    199220EVT_PAINT(PsuedoMiniMapPanel::PaintEvent)
    200 EVT_ERASE_BACKGROUND(PsuedoMiniMapPanel::EraseBackground)
    201221END_EVENT_TABLE()
    202  No newline at end of file
  • source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.h

    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.h b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.h
    index 87991a5..215a177 100644
    a b private:  
    3232    void OnMouseMove(wxMouseEvent& evt);
    3333
    3434    const int m_CurrentSize;
     35    wxImage m_Background;
    3536    std::map<int, wxBitmap> m_ScreenTones;
     37    std::map<int, wxBitmap> m_Backgrounds;
    3638
    3739    wxPoint m_LastMousePos;
    3840    bool m_Dragging;
  • source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp

    diff --git a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
    index 44d817c..a142f5e 100644
    a b  
    3535#include "ps/CLogger.h"
    3636#include "ps/Filesystem.h"
    3737#include "ps/Game.h"
     38#include "ps/GameSetup/GameSetup.h"
    3839#include "ps/Loader.h"
    3940#include "ps/World.h"
    4041#include "renderer/Renderer.h"
     42#include "renderer/WaterManager.h"
    4143#include "scriptinterface/ScriptInterface.h"
    4244#include "simulation2/Simulation2.h"
    4345#include "simulation2/components/ICmpPlayer.h"
     
    4547#include "simulation2/components/ICmpPosition.h"
    4648#include "simulation2/components/ICmpRangeManager.h"
    4749#include "simulation2/components/ICmpTerrain.h"
     50#include "simulation2/system/ParamNode.h"
    4851
    4952namespace
    5053{
    QUERYHANDLER(GetMapSizes)  
    307310    msg->sizes = g_Game->GetSimulation2()->GetMapSizes();
    308311}
    309312
     313QUERYHANDLER(GetMiniMapDisplay)
     314{
     315    const CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
     316    const ssize_t dimension = terrain->GetVerticesPerSide() - 1;
     317    const ssize_t bpp = 24;
     318    const ssize_t buf_size = dimension * dimension * (bpp / 8);
     319
     320    // Data is destined for a wxImage, which uses free.
     321    unsigned char* img = static_cast<unsigned char*>(malloc(buf_size));
     322    if (img)
     323    {
     324        // Stolen from MiniMap.cpp
     325        float shallowPassageHeight = 0.0f;
     326        // Get the maximum height for unit passage in water.
     327        CParamNode externalParamNode;
     328        CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml", "pathfinder");
     329        const CParamNode pathingSettings = externalParamNode.GetChild("Pathfinder").GetChild("PassabilityClasses");
     330        if (pathingSettings.GetChild("default").IsOk() && pathingSettings.GetChild("default").GetChild("MaxWaterDepth").IsOk())
     331            shallowPassageHeight = pathingSettings.GetChild("default").GetChild("MaxWaterDepth").ToFloat();
     332
     333        ssize_t w = dimension;
     334        ssize_t h = dimension;
     335        float waterHeight = g_Renderer.GetWaterManager()->m_WaterHeight;
     336
     337        for (ssize_t j = 0; j < h; ++j)
     338        {
     339            // Work backwards to vertically flip the image.
     340            unsigned char* dataPtr = img + 3 * (h - j - 1) * dimension;
     341            for (ssize_t i = 0; i < w; ++i)
     342            {
     343                float avgHeight = (terrain->GetVertexGroundLevel(i, j)
     344                    + terrain->GetVertexGroundLevel(i + 1, j)
     345                    + terrain->GetVertexGroundLevel(i, j + 1)
     346                    + terrain->GetVertexGroundLevel(i + 1, j + 1)
     347                    ) / 4.0f;
     348
     349                if (avgHeight < waterHeight && avgHeight > waterHeight - shallowPassageHeight)
     350                {
     351                    // shallow water
     352                    *dataPtr++ = 0x70;
     353                    *dataPtr++ = 0x98;
     354                    *dataPtr++ = 0xc0;
     355                }
     356                else if (avgHeight < waterHeight)
     357                {
     358                    // Set water as constant color for consistency on different maps
     359                    *dataPtr++ = 0x50;
     360                    *dataPtr++ = 0x78;
     361                    *dataPtr++ = 0xa0;
     362                }
     363                else
     364                {
     365                    int hmap = ((int)terrain->GetHeightMap()[j * dimension + i]) >> 8;
     366                    float scale = float((hmap / 3) + 170) / 255.0f;
     367
     368                    u32 color = 0xFFFFFFFF;
     369
     370                    CMiniPatch* mp = terrain->GetTile(i, j);
     371                    if (mp)
     372                    {
     373                        CTerrainTextureEntry* tex = mp->GetTextureEntry();
     374                        if (tex)
     375                        {
     376                            color = tex->GetBaseColor();
     377                        }
     378                    }
     379
     380                    // Convert
     381                    *dataPtr++ = unsigned char(float(color & 0xff) * scale);
     382                    *dataPtr++ = unsigned char(float((color >> 8) & 0xff) * scale);
     383                    *dataPtr++ = unsigned char(float((color >> 16) & 0xff) * scale);
     384                }
     385            }
     386        }
     387    }
     388       
     389    msg->imageBytes = static_cast<void*>(img);
     390    msg->dimension = dimension;
     391}
     392
    310393QUERYHANDLER(GetRMSData)
    311394{
    312395    msg->data = g_Game->GetSimulation2()->GetRMSData();
  • source/tools/atlas/GameInterface/Messages.h

    diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h
    index f2f3953..3b1368f 100644
    a b QUERY(GetCurrentMapSize,  
    198198        ((int, size))
    199199        );
    200200
     201QUERY(GetMiniMapDisplay,
     202        ,
     203        ((int, dimension))
     204        ((void*, imageBytes))
     205        );
     206
    201207QUERY(GetRMSData,
    202208        ,
    203209        ((std::vector<std::string>, data))
  • source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp

    -- 
    2.8.1.windows.1
    
    From c70df887ae6b434be878d77d9b8708bcbc5065d5 Mon Sep 17 00:00:00 2001
    From: "Stephen A. Imhoff" <clockwork-muse@outlook.com>
    Date: Sat, 18 Jun 2016 16:42:09 +0900
    Subject: [PATCH] Add psuedo map panel.
    
    ---
     .../MapResizeDialog/MapResizeDialog.cpp            |  48 +++--
     .../MapResizeDialog/MapResizeDialog.h              |   4 +-
     .../MapResizeDialog/PsuedoMiniMapPanel.cpp         | 201 +++++++++++++++++++++
     .../MapResizeDialog/PsuedoMiniMapPanel.h           |  45 +++++
     .../ScenarioEditor/Sections/Terrain/Terrain.cpp    |   6 +-
     5 files changed, 277 insertions(+), 27 deletions(-)
     create mode 100644 source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.cpp
     create mode 100644 source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.h
    
    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp
    index 9ce0ec3..17ded82 100644
    a b  
    2424#include "GameInterface/Messages.h"
    2525
    2626#include <wx/statline.h>
     27#include "PsuedoMiniMapPanel.h"
    2728
    28 MapResizeDialog::MapResizeDialog(wxWindow* parent, size_t currentSize)
    29     : wxDialog(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(600, 400), wxCAPTION | wxRESIZE_BORDER),
     29MapResizeDialog::MapResizeDialog(wxWindow* parent)
     30    : wxDialog(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxCAPTION | wxRESIZE_BORDER),
    3031    m_NewSize(0)
    3132{
    3233    Freeze();
    3334
     35    AtlasMessage::qGetCurrentMapSize qrySize;
     36    qrySize.Post();
     37    int currentSize = qrySize.size;
     38
     39    SetTitle(_("Resize map"));
     40    wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
     41    wxStaticText* label = new wxStaticText(this, wxID_ANY, _("Select new map size. WARNING: This probably only works reliably on blank maps."), wxDefaultPosition, wxDefaultSize);
     42    sizer->Add(label, wxSizerFlags().Align(wxALIGN_CENTER_HORIZONTAL).Border(wxALL, 10));
     43
     44    wxBoxSizer* listAndMap = new wxBoxSizer(wxHORIZONTAL);
     45   
     46    wxListBox* listBox = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE | wxLB_HSCROLL);
    3447    // Load the map sizes list
    3548    AtlasMessage::qGetMapSizes qrySizes;
    3649    qrySizes.Post();
    3750    AtObj sizes = AtlasObject::LoadFromJSON(*qrySizes.sizes);
    3851    for (AtIter s = sizes["Data"]["item"]; s.defined(); ++s)
    39     {
    40         long tiles = 0;
    41         wxString(s["Tiles"]).ToLong(&tiles);
    42         m_SizeNames.Add(wxString(s["Name"]));
    43         m_SizeTiles.push_back((size_t)tiles);
     52    {   
     53        wxString size(s["Tiles"]);
     54        listBox->Append(wxString(s["Name"]), new wxStringClientData(size));
     55        if (currentSize == wxAtoi(size))
     56            listBox->SetSelection(listBox->GetCount() - 1);
    4457    }
     58    listAndMap->Add(listBox, wxSizerFlags().Align(wxALIGN_LEFT).Proportion(1).Expand());
     59    listAndMap->AddSpacer(10);
    4560
    46     SetTitle(_("Resize map"));
    47 
    48     wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
    49 
    50     wxStaticText* label = new wxStaticText(this, wxID_ANY, _("Select new map size. WARNING: This probably only works reliably on blank maps."), wxDefaultPosition, wxDefaultSize);
    51     sizer->Add(label, wxSizerFlags().Align(wxALIGN_CENTER).Border(wxALL, 10));
    52    
    53     wxListBox* listBox = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE | wxLB_HSCROLL);
    54     listBox->Append(m_SizeNames);
     61    PsuedoMiniMapPanel* miniMap = new PsuedoMiniMapPanel(this, currentSize);
     62    listBox->Bind(wxEVT_LISTBOX, &PsuedoMiniMapPanel::OnNewSize, miniMap);
    5563
     64    listAndMap->Add(miniMap, wxSizerFlags());
     65    sizer->Add(listAndMap, wxSizerFlags().Proportion(1).Expand().Border(wxLEFT | wxRIGHT, 10));
    5666
     67    sizer->AddSpacer(5);
    5768    sizer->Add(new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL), wxSizerFlags().Expand().Border(wxRIGHT | wxLEFT, 7));
    5869    sizer->AddSpacer(5);
    5970
    size_t MapResizeDialog::GetNewSize() const  
    7687
    7788void MapResizeDialog::OnListBox(wxCommandEvent& evt)
    7889{
    79     int index = evt.GetInt();
    80     if (index < 0 || index >= m_SizeTiles.size())
     90    if (!evt.IsSelection())
    8191        return;
    8292
    83     m_NewSize = m_SizeTiles[index];
     93    m_NewSize = wxAtoi(static_cast<wxStringClientData*>(evt.GetClientObject())->GetData());
    8494   
    8595    if (evt.GetEventType() == wxEVT_COMMAND_LISTBOX_DOUBLECLICKED)
    8696    {
  • source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h

    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h
    index f19a9f6..cc07341 100644
    a b  
    2323class MapResizeDialog : public wxDialog
    2424{
    2525public:
    26     MapResizeDialog(wxWindow* parent, size_t currentSize);
     26    MapResizeDialog(wxWindow* parent);
    2727
    2828    /**
    2929     * Returns selected new size.
    private:  
    3636    void OnListBox(wxCommandEvent& evt);
    3737
    3838    size_t m_NewSize;
    39     wxArrayString m_SizeNames;
    40     std::vector<size_t> m_SizeTiles;
    4139
    4240    DECLARE_EVENT_TABLE();
    4341};
  • new file source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.cpp

    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.cpp b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.cpp
    new file mode 100644
    index 0000000..020faee
    - +  
     1/* Copyright (C) 2016 Wildfire Games.
     2* This file is part of 0 A.D.
     3*
     4* 0 A.D. is free software: you can redistribute it and/or modify
     5* it under the terms of the GNU General Public License as published by
     6* the Free Software Foundation, either version 2 of the License, or
     7* (at your option) any later version.
     8*
     9* 0 A.D. is distributed in the hope that it will be useful,
     10* but WITHOUT ANY WARRANTY; without even the implied warranty of
     11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12* GNU General Public License for more details.
     13*
     14* You should have received a copy of the GNU General Public License
     15* along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16*/
     17
     18#include "precompiled.h"
     19
     20#include "PsuedoMiniMapPanel.h"
     21
     22#include "GameInterface/Messages.h"
     23#include "ScenarioEditor/Tools/Common/Tools.h"
     24
     25#include <math.h>
     26#include <wx/dcbuffer.h>
     27#include <wx/dcgraph.h>
     28#include <wx/defs.h>
     29
     30namespace
     31{
     32    const int PanelRadius = 75;
     33    const wxPoint PanelCenter = wxPoint(PanelRadius + 1, PanelRadius + 1);
     34    const char* ScreenToneMask[] =
     35    {
     36        /* columns rows colors chars-per-pixel */
     37        "4 4 2 1",
     38        "X c White",
     39        "O c Black",
     40        /* pixels */
     41        "OOOO",
     42        "OXXO",
     43        "OXXO",
     44        "OOOO"
     45    };
     46    const wxPoint ScreenToneOffset(-2 * PanelRadius, -2 * PanelRadius);
     47    const wxPen Rim(*wxBLACK, 3);
     48
     49    bool Within(const wxPoint& test, const wxPoint& center, int radius)
     50    {
     51        int dx = abs(test.x - center.x);
     52        if (dx > radius)
     53            return false;
     54        int dy = abs(test.y - center.y);
     55        if (dy > radius)
     56            return false;
     57        if (dx + dy <= radius)
     58            return true;
     59        return (dx * dx + dy * dy <= radius * radius);
     60    }
     61}
     62
     63PsuedoMiniMapPanel::PsuedoMiniMapPanel(wxWindow* parent, int currentSize)
     64    : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(PanelRadius * 2 + 1, PanelRadius * 2 + 1)),
     65    m_CurrentSize(currentSize), m_ScreenTones(),
     66    m_LastMousePos(-1, -1), m_Dragging(false),
     67    m_SelectionRadius(PanelRadius), m_SelectionCenter(PanelCenter), m_SameOrGrowing(true)
     68{
     69    SetBackgroundStyle(wxBG_STYLE_PAINT);
     70}
     71
     72void PsuedoMiniMapPanel::OnNewSize(wxCommandEvent& evt)
     73{
     74    if (!evt.IsSelection())
     75        return;
     76
     77    int newSize = wxAtoi(static_cast<wxStringClientData*>(evt.GetClientObject())->GetData());
     78
     79    m_SameOrGrowing = newSize >= m_CurrentSize;
     80    m_SelectionRadius = double(std::min(newSize, m_CurrentSize)) / std::max(newSize, m_CurrentSize) * PanelRadius;
     81
     82    if (!m_SameOrGrowing && m_ScreenTones.find(m_SelectionRadius) == m_ScreenTones.cend())
     83    {
     84        wxImage overlay = wxImage(PanelRadius * 4, PanelRadius * 4);
     85        overlay.InitAlpha();
     86        wxGraphicsContext* gc = wxGraphicsContext::Create(overlay);
     87        gc->SetBrush(wxBrush(ScreenToneMask));
     88        gc->DrawRectangle(0, 0, PanelRadius * 4, PanelRadius * 4);
     89        gc->SetBrush(*wxBLACK_BRUSH);
     90        gc->DrawEllipse(PanelRadius * 2 - m_SelectionRadius, PanelRadius * 2  - m_SelectionRadius, m_SelectionRadius * 2, m_SelectionRadius * 2);
     91        gc->SetPen(*wxWHITE_PEN);
     92        gc->DrawEllipse(PanelRadius * 2 - m_SelectionRadius, PanelRadius * 2 - m_SelectionRadius, m_SelectionRadius * 2, m_SelectionRadius * 2);
     93        delete gc;
     94        // Black -> Converted to transparent.
     95        // White -> converted to black.
     96        overlay.ConvertColourToAlpha(0, 0, 0);
     97
     98        m_ScreenTones[m_SelectionRadius] = wxBitmap(overlay);
     99    }
     100
     101    Refresh();
     102}
     103
     104void PsuedoMiniMapPanel::OnMouseDown(wxMouseEvent& evt)
     105{
     106    // Capture on button-down, so we can respond even when the mouse
     107    // moves off the window
     108    if (!m_Dragging && evt.ButtonDown() &&
     109        Within(evt.GetPosition(), PanelCenter, PanelRadius) &&
     110        Within(evt.GetPosition(), m_SelectionCenter, m_SelectionRadius))
     111    {
     112        m_LastMousePos = evt.GetPosition();
     113        m_Dragging = true;
     114    }
     115}
     116
     117void PsuedoMiniMapPanel::OnMouseUp(wxMouseEvent& evt)
     118{
     119    if (m_Dragging &&
     120        !(evt.ButtonIsDown(wxMOUSE_BTN_LEFT) || evt.ButtonIsDown(wxMOUSE_BTN_MIDDLE) || evt.ButtonIsDown(wxMOUSE_BTN_RIGHT))
     121        )
     122    {
     123        m_Dragging = false;
     124    }
     125}
     126
     127void PsuedoMiniMapPanel::OnMouseMove(wxMouseEvent& evt)
     128{
     129    if (m_Dragging && evt.Dragging())
     130    {
     131        if (m_LastMousePos == evt.GetPosition())
     132            return;
     133
     134        wxPoint delta = evt.GetPosition() - m_LastMousePos;
     135        wxPoint moved = m_SelectionCenter + delta;
     136
     137        if (!Within(moved, PanelCenter, PanelRadius))
     138            return;
     139
     140        m_SelectionCenter = moved;
     141        m_LastMousePos = evt.GetPosition();
     142        Refresh();
     143    }
     144}
     145
     146void PsuedoMiniMapPanel::PaintEvent(wxPaintEvent& WXUNUSED(evt))
     147{
     148    wxAutoBufferedPaintDC dca(this);
     149    // Background must be grabbed from paint dc, not gc, or color may be transparent.
     150    wxColor background = dca.GetBackground().GetColour();
     151    wxGCDC dc(dca);
     152    if (m_SameOrGrowing)
     153    {
     154        dc.SetBrush(*wxBLACK_BRUSH);
     155        dc.DrawRectangle(0, 0, 2 * PanelRadius, 2 * PanelRadius);
     156        dc.SetBrush(*wxWHITE_BRUSH);
     157        dc.DrawCircle(m_SelectionCenter, m_SelectionRadius + 1);
     158        dc.SetBrush(*wxGREEN_BRUSH);
     159        dc.DrawCircle(m_SelectionCenter, m_SelectionRadius);
     160    }
     161    else
     162    {
     163        dc.SetBrush(*wxGREEN_BRUSH);
     164        dc.DrawRectangle(0, 0, 2 * PanelRadius, 2 * PanelRadius);
     165       
     166        // "fade out" trimmed areas by drawing a screentone ring ring.
     167        dc.DrawBitmap(m_ScreenTones[m_SelectionRadius], ScreenToneOffset + m_SelectionCenter);
     168    }
     169
     170    // Centering markers.
     171    dc.SetBrush(*wxBLACK_BRUSH);
     172    dc.DrawCircle(m_SelectionCenter, 3);
     173    dc.SetPen(*wxWHITE_PEN);
     174    dc.DrawLine(PanelRadius - 10, PanelRadius, PanelRadius + 10, PanelRadius);
     175    dc.DrawLine(PanelRadius, PanelRadius + 10, PanelRadius, PanelRadius - 10);
     176
     177    // Round border.
     178    dc.SetBrush(*wxTRANSPARENT_BRUSH);
     179    dc.SetPen(Rim);
     180    dc.DrawCircle(PanelCenter, PanelRadius - 1);
     181    wxPen mask(background, PanelRadius);
     182    dc.SetPen(mask);
     183    dc.DrawCircle(PanelCenter, PanelRadius + PanelRadius / 2 - 1);
     184}
     185
     186void PsuedoMiniMapPanel::EraseBackground(wxEraseEvent& WXUNUSED(evt))
     187{
     188    // Do nothing - don't erase to remove flicker.
     189}
     190
     191BEGIN_EVENT_TABLE(PsuedoMiniMapPanel, wxPanel)
     192EVT_LEFT_DOWN(PsuedoMiniMapPanel::OnMouseDown)
     193EVT_LEFT_UP(PsuedoMiniMapPanel::OnMouseUp)
     194EVT_RIGHT_DOWN(PsuedoMiniMapPanel::OnMouseDown)
     195EVT_RIGHT_UP(PsuedoMiniMapPanel::OnMouseUp)
     196EVT_MIDDLE_DOWN(PsuedoMiniMapPanel::OnMouseDown)
     197EVT_MIDDLE_UP(PsuedoMiniMapPanel::OnMouseUp)
     198EVT_MOTION(PsuedoMiniMapPanel::OnMouseMove)
     199EVT_PAINT(PsuedoMiniMapPanel::PaintEvent)
     200EVT_ERASE_BACKGROUND(PsuedoMiniMapPanel::EraseBackground)
     201END_EVENT_TABLE()
     202 No newline at end of file
  • new file source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.h

    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.h b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/PsuedoMiniMapPanel.h
    new file mode 100644
    index 0000000..87991a5
    - +  
     1/* Copyright (C) 2016 Wildfire Games.
     2* This file is part of 0 A.D.
     3*
     4* 0 A.D. is free software: you can redistribute it and/or modify
     5* it under the terms of the GNU General Public License as published by
     6* the Free Software Foundation, either version 2 of the License, or
     7* (at your option) any later version.
     8*
     9* 0 A.D. is distributed in the hope that it will be useful,
     10* but WITHOUT ANY WARRANTY; without even the implied warranty of
     11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12* GNU General Public License for more details.
     13*
     14* You should have received a copy of the GNU General Public License
     15* along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16*/
     17
     18#include <wx/panel.h>
     19
     20class PsuedoMiniMapPanel : public wxPanel
     21{
     22public:
     23    PsuedoMiniMapPanel(wxWindow* parent, int currentSize);
     24
     25    void PaintEvent(wxPaintEvent& evt);
     26    void EraseBackground(wxEraseEvent& evt);
     27
     28    void OnNewSize(wxCommandEvent& evt);
     29private:
     30    void OnMouseDown(wxMouseEvent& evt);
     31    void OnMouseUp(wxMouseEvent& evt);
     32    void OnMouseMove(wxMouseEvent& evt);
     33
     34    const int m_CurrentSize;
     35    std::map<int, wxBitmap> m_ScreenTones;
     36
     37    wxPoint m_LastMousePos;
     38    bool m_Dragging;
     39
     40    wxPoint m_SelectionCenter;
     41    int m_SelectionRadius;
     42    bool m_SameOrGrowing;
     43
     44    DECLARE_EVENT_TABLE();
     45};
  • source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp

    diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp
    index ead2117..b67d275 100644
    a b void TerrainSidebar::OnShowPriorities(wxCommandEvent& evt)  
    280280
    281281void TerrainSidebar::OnResizeMap(wxCommandEvent& WXUNUSED(evt))
    282282{
    283 
    284     AtlasMessage::qGetCurrentMapSize qrySize;
    285     qrySize.Post();
    286 
    287     MapResizeDialog dlg(this, qrySize.size);
     283    MapResizeDialog dlg(this);
    288284
    289285    if (dlg.ShowModal() != wxID_OK)
    290286        return;
  • new file source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp

    -- 
    2.8.1.windows.1
    
    From ee49f74f45fb2b668298c9f1e810a3451a5c8af5 Mon Sep 17 00:00:00 2001
    From: "Stephen A. Imhoff" <clockwork-muse@outlook.com>
    Date: Wed, 15 Jun 2016 20:29:33 +0900
    Subject: [PATCH] Recreate existing dialog, add initial size.
    
    ---
     .../MapResizeDialog/MapResizeDialog.cpp            | 106 +++++++++++++++++++++
     .../MapResizeDialog/MapResizeDialog.h              |  45 +++++++++
     .../ScenarioEditor/Sections/Terrain/Terrain.cpp    |  26 ++---
     .../atlas/GameInterface/Handlers/MapHandlers.cpp   |   5 +
     source/tools/atlas/GameInterface/Messages.h        |   5 +
     5 files changed, 167 insertions(+), 20 deletions(-)
     create mode 100644 source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp
     create mode 100644 source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h
    
    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.cpp
    new file mode 100644
    index 0000000..9ce0ec3
    - +  
     1/* Copyright (C) 2016 Wildfire Games.
     2* This file is part of 0 A.D.
     3*
     4* 0 A.D. is free software: you can redistribute it and/or modify
     5* it under the terms of the GNU General Public License as published by
     6* the Free Software Foundation, either version 2 of the License, or
     7* (at your option) any later version.
     8*
     9* 0 A.D. is distributed in the hope that it will be useful,
     10* but WITHOUT ANY WARRANTY; without even the implied warranty of
     11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12* GNU General Public License for more details.
     13*
     14* You should have received a copy of the GNU General Public License
     15* along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16*/
     17
     18#include "precompiled.h"
     19
     20#include "MapResizeDialog.h"
     21#include "ScenarioEditor/ScenarioEditor.h"
     22
     23#include "GameInterface/MessagePasser.h"
     24#include "GameInterface/Messages.h"
     25
     26#include <wx/statline.h>
     27
     28MapResizeDialog::MapResizeDialog(wxWindow* parent, size_t currentSize)
     29    : wxDialog(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(600, 400), wxCAPTION | wxRESIZE_BORDER),
     30    m_NewSize(0)
     31{
     32    Freeze();
     33
     34    // Load the map sizes list
     35    AtlasMessage::qGetMapSizes qrySizes;
     36    qrySizes.Post();
     37    AtObj sizes = AtlasObject::LoadFromJSON(*qrySizes.sizes);
     38    for (AtIter s = sizes["Data"]["item"]; s.defined(); ++s)
     39    {
     40        long tiles = 0;
     41        wxString(s["Tiles"]).ToLong(&tiles);
     42        m_SizeNames.Add(wxString(s["Name"]));
     43        m_SizeTiles.push_back((size_t)tiles);
     44    }
     45
     46    SetTitle(_("Resize map"));
     47
     48    wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
     49
     50    wxStaticText* label = new wxStaticText(this, wxID_ANY, _("Select new map size. WARNING: This probably only works reliably on blank maps."), wxDefaultPosition, wxDefaultSize);
     51    sizer->Add(label, wxSizerFlags().Align(wxALIGN_CENTER).Border(wxALL, 10));
     52   
     53    wxListBox* listBox = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE | wxLB_HSCROLL);
     54    listBox->Append(m_SizeNames);
     55
     56
     57    sizer->Add(new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL), wxSizerFlags().Expand().Border(wxRIGHT | wxLEFT, 7));
     58    sizer->AddSpacer(5);
     59
     60    wxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL);
     61    buttonSizer->Add(new wxButton(this, wxID_OK, _("OK")));
     62    buttonSizer->AddSpacer(5);
     63    buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")));
     64
     65    sizer->Add(buttonSizer, wxSizerFlags().Align(wxALIGN_RIGHT | wxALIGN_BOTTOM).Border(wxRIGHT | wxBOTTOM, 10));
     66
     67    SetSizerAndFit(sizer);
     68    Layout();
     69    Thaw();
     70}
     71
     72size_t MapResizeDialog::GetNewSize() const
     73{
     74    return m_NewSize;
     75}
     76
     77void MapResizeDialog::OnListBox(wxCommandEvent& evt)
     78{
     79    int index = evt.GetInt();
     80    if (index < 0 || index >= m_SizeTiles.size())
     81        return;
     82
     83    m_NewSize = m_SizeTiles[index];
     84   
     85    if (evt.GetEventType() == wxEVT_COMMAND_LISTBOX_DOUBLECLICKED)
     86    {
     87        EndModal(wxID_OK);
     88    }
     89}
     90
     91void MapResizeDialog::OnCancel(wxCommandEvent& WXUNUSED(evt))
     92{
     93    EndModal(wxID_CANCEL);
     94}
     95
     96void MapResizeDialog::OnOK(wxCommandEvent& WXUNUSED(evt))
     97{
     98    EndModal(wxID_OK);
     99}
     100
     101BEGIN_EVENT_TABLE(MapResizeDialog, wxDialog)
     102    EVT_BUTTON(wxID_CANCEL, MapResizeDialog::OnCancel)
     103    EVT_BUTTON(wxID_OK, MapResizeDialog::OnOK)
     104    EVT_LISTBOX(wxID_ANY, MapResizeDialog::OnListBox)
     105    EVT_LISTBOX_DCLICK(wxID_ANY, MapResizeDialog::OnListBox)
     106END_EVENT_TABLE()
     107 No newline at end of file
  • new file source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h

    diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h b/source/tools/atlas/AtlasUI/CustomControls/MapResizeDialog/MapResizeDialog.h
    new file mode 100644
    index 0000000..f19a9f6
    - +  
     1/* Copyright (C) 2016 Wildfire Games.
     2* This file is part of 0 A.D.
     3*
     4* 0 A.D. is free software: you can redistribute it and/or modify
     5* it under the terms of the GNU General Public License as published by
     6* the Free Software Foundation, either version 2 of the License, or
     7* (at your option) any later version.
     8*
     9* 0 A.D. is distributed in the hope that it will be useful,
     10* but WITHOUT ANY WARRANTY; without even the implied warranty of
     11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12* GNU General Public License for more details.
     13*
     14* You should have received a copy of the GNU General Public License
     15* along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
     16*/
     17
     18#ifndef INCLUDED_MAPRESIZEDIALOG
     19#define INCLUDED_MAPRESIZEDIALOG
     20
     21#include <wx/dialog.h>
     22
     23class MapResizeDialog : public wxDialog
     24{
     25public:
     26    MapResizeDialog(wxWindow* parent, size_t currentSize);
     27
     28    /**
     29     * Returns selected new size.
     30     */
     31    size_t GetNewSize() const;
     32
     33private:
     34    void OnCancel(wxCommandEvent& evt);
     35    void OnOK(wxCommandEvent& evt);
     36    void OnListBox(wxCommandEvent& evt);
     37
     38    size_t m_NewSize;
     39    wxArrayString m_SizeNames;
     40    std::vector<size_t> m_SizeTiles;
     41
     42    DECLARE_EVENT_TABLE();
     43};
     44
     45#endif // INCLUDED_MAPRESIZEDIALOG
     46 No newline at end of file
  • source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp

    diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Terrain/Terrain.cpp
    index 2c2287a..ead2117 100644
    a b  
    2323#include "ScenarioEditor/ScenarioEditor.h"
    2424#include "ScenarioEditor/Tools/Common/Brushes.h"
    2525#include "ScenarioEditor/Tools/Common/MiscState.h"
     26#include "MapResizeDialog/MapResizeDialog.h"
    2627
    2728#include "GameInterface/Messages.h"
    2829
    void TerrainSidebar::OnShowPriorities(wxCommandEvent& evt)  
    279280
    280281void TerrainSidebar::OnResizeMap(wxCommandEvent& WXUNUSED(evt))
    281282{
    282     wxArrayString sizeNames;
    283     std::vector<size_t> sizeTiles;
    284 
    285     // Load the map sizes list
    286     AtlasMessage::qGetMapSizes qrySizes;
    287     qrySizes.Post();
    288     AtObj sizes = AtlasObject::LoadFromJSON(*qrySizes.sizes);
    289     for (AtIter s = sizes["Data"]["item"]; s.defined(); ++s)
    290     {
    291         long tiles = 0;
    292         wxString(s["Tiles"]).ToLong(&tiles);
    293         sizeNames.Add(wxString(s["Name"]));
    294         sizeTiles.push_back((size_t)tiles);
    295     }
    296283
    297     // TODO: set default based on current map size
     284    AtlasMessage::qGetCurrentMapSize qrySize;
     285    qrySize.Post();
    298286
    299     wxSingleChoiceDialog dlg(this, _("Select new map size. WARNING: This probably only works reliably on blank maps."),
    300             _("Resize map"), sizeNames);
     287    MapResizeDialog dlg(this, qrySize.size);
    301288
    302289    if (dlg.ShowModal() != wxID_OK)
    303290        return;
    304 
    305     size_t tiles = sizeTiles.at(dlg.GetSelection());
    306     POST_COMMAND(ResizeMap, (tiles));
     291   
     292    POST_COMMAND(ResizeMap, (dlg.GetNewSize()));
    307293}
    308294
    309295BEGIN_EVENT_TABLE(TerrainSidebar, Sidebar)
  • source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp

    diff --git a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
    index b351812..44d817c 100644
    a b QUERYHANDLER(GetRMSData)  
    312312    msg->data = g_Game->GetSimulation2()->GetRMSData();
    313313}
    314314
     315QUERYHANDLER(GetCurrentMapSize)
     316{
     317    msg->size = g_Game->GetWorld()->GetTerrain()->GetTilesPerSide();
     318}
     319
    315320BEGIN_COMMAND(ResizeMap)
    316321{
    317322    int m_OldTiles, m_NewTiles;
  • source/tools/atlas/GameInterface/Messages.h

    diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h
    index 013d58d..f2f3953 100644
    a b QUERY(GetMapSizes,  
    193193        ((std::string, sizes))
    194194        );
    195195
     196QUERY(GetCurrentMapSize,
     197        ,
     198        ((int, size))
     199        );
     200
    196201QUERY(GetRMSData,
    197202        ,
    198203        ((std::vector<std::string>, data))
  • build/premake/premake4.lua

    -- 
    2.8.1.windows.1
    
    From 9cf9404e4c9d6b5f4fba185a19e1aa6f219fb73a Mon Sep 17 00:00:00 2001
    From: "Stephen A. Imhoff" <clockwork-muse@outlook.com>
    Date: Wed, 15 Jun 2016 20:17:44 +0900
    Subject: [PATCH] Add premake entry
    
    ---
     build/premake/premake4.lua | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/build/premake/premake4.lua b/build/premake/premake4.lua
    index 8473679..d4a8096 100644
    a b function setup_atlas_projects()  
    11181118        "CustomControls/FileHistory",
    11191119        "CustomControls/HighResTimer",
    11201120        "CustomControls/MapDialog",
     1121        "CustomControls/MapResizeDialog",
    11211122        "CustomControls/SnapSplitterWindow",
    11221123        "CustomControls/VirtualDirTreeCtrl",
    11231124        "CustomControls/Windows",