mirror of
https://github.com/edubart/otclient.git
synced 2025-11-03 12:16:23 +01:00
Minimap, hotkeys and lot of other changes
* Begin working on a new layout system for UIMinimap and later UIMap, this new layout system allows to add widgets to the minimap * Add option to disable motd * Rework hotkey binding * Lots of fixes in hotkeys manager * Add fullmap view using Ctrl+Shift+M * Prevent some crashs in ThingType draw * Add function to load minimap from PNG files * Fixes in minimap saving * Fixes in Tile::isClickable * Add UIMapAnchorLayout, new layout for maps * Fix freezes in win32 when pressing alt key
This commit is contained in:
@@ -23,13 +23,14 @@
|
||||
|
||||
#include "minimap.h"
|
||||
#include "tile.h"
|
||||
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/texture.h>
|
||||
#include <framework/graphics/painter.h>
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/filestream.h>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <zlib.h>
|
||||
|
||||
Minimap g_minimap;
|
||||
@@ -51,10 +52,14 @@ void MinimapBlock::update()
|
||||
bool shouldDraw = false;
|
||||
for(int x=0;x<MMBLOCK_SIZE;++x) {
|
||||
for(int y=0;y<MMBLOCK_SIZE;++y) {
|
||||
uint32 col = Color::from8bit(getTile(x, y).color).rgba();
|
||||
image->setPixel(x, y, col);
|
||||
if(col != 0)
|
||||
uint8 c = getTile(x, y).color;
|
||||
uint32 col;
|
||||
if(c != 255) {
|
||||
col = Color::from8bit(c).rgba();
|
||||
shouldDraw = true;
|
||||
} else
|
||||
col = Color::alpha.rgba();
|
||||
image->setPixel(x, y, col);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,14 +98,14 @@ void Minimap::clean()
|
||||
m_tileBlocks[i].clear();
|
||||
}
|
||||
|
||||
void Minimap::draw(const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
void Minimap::draw(const Rect& screenRect, const Position& mapCenter, float scale, const Color& color)
|
||||
{
|
||||
if(screenRect.isEmpty())
|
||||
return;
|
||||
|
||||
Rect mapRect = calcMapRect(screenRect, mapCenter, scale);
|
||||
g_painter->saveState();
|
||||
g_painter->setColor(Color::black);
|
||||
g_painter->setColor(color);
|
||||
g_painter->drawFilledRect(screenRect);
|
||||
g_painter->resetColor();
|
||||
g_painter->setClipRect(screenRect);
|
||||
@@ -137,15 +142,16 @@ void Minimap::draw(const Rect& screenRect, const Position& mapCenter, float scal
|
||||
tex->setSmooth(scale < 1.0f);
|
||||
g_painter->drawTexturedRect(dest, tex, src);
|
||||
}
|
||||
//g_painter->drawBoundingRect(Rect(xs,ys, MMBLOCK_SIZE * scale, MMBLOCK_SIZE * scale));
|
||||
}
|
||||
}
|
||||
|
||||
g_painter->restoreSavedState();
|
||||
}
|
||||
|
||||
Point Minimap::getPoint(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
Point Minimap::getTilePoint(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
{
|
||||
if(screenRect.isEmpty() || MMBLOCK_SIZE*scale <= 1 || !mapCenter.isMapPosition())
|
||||
if(screenRect.isEmpty() || pos.z != mapCenter.z)
|
||||
return Point(-1,-1);
|
||||
|
||||
Rect mapRect = calcMapRect(screenRect, mapCenter, scale);
|
||||
@@ -154,9 +160,9 @@ Point Minimap::getPoint(const Position& pos, const Rect& screenRect, const Posit
|
||||
return posoff + screenRect.topLeft() - off + (Point(1,1)*scale)/2;
|
||||
}
|
||||
|
||||
Position Minimap::getPosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
Position Minimap::getTilePosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
{
|
||||
if(screenRect.isEmpty() || MMBLOCK_SIZE*scale <= 1 || !mapCenter.isMapPosition())
|
||||
if(screenRect.isEmpty())
|
||||
return Position();
|
||||
|
||||
Rect mapRect = calcMapRect(screenRect, mapCenter, scale);
|
||||
@@ -165,24 +171,25 @@ Position Minimap::getPosition(const Point& point, const Rect& screenRect, const
|
||||
return Position(pos2d.x, pos2d.y, mapCenter.z);
|
||||
}
|
||||
|
||||
Rect Minimap::getTileRect(const Position& pos, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
{
|
||||
if(screenRect.isEmpty() || pos.z != mapCenter.z)
|
||||
return Rect();
|
||||
|
||||
int tileSize = 32 * scale;
|
||||
Rect tileRect(0,0,tileSize, tileSize);
|
||||
tileRect.moveCenter(getTilePoint(pos, screenRect, mapCenter, scale));
|
||||
return tileRect;
|
||||
}
|
||||
|
||||
Rect Minimap::calcMapRect(const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
{
|
||||
int w, h;
|
||||
do {
|
||||
w = std::ceil(screenRect.width() / scale);
|
||||
h = std::ceil(screenRect.height() / scale);
|
||||
if(w % 2 == 0)
|
||||
w++;
|
||||
if(h % 2 == 0)
|
||||
h++;
|
||||
scale *= 2;
|
||||
} while(w > 8192 || h > 8192);
|
||||
int w = screenRect.width() / scale, h = std::ceil(screenRect.height() / scale);
|
||||
Rect mapRect(0,0,w,h);
|
||||
mapRect.moveCenter(Point(mapCenter.x, mapCenter.y));
|
||||
return mapRect;
|
||||
}
|
||||
|
||||
|
||||
void Minimap::updateTile(const Position& pos, const TilePtr& tile)
|
||||
{
|
||||
MinimapTile minimapTile;
|
||||
@@ -200,6 +207,7 @@ void Minimap::updateTile(const Position& pos, const TilePtr& tile)
|
||||
MinimapBlock& block = getBlock(pos);
|
||||
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
|
||||
block.updateTile(pos.x - offsetPos.x, pos.y - offsetPos.y, minimapTile);
|
||||
block.justSaw();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +222,87 @@ const MinimapTile& Minimap::getTile(const Position& pos)
|
||||
return nulltile;
|
||||
}
|
||||
|
||||
bool Minimap::loadImage(const std::string& fileName, const Position& topLeft, float colorFactor)
|
||||
{
|
||||
if(colorFactor <= 0.01f)
|
||||
colorFactor = 1.0f;
|
||||
|
||||
try {
|
||||
ImagePtr image = Image::load(fileName);
|
||||
|
||||
uint8 waterc = Color::to8bit(std::string("#3300cc"));
|
||||
|
||||
// non pathable colors
|
||||
Color nonPathableColors[] = {
|
||||
std::string("#ffff00"), // yellow
|
||||
};
|
||||
|
||||
// non walkable colors
|
||||
Color nonWalkableColors[] = {
|
||||
std::string("#000000"), // oil, black
|
||||
std::string("#006600"), // trees, dark green
|
||||
std::string("#ff3300"), // walls, red
|
||||
std::string("#666666"), // mountain, grey
|
||||
std::string("#ff6600"), // lava, orange
|
||||
std::string("#00ff00"), // positon
|
||||
std::string("#ccffff"), // ice, very light blue
|
||||
};
|
||||
|
||||
for(int y=0;y<image->getHeight();++y) {
|
||||
for(int x=0;x<image->getWidth();++x) {
|
||||
Color color = *(uint32*)image->getPixel(x,y);
|
||||
uint8 c = Color::to8bit(color * colorFactor);
|
||||
int flags = 0;
|
||||
|
||||
if(c == waterc || color.a() == 0) {
|
||||
flags |= MinimapTileNotWalkable;
|
||||
c = 255; // alpha
|
||||
}
|
||||
|
||||
if(flags != 0) {
|
||||
for(Color &col : nonWalkableColors) {
|
||||
if(col == color) {
|
||||
flags |= MinimapTileNotWalkable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(flags != 0) {
|
||||
for(Color &col : nonPathableColors) {
|
||||
if(col == color) {
|
||||
flags |= MinimapTileNotPathable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(c == 255)
|
||||
continue;
|
||||
|
||||
Position pos(topLeft.x + x, topLeft.y + y, topLeft.z);
|
||||
MinimapBlock& block = getBlock(pos);
|
||||
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
|
||||
MinimapTile& tile = block.getTile(pos.x - offsetPos.x, pos.y - offsetPos.y);
|
||||
if(!(tile.flags & MinimapTileWasSeen)) {
|
||||
tile.color = c;
|
||||
tile.flags = flags;
|
||||
block.mustUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("failed to load OTMM minimap: %s", e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Minimap::saveImage(const std::string& fileName, const Rect& mapRect)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
bool Minimap::loadOtmm(const std::string& fileName)
|
||||
{
|
||||
try {
|
||||
@@ -263,6 +352,7 @@ bool Minimap::loadOtmm(const std::string& fileName)
|
||||
assert(ret == Z_OK);
|
||||
assert(destLen == blockSize);
|
||||
block.mustUpdate();
|
||||
block.justSaw();
|
||||
}
|
||||
|
||||
fin->close();
|
||||
@@ -307,6 +397,9 @@ void Minimap::saveOtmm(const std::string& fileName)
|
||||
for(auto& it : m_tileBlocks[z]) {
|
||||
int index = it.first;
|
||||
MinimapBlock& block = it.second;
|
||||
if(!block.wasSeen())
|
||||
continue;
|
||||
|
||||
Position pos = getIndexPosition(index, z);
|
||||
fin->addU16(pos.x);
|
||||
fin->addU16(pos.y);
|
||||
@@ -319,7 +412,7 @@ void Minimap::saveOtmm(const std::string& fileName)
|
||||
fin->write(compressBuffer.data(), len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// end of file
|
||||
Position invalidPos;
|
||||
fin->addU16(invalidPos.x);
|
||||
|
||||
Reference in New Issue
Block a user