mirror of
https://github.com/edubart/otclient.git
synced 2025-10-15 03:54:54 +02:00
Rework minimap rendering
This commit is contained in:
@@ -44,6 +44,8 @@ set(client_SOURCES ${client_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/mapio.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mapview.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mapview.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/minimap.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/minimap.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/lightview.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/lightview.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/missile.cpp
|
||||
@@ -92,6 +94,8 @@ set(client_SOURCES ${client_SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiitem.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/uimap.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uimap.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiminimap.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiminimap.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/uiprogressrect.h
|
||||
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "map.h"
|
||||
#include "shadermanager.h"
|
||||
#include "spritemanager.h"
|
||||
#include "minimap.h"
|
||||
#include <framework/core/configmanager.h>
|
||||
|
||||
Client g_client;
|
||||
@@ -38,6 +39,7 @@ void Client::init(std::vector<std::string>& args)
|
||||
registerLuaFunctions();
|
||||
|
||||
g_map.init();
|
||||
g_minimap.init();
|
||||
g_game.init();
|
||||
g_shaders.init();
|
||||
g_things.init();
|
||||
@@ -84,6 +86,7 @@ void Client::terminate()
|
||||
g_creatures.terminate();
|
||||
g_game.terminate();
|
||||
g_map.terminate();
|
||||
g_minimap.terminate();
|
||||
g_things.terminate();
|
||||
g_sprites.terminate();
|
||||
g_shaders.terminate();
|
||||
|
@@ -502,7 +502,7 @@ void Creature::updateWalkingTile()
|
||||
|
||||
// recache visible tiles in map views
|
||||
if(newWalkingTile->isEmpty())
|
||||
g_map.notificateTileUpdateToMapViews(newWalkingTile->getPosition());
|
||||
g_map.notificateTileUpdate(newWalkingTile->getPosition());
|
||||
}
|
||||
m_walkingTile = newWalkingTile;
|
||||
}
|
||||
|
@@ -92,11 +92,13 @@ typedef stdext::shared_object_ptr<ProtocolLogin> ProtocolLoginPtr;
|
||||
class UIItem;
|
||||
class UICreature;
|
||||
class UIMap;
|
||||
class UIMinimap;
|
||||
class UIProgressRect;
|
||||
|
||||
typedef stdext::shared_object_ptr<UIItem> UIItemPtr;
|
||||
typedef stdext::shared_object_ptr<UICreature> UICreaturePtr;
|
||||
typedef stdext::shared_object_ptr<UIMap> UIMapPtr;
|
||||
typedef stdext::shared_object_ptr<UIMinimap> UIMinimapPtr;
|
||||
typedef stdext::shared_object_ptr<UIProgressRect> UIProgressRectPtr;
|
||||
|
||||
#endif
|
||||
|
@@ -43,6 +43,7 @@
|
||||
#include "uiitem.h"
|
||||
#include "uicreature.h"
|
||||
#include "uimap.h"
|
||||
#include "uiminimap.h"
|
||||
#include "uiprogressrect.h"
|
||||
#include "outfit.h"
|
||||
|
||||
@@ -548,7 +549,6 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<UIMap>("setAutoViewMode", &UIMap::setAutoViewMode);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setDrawFlags", &UIMap::setDrawFlags);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setDrawTexts", &UIMap::setDrawTexts);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setDrawMinimapColors", &UIMap::setDrawMinimapColors);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setDrawLights", &UIMap::setDrawLights);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setAnimated", &UIMap::setAnimated);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setKeepAspectRatio", &UIMap::setKeepAspectRatio);
|
||||
@@ -557,7 +557,6 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<UIMap>("isMultifloor", &UIMap::isMultifloor);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isAutoViewModeEnabled", &UIMap::isAutoViewModeEnabled);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isDrawingTexts", &UIMap::isDrawingTexts);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isDrawingMinimapColors", &UIMap::isDrawingMinimapColors);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isDrawingLights", &UIMap::isDrawingLights);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isAnimating", &UIMap::isAnimating);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isKeepAspectRatioEnabled", &UIMap::isKeepAspectRatioEnabled);
|
||||
@@ -574,6 +573,25 @@ void Client::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<UIMap>("getMapShader", &UIMap::getMapShader);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getMinimumAmbientLight", &UIMap::getMinimumAmbientLight);
|
||||
|
||||
g_lua.registerClass<UIMinimap, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UIMinimap>("create", []{ return UIMinimapPtr(new UIMinimap); });
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("zoomIn", &UIMinimap::zoomIn);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("zoomOut", &UIMinimap::zoomOut);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("setZoom", &UIMinimap::setZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("setMixZoom", &UIMinimap::setMinZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("setMaxZoom", &UIMinimap::setMaxZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("setCameraPosition", &UIMinimap::setCameraPosition);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("setCross", &UIMinimap::setCross);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("followCreature", &UIMinimap::followCreature);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getPosition", &UIMinimap::getPosition);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getCameraPosition", &UIMinimap::getCameraPosition);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getFollowingCreature", &UIMinimap::getFollowingCreature);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getMinZoom", &UIMinimap::getMinZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getMaxZoom", &UIMinimap::getMaxZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getZoom", &UIMinimap::getZoom);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getCross", &UIMinimap::getCross);
|
||||
g_lua.bindClassMemberFunction<UIMinimap>("getScale", &UIMinimap::getScale);
|
||||
|
||||
g_lua.registerClass<UIProgressRect, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UIProgressRect>("create", []{ return UIProgressRectPtr(new UIProgressRect); } );
|
||||
g_lua.bindClassMemberFunction<UIProgressRect>("setPercent", &UIProgressRect::setPercent);
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "missile.h"
|
||||
#include "statictext.h"
|
||||
#include "mapview.h"
|
||||
#include "minimap.h"
|
||||
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/core/application.h>
|
||||
@@ -57,10 +58,14 @@ void Map::removeMapView(const MapViewPtr& mapView)
|
||||
m_mapViews.erase(it);
|
||||
}
|
||||
|
||||
void Map::notificateTileUpdateToMapViews(const Position& pos)
|
||||
void Map::notificateTileUpdate(const Position& pos)
|
||||
{
|
||||
if(!pos.isMapPosition())
|
||||
return;
|
||||
|
||||
for(const MapViewPtr& mapView : m_mapViews)
|
||||
mapView->onTileUpdate(pos);
|
||||
g_minimap.updateTile(pos, getTile(pos));
|
||||
}
|
||||
|
||||
void Map::clean()
|
||||
@@ -159,7 +164,7 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos)
|
||||
thing->onAppear();
|
||||
}
|
||||
|
||||
notificateTileUpdateToMapViews(pos);
|
||||
notificateTileUpdate(pos);
|
||||
}
|
||||
|
||||
ThingPtr Map::getThing(const Position& pos, int stackPos)
|
||||
@@ -174,7 +179,7 @@ bool Map::removeThing(const ThingPtr& thing)
|
||||
if(!thing)
|
||||
return false;
|
||||
|
||||
notificateTileUpdateToMapViews(thing->getPosition());
|
||||
notificateTileUpdate(thing->getPosition());
|
||||
|
||||
if(thing->isMissile()) {
|
||||
MissilePtr missile = thing->static_self_cast<Missile>();
|
||||
@@ -288,7 +293,7 @@ void Map::cleanTile(const Position& pos)
|
||||
if(tile->canErase())
|
||||
block.remove(pos);
|
||||
|
||||
notificateTileUpdateToMapViews(pos);
|
||||
notificateTileUpdate(pos);
|
||||
}
|
||||
}
|
||||
for(auto it = m_staticTexts.begin();it != m_staticTexts.end();) {
|
||||
|
@@ -139,7 +139,7 @@ public:
|
||||
|
||||
void addMapView(const MapViewPtr& mapView);
|
||||
void removeMapView(const MapViewPtr& mapView);
|
||||
void notificateTileUpdateToMapViews(const Position& pos);
|
||||
void notificateTileUpdate(const Position& pos);
|
||||
|
||||
bool loadOtcm(const std::string& fileName);
|
||||
void saveOtcm(const std::string& fileName);
|
||||
|
@@ -440,6 +440,8 @@ bool Map::loadOtcm(const std::string& fileName)
|
||||
if(item->isValid())
|
||||
tile->addThing(item, stackPos++);
|
||||
}
|
||||
|
||||
g_map.notificateTileUpdate(pos);
|
||||
}
|
||||
|
||||
fin->close();
|
||||
|
@@ -130,19 +130,10 @@ void MapView::draw(const Rect& rect)
|
||||
else
|
||||
++it;
|
||||
|
||||
if(!m_drawMinimapColors)
|
||||
tile->draw(transformPositionTo2D(tilePos, cameraPosition), scaleFactor, drawFlags, m_lightView.get());
|
||||
else {
|
||||
uint8 c = tile->getMinimapColorByte();
|
||||
if(c == 0)
|
||||
continue;
|
||||
|
||||
g_painter->setColor(Color::from8bit(c));
|
||||
g_painter->drawFilledRect(Rect(transformPositionTo2D(tilePos, cameraPosition), tileSize));
|
||||
}
|
||||
tile->draw(transformPositionTo2D(tilePos, cameraPosition), scaleFactor, drawFlags, m_lightView.get());
|
||||
}
|
||||
|
||||
if(drawFlags & Otc::DrawMissiles && !m_drawMinimapColors) {
|
||||
if(drawFlags & Otc::DrawMissiles) {
|
||||
for(const MissilePtr& missile : g_map.getFloorMissiles(z)) {
|
||||
missile->draw(transformPositionTo2D(missile->getPosition(), cameraPosition), scaleFactor, drawFlags & Otc::DrawAnimations, m_lightView.get());
|
||||
}
|
||||
@@ -283,36 +274,6 @@ void MapView::draw(const Rect& rect)
|
||||
p += rect.topLeft();
|
||||
animatedText->drawText(p, rect);
|
||||
}
|
||||
} else if(m_viewMode > NEAR_VIEW) {
|
||||
// draw a cross in the center instead of our creature
|
||||
/*
|
||||
Known Issue: Changing Z axis causes the cross to go off a little bit.
|
||||
*/
|
||||
Rect vRect(0, 0, 2, 10);
|
||||
Rect hRect(0, 0, 10, 2);
|
||||
g_painter->setColor(Color::white);
|
||||
|
||||
if(!m_follow && m_followingCreature)
|
||||
{
|
||||
Position pos = m_followingCreature->getPosition();
|
||||
Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
|
||||
p.x = p.x * horizontalStretchFactor;
|
||||
p.y = p.y * verticalStretchFactor;
|
||||
p += rect.topLeft();
|
||||
|
||||
vRect.setX(p.x); vRect.setY(p.y - 4);
|
||||
hRect.setX(p.x - 4); hRect.setY(p.y);
|
||||
|
||||
hRect.setWidth(10); hRect.setHeight(2);
|
||||
vRect.setWidth(2); vRect.setHeight(10);
|
||||
}
|
||||
else {
|
||||
vRect.moveCenter(rect.center());
|
||||
hRect.moveCenter(rect.center());
|
||||
}
|
||||
|
||||
g_painter->drawFilledRect(vRect);
|
||||
g_painter->drawFilledRect(hRect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,25 +414,20 @@ void MapView::updateGeometry(const Size& visibleDimension, const Size& optimized
|
||||
int tileSize = 0;
|
||||
Size bufferSize;
|
||||
|
||||
if(!m_drawMinimapColors) {
|
||||
int possiblesTileSizes[] = {1,2,4,8,16,32};
|
||||
for(int candidateTileSize : possiblesTileSizes) {
|
||||
bufferSize = (visibleDimension + Size(3,3)) * candidateTileSize;
|
||||
if(bufferSize.width() > g_graphics.getMaxTextureSize() || bufferSize.height() > g_graphics.getMaxTextureSize())
|
||||
break;
|
||||
int possiblesTileSizes[] = {1,2,4,8,16,32};
|
||||
for(int candidateTileSize : possiblesTileSizes) {
|
||||
bufferSize = (visibleDimension + Size(3,3)) * candidateTileSize;
|
||||
if(bufferSize.width() > g_graphics.getMaxTextureSize() || bufferSize.height() > g_graphics.getMaxTextureSize())
|
||||
break;
|
||||
|
||||
tileSize = candidateTileSize;
|
||||
if(optimizedSize.width() < bufferSize.width() - 3*candidateTileSize && optimizedSize.height() < bufferSize.height() - 3*candidateTileSize)
|
||||
break;
|
||||
}
|
||||
tileSize = candidateTileSize;
|
||||
if(optimizedSize.width() < bufferSize.width() - 3*candidateTileSize && optimizedSize.height() < bufferSize.height() - 3*candidateTileSize)
|
||||
break;
|
||||
}
|
||||
|
||||
if(tileSize == 0) {
|
||||
g_logger.traceError("reached max zoom out");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tileSize = 1;
|
||||
bufferSize = visibleDimension + Size(3,3);
|
||||
if(tileSize == 0) {
|
||||
g_logger.traceError("reached max zoom out");
|
||||
return;
|
||||
}
|
||||
|
||||
Size drawDimension = visibleDimension + Size(3,3);
|
||||
@@ -518,8 +474,7 @@ void MapView::updateGeometry(const Size& visibleDimension, const Size& optimized
|
||||
|
||||
void MapView::onTileUpdate(const Position& pos)
|
||||
{
|
||||
if(!m_drawMinimapColors)
|
||||
requestVisibleTilesCacheUpdate();
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::onMapCenterChange(const Position& pos)
|
||||
@@ -682,17 +637,6 @@ Position MapView::getCameraPosition()
|
||||
return m_customCameraPosition;
|
||||
}
|
||||
|
||||
void MapView::setDrawMinimapColors(bool enable)
|
||||
{
|
||||
if(m_drawMinimapColors == enable)
|
||||
return;
|
||||
m_drawMinimapColors = enable;
|
||||
updateGeometry(m_visibleDimension, m_optimizedSize);
|
||||
requestVisibleTilesCacheUpdate();
|
||||
m_smooth = !enable;
|
||||
m_framebuffer->setSmooth(m_smooth);
|
||||
}
|
||||
|
||||
void MapView::setShader(const PainterShaderProgramPtr& shader, float fadein, float fadeout)
|
||||
{
|
||||
if((m_shader == shader && m_shaderSwitchDone) || (m_nextShader == shader && !m_shaderSwitchDone))
|
||||
|
@@ -98,9 +98,6 @@ public:
|
||||
void setDrawTexts(bool enable) { m_drawTexts = enable; }
|
||||
bool isDrawingTexts() { return m_drawTexts; }
|
||||
|
||||
void setDrawMinimapColors(bool enable);
|
||||
bool isDrawingMinimapColors() { return m_drawMinimapColors; }
|
||||
|
||||
void setAnimated(bool animated) { m_animated = animated; requestVisibleTilesCacheUpdate(); }
|
||||
bool isAnimating() { return m_animated; }
|
||||
|
||||
@@ -139,7 +136,6 @@ private:
|
||||
stdext::boolean<true> m_autoViewMode;
|
||||
stdext::boolean<true> m_drawTexts;
|
||||
stdext::boolean<true> m_smooth;
|
||||
stdext::boolean<false> m_drawMinimapColors;
|
||||
stdext::boolean<false> m_drawLights;
|
||||
stdext::boolean<true> m_follow;
|
||||
std::vector<TilePtr> m_cachedVisibleTiles;
|
||||
|
@@ -22,4 +22,200 @@
|
||||
|
||||
|
||||
#include "minimap.h"
|
||||
#include "tile.h"
|
||||
#include <framework/graphics/image.h>
|
||||
#include <framework/graphics/texture.h>
|
||||
#include <framework/graphics/painter.h>
|
||||
#include <framework/graphics/framebuffermanager.h>
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
Minimap g_minimap;
|
||||
|
||||
void MinimapBlock::updateImage()
|
||||
{
|
||||
if(!m_image)
|
||||
m_image = ImagePtr(new Image(Size(MMBLOCK_SIZE, MMBLOCK_SIZE)));
|
||||
else
|
||||
m_image->resize(Size(MMBLOCK_SIZE, MMBLOCK_SIZE));
|
||||
|
||||
for(int x=0;x<MMBLOCK_SIZE;++x)
|
||||
for(int y=0;y<MMBLOCK_SIZE;++y)
|
||||
m_image->setPixel(x, y, Color::from8bit(getTile(x, y).color).rgba());
|
||||
}
|
||||
|
||||
void MinimapBlock::updateTexture()
|
||||
{
|
||||
if(!m_image)
|
||||
return;
|
||||
|
||||
if(!m_texture) {
|
||||
m_texture = TexturePtr(new Texture(m_image, true));
|
||||
} else {
|
||||
m_texture->uploadPixels(m_image, true);
|
||||
}
|
||||
}
|
||||
|
||||
void MinimapBlock::clean()
|
||||
{
|
||||
m_tiles.fill(MinimapTile());
|
||||
m_image.reset();
|
||||
m_texture.reset();
|
||||
m_shouldDraw = false;
|
||||
m_mustUpdate = false;
|
||||
}
|
||||
|
||||
void MinimapBlock::update()
|
||||
{
|
||||
if(!m_mustUpdate)
|
||||
return;
|
||||
|
||||
if(m_shouldDraw) {
|
||||
updateImage();
|
||||
updateTexture();
|
||||
}
|
||||
|
||||
m_mustUpdate = false;
|
||||
}
|
||||
|
||||
void MinimapBlock::updateTile(int x, int y, const MinimapTile& tile)
|
||||
{
|
||||
if(!(m_tiles[getTileIndex(x,y)] == tile)) {
|
||||
m_tiles[getTileIndex(x,y)] = tile;
|
||||
|
||||
if(tile.color != 0)
|
||||
m_shouldDraw = true;
|
||||
m_mustUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Minimap::init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Minimap::terminate()
|
||||
{
|
||||
clean();
|
||||
}
|
||||
|
||||
void Minimap::clean()
|
||||
{
|
||||
for(int i=0;i<=Otc::MAX_Z;++i)
|
||||
m_tileBlocks[i].clear();
|
||||
}
|
||||
|
||||
void Minimap::draw(const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
{
|
||||
if(screenRect.isEmpty())
|
||||
return;
|
||||
|
||||
if(MMBLOCK_SIZE*scale <= 1)
|
||||
return;
|
||||
|
||||
Size mapSize = screenRect.size() / scale;
|
||||
while(mapSize.width() > 8192 || mapSize.height() > 8192) {
|
||||
scale *= 2;
|
||||
mapSize = screenRect.size() / scale;
|
||||
}
|
||||
Rect mapRect(0, 0, mapSize);
|
||||
mapRect.moveCenter(Point(mapCenter.x, mapCenter.y));
|
||||
|
||||
g_painter->saveState();
|
||||
g_painter->setColor(Color::black);
|
||||
g_painter->drawFilledRect(screenRect);
|
||||
g_painter->resetColor();
|
||||
g_painter->setClipRect(screenRect);
|
||||
g_painter->translate(screenRect.topLeft());
|
||||
|
||||
Point p = getBlockOffset(mapRect.topLeft() - Point(1,1));
|
||||
g_painter->translate(-(mapRect.topLeft() - p)*scale);
|
||||
|
||||
if(scale > 1.0f)
|
||||
g_painter->translate(Point(1,1) * scale * 0.5f);
|
||||
|
||||
for(int y = p.y, ys = 0;y<=mapRect.bottom();y += MMBLOCK_SIZE, ys += MMBLOCK_SIZE*scale) {
|
||||
if(y < 0 || y >= 65536 - MMBLOCK_SIZE)
|
||||
continue;
|
||||
|
||||
for(int x = p.x, xs = 0;x<=mapRect.right();x += MMBLOCK_SIZE, xs += MMBLOCK_SIZE*scale) {
|
||||
if(x < 0 || x >= 65536 - MMBLOCK_SIZE)
|
||||
continue;
|
||||
|
||||
MinimapBlock& block = getBlock(Position(x, y, mapCenter.z));
|
||||
block.update();
|
||||
|
||||
if(block.shouldDraw()) {
|
||||
Rect src(0, 0, MMBLOCK_SIZE, MMBLOCK_SIZE);
|
||||
Rect dest(Point(xs,ys), src.size() * scale);
|
||||
const TexturePtr& tex = block.getTexture();
|
||||
|
||||
tex->setSmooth(scale < 1.0f);
|
||||
g_painter->drawTexturedRect(dest, tex, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_painter->restoreSavedState();
|
||||
}
|
||||
|
||||
Position Minimap::getPosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale)
|
||||
{
|
||||
if(screenRect.isEmpty())
|
||||
return Position();
|
||||
|
||||
if(MMBLOCK_SIZE*scale <= 1)
|
||||
return Position();
|
||||
|
||||
Position pos(mapCenter);
|
||||
|
||||
Size mapSize = screenRect.size() / scale;
|
||||
while(mapSize.width() > 8192 || mapSize.height() > 8192) {
|
||||
scale *= 2;
|
||||
mapSize = screenRect.size() / scale;
|
||||
}
|
||||
Rect mapRect(0, 0, mapSize);
|
||||
mapRect.moveCenter(Point(mapCenter.x, mapCenter.y));
|
||||
|
||||
Point p = (point - screenRect.topLeft() - Point(1,1) * scale * 0.5f)/scale + mapRect.topLeft();
|
||||
|
||||
pos.x = p.x;
|
||||
pos.y = p.y;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void Minimap::updateTile(const Position& pos, const TilePtr& tile)
|
||||
{
|
||||
MinimapBlock& block = getBlock(pos);
|
||||
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
|
||||
|
||||
MinimapTile minimapTile;
|
||||
if(tile) {
|
||||
minimapTile.color = tile->getMinimapColorByte();
|
||||
if(tile->isWalkable())
|
||||
minimapTile.flags |= MinimapTileWalkable;
|
||||
if(tile->isPathable())
|
||||
minimapTile.flags |= MinimapTilePathable;
|
||||
if(tile->changesFloor())
|
||||
minimapTile.flags |= MinimapTileChangesFloor;
|
||||
}
|
||||
|
||||
block.updateTile(pos.x - offsetPos.x, pos.y - offsetPos.y, minimapTile);
|
||||
}
|
||||
|
||||
bool Minimap::checkTileProperty(const Position& pos, int flags)
|
||||
{
|
||||
MinimapBlock& block = getBlock(pos);
|
||||
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
|
||||
return block.getTile(pos.x - offsetPos.x, pos.y - offsetPos.y).flags & flags;
|
||||
}
|
||||
|
||||
void Minimap::loadOtmm(const std::string& fileName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Minimap::saveOtmm(const std::string& fileName)
|
||||
{
|
||||
|
||||
}
|
||||
|
@@ -24,19 +24,51 @@
|
||||
#ifndef MINIMAP_H
|
||||
#define MINIMAP_H
|
||||
|
||||
#include "global.h"
|
||||
#include <framework/graphics/image.h>
|
||||
/*
|
||||
#include "declarations.h"
|
||||
#include <framework/graphics/declarations.h>
|
||||
|
||||
enum {
|
||||
MINIMAP_AREA_SIZE = 32
|
||||
MMBLOCK_SIZE = 64
|
||||
};
|
||||
|
||||
struct MinimapArea
|
||||
enum MinimapTileFlags {
|
||||
MinimapTilePathable = 1,
|
||||
MinimapTileWalkable = 2,
|
||||
MinimapTileChangesFloor = 4
|
||||
};
|
||||
|
||||
#pragma pack(push,1) // disable memory alignment
|
||||
struct MinimapTile
|
||||
{
|
||||
ImagePtr img;
|
||||
TexturePtr tex;
|
||||
uint8 colors[MINIMAP_AREA_SIZE][MINIMAP_AREA_SIZE];
|
||||
stdext::boolean<true> mustUpdate;
|
||||
MinimapTile() : flags(0), color(0) { }
|
||||
uint8 flags;
|
||||
uint8 color;
|
||||
|
||||
bool operator==(const MinimapTile& other) { return color == other.color && flags == other.flags; }
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
class MinimapBlock
|
||||
{
|
||||
public:
|
||||
void updateImage();
|
||||
void updateTexture();
|
||||
void clean();
|
||||
void update();
|
||||
void updateTile(int x, int y, const MinimapTile& tile);
|
||||
MinimapTile& getTile(int x, int y) { return m_tiles[getTileIndex(x,y)]; }
|
||||
void resetTile(int x, int y) { m_tiles[getTileIndex(x,y)] = MinimapTile(); }
|
||||
uint getTileIndex(int x, int y) { return ((y % MMBLOCK_SIZE) * MMBLOCK_SIZE) + (x % MMBLOCK_SIZE); }
|
||||
const TexturePtr& getTexture() { return m_texture; }
|
||||
std::array<MinimapTile, MMBLOCK_SIZE *MMBLOCK_SIZE> getTiles() { return m_tiles; }
|
||||
bool shouldDraw() { return m_shouldDraw; }
|
||||
|
||||
private:
|
||||
ImagePtr m_image;
|
||||
TexturePtr m_texture;
|
||||
stdext::boolean<false> m_shouldDraw;
|
||||
std::array<MinimapTile, MMBLOCK_SIZE *MMBLOCK_SIZE> m_tiles;
|
||||
stdext::boolean<true> m_mustUpdate;
|
||||
};
|
||||
|
||||
class Minimap
|
||||
@@ -46,21 +78,25 @@ public:
|
||||
void init();
|
||||
void terminate();
|
||||
|
||||
void loadOtmm();
|
||||
void saveOtmm();
|
||||
void clean();
|
||||
|
||||
void updateTile(const Position& pos, uint8 color);
|
||||
void draw(const Rect& screenRect, const Position& mapCenter, float scale);
|
||||
Position getPosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale);
|
||||
|
||||
void updateTile(const Position& pos, const TilePtr& tile);
|
||||
bool checkTileProperty(const Position& pos, int flags);
|
||||
|
||||
void loadOtmm(const std::string& fileName);
|
||||
void saveOtmm(const std::string& fileName);
|
||||
|
||||
private:
|
||||
|
||||
struct MinimaAreaHasher : std::unary_function<Position, std::size_t> {
|
||||
std::size_t operator()(const Position& pos) const {
|
||||
return ((pos.x/MINIMAP_AREA_SIZE) * 0x8000 + (pos.y/MINIMAP_AREA_SIZE)) * 16 + pos.z;
|
||||
}
|
||||
};
|
||||
std::unordered_map<Position, ImagePtr, MinimaAreaHasher> m_areas;
|
||||
MinimapBlock& getBlock(const Position& pos) { return m_tileBlocks[pos.z][getBlockIndex(pos)]; }
|
||||
Point getBlockOffset(const Point& pos) { return Point(pos.x - pos.x % MMBLOCK_SIZE,
|
||||
pos.y - pos.y % MMBLOCK_SIZE); }
|
||||
uint getBlockIndex(const Position& pos) { return ((pos.y / MMBLOCK_SIZE) * (65536 / MMBLOCK_SIZE)) + (pos.x / MMBLOCK_SIZE); }
|
||||
std::unordered_map<uint, MinimapBlock> m_tileBlocks[Otc::MAX_Z+1];
|
||||
};
|
||||
|
||||
extern Minimap g_minimap;
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
@@ -179,8 +179,6 @@ void UIMap::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleN
|
||||
setAutoViewMode(node->value<bool>());
|
||||
else if(node->tag() == "draw-texts")
|
||||
setDrawTexts(node->value<bool>());
|
||||
else if(node->tag() == "draw-minimap-colors")
|
||||
setDrawMinimapColors(node->value<bool>());
|
||||
else if(node->tag() == "draw-lights")
|
||||
setDrawLights(node->value<bool>());
|
||||
else if(node->tag() == "animated")
|
||||
|
@@ -51,7 +51,6 @@ public:
|
||||
void setAutoViewMode(bool enable) { m_mapView->setAutoViewMode(enable); }
|
||||
void setDrawFlags(Otc::DrawFlags drawFlags) { m_mapView->setDrawFlags(drawFlags); }
|
||||
void setDrawTexts(bool enable) { m_mapView->setDrawTexts(enable); }
|
||||
void setDrawMinimapColors(bool enable) { m_mapView->setDrawMinimapColors(enable); }
|
||||
void setDrawLights(bool enable) { m_mapView->setDrawLights(enable); }
|
||||
void setAnimated(bool enable) { m_mapView->setAnimated(enable); }
|
||||
void setKeepAspectRatio(bool enable);
|
||||
@@ -61,7 +60,6 @@ public:
|
||||
bool isMultifloor() { return m_mapView->isMultifloor(); }
|
||||
bool isAutoViewModeEnabled() { return m_mapView->isAutoViewModeEnabled(); }
|
||||
bool isDrawingTexts() { return m_mapView->isDrawingTexts(); }
|
||||
bool isDrawingMinimapColors() { return m_mapView->isDrawingMinimapColors(); }
|
||||
bool isDrawingLights() { return m_mapView->isDrawingLights(); }
|
||||
bool isAnimating() { return m_mapView->isAnimating(); }
|
||||
bool isKeepAspectRatioEnabled() { return m_aspectRatio != 0.0f; }
|
||||
|
108
src/client/uiminimap.cpp
Normal file
108
src/client/uiminimap.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uiminimap.h"
|
||||
#include "minimap.h"
|
||||
#include "game.h"
|
||||
|
||||
#include <framework/graphics/painter.h>
|
||||
|
||||
UIMinimap::UIMinimap()
|
||||
{
|
||||
m_crossEnabled = true;
|
||||
m_zoom = 0;
|
||||
m_minZoom = -5;
|
||||
m_maxZoom = 5;
|
||||
}
|
||||
|
||||
void UIMinimap::drawSelf(Fw::DrawPane drawPane)
|
||||
{
|
||||
UIWidget::drawSelf(drawPane);
|
||||
|
||||
if((drawPane & Fw::ForegroundPane) == 0)
|
||||
return;
|
||||
|
||||
g_minimap.draw(getPaddingRect(), getCameraPosition(), m_scale);
|
||||
|
||||
// draw a cross in the center
|
||||
Rect vRect(0, 0, 2, 10);
|
||||
Rect hRect(0, 0, 10, 2);
|
||||
vRect.moveCenter(m_rect.center());
|
||||
hRect.moveCenter(m_rect.center());
|
||||
g_painter->setColor(Color::white);
|
||||
g_painter->drawFilledRect(vRect);
|
||||
g_painter->drawFilledRect(hRect);
|
||||
}
|
||||
|
||||
bool UIMinimap::setZoom(int zoom)
|
||||
{
|
||||
if(zoom < m_minZoom || zoom > m_maxZoom)
|
||||
return false;
|
||||
m_zoom = zoom;
|
||||
if(m_zoom < 0)
|
||||
m_scale = 1.0f / (1 << std::abs(zoom));
|
||||
else if(m_zoom > 0)
|
||||
m_scale = 1.0f * (1 << std::abs(zoom));
|
||||
else
|
||||
m_scale = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIMinimap::followCreature(const CreaturePtr& creature)
|
||||
{
|
||||
m_followingCreature = creature;
|
||||
m_cameraPosition = Position();
|
||||
}
|
||||
|
||||
void UIMinimap::setCameraPosition(const Position& pos)
|
||||
{
|
||||
m_followingCreature = nullptr;
|
||||
m_cameraPosition = pos;
|
||||
}
|
||||
|
||||
Position UIMinimap::getPosition(const Point& mousePos)
|
||||
{
|
||||
return g_minimap.getPosition(mousePos, getPaddingRect(), getCameraPosition(), m_scale);
|
||||
}
|
||||
|
||||
Position UIMinimap::getCameraPosition()
|
||||
{
|
||||
if(m_followingCreature)
|
||||
return m_followingCreature->getPosition();
|
||||
else
|
||||
return m_cameraPosition;
|
||||
}
|
||||
|
||||
void UIMinimap::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
|
||||
{
|
||||
UIWidget::onStyleApply(styleName, styleNode);
|
||||
for(const OTMLNodePtr& node : styleNode->children()) {
|
||||
if(node->tag() == "zoom")
|
||||
setZoom(node->value<int>());
|
||||
else if(node->tag() == "max-zoom")
|
||||
setMaxZoom(node->value<int>());
|
||||
else if(node->tag() == "min-zoom")
|
||||
setMinZoom(node->value<int>());
|
||||
else if(node->tag() == "cross")
|
||||
setCross(node->value<bool>());
|
||||
}
|
||||
}
|
69
src/client/uiminimap.h
Normal file
69
src/client/uiminimap.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UIMINIMAP_H
|
||||
#define UIMINIMAP_H
|
||||
|
||||
#include "declarations.h"
|
||||
#include <framework/ui/uiwidget.h>
|
||||
|
||||
class UIMinimap : public UIWidget
|
||||
{
|
||||
public:
|
||||
UIMinimap();
|
||||
|
||||
void drawSelf(Fw::DrawPane drawPane);
|
||||
|
||||
bool zoomIn() { return setZoom(m_zoom-1); }
|
||||
bool zoomOut() { return setZoom(m_zoom+1); }
|
||||
|
||||
bool setZoom(int zoom);
|
||||
void setMinZoom(int minZoom) { m_minZoom = minZoom; }
|
||||
void setMaxZoom(int maxZoom) { m_maxZoom = maxZoom; }
|
||||
void setCameraPosition(const Position& pos);
|
||||
void setCross(bool enable) { m_crossEnabled = enable; }
|
||||
void followCreature(const CreaturePtr& creature);
|
||||
|
||||
Position getPosition(const Point& mousePos);
|
||||
Position getCameraPosition();
|
||||
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
||||
int getMinZoom() { return m_minZoom; }
|
||||
int getMaxZoom() { return m_maxZoom; }
|
||||
int getZoom() { return m_zoom; }
|
||||
bool getCross() { return m_crossEnabled; }
|
||||
float getScale() { return m_scale; }
|
||||
|
||||
protected:
|
||||
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||
|
||||
private:
|
||||
Rect m_mapArea;
|
||||
bool m_crossEnabled;
|
||||
CreaturePtr m_followingCreature;
|
||||
Position m_cameraPosition;
|
||||
float m_scale;
|
||||
int m_zoom;
|
||||
int m_minZoom;
|
||||
int m_maxZoom;
|
||||
};
|
||||
|
||||
#endif
|
@@ -37,9 +37,11 @@ public:
|
||||
void overwriteMask(const Color& maskedColor, const Color& insideColor = Color::white, const Color& outsideColor = Color::alpha);
|
||||
void blit(const Point& dest, const ImagePtr& other);
|
||||
void paste(const ImagePtr& other);
|
||||
void resize(const Size& size) { m_size = size; m_pixels.resize(size.area() * m_bpp, 0); }
|
||||
bool nextMipmap();
|
||||
|
||||
void setPixel(int x, int y, uint8 *pixel) { memcpy(&m_pixels[(y * m_size.width() + x) * m_bpp], pixel, m_bpp);}
|
||||
void setPixel(int x, int y, const Color& color) { uint32 tmp = color.rgba(); setPixel(x,y,(uint8*)&tmp); }
|
||||
|
||||
std::vector<uint8>& getPixels() { return m_pixels; }
|
||||
uint8* getPixelData() { return &m_pixels[0]; }
|
||||
|
@@ -55,6 +55,21 @@ Texture::Texture(const ImagePtr& image, bool buildMipmaps, bool compress)
|
||||
|
||||
createTexture();
|
||||
|
||||
uploadPixels(image, buildMipmaps, compress);
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(!g_app.isTerminated());
|
||||
#endif
|
||||
// free texture from gl memory
|
||||
if(g_graphics.ok() && m_id != 0)
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
|
||||
void Texture::uploadPixels(const ImagePtr& image, bool buildMipmaps, bool compress)
|
||||
{
|
||||
ImagePtr glImage = image;
|
||||
if(m_size != m_glSize) {
|
||||
glImage = ImagePtr(new Image(m_glSize, image->getBpp()));
|
||||
@@ -77,16 +92,6 @@ Texture::Texture(const ImagePtr& image, bool buildMipmaps, bool compress)
|
||||
setupFilters();
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(!g_app.isTerminated());
|
||||
#endif
|
||||
// free texture from gl memory
|
||||
if(g_graphics.ok() && m_id != 0)
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
|
||||
void Texture::bind()
|
||||
{
|
||||
// must reset painter texture state
|
||||
|
@@ -33,6 +33,7 @@ public:
|
||||
Texture(const ImagePtr& image, bool buildMipmaps = false, bool compress = false);
|
||||
virtual ~Texture();
|
||||
|
||||
void uploadPixels(const ImagePtr& image, bool buildMipmaps = false, bool compress = false);
|
||||
void bind();
|
||||
void copyFromScreen(const Rect& screenRect);
|
||||
virtual bool buildHardwareMipmaps();
|
||||
|
@@ -95,7 +95,7 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
void scale(int w, int h, Fw::AspectRatioMode mode) { scale(TSize<T>(w, h)); }
|
||||
void scale(int w, int h, Fw::AspectRatioMode mode) { scale(TSize<T>(w, h), mode); }
|
||||
|
||||
float ratio() const { return (float)wd/ht; }
|
||||
T area() const { return wd*ht; }
|
||||
|
Reference in New Issue
Block a user