zoom out much more smoother
This commit is contained in:
parent
deedef235d
commit
51b0822267
|
@ -28,6 +28,7 @@ EventDispatcher g_dispatcher;
|
||||||
|
|
||||||
void EventDispatcher::flush()
|
void EventDispatcher::flush()
|
||||||
{
|
{
|
||||||
|
while(!m_eventList.empty())
|
||||||
poll();
|
poll();
|
||||||
|
|
||||||
while(!m_scheduledEventList.empty())
|
while(!m_scheduledEventList.empty())
|
||||||
|
@ -44,7 +45,8 @@ void EventDispatcher::poll()
|
||||||
scheduledEvent->execute();
|
scheduledEvent->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!m_eventList.empty()) {
|
int maxEvents = m_eventList.size();
|
||||||
|
for(int i=0;i<maxEvents;++i) {
|
||||||
EventPtr event = m_eventList.front();
|
EventPtr event = m_eventList.front();
|
||||||
m_eventList.pop_front();
|
m_eventList.pop_front();
|
||||||
event->execute();
|
event->execute();
|
||||||
|
|
|
@ -61,10 +61,10 @@ public:
|
||||||
TSize<T> operator/(const float v) const { return TSize<T>((T)wd/v, (T)ht/v); }
|
TSize<T> operator/(const float v) const { return TSize<T>((T)wd/v, (T)ht/v); }
|
||||||
TSize<T>& operator/=(const float v) { wd/=v; ht/=v; return *this; }
|
TSize<T>& operator/=(const float v) { wd/=v; ht/=v; return *this; }
|
||||||
|
|
||||||
bool operator<=(const TSize<T>&other) const { return wd<=other.wd || ht<=other.ht; }
|
bool operator<=(const TSize<T>&other) const { return wd<=other.wd && ht<=other.ht; }
|
||||||
bool operator>=(const TSize<T>&other) const { return wd>=other.wd || ht>=other.ht; }
|
bool operator>=(const TSize<T>&other) const { return wd>=other.wd && ht>=other.ht; }
|
||||||
bool operator<(const TSize<T>&other) const { return wd<other.wd || ht<other.ht; }
|
bool operator<(const TSize<T>&other) const { return wd<other.wd && ht<other.ht; }
|
||||||
bool operator>(const TSize<T>&other) const { return wd>other.wd || ht>other.ht; }
|
bool operator>(const TSize<T>&other) const { return wd>other.wd && ht>other.ht; }
|
||||||
|
|
||||||
TSize<T>& operator=(const TSize<T>& other) { wd = other.wd; ht = other.ht; return *this; }
|
TSize<T>& operator=(const TSize<T>& other) { wd = other.wd; ht = other.ht; return *this; }
|
||||||
bool operator==(const TSize<T>& other) const { return other.wd==wd && other.ht==ht; }
|
bool operator==(const TSize<T>& other) const { return other.wd==wd && other.ht==ht; }
|
||||||
|
|
|
@ -216,10 +216,20 @@ TilePtr Map::createTile(const Position& pos)
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TilePtr& Map::getTile(const Position& pos)
|
||||||
|
{
|
||||||
|
auto it = m_tiles.find(pos);
|
||||||
|
if(it != m_tiles.end())
|
||||||
|
return it->second;
|
||||||
|
static TilePtr nulltile;
|
||||||
|
return nulltile;
|
||||||
|
}
|
||||||
|
|
||||||
void Map::cleanTile(const Position& pos)
|
void Map::cleanTile(const Position& pos)
|
||||||
{
|
{
|
||||||
if(TilePtr tile = getTile(pos)) {
|
if(TilePtr tile = getTile(pos)) {
|
||||||
tile->clean();
|
tile->clean();
|
||||||
|
m_tiles.erase(m_tiles.find(pos));
|
||||||
|
|
||||||
notificateTileUpdateToMapViews(pos);
|
notificateTileUpdateToMapViews(pos);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
|
|
||||||
// tile related
|
// tile related
|
||||||
TilePtr createTile(const Position& pos);
|
TilePtr createTile(const Position& pos);
|
||||||
const TilePtr& getTile(const Position& pos) { return m_tiles[pos]; }
|
const TilePtr& getTile(const Position& pos);
|
||||||
void cleanTile(const Position& pos);
|
void cleanTile(const Position& pos);
|
||||||
bool removeThing(const ThingPtr& thing);
|
bool removeThing(const ThingPtr& thing);
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,14 @@
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
#include "statictext.h"
|
#include "statictext.h"
|
||||||
#include "animatedtext.h"
|
#include "animatedtext.h"
|
||||||
|
#include <framework/core/eventdispatcher.h>
|
||||||
|
|
||||||
MapView::MapView()
|
MapView::MapView()
|
||||||
{
|
{
|
||||||
int frameBufferSize = std::min(g_graphics.getMaxTextureSize(), (int)DEFAULT_FRAMBUFFER_SIZE);
|
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(Size(frameBufferSize, frameBufferSize)));
|
m_framebuffer = FrameBufferPtr(new FrameBuffer(frameBufferSize));
|
||||||
m_framebuffer->setClearColor(Fw::black);
|
m_framebuffer->setClearColor(Fw::black);
|
||||||
m_lockedFirstVisibleFloor = -1;
|
m_lockedFirstVisibleFloor = -1;
|
||||||
setVisibleDimension(Size(15, 11));
|
setVisibleDimension(Size(15, 11));
|
||||||
|
@ -50,42 +52,47 @@ MapView::MapView()
|
||||||
void MapView::draw(const Rect& rect)
|
void MapView::draw(const Rect& rect)
|
||||||
{
|
{
|
||||||
// update visible tiles cache when needed
|
// update visible tiles cache when needed
|
||||||
bool updated = updateVisibleTilesCache();
|
if(m_mustUpdateVisibleTilesCache)
|
||||||
|
updateVisibleTilesCache();
|
||||||
|
|
||||||
float scaleFactor = m_tileSize/(float)Otc::TILE_PIXELS;
|
float scaleFactor = m_tileSize/(float)Otc::TILE_PIXELS;
|
||||||
Position cameraPosition = getCameraPosition();
|
Position cameraPosition = getCameraPosition();
|
||||||
|
|
||||||
int tileDrawFlags = 0;
|
int tileDrawFlags = 0;
|
||||||
if(isNearView())
|
if(m_viewRange == NEAR_VIEW)
|
||||||
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems | Otc::DrawCreatures | Otc::DrawEffects;
|
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems | Otc::DrawCreatures | Otc::DrawEffects;
|
||||||
else if(isMidView())
|
else if(m_viewRange == MID_VIEW)
|
||||||
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems;
|
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems;
|
||||||
else if(isFarView())
|
else if(m_viewRange == FAR_VIEW)
|
||||||
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls;
|
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems;
|
||||||
else // huge far view
|
else // HUGE_VIEW
|
||||||
tileDrawFlags = Otc::DrawGround;
|
tileDrawFlags = Otc::DrawGround;
|
||||||
|
|
||||||
bool animate = m_animated;
|
bool animate = m_animated;
|
||||||
|
|
||||||
// avoid animation of mid/far views
|
// only animate in near views
|
||||||
if(!isNearView())
|
if(m_viewRange != NEAR_VIEW)
|
||||||
animate = false;
|
animate = false;
|
||||||
|
|
||||||
if(updated || animate) {
|
if(m_mustDrawVisibleTilesCache || animate) {
|
||||||
m_framebuffer->bind();
|
m_framebuffer->bind(m_mustCleanFramebuffer);
|
||||||
|
if(m_mustCleanFramebuffer)
|
||||||
|
m_mustCleanFramebuffer = false;
|
||||||
|
|
||||||
for(const TilePtr& tile : m_cachedVisibleTiles) {
|
for(const TilePtr& tile : m_cachedVisibleTiles) {
|
||||||
tile->draw(transformPositionTo2D(tile->getPosition()), scaleFactor, tileDrawFlags);
|
tile->draw(transformPositionTo2D(tile->getPosition()), scaleFactor, tileDrawFlags);
|
||||||
//TODO: restore missiles
|
//TODO: restore missiles
|
||||||
}
|
}
|
||||||
m_framebuffer->generateMipmaps();
|
m_framebuffer->generateMipmaps();
|
||||||
|
|
||||||
m_framebuffer->release();
|
m_framebuffer->release();
|
||||||
|
|
||||||
|
m_mustDrawVisibleTilesCache = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_painter.setCustomProgram(m_shaderProgram);
|
g_painter.setCustomProgram(m_shaderProgram);
|
||||||
g_painter.setColor(Fw::white);
|
g_painter.setColor(Fw::white);
|
||||||
|
|
||||||
Point drawOffset(m_tileSize, m_tileSize);
|
Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize;
|
||||||
if(m_followingCreature)
|
if(m_followingCreature)
|
||||||
drawOffset += m_followingCreature->getWalkOffset() * scaleFactor;
|
drawOffset += m_followingCreature->getWalkOffset() * scaleFactor;
|
||||||
Rect srcRect = Rect(drawOffset, m_visibleDimension * m_tileSize);
|
Rect srcRect = Rect(drawOffset, m_visibleDimension * m_tileSize);
|
||||||
|
@ -150,88 +157,103 @@ void MapView::draw(const Rect& rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw a arrow for position the center in non near views
|
// draw a arrow for position the center in non near views
|
||||||
if(!isNearView()) {
|
if(m_viewRange != NEAR_VIEW) {
|
||||||
g_painter.setColor(Fw::red);
|
g_painter.setColor(Fw::red);
|
||||||
g_painter.drawFilledRect(Rect(rect.center(), 4, 4));
|
g_painter.drawFilledRect(Rect(rect.center(), 4, 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapView::updateVisibleTilesCache()
|
void MapView::updateVisibleTilesCache(int start)
|
||||||
{
|
{
|
||||||
// update only when needed
|
if(start == 0) {
|
||||||
if(!m_mustUpdateVisibleTilesCache)
|
if(m_updateTilesCacheEvent) {
|
||||||
return false;
|
m_updateTilesCacheEvent->cancel();
|
||||||
|
m_updateTilesCacheEvent = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
int firstFloor = getFirstVisibleFloor();
|
m_cachedFirstVisibleFloor = getFirstVisibleFloor();
|
||||||
int lastFloor = getLastVisibleFloor();
|
m_cachedLastVisibleFloor = getLastVisibleFloor();
|
||||||
|
|
||||||
if(lastFloor < firstFloor)
|
if(m_cachedLastVisibleFloor < m_cachedFirstVisibleFloor)
|
||||||
lastFloor = firstFloor;
|
m_cachedLastVisibleFloor = m_cachedFirstVisibleFloor;
|
||||||
|
|
||||||
m_cachedFirstVisibleFloor = firstFloor;
|
m_cachedFloorVisibleCreatures.clear();
|
||||||
m_cachedLastVisibleFloor = lastFloor;
|
m_cachedVisibleTiles.clear();
|
||||||
|
|
||||||
|
m_mustCleanFramebuffer = true;
|
||||||
|
m_mustDrawVisibleTilesCache = true;
|
||||||
|
m_mustUpdateVisibleTilesCache = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// there is no tile to render on invalid positions
|
||||||
Position cameraPosition = getCameraPosition();
|
Position cameraPosition = getCameraPosition();
|
||||||
|
if(!cameraPosition.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
bool stop = false;
|
||||||
|
|
||||||
// clear current visible tiles cache
|
// clear current visible tiles cache
|
||||||
m_cachedVisibleTiles.clear();
|
m_cachedVisibleTiles.clear();
|
||||||
m_cachedFloorVisibleCreatures.clear();
|
m_mustDrawVisibleTilesCache = true;
|
||||||
|
|
||||||
// there is no tile to render on invalid positions
|
|
||||||
if(!cameraPosition.isValid())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// cache visible tiles in draw order
|
// cache visible tiles in draw order
|
||||||
// draw from last floor (the lower) to first floor (the higher)
|
// draw from last floor (the lower) to first floor (the higher)
|
||||||
for(int iz = m_cachedLastVisibleFloor; iz >= m_cachedFirstVisibleFloor; --iz) {
|
for(int iz = m_cachedLastVisibleFloor; iz >= m_cachedFirstVisibleFloor && !stop; --iz) {
|
||||||
// draw tiles like linus pauling's rule order
|
// draw tiles like linus pauling's rule order
|
||||||
const int numDiagonals = m_drawDimension.width() + m_drawDimension.height() - 1;
|
const int numDiagonals = m_drawDimension.width() + m_drawDimension.height() - 1;
|
||||||
for(int diagonal = 0; diagonal < numDiagonals; ++diagonal) {
|
for(int diagonal = 0; diagonal < numDiagonals && !stop; ++diagonal) {
|
||||||
// loop through / diagonal tiles
|
// loop through / diagonal tiles
|
||||||
for(int ix = std::min(diagonal, m_drawDimension.width() - 1), iy = std::max(diagonal - m_drawDimension.width() + 1, 0); ix >= 0 && iy < m_drawDimension.height(); --ix, ++iy) {
|
for(int ix = std::min(diagonal, m_drawDimension.width() - 1), iy = std::max(diagonal - m_drawDimension.width() + 1, 0); ix >= 0 && iy < m_drawDimension.height() && !stop; --ix, ++iy) {
|
||||||
|
// only start really looking tiles in the desired start
|
||||||
|
if(count < start) {
|
||||||
|
count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// avoid rendering too much tiles at once on far views
|
||||||
|
if(count - start + 1 > MAX_TILE_UPDATES && m_viewRange >= FAR_VIEW) {
|
||||||
|
stop = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// position on current floor
|
// position on current floor
|
||||||
|
//TODO: check position limits
|
||||||
Position tilePos = cameraPosition.translated(ix - m_virtualCenterOffset.x, iy - m_virtualCenterOffset.y);
|
Position tilePos = cameraPosition.translated(ix - m_virtualCenterOffset.x, iy - m_virtualCenterOffset.y);
|
||||||
// adjust tilePos to the wanted floor
|
// adjust tilePos to the wanted floor
|
||||||
tilePos.coveredUp(cameraPosition.z - iz);
|
tilePos.coveredUp(cameraPosition.z - iz);
|
||||||
if(const TilePtr& tile = g_map.getTile(tilePos)) {
|
if(const TilePtr& tile = g_map.getTile(tilePos)) {
|
||||||
// skip tiles that have nothing
|
// skip tiles that have nothing
|
||||||
if(tile->getThingCount() == 0)
|
if(tile->isEmpty())
|
||||||
continue;
|
continue;
|
||||||
// skip tiles that are completely behind another tile
|
// skip tiles that are completely behind another tile
|
||||||
if(g_map.isCompletelyCovered(tilePos, firstFloor))
|
if(g_map.isCompletelyCovered(tilePos, m_cachedLastVisibleFloor))
|
||||||
continue;
|
continue;
|
||||||
m_cachedVisibleTiles.push_back(tile);
|
m_cachedVisibleTiles.push_back(tile);
|
||||||
}
|
}
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
for(int range=0; range <= m_drawDimension.width() || range <= m_drawDimension.height(); ++range) {
|
||||||
|
for(int ix=0;ix<=range;++ix) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(stop) {
|
||||||
|
// schedule next update continuation
|
||||||
|
m_updateTilesCacheEvent = g_dispatcher.addEvent(std::bind(&MapView::updateVisibleTilesCache, asMapView(), count));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(start == 0)
|
||||||
m_cachedFloorVisibleCreatures = g_map.getSpectators(cameraPosition, false);
|
m_cachedFloorVisibleCreatures = g_map.getSpectators(cameraPosition, false);
|
||||||
|
|
||||||
m_mustUpdateVisibleTilesCache = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MapView::recalculateTileSize()
|
|
||||||
{
|
|
||||||
int possiblesTileSizes[] = {32,16,8,4,2,1};
|
|
||||||
|
|
||||||
int foundSize = 0;
|
|
||||||
for(int candidateTileSize : possiblesTileSizes) {
|
|
||||||
Size candidateFramebufferSize = m_drawDimension * candidateTileSize;
|
|
||||||
|
|
||||||
// found a valid size
|
|
||||||
if(candidateFramebufferSize.width() <= m_framebuffer->getSize().width() && candidateFramebufferSize.height() <= m_framebuffer->getSize().height()) {
|
|
||||||
foundSize = candidateTileSize;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(foundSize > 0);
|
|
||||||
m_tileSize = foundSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView::onTileUpdate(const Position& pos)
|
void MapView::onTileUpdate(const Position& pos)
|
||||||
{
|
{
|
||||||
|
//if(m_viewRange == NEAR_VIEW)
|
||||||
requestVisibleTilesCacheUpdate();
|
requestVisibleTilesCacheUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,15 +291,71 @@ void MapView::setVisibleDimension(const Size& visibleDimension)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(visibleDimension.width() <= 3 || visibleDimension.height() <= 3) {
|
if(visibleDimension.width() <= 3 || visibleDimension.height() <= 3) {
|
||||||
logTraceError("cannot render less than 3x3 tiles");
|
logTraceError("reach max zoom in");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_visibleDimension = visibleDimension;
|
int possiblesTileSizes[] = {32,16,8,4,2,1};
|
||||||
m_drawDimension = visibleDimension + Size(3,3);
|
int tileSize = 0;
|
||||||
m_virtualCenterOffset = (m_drawDimension/2 - Size(1,1)).toPoint();
|
Size drawDimension = visibleDimension + Size(3,3);
|
||||||
recalculateTileSize();
|
for(int candidateTileSize : possiblesTileSizes) {
|
||||||
|
Size candidateDrawSize = drawDimension * candidateTileSize;
|
||||||
|
|
||||||
|
// found a valid size
|
||||||
|
if(candidateDrawSize <= m_framebuffer->getSize()) {
|
||||||
|
tileSize = candidateTileSize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tileSize == 0) {
|
||||||
|
logTraceError("reached max zoom out");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tileSize != m_tileSize) {
|
||||||
|
dump << "tile size =" << tileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point virtualCenterOffset = (drawDimension/2 - Size(1,1)).toPoint();
|
||||||
|
|
||||||
|
ViewRange viewRange;
|
||||||
|
if(visibleDimension.area() <= NEAR_VIEW_AREA)
|
||||||
|
viewRange = NEAR_VIEW;
|
||||||
|
else if(visibleDimension.area() <= MID_VIEW_AREA)
|
||||||
|
viewRange = MID_VIEW;
|
||||||
|
else if(visibleDimension.area() <= FAR_VIEW_AREA)
|
||||||
|
viewRange = FAR_VIEW;
|
||||||
|
else
|
||||||
|
viewRange = HUGE_VIEW;
|
||||||
|
|
||||||
|
dump << visibleDimension;
|
||||||
|
if(m_viewRange != viewRange) {
|
||||||
|
if(viewRange == NEAR_VIEW) dump << "near view";
|
||||||
|
else if(viewRange == MID_VIEW) dump << "mid view";
|
||||||
|
else if(viewRange == FAR_VIEW) dump << "far view";
|
||||||
|
else if(viewRange == HUGE_VIEW) dump << "huge view";
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw actually more than what is needed to avoid massive recalculations on far views
|
||||||
|
if(viewRange >= FAR_VIEW) {
|
||||||
|
Size oldDimension = drawDimension;
|
||||||
|
drawDimension = (m_framebuffer->getSize() / tileSize);
|
||||||
|
virtualCenterOffset += (drawDimension - oldDimension).toPoint() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mustUpdate = (m_drawDimension != drawDimension ||
|
||||||
|
m_viewRange != viewRange ||
|
||||||
|
m_virtualCenterOffset != virtualCenterOffset ||
|
||||||
|
m_tileSize != tileSize);
|
||||||
|
|
||||||
|
m_visibleDimension = visibleDimension;
|
||||||
|
m_drawDimension = drawDimension;
|
||||||
|
m_tileSize = tileSize;
|
||||||
|
m_viewRange = viewRange;
|
||||||
|
m_virtualCenterOffset = virtualCenterOffset;
|
||||||
|
|
||||||
|
if(mustUpdate)
|
||||||
requestVisibleTilesCacheUpdate();
|
requestVisibleTilesCacheUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,7 +368,7 @@ int MapView::getFirstVisibleFloor()
|
||||||
Position cameraPosition = getCameraPosition();
|
Position cameraPosition = getCameraPosition();
|
||||||
|
|
||||||
// avoid rendering multile floors on far views
|
// avoid rendering multile floors on far views
|
||||||
if(!isNearView() && !isMidView())
|
if(m_viewRange >= FAR_VIEW)
|
||||||
return cameraPosition.z;
|
return cameraPosition.z;
|
||||||
|
|
||||||
// if nothing is limiting the view, the first visible floor is 0
|
// if nothing is limiting the view, the first visible floor is 0
|
||||||
|
@ -324,9 +402,6 @@ int MapView::getFirstVisibleFloor()
|
||||||
firstFloor = coveredPos.z + 1;
|
firstFloor = coveredPos.z + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(upperPos.z == 0)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,7 +415,7 @@ int MapView::getLastVisibleFloor()
|
||||||
Position cameraPosition = getCameraPosition();
|
Position cameraPosition = getCameraPosition();
|
||||||
|
|
||||||
// avoid rendering multile floors on far views
|
// avoid rendering multile floors on far views
|
||||||
if(!isNearView() && !isMidView())
|
if(m_viewRange >= FAR_VIEW)
|
||||||
return cameraPosition.z;
|
return cameraPosition.z;
|
||||||
|
|
||||||
// view only underground floors when below sea level
|
// view only underground floors when below sea level
|
||||||
|
|
|
@ -26,14 +26,28 @@
|
||||||
#include "declarations.h"
|
#include "declarations.h"
|
||||||
#include <framework/graphics/declarations.h>
|
#include <framework/graphics/declarations.h>
|
||||||
#include <framework/luascript/luaobject.h>
|
#include <framework/luascript/luaobject.h>
|
||||||
|
#include <framework/core/declarations.h>
|
||||||
|
|
||||||
class MapView : public LuaObject
|
class MapView : public LuaObject
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
DEFAULT_FRAMBUFFER_SIZE = 3840,
|
// 3840x2160 => 1080p optimized
|
||||||
NEAR_VIEW_AREA = 64*64,
|
// 2560x1440 => 720p optimized
|
||||||
MID_VIEW_AREA = 128*128,
|
// 1728x972 => 480p optimized
|
||||||
FAR_VIEW_AREA = 256*256
|
DEFAULT_FRAMBUFFER_WIDTH = 3840,
|
||||||
|
DEFAULT_FRAMBUFFER_HEIGHT = 2160,
|
||||||
|
|
||||||
|
NEAR_VIEW_AREA = 48*48,
|
||||||
|
MID_VIEW_AREA = 96*96,
|
||||||
|
FAR_VIEW_AREA = 384*384,
|
||||||
|
MAX_TILE_UPDATES = NEAR_VIEW_AREA*7
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ViewRange {
|
||||||
|
NEAR_VIEW,
|
||||||
|
MID_VIEW,
|
||||||
|
FAR_VIEW,
|
||||||
|
HUGE_VIEW
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -41,8 +55,7 @@ public:
|
||||||
void draw(const Rect& rect);
|
void draw(const Rect& rect);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void recalculateTileSize();
|
void updateVisibleTilesCache(int start = 0);
|
||||||
bool updateVisibleTilesCache();
|
|
||||||
void requestVisibleTilesCacheUpdate() { m_mustUpdateVisibleTilesCache = true; }
|
void requestVisibleTilesCacheUpdate() { m_mustUpdateVisibleTilesCache = true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -71,10 +84,7 @@ public:
|
||||||
Size getVisibleSize() { return m_visibleDimension * m_tileSize; }
|
Size getVisibleSize() { return m_visibleDimension * m_tileSize; }
|
||||||
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
CreaturePtr getFollowingCreature() { return m_followingCreature; }
|
||||||
|
|
||||||
bool isNearView() { return m_drawDimension.area() <= NEAR_VIEW_AREA; }
|
bool getViewRange() { return m_viewRange; }
|
||||||
bool isMidView() { return m_drawDimension.area() > NEAR_VIEW_AREA && m_drawDimension.area() <= MID_VIEW_AREA; }
|
|
||||||
bool isFarView() { return m_drawDimension.area() > MID_VIEW_AREA && m_drawDimension.area() <= FAR_VIEW_AREA; }
|
|
||||||
bool isHugeFarView() { return m_drawDimension.area() > FAR_VIEW_AREA; }
|
|
||||||
bool isAnimated() { return m_animated; }
|
bool isAnimated() { return m_animated; }
|
||||||
|
|
||||||
Point transformPositionTo2D(const Position& position);
|
Point transformPositionTo2D(const Position& position);
|
||||||
|
@ -91,13 +101,18 @@ private:
|
||||||
Size m_visibleDimension;
|
Size m_visibleDimension;
|
||||||
Point m_virtualCenterOffset;
|
Point m_virtualCenterOffset;
|
||||||
Position m_customCameraPosition;
|
Position m_customCameraPosition;
|
||||||
|
Position m_framebufferCenterPosition;
|
||||||
Boolean<true> m_mustUpdateVisibleTilesCache;
|
Boolean<true> m_mustUpdateVisibleTilesCache;
|
||||||
|
Boolean<true> m_mustDrawVisibleTilesCache;
|
||||||
|
Boolean<true> m_mustCleanFramebuffer;
|
||||||
Boolean<true> m_animated;
|
Boolean<true> m_animated;
|
||||||
std::vector<TilePtr> m_cachedVisibleTiles;
|
std::vector<TilePtr> m_cachedVisibleTiles;
|
||||||
std::vector<CreaturePtr> m_cachedFloorVisibleCreatures;
|
std::vector<CreaturePtr> m_cachedFloorVisibleCreatures;
|
||||||
|
EventPtr m_updateTilesCacheEvent;
|
||||||
CreaturePtr m_followingCreature;
|
CreaturePtr m_followingCreature;
|
||||||
FrameBufferPtr m_framebuffer;
|
FrameBufferPtr m_framebuffer;
|
||||||
PainterShaderProgramPtr m_shaderProgram;
|
PainterShaderProgramPtr m_shaderProgram;
|
||||||
|
ViewRange m_viewRange;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -40,6 +40,14 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
|
||||||
{
|
{
|
||||||
int drawElevation = 0;
|
int drawElevation = 0;
|
||||||
|
|
||||||
|
// optimization far far views
|
||||||
|
if(drawFlags == Otc::DrawGround) {
|
||||||
|
const ThingPtr& thing = m_things.front();
|
||||||
|
if(thing)
|
||||||
|
thing->draw(dest, scaleFactor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// first bottom items
|
// first bottom items
|
||||||
if(drawFlags & Otc::DrawGround || drawFlags & Otc::DrawWalls) {
|
if(drawFlags & Otc::DrawGround || drawFlags & Otc::DrawWalls) {
|
||||||
for(const ThingPtr& thing : m_things) {
|
for(const ThingPtr& thing : m_things) {
|
||||||
|
|
Loading…
Reference in New Issue