mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-15 20:03:15 +02:00
Cleaned up code of Minimap
This commit is contained in:
@@ -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>
|
ColorRGBA CMinimapInstance::getTileColor(const int3 & pos) const
|
||||||
|
|
||||||
const SDL_Color & CMinimapInstance::getTileColor(const int3 & pos)
|
|
||||||
{
|
{
|
||||||
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;
|
return CSDL_Ext::fromSDL(*graphics->neutralColor);
|
||||||
else
|
|
||||||
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;
|
return tile->terType->minimapUnblocked;
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
for (int y = 0; y < mapSizes.y; ++y)
|
||||||
double stepX = double(pos.w) / mapSizes.x;
|
for (int x = 0; x < mapSizes.x; ++x)
|
||||||
double stepY = double(pos.h) / mapSizes.y;
|
minimap->drawPoint(Point(x, y), getTileColor(int3(x, y, level)));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
redrawMinimap();
|
||||||
}
|
|
||||||
|
|
||||||
CMinimapInstance::~CMinimapInstance()
|
|
||||||
{
|
|
||||||
SDL_FreeSurface(minimap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMinimapInstance::showAll(SDL_Surface * to)
|
void CMinimapInstance::showAll(SDL_Surface * to)
|
||||||
{
|
{
|
||||||
blitAtLoc(minimap, 0, 0, to);
|
Canvas target(to);
|
||||||
|
target.draw(*minimap, pos.topLeft(), pos.dimensions());
|
||||||
//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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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),
|
level(0)
|
||||||
colors(loadColors())
|
|
||||||
{
|
{
|
||||||
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 dx = static_cast<double>(cursorPos.x) / pos.w;
|
||||||
double dy = double(GH.getCursorPosition().y - pos.y) / pos.h;
|
double dy = static_cast<double>(cursorPos.y) / pos.h;
|
||||||
|
|
||||||
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
||||||
|
|
||||||
int3 tile ((si32)(mapSizes.x * dx), (si32)(mapSizes.y * dy), level);
|
int tileX(std::round(mapSizes.x * dx));
|
||||||
return tile;
|
int tileY(std::round(mapSizes.y * dy));
|
||||||
|
|
||||||
|
return int3(tileX, tileY, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point CMinimap::tileToPixels(const int3 &tile) const
|
||||||
|
{
|
||||||
|
int3 mapSizes = LOCPLINT->cb->getMapSize();
|
||||||
|
|
||||||
|
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),
|
adventureInt->position.x * pos.w / mapSizes.x,
|
||||||
si16(adventureInt->position.y * pos.h / mapSizes.y + pos.y),
|
adventureInt->position.y * pos.h / mapSizes.y,
|
||||||
ui16(tileCountOnScreen.x * pos.w / mapSizes.x),
|
tileCountOnScreen.x * pos.w / mapSizes.x - 1,
|
||||||
ui16(tileCountOnScreen.y * pos.h / mapSizes.y)
|
tileCountOnScreen.y * pos.h / mapSizes.y - 1
|
||||||
};
|
};
|
||||||
|
|
||||||
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
Canvas clippedTarget(target, pos);
|
||||||
{
|
clippedTarget.drawBorderDashed(radar, CSDL_Ext::fromSDL(Colors::PURPLE));
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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)
|
void CMinimap::updateTile(const int3 &pos)
|
||||||
{
|
|
||||||
if(minimap)
|
|
||||||
minimap->refreshTile(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMinimap::showTile(const int3 &pos)
|
|
||||||
{
|
{
|
||||||
if(minimap)
|
if(minimap)
|
||||||
minimap->refreshTile(pos);
|
minimap->refreshTile(pos);
|
||||||
|
@@ -11,67 +11,60 @@
|
|||||||
|
|
||||||
#include "../gui/CIntObject.h"
|
#include "../gui/CIntObject.h"
|
||||||
#include "../../lib/GameConstants.h"
|
#include "../../lib/GameConstants.h"
|
||||||
|
#include "../render/Canvas.h"
|
||||||
|
|
||||||
|
class ColorRGBA;
|
||||||
struct SDL_Color;
|
|
||||||
class CMinimap;
|
class CMinimap;
|
||||||
|
|
||||||
class CMinimapInstance : public CIntObject
|
class CMinimapInstance : public CIntObject
|
||||||
{
|
{
|
||||||
CMinimap * parent;
|
CMinimap * parent;
|
||||||
SDL_Surface * minimap;
|
std::unique_ptr<Canvas> minimap;
|
||||||
int level;
|
int level;
|
||||||
|
|
||||||
//get color of selected tile on minimap
|
//get color of selected tile on minimap
|
||||||
const SDL_Color & getTileColor(const int3 & pos);
|
ColorRGBA getTileColor(const int3 & pos) const;
|
||||||
|
|
||||||
void blitTileWithColor(const SDL_Color & color, const int3 & pos, SDL_Surface * to, int x, int y);
|
void redrawMinimap();
|
||||||
|
|
||||||
//draw minimap already scaled.
|
|
||||||
//result is not antialiased. Will result in "missing" pixels on huge maps (>144)
|
|
||||||
void drawScaled(int level);
|
|
||||||
public:
|
public:
|
||||||
CMinimapInstance(CMinimap * parent, int level);
|
CMinimapInstance(CMinimap * parent, int level);
|
||||||
~CMinimapInstance();
|
|
||||||
|
|
||||||
void showAll(SDL_Surface * to) override;
|
void showAll(SDL_Surface * to) override;
|
||||||
void tileToPixels (const int3 & tile, int & x, int & y, int toX = 0, int toY = 0);
|
|
||||||
void refreshTile(const int3 & pos);
|
void refreshTile(const int3 & pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Minimap which is displayed at the right upper corner of adventure map
|
/// Minimap which is displayed at the right upper corner of adventure map
|
||||||
class CMinimap : public CIntObject
|
class CMinimap : public CIntObject
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
std::shared_ptr<CPicture> aiShield; //the graphic displayed during AI turn
|
std::shared_ptr<CPicture> aiShield; //the graphic displayed during AI turn
|
||||||
std::shared_ptr<CMinimapInstance> minimap;
|
std::shared_ptr<CMinimapInstance> minimap;
|
||||||
int level;
|
int level;
|
||||||
|
|
||||||
//to initialize colors
|
|
||||||
std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > loadColors();
|
|
||||||
|
|
||||||
void clickLeft(tribool down, bool previousState) override;
|
void clickLeft(tribool down, bool previousState) override;
|
||||||
void clickRight(tribool down, bool previousState) override;
|
void clickRight(tribool down, bool previousState) override;
|
||||||
void hover (bool on) override;
|
void hover (bool on) override;
|
||||||
void mouseMoved (const Point & cursorPosition) override;
|
void mouseMoved (const Point & cursorPosition) override;
|
||||||
|
|
||||||
|
/// relocates center of adventure map screen to currently hovered tile
|
||||||
void moveAdvMapSelection();
|
void moveAdvMapSelection();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// computes coordinates of tile below cursor pos
|
||||||
|
int3 pixelToTile(const Point & cursorPos) const;
|
||||||
|
|
||||||
|
/// computes position of tile within minimap instance
|
||||||
|
Point tileToPixels(const int3 & position) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// terrainID -> (normal color, blocked color)
|
|
||||||
const std::map<TerrainId, std::pair<SDL_Color, SDL_Color> > colors;
|
|
||||||
|
|
||||||
CMinimap(const Rect & position);
|
explicit CMinimap(const Rect & position);
|
||||||
|
|
||||||
//should be called to invalidate whole map - different player or level
|
|
||||||
int3 translateMousePosition();
|
|
||||||
void update();
|
void update();
|
||||||
void setLevel(int level);
|
void setLevel(int level);
|
||||||
void setAIRadar(bool on);
|
void setAIRadar(bool on);
|
||||||
|
|
||||||
void showAll(SDL_Surface * to) override;
|
void showAll(SDL_Surface * to) override;
|
||||||
|
|
||||||
void hideTile(const int3 &pos); //puts FoW
|
void updateTile(const int3 &pos);
|
||||||
void showTile(const int3 &pos); //removes FoW
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -23,14 +23,14 @@ Canvas::Canvas(SDL_Surface * surface):
|
|||||||
surface->refcount++;
|
surface->refcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas::Canvas(Canvas & other):
|
Canvas::Canvas(const Canvas & other):
|
||||||
surface(other.surface),
|
surface(other.surface),
|
||||||
renderOffset(other.renderOffset)
|
renderOffset(other.renderOffset)
|
||||||
{
|
{
|
||||||
surface->refcount++;
|
surface->refcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas::Canvas(Canvas & other, const Rect & newClipRect):
|
Canvas::Canvas(const Canvas & other, const Rect & newClipRect):
|
||||||
Canvas(other)
|
Canvas(other)
|
||||||
{
|
{
|
||||||
clipRect.emplace();
|
clipRect.emplace();
|
||||||
@@ -43,9 +43,9 @@ Canvas::Canvas(Canvas & other, const Rect & newClipRect):
|
|||||||
}
|
}
|
||||||
|
|
||||||
Canvas::Canvas(const Point & size):
|
Canvas::Canvas(const Point & size):
|
||||||
renderOffset(0,0)
|
renderOffset(0,0),
|
||||||
|
surface(CSDL_Ext::newSurface(size.x, size.y))
|
||||||
{
|
{
|
||||||
surface = CSDL_Ext::newSurface(size.x, size.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas::~Canvas()
|
Canvas::~Canvas()
|
||||||
@@ -75,9 +75,35 @@ void Canvas::draw(Canvas & image, const Point & pos)
|
|||||||
CSDL_Ext::blitAt(image.surface, renderOffset.x + pos.x, renderOffset.y + pos.y, surface);
|
CSDL_Ext::blitAt(image.surface, renderOffset.x + pos.x, renderOffset.y + pos.y, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Canvas::draw(Canvas & image, const Point & pos, const Point & targetSize)
|
||||||
|
{
|
||||||
|
SDL_Rect targetRect = CSDL_Ext::toSDL(Rect(pos, targetSize));
|
||||||
|
SDL_BlitScaled(image.surface, nullptr, surface, &targetRect );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::drawPoint(const Point & dest, const ColorRGBA & color)
|
||||||
|
{
|
||||||
|
CSDL_Ext::putPixelWithoutRefreshIfInSurf(surface, dest.x, dest.y, color.r, color.g, color.b, color.a);
|
||||||
|
}
|
||||||
|
|
||||||
void Canvas::drawLine(const Point & from, const Point & dest, const ColorRGBA & colorFrom, const ColorRGBA & colorDest)
|
void Canvas::drawLine(const Point & from, const Point & dest, const ColorRGBA & colorFrom, const ColorRGBA & colorDest)
|
||||||
{
|
{
|
||||||
CSDL_Ext::drawLine(surface, renderOffset.x + from.x, renderOffset.y + from.y, renderOffset.x + dest.x, renderOffset.y + dest.y, CSDL_Ext::toSDL(colorFrom), CSDL_Ext::toSDL(colorDest));
|
CSDL_Ext::drawLine(surface, renderOffset + from, renderOffset + dest, CSDL_Ext::toSDL(colorFrom), CSDL_Ext::toSDL(colorDest));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::drawLineDashed(const Point & from, const Point & dest, const ColorRGBA & color)
|
||||||
|
{
|
||||||
|
CSDL_Ext::drawLineDashed(surface, renderOffset + from, renderOffset + dest, CSDL_Ext::toSDL(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::drawBorderDashed(const Rect & target, const ColorRGBA & color)
|
||||||
|
{
|
||||||
|
Rect realTarget = target + renderOffset;
|
||||||
|
|
||||||
|
CSDL_Ext::drawLineDashed(surface, realTarget.topLeft(), realTarget.topRight(), CSDL_Ext::toSDL(color));
|
||||||
|
CSDL_Ext::drawLineDashed(surface, realTarget.bottomLeft(), realTarget.bottomRight(), CSDL_Ext::toSDL(color));
|
||||||
|
CSDL_Ext::drawLineDashed(surface, realTarget.topLeft(), realTarget.bottomLeft(), CSDL_Ext::toSDL(color));
|
||||||
|
CSDL_Ext::drawLineDashed(surface, realTarget.topRight(), realTarget.bottomRight(), CSDL_Ext::toSDL(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::drawText(const Point & position, const EFonts & font, const SDL_Color & colorDest, ETextAlignment alignment, const std::string & text )
|
void Canvas::drawText(const Point & position, const EFonts & font, const SDL_Color & colorDest, ETextAlignment alignment, const std::string & text )
|
||||||
|
@@ -34,16 +34,16 @@ class Canvas
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/// constructs canvas using existing surface. Caller maintains ownership on the surface
|
/// constructs canvas using existing surface. Caller maintains ownership on the surface
|
||||||
Canvas(SDL_Surface * surface);
|
explicit Canvas(SDL_Surface * surface);
|
||||||
|
|
||||||
/// copy contructor
|
/// copy contructor
|
||||||
Canvas(Canvas & other);
|
Canvas(const Canvas & other);
|
||||||
|
|
||||||
/// creates canvas that only covers specified subsection of a surface
|
/// creates canvas that only covers specified subsection of a surface
|
||||||
Canvas(Canvas & other, const Rect & clipRect);
|
Canvas(const Canvas & other, const Rect & clipRect);
|
||||||
|
|
||||||
/// constructs canvas of specified size
|
/// constructs canvas of specified size
|
||||||
Canvas(const Point & size);
|
explicit Canvas(const Point & size);
|
||||||
|
|
||||||
~Canvas();
|
~Canvas();
|
||||||
|
|
||||||
@@ -56,9 +56,21 @@ public:
|
|||||||
/// renders another canvas onto this canvas
|
/// renders another canvas onto this canvas
|
||||||
void draw(Canvas & image, const Point & pos);
|
void draw(Canvas & image, const Point & pos);
|
||||||
|
|
||||||
|
/// renders another canvas onto this canvas with scaling
|
||||||
|
void draw(Canvas & image, const Point & pos, const Point & targetSize);
|
||||||
|
|
||||||
|
/// renders single pixels with specified color
|
||||||
|
void drawPoint(const Point & dest, const ColorRGBA & color);
|
||||||
|
|
||||||
/// renders continuous, 1-pixel wide line with color gradient
|
/// renders continuous, 1-pixel wide line with color gradient
|
||||||
void drawLine(const Point & from, const Point & dest, const ColorRGBA & colorFrom, const ColorRGBA & colorDest);
|
void drawLine(const Point & from, const Point & dest, const ColorRGBA & colorFrom, const ColorRGBA & colorDest);
|
||||||
|
|
||||||
|
/// renders dashed, 1-pixel wide line with specified color
|
||||||
|
void drawLineDashed(const Point & from, const Point & dest, const ColorRGBA & color);
|
||||||
|
|
||||||
|
/// renders rectangular, dashed border in specified location
|
||||||
|
void drawBorderDashed(const Rect & target, const ColorRGBA & color);
|
||||||
|
|
||||||
/// renders single line of text with specified parameters
|
/// renders single line of text with specified parameters
|
||||||
void drawText(const Point & position, const EFonts & font, const SDL_Color & colorDest, ETextAlignment alignment, const std::string & text );
|
void drawText(const Point & position, const EFonts & font, const SDL_Color & colorDest, ETextAlignment alignment, const std::string & text );
|
||||||
|
|
||||||
|
@@ -364,11 +364,40 @@ uint32_t CSDL_Ext::colorTouint32_t(const SDL_Color * color)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawLineX(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2)
|
static void drawLineXDashed(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color)
|
||||||
{
|
{
|
||||||
|
double length(x2 - x1);
|
||||||
|
|
||||||
for(int x = x1; x <= x2; x++)
|
for(int x = x1; x <= x2; x++)
|
||||||
{
|
{
|
||||||
float f = float(x - x1) / float(x2 - x1);
|
double f = (x - x1) / length;
|
||||||
|
int y = vstd::lerp(y1, y2, f);
|
||||||
|
|
||||||
|
if (std::abs(x - x1) % 5 != 4)
|
||||||
|
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x, y, color.r, color.g, color.b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawLineYDashed(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color)
|
||||||
|
{
|
||||||
|
double length(y2 - y1);
|
||||||
|
|
||||||
|
for(int y = y1; y <= y2; y++)
|
||||||
|
{
|
||||||
|
double f = (y - y1) / length;
|
||||||
|
int x = vstd::lerp(x1, x2, f);
|
||||||
|
|
||||||
|
if (std::abs(y - y1) % 5 != 4)
|
||||||
|
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x, y, color.r, color.g, color.b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawLineX(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2)
|
||||||
|
{
|
||||||
|
double length(x2 - x1);
|
||||||
|
for(int x = x1; x <= x2; x++)
|
||||||
|
{
|
||||||
|
double f = (x - x1) / length;
|
||||||
int y = vstd::lerp(y1, y2, f);
|
int y = vstd::lerp(y1, y2, f);
|
||||||
|
|
||||||
uint8_t r = vstd::lerp(color1.r, color2.r, f);
|
uint8_t r = vstd::lerp(color1.r, color2.r, f);
|
||||||
@@ -383,9 +412,10 @@ static void drawLineX(SDL_Surface * sur, int x1, int y1, int x2, int y2, const S
|
|||||||
|
|
||||||
static void drawLineY(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2)
|
static void drawLineY(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2)
|
||||||
{
|
{
|
||||||
|
double length(y2 - y1);
|
||||||
for(int y = y1; y <= y2; y++)
|
for(int y = y1; y <= y2; y++)
|
||||||
{
|
{
|
||||||
float f = float(y - y1) / float(y2 - y1);
|
double f = (y - y1) / length;
|
||||||
int x = vstd::lerp(x1, x2, f);
|
int x = vstd::lerp(x1, x2, f);
|
||||||
|
|
||||||
uint8_t r = vstd::lerp(color1.r, color2.r, f);
|
uint8_t r = vstd::lerp(color1.r, color2.r, f);
|
||||||
@@ -398,31 +428,60 @@ static void drawLineY(SDL_Surface * sur, int x1, int y1, int x2, int y2, const S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSDL_Ext::drawLine(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2)
|
void CSDL_Ext::drawLine(SDL_Surface * sur, const Point & from, const Point & dest, const SDL_Color & color1, const SDL_Color & color2)
|
||||||
{
|
{
|
||||||
int width = std::abs(x1-x2);
|
//FIXME: duplicated code with drawLineDashed
|
||||||
int height = std::abs(y1-y2);
|
int width = std::abs(from.x - dest.x);
|
||||||
|
int height = std::abs(from.y - dest.y);
|
||||||
|
|
||||||
if ( width == 0 && height == 0)
|
if ( width == 0 && height == 0)
|
||||||
{
|
{
|
||||||
uint8_t *p = CSDL_Ext::getPxPtr(sur, x1, y1);
|
uint8_t *p = CSDL_Ext::getPxPtr(sur, from.x, from.y);
|
||||||
ColorPutter<4, 0>::PutColorAlpha(p, color1);
|
ColorPutter<4, 0>::PutColorAlpha(p, color1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width > height)
|
if (width > height)
|
||||||
{
|
{
|
||||||
if ( x1 < x2)
|
if ( from.x < dest.x)
|
||||||
drawLineX(sur, x1,y1,x2,y2, color1, color2);
|
drawLineX(sur, from.x, from.y, dest.x, dest.y, color1, color2);
|
||||||
else
|
else
|
||||||
drawLineX(sur, x2,y2,x1,y1, color2, color1);
|
drawLineX(sur, dest.x, dest.y, from.x, from.y, color2, color1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( y1 < y2)
|
if ( from.y < dest.y)
|
||||||
drawLineY(sur, x1,y1,x2,y2, color1, color2);
|
drawLineY(sur, from.x, from.y, dest.x, dest.y, color1, color2);
|
||||||
else
|
else
|
||||||
drawLineY(sur, x2,y2,x1,y1, color2, color1);
|
drawLineY(sur, dest.x, dest.y, from.x, from.y, color2, color1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSDL_Ext::drawLineDashed(SDL_Surface * sur, const Point & from, const Point & dest, const SDL_Color & color)
|
||||||
|
{
|
||||||
|
//FIXME: duplicated code with drawLine
|
||||||
|
int width = std::abs(from.x - dest.x);
|
||||||
|
int height = std::abs(from.y - dest.y);
|
||||||
|
|
||||||
|
if ( width == 0 && height == 0)
|
||||||
|
{
|
||||||
|
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, from.x, from.y, color.r, color.g, color.b);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width > height)
|
||||||
|
{
|
||||||
|
if ( from.x < dest.x)
|
||||||
|
drawLineXDashed(sur, from.x, from.y, dest.x, dest.y, color);
|
||||||
|
else
|
||||||
|
drawLineXDashed(sur, dest.x, dest.y, from.x, from.y, color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( from.y < dest.y)
|
||||||
|
drawLineYDashed(sur, from.x, from.y, dest.x, dest.y, color);
|
||||||
|
else
|
||||||
|
drawLineYDashed(sur, dest.x, dest.y, from.x, from.y, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,31 +508,6 @@ void CSDL_Ext::drawBorder( SDL_Surface * sur, const Rect &r, const SDL_Color &co
|
|||||||
drawBorder(sur, r.x, r.y, r.w, r.h, color, depth);
|
drawBorder(sur, r.x, r.y, r.w, r.h, color, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSDL_Ext::drawDashedBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color)
|
|
||||||
{
|
|
||||||
const int y1 = r.y, y2 = r.y + r.h-1;
|
|
||||||
for (int i=0; i<r.w; i++)
|
|
||||||
{
|
|
||||||
const int x = r.x + i;
|
|
||||||
if (i%4 || (i==0))
|
|
||||||
{
|
|
||||||
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x, y1, color.r, color.g, color.b);
|
|
||||||
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x, y2, color.r, color.g, color.b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const int x1 = r.x, x2 = r.x + r.w-1;
|
|
||||||
for (int i=0; i<r.h; i++)
|
|
||||||
{
|
|
||||||
const int y = r.y + i;
|
|
||||||
if ((i%4) || (i==0))
|
|
||||||
{
|
|
||||||
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x1, y, color.r, color.g, color.b);
|
|
||||||
CSDL_Ext::putPixelWithoutRefreshIfInSurf(sur, x2, y, color.r, color.g, color.b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSDL_Ext::setPlayerColor(SDL_Surface * sur, PlayerColor player)
|
void CSDL_Ext::setPlayerColor(SDL_Surface * sur, PlayerColor player)
|
||||||
{
|
{
|
||||||
if(player==PlayerColor::UNFLAGGABLE)
|
if(player==PlayerColor::UNFLAGGABLE)
|
||||||
|
@@ -81,10 +81,11 @@ typedef void (*TColorPutterAlpha)(uint8_t *&ptr, const uint8_t & R, const uint8_
|
|||||||
uint32_t colorTouint32_t(const SDL_Color * color); //little endian only
|
uint32_t colorTouint32_t(const SDL_Color * color); //little endian only
|
||||||
SDL_Color makeColor(ui8 r, ui8 g, ui8 b, ui8 a);
|
SDL_Color makeColor(ui8 r, ui8 g, ui8 b, ui8 a);
|
||||||
|
|
||||||
void drawLine(SDL_Surface * sur, int x1, int y1, int x2, int y2, const SDL_Color & color1, const SDL_Color & color2);
|
void drawLine(SDL_Surface * sur, const Point & from, const Point & dest, const SDL_Color & color1, const SDL_Color & color2);
|
||||||
|
void drawLineDashed(SDL_Surface * sur, const Point & from, const Point & dest, const SDL_Color & color);
|
||||||
|
|
||||||
void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const SDL_Color &color, int depth = 1);
|
void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const SDL_Color &color, int depth = 1);
|
||||||
void drawBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color, int depth = 1);
|
void drawBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color, int depth = 1);
|
||||||
void drawDashedBorder(SDL_Surface * sur, const Rect &r, const SDL_Color &color);
|
|
||||||
void setPlayerColor(SDL_Surface * sur, PlayerColor player); //sets correct color of flags; -1 for neutral
|
void setPlayerColor(SDL_Surface * sur, PlayerColor player); //sets correct color of flags; -1 for neutral
|
||||||
|
|
||||||
SDL_Surface * newSurface(int w, int h, SDL_Surface * mod); //creates new surface, with flags/format same as in surface given
|
SDL_Surface * newSurface(int w, int h, SDL_Surface * mod); //creates new surface, with flags/format same as in surface given
|
||||||
|
@@ -82,13 +82,11 @@ void CQuestMinimap::addQuestMarks (const QuestInfo * q)
|
|||||||
else
|
else
|
||||||
tile = q->tile;
|
tile = q->tile;
|
||||||
|
|
||||||
int x,y;
|
Point offset = tileToPixels(tile);
|
||||||
minimap->tileToPixels (tile, x, y);
|
|
||||||
|
|
||||||
if (level != tile.z)
|
setLevel(tile.z);
|
||||||
setLevel(tile.z);
|
|
||||||
|
|
||||||
auto pic = std::make_shared<CQuestIcon>("VwSymbol.def", 3, x, y);
|
auto pic = std::make_shared<CQuestIcon>("VwSymbol.def", 3, offset.x, offset.y);
|
||||||
|
|
||||||
pic->moveBy (Point ( -pic->pos.w/2, -pic->pos.h/2));
|
pic->moveBy (Point ( -pic->pos.w/2, -pic->pos.h/2));
|
||||||
pic->callback = std::bind (&CQuestMinimap::iconClicked, this);
|
pic->callback = std::bind (&CQuestMinimap::iconClicked, this);
|
||||||
|
Reference in New Issue
Block a user