|
@@ -19,6 +19,7 @@
|
|
|
#include "../gui/CGuiHandler.h"
|
|
#include "../gui/CGuiHandler.h"
|
|
|
#include "../render/Colors.h"
|
|
#include "../render/Colors.h"
|
|
|
#include "../renderSDL/SDL_PixelAccess.h"
|
|
#include "../renderSDL/SDL_PixelAccess.h"
|
|
|
|
|
+#include "../windows/InfoWindows.h"
|
|
|
|
|
|
|
|
#include "../../CCallback.h"
|
|
#include "../../CCallback.h"
|
|
|
#include "../../lib/CGeneralTextHandler.h"
|
|
#include "../../lib/CGeneralTextHandler.h"
|
|
@@ -26,159 +27,65 @@
|
|
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
|
|
#include "../../lib/mapping/CMapDefines.h"
|
|
#include "../../lib/mapping/CMapDefines.h"
|
|
|
|
|
|
|
|
-#include <SDL_surface.h>
|
|
|
|
|
-
|
|
|
|
|
-const SDL_Color & CMinimapInstance::getTileColor(const int3 & pos)
|
|
|
|
|
|
|
+ColorRGBA CMinimapInstance::getTileColor(const int3 & pos) const
|
|
|
{
|
|
{
|
|
|
const TerrainTile * tile = LOCPLINT->cb->getTile(pos, false);
|
|
const TerrainTile * tile = LOCPLINT->cb->getTile(pos, false);
|
|
|
|
|
|
|
|
// if tile is not visible it will be black on minimap
|
|
// if tile is not visible it will be black on minimap
|
|
|
if(!tile)
|
|
if(!tile)
|
|
|
- return Colors::BLACK;
|
|
|
|
|
|
|
+ return CSDL_Ext::fromSDL(Colors::BLACK);
|
|
|
|
|
|
|
|
// if object at tile is owned - it will be colored as its owner
|
|
// if object at tile is owned - it will be colored as its owner
|
|
|
for (const CGObjectInstance *obj : tile->blockingObjects)
|
|
for (const CGObjectInstance *obj : tile->blockingObjects)
|
|
|
{
|
|
{
|
|
|
- //heroes will be blitted later
|
|
|
|
|
- switch (obj->ID)
|
|
|
|
|
- {
|
|
|
|
|
- case Obj::HERO:
|
|
|
|
|
- case Obj::PRISON:
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
PlayerColor player = obj->getOwner();
|
|
PlayerColor player = obj->getOwner();
|
|
|
if(player == PlayerColor::NEUTRAL)
|
|
if(player == PlayerColor::NEUTRAL)
|
|
|
- return *graphics->neutralColor;
|
|
|
|
|
- else
|
|
|
|
|
|
|
+ return CSDL_Ext::fromSDL(*graphics->neutralColor);
|
|
|
|
|
+
|
|
|
if (player < PlayerColor::PLAYER_LIMIT)
|
|
if (player < PlayerColor::PLAYER_LIMIT)
|
|
|
- return graphics->playerColors[player.getNum()];
|
|
|
|
|
|
|
+ return CSDL_Ext::fromSDL(graphics->playerColors[player.getNum()]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // else - use terrain color (blocked version or normal)
|
|
|
|
|
- const auto & colorPair = parent->colors.find(tile->terType->getId())->second;
|
|
|
|
|
if (tile->blocked && (!tile->visitable))
|
|
if (tile->blocked && (!tile->visitable))
|
|
|
- return colorPair.second;
|
|
|
|
|
|
|
+ return tile->terType->minimapBlocked;
|
|
|
else
|
|
else
|
|
|
- return colorPair.first;
|
|
|
|
|
-}
|
|
|
|
|
-void CMinimapInstance::tileToPixels (const int3 &tile, int &x, int &y, int toX, int toY)
|
|
|
|
|
-{
|
|
|
|
|
- int3 mapSizes = LOCPLINT->cb->getMapSize();
|
|
|
|
|
-
|
|
|
|
|
- double stepX = double(pos.w) / mapSizes.x;
|
|
|
|
|
- double stepY = double(pos.h) / mapSizes.y;
|
|
|
|
|
-
|
|
|
|
|
- x = static_cast<int>(toX + stepX * tile.x);
|
|
|
|
|
- y = static_cast<int>(toY + stepY * tile.y);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void CMinimapInstance::blitTileWithColor(const SDL_Color &color, const int3 &tile, SDL_Surface *to, int toX, int toY)
|
|
|
|
|
-{
|
|
|
|
|
- //coordinates of rectangle on minimap representing this tile
|
|
|
|
|
- // begin - first to blit, end - first NOT to blit
|
|
|
|
|
- int xBegin, yBegin, xEnd, yEnd;
|
|
|
|
|
- tileToPixels (tile, xBegin, yBegin, toX, toY);
|
|
|
|
|
- tileToPixels (int3 (tile.x + 1, tile.y + 1, tile.z), xEnd, yEnd, toX, toY);
|
|
|
|
|
-
|
|
|
|
|
- for (int y=yBegin; y<yEnd; y++)
|
|
|
|
|
- {
|
|
|
|
|
- uint8_t *ptr = (uint8_t*)to->pixels + y * to->pitch + xBegin * minimap->format->BytesPerPixel;
|
|
|
|
|
-
|
|
|
|
|
- for (int x=xBegin; x<xEnd; x++)
|
|
|
|
|
- ColorPutter<4, 1>::PutColor(ptr, color);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ return tile->terType->minimapUnblocked;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CMinimapInstance::refreshTile(const int3 &tile)
|
|
void CMinimapInstance::refreshTile(const int3 &tile)
|
|
|
{
|
|
{
|
|
|
- blitTileWithColor(getTileColor(int3(tile.x, tile.y, level)), tile, minimap, 0, 0);
|
|
|
|
|
|
|
+ if (level == tile.z)
|
|
|
|
|
+ minimap->drawPoint(Point(tile.x, tile.y), getTileColor(tile));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void CMinimapInstance::drawScaled(int level)
|
|
|
|
|
|
|
+void CMinimapInstance::redrawMinimap()
|
|
|
{
|
|
{
|
|
|
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
|
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
|
|
|
|
|
|
|
- //size of one map tile on our minimap
|
|
|
|
|
- double stepX = double(pos.w) / mapSizes.x;
|
|
|
|
|
- double stepY = double(pos.h) / mapSizes.y;
|
|
|
|
|
-
|
|
|
|
|
- double currY = 0;
|
|
|
|
|
- for (int y=0; y<mapSizes.y; y++, currY += stepY)
|
|
|
|
|
- {
|
|
|
|
|
- double currX = 0;
|
|
|
|
|
- for (int x=0; x<mapSizes.x; x++, currX += stepX)
|
|
|
|
|
- {
|
|
|
|
|
- const SDL_Color &color = getTileColor(int3(x,y,level));
|
|
|
|
|
-
|
|
|
|
|
- //coordinates of rectangle on minimap representing this tile
|
|
|
|
|
- // begin - first to blit, end - first NOT to blit
|
|
|
|
|
- int xBegin = static_cast<int>(currX);
|
|
|
|
|
- int yBegin = static_cast<int>(currY);
|
|
|
|
|
- int xEnd = static_cast<int>(currX + stepX);
|
|
|
|
|
- int yEnd = static_cast<int>(currY + stepY);
|
|
|
|
|
-
|
|
|
|
|
- for (int y=yBegin; y<yEnd; y++)
|
|
|
|
|
- {
|
|
|
|
|
- uint8_t *ptr = (uint8_t*)minimap->pixels + y * minimap->pitch + xBegin * minimap->format->BytesPerPixel;
|
|
|
|
|
-
|
|
|
|
|
- for (int x=xBegin; x<xEnd; x++)
|
|
|
|
|
- ColorPutter<4, 1>::PutColor(ptr, color);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ for (int y = 0; y < mapSizes.y; ++y)
|
|
|
|
|
+ for (int x = 0; x < mapSizes.x; ++x)
|
|
|
|
|
+ minimap->drawPoint(Point(x, y), getTileColor(int3(x, y, level)));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
CMinimapInstance::CMinimapInstance(CMinimap *Parent, int Level):
|
|
CMinimapInstance::CMinimapInstance(CMinimap *Parent, int Level):
|
|
|
parent(Parent),
|
|
parent(Parent),
|
|
|
- minimap(CSDL_Ext::createSurfaceWithBpp<4>(parent->pos.w, parent->pos.h)),
|
|
|
|
|
|
|
+ minimap(new Canvas(Point(LOCPLINT->cb->getMapSize().x, LOCPLINT->cb->getMapSize().y))),
|
|
|
level(Level)
|
|
level(Level)
|
|
|
{
|
|
{
|
|
|
pos.w = parent->pos.w;
|
|
pos.w = parent->pos.w;
|
|
|
pos.h = parent->pos.h;
|
|
pos.h = parent->pos.h;
|
|
|
- drawScaled(level);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-CMinimapInstance::~CMinimapInstance()
|
|
|
|
|
-{
|
|
|
|
|
- SDL_FreeSurface(minimap);
|
|
|
|
|
|
|
+ redrawMinimap();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CMinimapInstance::showAll(SDL_Surface * to)
|
|
void CMinimapInstance::showAll(SDL_Surface * to)
|
|
|
{
|
|
{
|
|
|
- blitAtLoc(minimap, 0, 0, to);
|
|
|
|
|
-
|
|
|
|
|
- //draw heroes
|
|
|
|
|
- std::vector <const CGHeroInstance *> heroes = LOCPLINT->cb->getHeroesInfo(false); //TODO: do we really need separate function for drawing heroes?
|
|
|
|
|
- for(auto & hero : heroes)
|
|
|
|
|
- {
|
|
|
|
|
- int3 position = hero->visitablePos();
|
|
|
|
|
- if(position.z == level)
|
|
|
|
|
- {
|
|
|
|
|
- const SDL_Color & color = graphics->playerColors[hero->getOwner().getNum()];
|
|
|
|
|
- blitTileWithColor(color, position, to, pos.x, pos.y);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors()
|
|
|
|
|
-{
|
|
|
|
|
- std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > ret;
|
|
|
|
|
-
|
|
|
|
|
- for(const auto & terrain : CGI->terrainTypeHandler->objects)
|
|
|
|
|
- {
|
|
|
|
|
- SDL_Color normal = CSDL_Ext::toSDL(terrain->minimapUnblocked);
|
|
|
|
|
- SDL_Color blocked = CSDL_Ext::toSDL(terrain->minimapBlocked);
|
|
|
|
|
-
|
|
|
|
|
- ret[terrain->getId()] = std::make_pair(normal, blocked);
|
|
|
|
|
- }
|
|
|
|
|
- return ret;
|
|
|
|
|
|
|
+ Canvas target(to);
|
|
|
|
|
+ target.draw(*minimap, pos.topLeft(), pos.dimensions());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
CMinimap::CMinimap(const Rect & position)
|
|
CMinimap::CMinimap(const Rect & position)
|
|
|
: CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()),
|
|
: CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()),
|
|
|
- level(0),
|
|
|
|
|
- colors(loadColors())
|
|
|
|
|
|
|
+ level(0)
|
|
|
{
|
|
{
|
|
|
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
|
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
|
|
pos.w = position.w;
|
|
pos.w = position.w;
|
|
@@ -188,21 +95,36 @@ CMinimap::CMinimap(const Rect & position)
|
|
|
aiShield->disable();
|
|
aiShield->disable();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-int3 CMinimap::translateMousePosition()
|
|
|
|
|
|
|
+int3 CMinimap::pixelToTile(const Point & cursorPos) const
|
|
|
{
|
|
{
|
|
|
// 0 = top-left corner, 1 = bottom-right corner
|
|
// 0 = top-left corner, 1 = bottom-right corner
|
|
|
- double dx = double(GH.getCursorPosition().x - pos.x) / pos.w;
|
|
|
|
|
- double dy = double(GH.getCursorPosition().y - pos.y) / pos.h;
|
|
|
|
|
|
|
+ double dx = static_cast<double>(cursorPos.x) / pos.w;
|
|
|
|
|
+ double dy = static_cast<double>(cursorPos.y) / pos.h;
|
|
|
|
|
+
|
|
|
|
|
+ int3 mapSizes = LOCPLINT->cb->getMapSize();
|
|
|
|
|
+
|
|
|
|
|
+ int tileX(std::round(mapSizes.x * dx));
|
|
|
|
|
+ int tileY(std::round(mapSizes.y * dy));
|
|
|
|
|
+
|
|
|
|
|
+ return int3(tileX, tileY, level);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
+Point CMinimap::tileToPixels(const int3 &tile) const
|
|
|
|
|
+{
|
|
|
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
|
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
|
|
|
|
|
|
|
- int3 tile ((si32)(mapSizes.x * dx), (si32)(mapSizes.y * dy), level);
|
|
|
|
|
- return tile;
|
|
|
|
|
|
|
+ double stepX = static_cast<double>(pos.w) / mapSizes.x;
|
|
|
|
|
+ double stepY = static_cast<double>(pos.h) / mapSizes.y;
|
|
|
|
|
+
|
|
|
|
|
+ int x = static_cast<int>(stepX * tile.x);
|
|
|
|
|
+ int y = static_cast<int>(stepY * tile.y);
|
|
|
|
|
+
|
|
|
|
|
+ return Point(x,y);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CMinimap::moveAdvMapSelection()
|
|
void CMinimap::moveAdvMapSelection()
|
|
|
{
|
|
{
|
|
|
- int3 newLocation = translateMousePosition();
|
|
|
|
|
|
|
+ int3 newLocation = pixelToTile(GH.getCursorPosition() - pos.topLeft());
|
|
|
adventureInt->centerOn(newLocation);
|
|
adventureInt->centerOn(newLocation);
|
|
|
|
|
|
|
|
if (!(adventureInt->active & GENERAL))
|
|
if (!(adventureInt->active & GENERAL))
|
|
@@ -219,7 +141,8 @@ void CMinimap::clickLeft(tribool down, bool previousState)
|
|
|
|
|
|
|
|
void CMinimap::clickRight(tribool down, bool previousState)
|
|
void CMinimap::clickRight(tribool down, bool previousState)
|
|
|
{
|
|
{
|
|
|
- adventureInt->handleRightClick(CGI->generaltexth->zelp[291].second, down);
|
|
|
|
|
|
|
+ if (down)
|
|
|
|
|
+ CRClickPopup::createAndPush(CGI->generaltexth->zelp[291].second);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CMinimap::hover(bool on)
|
|
void CMinimap::hover(bool on)
|
|
@@ -241,33 +164,22 @@ void CMinimap::showAll(SDL_Surface * to)
|
|
|
CIntObject::showAll(to);
|
|
CIntObject::showAll(to);
|
|
|
if(minimap)
|
|
if(minimap)
|
|
|
{
|
|
{
|
|
|
|
|
+ Canvas target(to);
|
|
|
|
|
+
|
|
|
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
|
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
|
|
int3 tileCountOnScreen = adventureInt->terrain.tileCountOnScreen();
|
|
int3 tileCountOnScreen = adventureInt->terrain.tileCountOnScreen();
|
|
|
|
|
|
|
|
//draw radar
|
|
//draw radar
|
|
|
- Rect oldClip;
|
|
|
|
|
Rect radar =
|
|
Rect radar =
|
|
|
{
|
|
{
|
|
|
- si16(adventureInt->position.x * pos.w / mapSizes.x + pos.x),
|
|
|
|
|
- si16(adventureInt->position.y * pos.h / mapSizes.y + pos.y),
|
|
|
|
|
- ui16(tileCountOnScreen.x * pos.w / mapSizes.x),
|
|
|
|
|
- ui16(tileCountOnScreen.y * pos.h / mapSizes.y)
|
|
|
|
|
|
|
+ adventureInt->position.x * pos.w / mapSizes.x,
|
|
|
|
|
+ adventureInt->position.y * pos.h / mapSizes.y,
|
|
|
|
|
+ tileCountOnScreen.x * pos.w / mapSizes.x - 1,
|
|
|
|
|
+ tileCountOnScreen.y * pos.h / mapSizes.y - 1
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
|
|
|
|
- {
|
|
|
|
|
- // adjusts radar so that it doesn't go out of map in world view mode (since there's no frame)
|
|
|
|
|
- radar.x = std::min<int>(std::max(pos.x, radar.x), pos.x + pos.w - radar.w);
|
|
|
|
|
- radar.y = std::min<int>(std::max(pos.y, radar.y), pos.y + pos.h - radar.h);
|
|
|
|
|
-
|
|
|
|
|
- if(radar.x < pos.x && radar.y < pos.y)
|
|
|
|
|
- return; // whole map is visible at once, no point in redrawing border
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- CSDL_Ext::getClipRect(to, oldClip);
|
|
|
|
|
- CSDL_Ext::setClipRect(to, pos);
|
|
|
|
|
- CSDL_Ext::drawDashedBorder(to, radar, Colors::PURPLE);
|
|
|
|
|
- CSDL_Ext::setClipRect(to, oldClip);
|
|
|
|
|
|
|
+ Canvas clippedTarget(target, pos);
|
|
|
|
|
+ clippedTarget.drawBorderDashed(radar, CSDL_Ext::fromSDL(Colors::PURPLE));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -283,6 +195,9 @@ void CMinimap::update()
|
|
|
|
|
|
|
|
void CMinimap::setLevel(int newLevel)
|
|
void CMinimap::setLevel(int newLevel)
|
|
|
{
|
|
{
|
|
|
|
|
+ if (level == newLevel)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
level = newLevel;
|
|
level = newLevel;
|
|
|
update();
|
|
update();
|
|
|
}
|
|
}
|
|
@@ -299,18 +214,13 @@ void CMinimap::setAIRadar(bool on)
|
|
|
aiShield->disable();
|
|
aiShield->disable();
|
|
|
update();
|
|
update();
|
|
|
}
|
|
}
|
|
|
- // this my happen during AI turn when this interface is inactive
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // this may happen during AI turn when this interface is inactive
|
|
|
// force redraw in order to properly update interface
|
|
// force redraw in order to properly update interface
|
|
|
GH.totalRedraw();
|
|
GH.totalRedraw();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void CMinimap::hideTile(const int3 &pos)
|
|
|
|
|
-{
|
|
|
|
|
- if(minimap)
|
|
|
|
|
- minimap->refreshTile(pos);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-void CMinimap::showTile(const int3 &pos)
|
|
|
|
|
|
|
+void CMinimap::updateTile(const int3 &pos)
|
|
|
{
|
|
{
|
|
|
if(minimap)
|
|
if(minimap)
|
|
|
minimap->refreshTile(pos);
|
|
minimap->refreshTile(pos);
|