experimental minimap
* a lot of rework in MapView * new APIs for UIMap
This commit is contained in:
parent
fba5f188d7
commit
2835a66bab
|
@ -20,6 +20,7 @@ Module
|
|||
- game_containers
|
||||
- game_viplist
|
||||
- game_battle
|
||||
- game_minimap
|
||||
- game_hotkeys
|
||||
|
||||
@onLoad: |
|
||||
|
|
|
@ -2,6 +2,8 @@ UIGameMap = extends(UIMap)
|
|||
|
||||
function UIGameMap.create()
|
||||
local gameMap = UIGameMap.internalCreate()
|
||||
gameMap:setKeepAspectRatio(true)
|
||||
gameMap:setVisibleDimension({width = 15, height = 11})
|
||||
return gameMap
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
Minimap = {}
|
||||
|
||||
-- private variables
|
||||
local minimapWidget
|
||||
local minimapButton
|
||||
|
||||
-- private functions
|
||||
function onMinimapMouseRelease(self, mousePosition, mouseButton)
|
||||
local tile = self:getTile(mousePosition)
|
||||
if tile and mouseButton == MouseLeftButton and self:isPressed() then
|
||||
local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), tile:getPosition(), 255)
|
||||
if #dirs == 0 then
|
||||
TextMessage.displayStatus('There is no way.')
|
||||
return true
|
||||
end
|
||||
g_game.autoWalk(dirs)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function onMinimapMouseWheel(self, mousePos, direction)
|
||||
if direction == MouseWheelUp then
|
||||
self:zoomIn()
|
||||
else
|
||||
self:zoomOut()
|
||||
end
|
||||
end
|
||||
|
||||
-- public functions
|
||||
function Minimap.init()
|
||||
connect(g_game, { onLogin = Minimap.reset })
|
||||
Keyboard.bindKeyDown('Ctrl+M', Minimap.toggle)
|
||||
|
||||
minimapButton = TopMenu.addGameToggleButton('minimapButton', 'Minimap (Ctrl+M)', 'minimap.png', Minimap.toggle)
|
||||
minimapButton:setOn(true)
|
||||
|
||||
minimapWidget = loadUI('minimap.otui', GameInterface.getMapPanel())
|
||||
minimapWidget.onMouseRelease = onMinimapMouseRelease
|
||||
minimapWidget.onMouseWheel = onMinimapMouseWheel
|
||||
end
|
||||
|
||||
function Minimap.terminate()
|
||||
Keyboard.unbindKeyDown('Ctrl+M')
|
||||
disconnect(g_game, { onLogin = Minimap.reset })
|
||||
|
||||
minimapWidget:destroy()
|
||||
minimapWidget = nil
|
||||
minimapButton:destroy()
|
||||
minimapButton = nil
|
||||
end
|
||||
|
||||
function Minimap.toggle()
|
||||
local visible = not minimapWidget:isExplicitlyVisible()
|
||||
minimapWidget:setVisible(visible)
|
||||
minimapButton:setOn(visible)
|
||||
end
|
||||
|
||||
function Minimap.reset()
|
||||
minimapWidget:followCreature(g_game.getLocalPlayer())
|
||||
for i=1,10 do minimapWidget:zoomOut() end
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
Module
|
||||
name: game_minimap
|
||||
description: Manage minimap
|
||||
author: OTClient team
|
||||
website: https://github.com/edubart/otclient
|
||||
|
||||
dependecies:
|
||||
- game
|
||||
|
||||
@onLoad: |
|
||||
dofile 'minimap'
|
||||
Minimap.init()
|
||||
|
||||
@onUnload:
|
||||
Minimap.terminate()
|
|
@ -0,0 +1,21 @@
|
|||
UIMap
|
||||
id: minimap
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
size: 256 192
|
||||
margin-top: 2
|
||||
margin-right: 2
|
||||
border-width: 1
|
||||
border-color: #888888
|
||||
padding: 1
|
||||
//draw-minimap-colors: true
|
||||
multifloor: false
|
||||
draw-texts: false
|
||||
|
||||
CheckBox
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
margin-top: 2
|
||||
margin-right: 2
|
||||
size: 16 16
|
||||
@onCheckChange: self:getParent():setDrawMinimapColors(self:isChecked())
|
Binary file not shown.
After Width: | Height: | Size: 910 B |
|
@ -3,8 +3,84 @@ uniform vec4 color; // painter color
|
|||
uniform float time; // time in seconds since shader linkage
|
||||
uniform sampler2D texture; // map texture
|
||||
varying vec2 textureCoords; // map texture coords
|
||||
//uniform vec4 awareArea;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(texture, textureCoords);
|
||||
}
|
||||
|
||||
/*
|
||||
vec4 grayScale(vec4 color, float factor)
|
||||
{
|
||||
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
|
||||
return vec4(gray*factor + (1-factor)*color.r,
|
||||
gray*factor + (1-factor)*color.g,
|
||||
gray*factor + (1-factor)*color.b, 1);
|
||||
}
|
||||
|
||||
// grayscale fog
|
||||
void main()
|
||||
{
|
||||
vec4 color = texture2D(texture, textureCoords);
|
||||
float dist = 0;
|
||||
// left
|
||||
if(textureCoords.x < awareArea.x && textureCoords.y < awareArea.y)
|
||||
dist = distance(textureCoords, awareArea.xy);
|
||||
else if(textureCoords.x < awareArea.x && textureCoords.y < awareArea.w)
|
||||
dist = distance(textureCoords, vec2(awareArea.x, textureCoords.y));
|
||||
else if(textureCoords.x < awareArea.x)
|
||||
dist = distance(textureCoords, awareArea.xw);
|
||||
// right
|
||||
else if(textureCoords.x > awareArea.z && textureCoords.y < awareArea.y)
|
||||
dist = distance(textureCoords, awareArea.zy);
|
||||
else if(textureCoords.x > awareArea.z && textureCoords.y < awareArea.w)
|
||||
dist = distance(textureCoords, vec2(awareArea.z, textureCoords.y));
|
||||
else if(textureCoords.x > awareArea.z)
|
||||
dist = distance(textureCoords, awareArea.zw);
|
||||
// top
|
||||
else if(textureCoords.y < awareArea.y)
|
||||
dist = distance(textureCoords, vec2(textureCoords.x, awareArea.y));
|
||||
// bottom
|
||||
else if(textureCoords.y > awareArea.w)
|
||||
dist = distance(textureCoords, vec2(textureCoords.x, awareArea.w));
|
||||
if(dist > 0) {
|
||||
float range = 0.01;
|
||||
float factor = min(dist/range, 1.0);
|
||||
color = grayScale(color, factor);
|
||||
//color.rgb *= 1 - (factor * 0.5);
|
||||
}
|
||||
gl_FragColor = color;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
sepia
|
||||
void main()
|
||||
{
|
||||
vec4 color = texture2D(texture, textureCoords);
|
||||
if(textureCoords.x < awareArea.x || textureCoords.y < awareArea.y || textureCoords.x > awareArea.z || textureCoords.y > awareArea.w) {
|
||||
gl_FragColor.r = dot(color, vec4(.393, .769, .189, .0));
|
||||
gl_FragColor.g = dot(color, vec4(.349, .686, .168, .0));
|
||||
gl_FragColor.b = dot(color, vec4(.272, .534, .131, .0));
|
||||
gl_FragColor.a = 1;
|
||||
} else
|
||||
gl_FragColor = color;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
void main()
|
||||
{
|
||||
vec4 color = texture2D(texture, textureCoords);
|
||||
vec2 awareRange = (awareArea.zw - awareArea.xy)/2.0;
|
||||
float dist = distance(textureCoords, awareArea.xy + awareRange);
|
||||
float start = min(awareRange.x, awareRange.y);
|
||||
float range = awareRange*0.1;
|
||||
float endFactor = 0.3;
|
||||
if(dist >= start) {
|
||||
color.rgb *= 1 - (min((dist - start)/range, 1.0) * (2.0 - endFactor));
|
||||
}
|
||||
gl_FragColor = color;
|
||||
}
|
||||
*/
|
|
@ -76,6 +76,8 @@ void Graphics::init()
|
|||
|
||||
#endif
|
||||
|
||||
glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
|
||||
glEnable(GL_BLEND);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
|
@ -99,8 +101,6 @@ bool Graphics::parseOption(const std::string& option)
|
|||
m_generateMipmaps = false;
|
||||
else if(option == "-no-smoothing")
|
||||
m_useBilinearFiltering = false;
|
||||
else if(option == "-realtime-mipmapping")
|
||||
m_generateRealtimeMipmaps = true;
|
||||
else if(option == "-no-hardware-buffering")
|
||||
m_useHardwareBuffers = false;
|
||||
else
|
||||
|
|
|
@ -38,7 +38,6 @@ public:
|
|||
bool canUseHardwareBuffers() { return m_useHardwareBuffers; }
|
||||
bool canGenerateMipmaps() { return m_generateMipmaps; }
|
||||
bool canGenerateHardwareMipmaps() { return m_generateHardwareMipmaps; }
|
||||
bool canGenerateRealtimeMipmaps() { return m_generateRealtimeMipmaps; }
|
||||
|
||||
void resize(const Size& size);
|
||||
void beginRender();
|
||||
|
@ -59,7 +58,6 @@ private:
|
|||
Boolean<true> m_useBilinearFiltering;
|
||||
Boolean<true> m_generateMipmaps;
|
||||
Boolean<true> m_generateHardwareMipmaps;
|
||||
Boolean<false> m_generateRealtimeMipmaps;
|
||||
};
|
||||
|
||||
extern Graphics g_graphics;
|
||||
|
|
|
@ -33,6 +33,8 @@ public:
|
|||
Color() : m_r(1.0f), m_g(1.0f), m_b(1.0f), m_a(1.0f) { }
|
||||
Color(uint32 rgba) { setRGBA(rgba); }
|
||||
Color(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) : m_r(r/255.0f), m_g(g/255.0f), m_b(b/255.0f), m_a(a/255.0f) { }
|
||||
Color(int r, int g, int b, int a = 0xFF) : m_r(r/255.0f), m_g(g/255.0f), m_b(b/255.0f), m_a(a/255.0f) { }
|
||||
Color(float r, float g, float b, float a = 1.0f) : m_r(r), m_g(g), m_b(b), m_a(a) { }
|
||||
|
||||
uint8 a() const { return m_a*255.0f; }
|
||||
uint8 b() const { return m_b*255.0f; }
|
||||
|
|
|
@ -34,23 +34,24 @@
|
|||
#include "missile.h"
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
|
||||
//int AWARE_AREA_UNIFORM = 10;
|
||||
|
||||
MapView::MapView()
|
||||
{
|
||||
m_viewRange = NEAR_VIEW;
|
||||
m_viewMode = NEAR_VIEW;
|
||||
m_lockedFirstVisibleFloor = -1;
|
||||
m_cachedFirstVisibleFloor = 0;
|
||||
m_cachedFirstVisibleFloor = 7;
|
||||
m_cachedLastVisibleFloor = 7;
|
||||
m_optimizedSize = Size(Otc::AWARE_X_TILES, Otc::AWARE_Y_TILES) * Otc::TILE_PIXELS;
|
||||
|
||||
Size frameBufferSize(std::min(g_graphics.getMaxTextureSize(), (int)DEFAULT_FRAMBUFFER_WIDTH),
|
||||
std::min(g_graphics.getMaxTextureSize(), (int)DEFAULT_FRAMBUFFER_HEIGHT));
|
||||
|
||||
m_framebuffer = FrameBufferPtr(new FrameBuffer(frameBufferSize));
|
||||
m_framebuffer = FrameBufferPtr(new FrameBuffer());
|
||||
setVisibleDimension(Size(15, 11));
|
||||
|
||||
m_shaderProgram = PainterShaderProgramPtr(new PainterShaderProgram);
|
||||
m_shaderProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
|
||||
m_shaderProgram->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/map.frag");
|
||||
m_shaderProgram->link();
|
||||
//m_shaderProgram->bindUniformLocation(AWARE_AREA_UNIFORM, "awareArea");
|
||||
}
|
||||
|
||||
void MapView::draw(const Rect& rect)
|
||||
|
@ -63,18 +64,19 @@ void MapView::draw(const Rect& rect)
|
|||
Position cameraPosition = getCameraPosition();
|
||||
|
||||
int drawFlags = 0;
|
||||
if(m_viewRange == NEAR_VIEW)
|
||||
if(m_viewMode == NEAR_VIEW)
|
||||
drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls |
|
||||
Otc::DrawItems | Otc::DrawCreatures | Otc::DrawEffects | Otc::DrawMissiles | Otc::DrawAnimations;
|
||||
else if(m_viewRange == MID_VIEW)
|
||||
else if(m_viewMode == MID_VIEW)
|
||||
drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls | Otc::DrawItems;
|
||||
else if(m_viewRange == FAR_VIEW)
|
||||
else if(m_viewMode == FAR_VIEW)
|
||||
drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls;
|
||||
else if(m_tileSize >= 4) // HUGE_VIEW 1
|
||||
drawFlags = Otc::DrawGround | Otc::DrawGroundBorders;
|
||||
else // HUGE_VIEW 2
|
||||
drawFlags = Otc::DrawGround;
|
||||
|
||||
Size tileSize = Size(1,1) * m_tileSize;
|
||||
if(m_mustDrawVisibleTilesCache || (drawFlags & Otc::DrawAnimations)) {
|
||||
g_painter.saveAndResetState();
|
||||
m_framebuffer->bind();
|
||||
|
@ -86,6 +88,8 @@ void MapView::draw(const Rect& rect)
|
|||
g_painter.setColor(Color::black);
|
||||
g_painter.drawFilledRect(clearRect);
|
||||
g_painter.setColor(Color::white);
|
||||
|
||||
// m_framebuffer->clear(Color::black);
|
||||
}
|
||||
|
||||
auto it = m_cachedVisibleTiles.begin();
|
||||
|
@ -98,29 +102,26 @@ void MapView::draw(const Rect& rect)
|
|||
else
|
||||
++it;
|
||||
|
||||
if(!m_drawMinimapColors)
|
||||
tile->draw(transformPositionTo2D(tile->getPosition()), scaleFactor, drawFlags);
|
||||
else {
|
||||
g_painter.setColor(tile->getMinimapColor());
|
||||
g_painter.drawFilledRect(Rect(transformPositionTo2D(tile->getPosition()), tileSize));
|
||||
}
|
||||
}
|
||||
|
||||
if(drawFlags & Otc::DrawMissiles) {
|
||||
if(drawFlags & Otc::DrawMissiles && !m_drawMinimapColors) {
|
||||
for(const MissilePtr& missile : g_map.getFloorMissiles(z)) {
|
||||
missile->draw(transformPositionTo2D(missile->getPosition()), scaleFactor, drawFlags & Otc::DrawAnimations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// debug source area
|
||||
g_painter.setColor(Color(255,255,255,100));
|
||||
Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize;
|
||||
g_painter.drawFilledRect(Rect(drawOffset, m_visibleDimension * m_tileSize));
|
||||
*/
|
||||
|
||||
m_framebuffer->release();
|
||||
g_painter.restoreSavedState();
|
||||
|
||||
// generating mipmaps each frame can be slow in older cards
|
||||
if(g_graphics.canGenerateRealtimeMipmaps())
|
||||
m_framebuffer->getTexture()->generateHardwareMipmaps();
|
||||
//m_framebuffer->getTexture()->generateHardwareMipmaps();
|
||||
|
||||
m_mustDrawVisibleTilesCache = false;
|
||||
}
|
||||
|
@ -130,20 +131,57 @@ void MapView::draw(const Rect& rect)
|
|||
Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize;
|
||||
if(m_followingCreature)
|
||||
drawOffset += m_followingCreature->getWalkOffset() * scaleFactor;
|
||||
Rect srcRect = Rect(drawOffset, m_visibleDimension * m_tileSize);
|
||||
|
||||
Size srcSize = rect.size();
|
||||
Size srcVisible = m_visibleDimension * m_tileSize;
|
||||
srcSize.scale(srcVisible, Fw::KeepAspectRatio);
|
||||
drawOffset.x += (srcVisible.width() - srcSize.width()) / 2;
|
||||
drawOffset.y += (srcVisible.height() - srcSize.height()) / 2;
|
||||
Rect srcRect = Rect(drawOffset, srcSize);
|
||||
|
||||
/*
|
||||
// pass aware area to the shader program
|
||||
Rect awareRect;
|
||||
if(m_followingCreature) {
|
||||
Point awareOffset = transformPositionTo2D(m_followingCreature->getPosition().translated(-Otc::AWARE_X_LEFT_TILES + 1, -Otc::AWARE_Y_TOP_TILES + 1));
|
||||
awareOffset += m_followingCreature->getWalkOffset() * scaleFactor;
|
||||
|
||||
awareRect.setTopLeft(awareOffset);
|
||||
awareRect.resize(Otc::VISIBLE_X_TILES * m_tileSize, Otc::VISIBLE_Y_TILES * m_tileSize);
|
||||
}
|
||||
|
||||
m_shaderProgram->bind();
|
||||
m_shaderProgram->setUniformValue(AWARE_AREA_UNIFORM,
|
||||
awareRect.left()/(float)m_framebuffer->getSize().width(),
|
||||
awareRect.top()/(float)m_framebuffer->getSize().height(),
|
||||
awareRect.right()/(float)m_framebuffer->getSize().width(),
|
||||
awareRect.bottom()/(float)m_framebuffer->getSize().height());
|
||||
*/
|
||||
|
||||
#if 0
|
||||
// debug source area
|
||||
g_painter.saveAndResetState();
|
||||
m_framebuffer->bind();
|
||||
g_painter.setColor(Color::green);
|
||||
g_painter.drawBoundingRect(srcRect, 2);
|
||||
m_framebuffer->release();
|
||||
g_painter.restoreSavedState();
|
||||
m_framebuffer->draw(rect);
|
||||
#else
|
||||
m_framebuffer->draw(rect, srcRect);
|
||||
#endif
|
||||
|
||||
g_painter.releaseCustomProgram();
|
||||
|
||||
// this could happen if the player position is not known yet
|
||||
if(!cameraPosition.isValid())
|
||||
return;
|
||||
|
||||
float horizontalStretchFactor = rect.width() / (float)(m_visibleDimension.width() * m_tileSize);
|
||||
float verticalStretchFactor = rect.height() / (float)(m_visibleDimension.height() * m_tileSize);
|
||||
//Size tileStretchedSize = Size(m_tileSize * horizontalStretchFactor, m_tileSize * verticalStretchFactor);
|
||||
float horizontalStretchFactor = rect.width() / (float)srcRect.width();
|
||||
float verticalStretchFactor = rect.height() / (float)srcRect.height();
|
||||
|
||||
// avoid drawing texts on map in far zoom outs
|
||||
if(m_viewRange == NEAR_VIEW) {
|
||||
if(m_viewMode == NEAR_VIEW && m_drawTexts) {
|
||||
for(const CreaturePtr& creature : m_cachedFloorVisibleCreatures) {
|
||||
Position pos = creature->getPosition();
|
||||
|
||||
|
@ -187,7 +225,7 @@ void MapView::draw(const Rect& rect)
|
|||
p += rect.topLeft();
|
||||
animatedText->draw(p, rect);
|
||||
}
|
||||
} else {
|
||||
} else if(m_viewMode > NEAR_VIEW) {
|
||||
// draw a cross in the center instead of our creature
|
||||
Rect vRect(0, 0, 2, 10);
|
||||
Rect hRect(0, 0, 10, 2);
|
||||
|
@ -239,16 +277,13 @@ void MapView::updateVisibleTilesCache(int start)
|
|||
// cache visible tiles in draw order
|
||||
// draw from last floor (the lower) to first floor (the higher)
|
||||
for(int iz = m_cachedLastVisibleFloor; iz >= m_cachedFirstVisibleFloor && !stop; --iz) {
|
||||
if(m_viewRange <= FAR_VIEW) {
|
||||
if(m_viewMode <= FAR_VIEW) {
|
||||
const int numDiagonals = m_drawDimension.width() + m_drawDimension.height() - 1;
|
||||
// loop through / diagonals beginning at top left and going to top right
|
||||
for(int diagonal = 0; diagonal < numDiagonals && !stop; ++diagonal) {
|
||||
// loop current diagonal tiles
|
||||
for(int iy = std::min(diagonal, m_drawDimension.width() - 1), ix = std::max(diagonal - m_drawDimension.width() + 1, 0); iy >= 0 && ix < m_drawDimension.width() && !stop; --iy, ++ix) {
|
||||
// skip bottom tiles that are outside the draw dimension
|
||||
if(iy >= m_drawDimension.height())
|
||||
continue;
|
||||
|
||||
int advance = std::max(diagonal - m_drawDimension.height(), 0);
|
||||
for(int iy = diagonal - advance, ix = advance; iy >= 0 && ix < m_drawDimension.width() && !stop; --iy, ++ix) {
|
||||
// only start really looking tiles in the desired start
|
||||
if(count < start) {
|
||||
count++;
|
||||
|
@ -256,7 +291,7 @@ void MapView::updateVisibleTilesCache(int start)
|
|||
}
|
||||
|
||||
// avoid rendering too much tiles at once on far views
|
||||
if(count - start + 1 > MAX_TILE_UPDATES && m_viewRange >= HUGE_VIEW) {
|
||||
if(count - start + 1 > MAX_TILE_UPDATES && m_viewMode >= HUGE_VIEW) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
|
@ -378,13 +413,71 @@ void MapView::updateVisibleTilesCache(int start)
|
|||
// schedule next update continuation to avoid freezes
|
||||
m_updateTilesCacheEvent = g_eventDispatcher.scheduleEvent(std::bind(&MapView::updateVisibleTilesCache, asMapView(), count), 1);
|
||||
}
|
||||
if(start == 0)
|
||||
|
||||
if(start == 0 && m_drawTexts && m_viewMode <= NEAR_VIEW)
|
||||
m_cachedFloorVisibleCreatures = g_map.getSpectators(cameraPosition, false);
|
||||
}
|
||||
|
||||
void MapView::updateGeometry(const Size& visibleDimension, const Size& optimizedSize)
|
||||
{
|
||||
int possiblesTileSizes[] = {1,2,4,8,16,32};
|
||||
int tileSize = 0;
|
||||
Size bufferSize;
|
||||
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;
|
||||
}
|
||||
|
||||
if(tileSize == 0) {
|
||||
logTraceError("reached max zoom out");
|
||||
return;
|
||||
}
|
||||
|
||||
Size drawDimension = visibleDimension + Size(3,3);
|
||||
Point virtualCenterOffset = (drawDimension/2 - Size(1,1)).toPoint();
|
||||
Point visibleCenterOffset = virtualCenterOffset;
|
||||
|
||||
ViewMode viewMode = m_viewMode;
|
||||
if(m_autoViewMode) {
|
||||
if(tileSize >= 32 && visibleDimension.area() <= NEAR_VIEW_AREA)
|
||||
viewMode = NEAR_VIEW;
|
||||
else if(tileSize >= 16 && visibleDimension.area() <= MID_VIEW_AREA)
|
||||
viewMode = MID_VIEW;
|
||||
else if(tileSize >= 8 && visibleDimension.area() <= FAR_VIEW_AREA)
|
||||
viewMode = FAR_VIEW;
|
||||
else
|
||||
viewMode = HUGE_VIEW;
|
||||
}
|
||||
|
||||
// draw actually more than what is needed to avoid massive recalculations on huge views
|
||||
/*
|
||||
if(viewMode >= HUGE_VIEW) {
|
||||
Size oldDimension = drawDimension;
|
||||
drawDimension = (m_framebuffer->getSize() / tileSize);
|
||||
virtualCenterOffset += (drawDimension - oldDimension).toPoint() / 2;
|
||||
}
|
||||
*/
|
||||
|
||||
m_viewMode = viewMode;
|
||||
m_visibleDimension = visibleDimension;
|
||||
m_drawDimension = drawDimension;
|
||||
m_tileSize = tileSize;
|
||||
m_virtualCenterOffset = virtualCenterOffset;
|
||||
m_visibleCenterOffset = visibleCenterOffset;
|
||||
m_optimizedSize = optimizedSize;
|
||||
m_framebuffer->resize(bufferSize);
|
||||
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::onTileUpdate(const Position& pos)
|
||||
{
|
||||
//if(m_viewRange <= FAR_VIEW)
|
||||
//if(m_viewMode <= FAR_VIEW)
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
|
@ -400,21 +493,11 @@ void MapView::unlockFirstVisibleFloor()
|
|||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::followCreature(const CreaturePtr& creature)
|
||||
{
|
||||
m_followingCreature = creature;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::setCameraPosition(const Position& pos)
|
||||
{
|
||||
m_customCameraPosition = pos;
|
||||
m_followingCreature = nullptr;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
void MapView::setVisibleDimension(const Size& visibleDimension)
|
||||
{
|
||||
if(visibleDimension == m_visibleDimension)
|
||||
return;
|
||||
|
||||
if(visibleDimension.width() % 2 != 1 || visibleDimension.height() % 2 != 1) {
|
||||
logTraceError("visible dimension must be odd");
|
||||
return;
|
||||
|
@ -425,52 +508,37 @@ void MapView::setVisibleDimension(const Size& visibleDimension)
|
|||
return;
|
||||
}
|
||||
|
||||
int possiblesTileSizes[] = {32,16,8,4,2,1};
|
||||
int tileSize = 0;
|
||||
Size drawDimension = visibleDimension + Size(3,3);
|
||||
Size framebufferSize = m_framebuffer->getSize();
|
||||
for(int candidateTileSize : possiblesTileSizes) {
|
||||
Size candidateDrawSize = drawDimension * candidateTileSize;
|
||||
updateGeometry(visibleDimension, m_optimizedSize);
|
||||
}
|
||||
|
||||
// found a valid size
|
||||
if(candidateDrawSize.width() <= framebufferSize.width() && candidateDrawSize.height() <= framebufferSize.height()) {
|
||||
tileSize = candidateTileSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
void MapView::setViewMode(MapView::ViewMode viewMode)
|
||||
{
|
||||
m_viewMode = viewMode;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
if(tileSize == 0) {
|
||||
logTraceError("reached max zoom out");
|
||||
return;
|
||||
}
|
||||
void MapView::setAutoViewMode(bool enable)
|
||||
{
|
||||
m_autoViewMode = enable;
|
||||
if(enable)
|
||||
updateGeometry(m_visibleDimension, m_optimizedSize);
|
||||
}
|
||||
|
||||
Point virtualCenterOffset = (drawDimension/2 - Size(1,1)).toPoint();
|
||||
Point visibleCenterOffset = virtualCenterOffset;
|
||||
void MapView::optimizeForSize(const Size& visibleSize)
|
||||
{
|
||||
updateGeometry(m_visibleDimension, visibleSize);
|
||||
}
|
||||
|
||||
ViewRange viewRange;
|
||||
if(tileSize >= 32 && visibleDimension.area() <= NEAR_VIEW_AREA)
|
||||
viewRange = NEAR_VIEW;
|
||||
else if(tileSize >= 16 && visibleDimension.area() <= MID_VIEW_AREA)
|
||||
viewRange = MID_VIEW;
|
||||
else if(tileSize >= 8 && visibleDimension.area() <= FAR_VIEW_AREA)
|
||||
viewRange = FAR_VIEW;
|
||||
else
|
||||
viewRange = HUGE_VIEW;
|
||||
void MapView::followCreature(const CreaturePtr& creature)
|
||||
{
|
||||
m_followingCreature = creature;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
bool mustUpdate = (m_drawDimension != drawDimension ||
|
||||
m_viewRange != viewRange ||
|
||||
m_virtualCenterOffset != virtualCenterOffset ||
|
||||
m_visibleCenterOffset != visibleCenterOffset ||
|
||||
m_tileSize != tileSize);
|
||||
|
||||
m_visibleDimension = visibleDimension;
|
||||
m_drawDimension = drawDimension;
|
||||
m_tileSize = tileSize;
|
||||
m_viewRange = viewRange;
|
||||
m_virtualCenterOffset = virtualCenterOffset;
|
||||
m_visibleCenterOffset = visibleCenterOffset;
|
||||
|
||||
if(mustUpdate)
|
||||
void MapView::setCameraPosition(const Position& pos)
|
||||
{
|
||||
m_customCameraPosition = pos;
|
||||
m_followingCreature = nullptr;
|
||||
requestVisibleTilesCacheUpdate();
|
||||
}
|
||||
|
||||
|
@ -486,7 +554,7 @@ int MapView::calcFirstVisibleFloor()
|
|||
// this could happens if the player is not known yet
|
||||
if(cameraPosition.isValid()) {
|
||||
// avoid rendering multifloors in far views
|
||||
if(m_viewRange >= FAR_VIEW) {
|
||||
if(m_viewMode >= FAR_VIEW || !m_multifloor) {
|
||||
z = cameraPosition.z;
|
||||
} else {
|
||||
// if nothing is limiting the view, the first visible floor is 0
|
||||
|
@ -536,22 +604,23 @@ int MapView::calcFirstVisibleFloor()
|
|||
|
||||
int MapView::calcLastVisibleFloor()
|
||||
{
|
||||
if(!m_multifloor || m_viewMode >= FAR_VIEW)
|
||||
return calcFirstVisibleFloor();
|
||||
|
||||
int z = 7;
|
||||
|
||||
Position cameraPosition = getCameraPosition();
|
||||
// this could happens if the player is not known yet
|
||||
if(cameraPosition.isValid()) {
|
||||
// avoid rendering multifloors in far views
|
||||
if(m_viewRange >= FAR_VIEW) {
|
||||
z = cameraPosition.z;
|
||||
} else {
|
||||
// view only underground floors when below sea level
|
||||
if(cameraPosition.z > Otc::SEA_FLOOR)
|
||||
z = cameraPosition.z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE;
|
||||
else
|
||||
z = Otc::SEA_FLOOR;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_lockedFirstVisibleFloor != -1)
|
||||
z = std::max(m_lockedFirstVisibleFloor, z);
|
||||
|
||||
// just ensure the that the floor is in the valid range
|
||||
z = std::min(std::max(z, 0), (int)Otc::MAX_Z);
|
||||
|
@ -568,7 +637,7 @@ Position MapView::getCameraPosition()
|
|||
TilePtr MapView::getTile(const Point& mousePos, const Rect& mapRect)
|
||||
{
|
||||
Point relativeMousePos = mousePos - mapRect.topLeft();
|
||||
Size visibleSize = getVisibleSize();
|
||||
Size visibleSize = m_visibleDimension * m_tileSize;
|
||||
Position cameraPosition = getCameraPosition();
|
||||
|
||||
// if we have no camera, its impossible to get the tile
|
||||
|
@ -608,6 +677,7 @@ TilePtr MapView::getTile(const Point& mousePos, const Rect& mapRect)
|
|||
return tile;
|
||||
}
|
||||
|
||||
|
||||
Point MapView::transformPositionTo2D(const Position& position)
|
||||
{
|
||||
Position cameraPosition = getCameraPosition();
|
||||
|
|
|
@ -34,8 +34,6 @@ class MapView : public LuaObject
|
|||
// 3840x2160 => 1080p optimized
|
||||
// 2560x1440 => 720p optimized
|
||||
// 1728x972 => 480p optimized
|
||||
DEFAULT_FRAMBUFFER_WIDTH = 2560,
|
||||
DEFAULT_FRAMBUFFER_HEIGHT = 1440,
|
||||
|
||||
NEAR_VIEW_AREA = 32*32,
|
||||
MID_VIEW_AREA = 64*64,
|
||||
|
@ -43,18 +41,19 @@ class MapView : public LuaObject
|
|||
MAX_TILE_UPDATES = NEAR_VIEW_AREA*7
|
||||
};
|
||||
|
||||
enum ViewRange {
|
||||
public:
|
||||
enum ViewMode {
|
||||
NEAR_VIEW,
|
||||
MID_VIEW,
|
||||
FAR_VIEW,
|
||||
HUGE_VIEW
|
||||
};
|
||||
|
||||
public:
|
||||
MapView();
|
||||
void draw(const Rect& rect);
|
||||
|
||||
private:
|
||||
void updateGeometry(const Size& visibleDimension, const Size& optimizedSize);
|
||||
void updateVisibleTilesCache(int start = 0);
|
||||
void requestVisibleTilesCacheUpdate() { m_mustUpdateVisibleTilesCache = true; }
|
||||
|
||||
|
@ -64,55 +63,82 @@ protected:
|
|||
friend class Map;
|
||||
|
||||
public:
|
||||
// floor visibility related
|
||||
void lockFirstVisibleFloor(int firstVisibleFloor);
|
||||
void unlockFirstVisibleFloor();
|
||||
void followCreature(const CreaturePtr& creature);
|
||||
int getLockedFirstVisibleFloor() { return m_lockedFirstVisibleFloor; }
|
||||
|
||||
void setCameraPosition(const Position& pos);
|
||||
void setMultifloor(bool enable) { m_multifloor = enable; requestVisibleTilesCacheUpdate(); }
|
||||
bool isMultifloor() { return m_multifloor; }
|
||||
|
||||
// map dimension related
|
||||
void setVisibleDimension(const Size& visibleDimension);
|
||||
void setAnimated(bool animated) { m_animated = animated; }
|
||||
|
||||
//void zoomIn(float factor);
|
||||
//void zoomOut(float factor);
|
||||
|
||||
bool isFollowingCreature() { return !!m_followingCreature; }
|
||||
|
||||
int calcFirstVisibleFloor();
|
||||
int calcLastVisibleFloor();
|
||||
Position getCameraPosition();
|
||||
TilePtr getTile(const Point& mousePos, const Rect& mapRect);
|
||||
Size getVisibleDimension() { return m_visibleDimension; }
|
||||
Size getVisibleSize() { return m_visibleDimension * m_tileSize; }
|
||||
|
||||
// view mode related
|
||||
void setViewMode(ViewMode viewMode);
|
||||
ViewMode getViewMode() { return m_viewMode; }
|
||||
void optimizeForSize(const Size& visibleSize);
|
||||
|
||||
void setAutoViewMode(bool enable);
|
||||
bool isAutoViewModeEnabled() { return m_autoViewMode; }
|
||||
|
||||
// camera related
|
||||
void followCreature(const CreaturePtr& creature);
|
||||
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
||||
|
||||
bool getViewRange() { return m_viewRange; }
|
||||
bool isAnimated() { return m_animated; }
|
||||
void setCameraPosition(const Position& pos);
|
||||
Position getCameraPosition();
|
||||
|
||||
Point transformPositionTo2D(const Position& position);
|
||||
// drawing related
|
||||
void setDrawFlags(Otc::DrawFlags drawFlags) { m_drawFlags = drawFlags; requestVisibleTilesCacheUpdate(); }
|
||||
Otc::DrawFlags getDrawFlags() { return m_drawFlags; }
|
||||
|
||||
void setDrawTexts(bool enable) { m_drawTexts = enable; }
|
||||
bool isDrawingTexts() { return m_drawTexts; }
|
||||
|
||||
void setDrawMinimapColors(bool enable) { m_drawMinimapColors = enable; requestVisibleTilesCacheUpdate(); }
|
||||
bool isDrawingMinimapColors() { return m_drawMinimapColors; }
|
||||
|
||||
void setAnimated(bool animated) { m_animated = animated; requestVisibleTilesCacheUpdate(); }
|
||||
bool isAnimating() { return m_animated; }
|
||||
|
||||
// get tile
|
||||
TilePtr getTile(const Point& mousePos, const Rect& mapRect);
|
||||
|
||||
MapViewPtr asMapView() { return std::static_pointer_cast<MapView>(shared_from_this()); }
|
||||
|
||||
private:
|
||||
int calcFirstVisibleFloor();
|
||||
int calcLastVisibleFloor();
|
||||
Point transformPositionTo2D(const Position& position);
|
||||
|
||||
int m_lockedFirstVisibleFloor;
|
||||
int m_cachedFirstVisibleFloor;
|
||||
int m_cachedLastVisibleFloor;
|
||||
int m_tileSize;
|
||||
Size m_drawDimension;
|
||||
Size m_visibleDimension;
|
||||
Size m_optimizedSize;
|
||||
Point m_virtualCenterOffset;
|
||||
Point m_visibleCenterOffset;
|
||||
Position m_customCameraPosition;
|
||||
Boolean<true> m_mustUpdateVisibleTilesCache;
|
||||
Boolean<true> m_mustDrawVisibleTilesCache;
|
||||
Boolean<true> m_mustCleanFramebuffer;
|
||||
Boolean<true> m_multifloor;
|
||||
Boolean<true> m_animated;
|
||||
Boolean<true> m_autoViewMode;
|
||||
Boolean<true> m_drawTexts;
|
||||
Boolean<false> m_drawMinimapColors;
|
||||
std::vector<TilePtr> m_cachedVisibleTiles;
|
||||
std::vector<CreaturePtr> m_cachedFloorVisibleCreatures;
|
||||
EventPtr m_updateTilesCacheEvent;
|
||||
CreaturePtr m_followingCreature;
|
||||
FrameBufferPtr m_framebuffer;
|
||||
PainterShaderProgramPtr m_shaderProgram;
|
||||
ViewRange m_viewRange;
|
||||
ViewMode m_viewMode;
|
||||
Otc::DrawFlags m_drawFlags;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -104,6 +104,7 @@ public:
|
|||
int getAnimationPhases() { return m_type->dimensions[ThingType::AnimationPhases]; }
|
||||
int getGroundSpeed() { return m_type->parameters[ThingType::GroundSpeed]; }
|
||||
int getElevation() { return m_type->parameters[ThingType::Elevation]; }
|
||||
int getMinimapColor() { return m_type->parameters[ThingType::MiniMapColor]; }
|
||||
|
||||
int getSpriteId(int w = 0, int h = 0, int layer = 0,
|
||||
int xPattern = 0, int yPattern = 0, int zPattern = 0,
|
||||
|
|
|
@ -265,6 +265,19 @@ int Tile::getGroundSpeed()
|
|||
return groundSpeed;
|
||||
}
|
||||
|
||||
Color Tile::getMinimapColor()
|
||||
{
|
||||
Color color = Color::black;
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop())
|
||||
break;
|
||||
int c = thing->getMinimapColor();
|
||||
if(c != 0)
|
||||
color = Color::from8bit(c);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
ThingPtr Tile::getTopLookThing()
|
||||
{
|
||||
if(isEmpty())
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
const std::vector<ThingPtr>& getThings() { return m_things; }
|
||||
ItemPtr getGround();
|
||||
int getGroundSpeed();
|
||||
Color getMinimapColor();
|
||||
int getThingCount() { return m_things.size() + m_effects.size(); }
|
||||
bool isPathable();
|
||||
bool isWalkable();
|
||||
|
|
|
@ -333,10 +333,37 @@ void OTClient::registerLuaFunctions()
|
|||
g_lua.bindClassMemberFunction<UICreature>("isFixedCreatureSize", &UICreature::isFixedCreatureSize);
|
||||
|
||||
g_lua.registerClass<UIMap, UIWidget>();
|
||||
g_lua.bindClassStaticFunction<UIMap>("create", []{ return UIMapPtr(new UIMap); } );
|
||||
g_lua.bindClassMemberFunction<UIMap>("followCreature", &UIMap::followCreature);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setCameraPosition", &UIMap::setCameraPosition);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getTile", &UIMap::getTile);
|
||||
g_lua.bindClassStaticFunction<UIMap>("create", []{ return UIMapPtr(new UIMap); });
|
||||
g_lua.bindClassMemberFunction<UIMap>("drawSelf", &UIMap::drawSelf);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setZoom", &UIMap::setZoom);
|
||||
g_lua.bindClassMemberFunction<UIMap>("zoomIn", &UIMap::zoomIn);
|
||||
g_lua.bindClassMemberFunction<UIMap>("zoomOut", &UIMap::zoomOut);
|
||||
g_lua.bindClassMemberFunction<UIMap>("followCreature", &UIMap::followCreature);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setCameraPosition", &UIMap::setCameraPosition);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setMaxZoomIn", &UIMap::setMaxZoomIn);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setMaxZoomOut", &UIMap::setMaxZoomOut);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setMultifloor", &UIMap::setMultifloor);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setVisibleDimension", &UIMap::setVisibleDimension);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setViewMode", &UIMap::setViewMode);
|
||||
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>("setAnimated", &UIMap::setAnimated);
|
||||
g_lua.bindClassMemberFunction<UIMap>("setKeepAspectRatio", &UIMap::setKeepAspectRatio);
|
||||
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>("isAnimating", &UIMap::isAnimating);
|
||||
g_lua.bindClassMemberFunction<UIMap>("isKeepAspectRatioEnabled", &UIMap::isKeepAspectRatioEnabled);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getVisibleDimension", &UIMap::getVisibleDimension);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getViewMode", &UIMap::getViewMode);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getFollowingCreature", &UIMap::getFollowingCreature);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getDrawFlags", &UIMap::getDrawFlags);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getCameraPosition", &UIMap::getCameraPosition);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getTile", &UIMap::getTile);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getMaxZoomIn", &UIMap::getMaxZoomIn);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getMaxZoomOut", &UIMap::getMaxZoomOut);
|
||||
g_lua.bindClassMemberFunction<UIMap>("getZoom", &UIMap::getZoom);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@ UIMap::UIMap()
|
|||
{
|
||||
m_dragable = true;
|
||||
m_mapView = MapViewPtr(new MapView);
|
||||
m_zoom = m_mapView->getVisibleDimension().height();
|
||||
m_aspectRatio = 0.0f;
|
||||
m_maxZoomIn = 3;
|
||||
m_maxZoomOut = 512;
|
||||
g_map.addMapView(m_mapView);
|
||||
}
|
||||
|
||||
|
@ -51,56 +55,48 @@ void UIMap::drawSelf()
|
|||
m_mapView->draw(m_mapRect);
|
||||
}
|
||||
|
||||
void UIMap::zoomIn()
|
||||
bool UIMap::setZoom(int zoom)
|
||||
{
|
||||
int dimensionHeight = m_mapView->getVisibleDimension().height() * 0.99;
|
||||
if(dimensionHeight == m_mapView->getVisibleDimension().height())
|
||||
dimensionHeight -= 1;
|
||||
if(dimensionHeight % 2 == 0)
|
||||
dimensionHeight -= 1;
|
||||
int dimensionWidth = dimensionHeight * getSize().ratio();
|
||||
if(dimensionWidth % 2 == 0)
|
||||
dimensionWidth -= 1;
|
||||
|
||||
m_mapView->setVisibleDimension(Size(dimensionWidth, dimensionHeight));
|
||||
|
||||
Rect mapRect = getClippingRect().expanded(-1);
|
||||
Size mapSize = m_mapView->getVisibleSize();
|
||||
mapSize.scale(mapRect.size(), Fw::KeepAspectRatio);
|
||||
|
||||
m_mapRect.resize(mapSize);
|
||||
m_mapRect.moveCenter(m_rect.center());
|
||||
//TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
void UIMap::zoomOut()
|
||||
bool UIMap::zoomIn()
|
||||
{
|
||||
int dimensionHeight = m_mapView->getVisibleDimension().height() * 1.01;
|
||||
if(dimensionHeight == m_mapView->getVisibleDimension().height())
|
||||
dimensionHeight += 1;
|
||||
if(dimensionHeight % 2 == 0)
|
||||
dimensionHeight += 1;
|
||||
int dimensionWidth = dimensionHeight * getSize().ratio();
|
||||
if(dimensionWidth % 2 == 0)
|
||||
dimensionWidth += 1;
|
||||
int delta = 2;
|
||||
if(m_zoom - delta <= m_maxZoomIn)
|
||||
return false;
|
||||
|
||||
m_mapView->setVisibleDimension(Size(dimensionWidth, dimensionHeight));
|
||||
|
||||
Rect mapRect = getClippingRect().expanded(-1);
|
||||
Size mapSize = m_mapView->getVisibleSize();
|
||||
mapSize.scale(mapRect.size(), Fw::KeepAspectRatio);
|
||||
|
||||
m_mapRect.resize(mapSize);
|
||||
m_mapRect.moveCenter(m_rect.center());
|
||||
m_zoom -= delta;
|
||||
updateVisibleDimension();
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIMap::followCreature(const CreaturePtr& creature)
|
||||
bool UIMap::zoomOut()
|
||||
{
|
||||
m_mapView->followCreature(creature);
|
||||
int delta = 2;
|
||||
if(m_zoom + delta >= m_maxZoomOut)
|
||||
return false;
|
||||
|
||||
m_zoom += 2;
|
||||
updateVisibleDimension();
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIMap::setCameraPosition(const Position& pos)
|
||||
void UIMap::setVisibleDimension(const Size& visibleDimension)
|
||||
{
|
||||
m_mapView->setCameraPosition(pos);
|
||||
m_mapView->setVisibleDimension(visibleDimension);
|
||||
|
||||
if(m_aspectRatio != 0.0f)
|
||||
m_aspectRatio = visibleDimension.ratio();
|
||||
}
|
||||
|
||||
void UIMap::setKeepAspectRatio(bool enable)
|
||||
{
|
||||
if(enable)
|
||||
m_aspectRatio = getVisibleDimension().ratio();
|
||||
else
|
||||
m_aspectRatio = 0.0f;
|
||||
}
|
||||
|
||||
TilePtr UIMap::getTile(const Point& mousePos)
|
||||
|
@ -112,14 +108,61 @@ TilePtr UIMap::getTile(const Point& mousePos)
|
|||
return m_mapView->getTile(mousePos, m_mapRect);
|
||||
}
|
||||
|
||||
void UIMap::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
|
||||
{
|
||||
UIWidget::onStyleApply(styleName, styleNode);
|
||||
for(const OTMLNodePtr& node : styleNode->children()) {
|
||||
if(node->tag() == "multifloor")
|
||||
setMultifloor(node->value<bool>());
|
||||
else if(node->tag() == "auto-view-mode")
|
||||
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() == "animated")
|
||||
setAnimated(node->value<bool>());
|
||||
}
|
||||
}
|
||||
|
||||
void UIMap::onGeometryChange(const Rect& oldRect, const Rect& newRect)
|
||||
{
|
||||
UIWidget::onGeometryChange(oldRect, newRect);
|
||||
updateMapSize();
|
||||
}
|
||||
|
||||
Rect mapRect = getClippingRect().expanded(-1);
|
||||
Size mapSize = m_mapView->getVisibleSize();
|
||||
void UIMap::updateVisibleDimension()
|
||||
{
|
||||
int dimensionHeight = m_zoom;
|
||||
if(dimensionHeight % 2 == 0)
|
||||
dimensionHeight += 1;
|
||||
int dimensionWidth = m_zoom * m_mapRect.size().ratio();
|
||||
if(dimensionWidth % 2 == 0)
|
||||
dimensionWidth += 1;
|
||||
|
||||
m_mapView->setVisibleDimension(Size(dimensionWidth, dimensionHeight));
|
||||
|
||||
if(m_aspectRatio != 0.0f)
|
||||
updateMapSize();
|
||||
}
|
||||
|
||||
void UIMap::updateMapSize()
|
||||
{
|
||||
Rect clippingRect = getClippingRect();
|
||||
Size mapSize;
|
||||
if(m_aspectRatio != 0.0f) {
|
||||
Rect mapRect = clippingRect.expanded(-1);
|
||||
mapSize = Size(m_aspectRatio*m_zoom, m_zoom);
|
||||
mapSize.scale(mapRect.size(), Fw::KeepAspectRatio);
|
||||
} else {
|
||||
mapSize = clippingRect.expanded(-1).size();
|
||||
}
|
||||
|
||||
m_mapRect.resize(mapSize);
|
||||
m_mapRect.moveCenter(newRect.center());
|
||||
m_mapRect.moveCenter(clippingRect.center());
|
||||
m_mapView->optimizeForSize(mapSize);
|
||||
|
||||
if(m_aspectRatio == 0.0f)
|
||||
updateVisibleDimension();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <framework/ui/uiwidget.h>
|
||||
#include <otclient/core/tile.h>
|
||||
|
||||
#include <otclient/core/mapview.h>
|
||||
|
||||
class UIMap : public UIWidget
|
||||
{
|
||||
public:
|
||||
|
@ -35,19 +37,55 @@ public:
|
|||
|
||||
void drawSelf();
|
||||
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
void followCreature(const CreaturePtr& creature);
|
||||
void setCameraPosition(const Position& pos);
|
||||
bool setZoom(int zoom);
|
||||
bool zoomIn();
|
||||
bool zoomOut();
|
||||
void followCreature(const CreaturePtr& creature) { m_mapView->followCreature(creature); }
|
||||
|
||||
void setCameraPosition(const Position& pos) { m_mapView->setCameraPosition(pos); }
|
||||
void setMaxZoomIn(int maxZoomIn) { m_maxZoomIn = maxZoomIn; }
|
||||
void setMaxZoomOut(int maxZoomOut) { m_maxZoomOut = maxZoomOut; }
|
||||
void setMultifloor(bool enable) { m_mapView->setMultifloor(enable); }
|
||||
void setVisibleDimension(const Size& visibleDimension);
|
||||
void setViewMode(MapView::ViewMode viewMode) { m_mapView->setViewMode(viewMode); }
|
||||
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 setAnimated(bool enable) { m_mapView->setAnimated(enable); }
|
||||
void setKeepAspectRatio(bool enable);
|
||||
|
||||
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 isAnimating() { return m_mapView->isAnimating(); }
|
||||
float isKeepAspectRatioEnabled() { return m_aspectRatio != 0.0f; }
|
||||
|
||||
Size getVisibleDimension() { return m_mapView->getVisibleDimension(); }
|
||||
MapView::ViewMode getViewMode() { return m_mapView->getViewMode(); }
|
||||
CreaturePtr getFollowingCreature() { return m_mapView->getFollowingCreature(); }
|
||||
Otc::DrawFlags getDrawFlags() { return m_mapView->getDrawFlags(); }
|
||||
Position getCameraPosition() { return m_mapView->getCameraPosition(); }
|
||||
TilePtr getTile(const Point& mousePos);
|
||||
int getMaxZoomIn() { return m_maxZoomIn; }
|
||||
int getMaxZoomOut() { return m_maxZoomOut; }
|
||||
int getZoom() { return m_zoom; }
|
||||
|
||||
protected:
|
||||
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||
virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect);
|
||||
|
||||
private:
|
||||
void updateVisibleDimension();
|
||||
void updateMapSize();
|
||||
|
||||
int m_zoom;
|
||||
MapViewPtr m_mapView;
|
||||
Rect m_mapRect;
|
||||
float m_aspectRatio;
|
||||
int m_maxZoomIn;
|
||||
int m_maxZoomOut;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue