fix possible mapview crash

master
Eduardo Bart 12 years ago
parent 4743763d48
commit a4cef0d390

@ -10,6 +10,7 @@ end
function UIResizeBorder:onHoverChange(hovered) function UIResizeBorder:onHoverChange(hovered)
if hovered then if hovered then
if g_ui.getDraggingWidget() then return end
if self:getWidth() > self:getHeight() then if self:getWidth() > self:getHeight() then
Mouse.setVerticalCursor() Mouse.setVerticalCursor()
self.vertical = true self.vertical = true
@ -17,13 +18,15 @@ function UIResizeBorder:onHoverChange(hovered)
Mouse.setHorizontalCursor() Mouse.setHorizontalCursor()
self.vertical = false self.vertical = false
end end
self.hovering = true
if not self:isPressed() then if not self:isPressed() then
Effects.fadeIn(self) Effects.fadeIn(self)
end end
else else
if not self:isPressed() then if not self:isPressed() and self.hovering then
Mouse.restoreCursor() Mouse.restoreCursor()
Effects.fadeOut(self) Effects.fadeOut(self)
self.hovering = false
end end
end end
end end
@ -63,6 +66,7 @@ function UIResizeBorder:onMouseRelease(mousePos, mouseButton)
if not self:isHovered() then if not self:isHovered() then
Mouse.restoreCursor() Mouse.restoreCursor()
Effects.fadeOut(self) Effects.fadeOut(self)
self.hovering = false
end end
end end

@ -73,3 +73,6 @@ function UIMiniWindow:onMinimize()
end end
end end
function UIMiniWindow:getClassName()
return 'UIMiniWindow'
end

@ -8,8 +8,10 @@ function UIMiniWindowContainer.create()
end end
function UIMiniWindowContainer:onDrop(widget, mousePos) function UIMiniWindowContainer:onDrop(widget, mousePos)
widget:setParent(self) if widget:getClassName() == 'UIMiniWindow' then
return true widget:setParent(self)
return true
end
end end
function UIMiniWindowContainer:getClassName() function UIMiniWindowContainer:getClassName()

@ -45,19 +45,29 @@ void EventDispatcher::poll()
scheduledEvent->execute(); scheduledEvent->execute();
} }
// execute events list up to 3 times, this is needed because some events can schedule new events that would // execute events list up to 10 times, this is needed because some events can schedule new events that would
// change the UIWidgets layout, in this case we must execute these new events before we continue rendering, // change the UIWidgets layout, in this case we must execute these new events before we continue rendering,
// we can't loop until the event list is empty, because this could lead to infinite loops // we can't loop until the event list is empty, because this could lead to infinite loops
// if someone write a module with bad code // if someone write a module with bad code
for(int i=0;i<3;++i) { m_pollEventsSize = m_eventList.size();
m_pollEventsSize = m_eventList.size(); int count = 0;
if(m_pollEventsSize == 0) while(m_pollEventsSize > 0) {
if(count > 50) {
static bool reported = false;
if(!reported) {
logError("ATTENTION the event list is not getting empty, this could be caused by some bad code");
reported = true;
}
break; break;
}
for(int i=0;i<m_pollEventsSize;++i) { for(int i=0;i<m_pollEventsSize;++i) {
EventPtr event = m_eventList.front(); EventPtr event = m_eventList.front();
m_eventList.pop_front(); m_eventList.pop_front();
event->execute(); event->execute();
} }
m_pollEventsSize = m_eventList.size();
count++;
} }
} }

@ -193,8 +193,10 @@ void MapView::updateVisibleTilesCache(int start)
m_updateTilesCacheEvent = nullptr; m_updateTilesCacheEvent = nullptr;
} }
m_cachedFirstVisibleFloor = getFirstVisibleFloor(); m_cachedFirstVisibleFloor = calcFirstVisibleFloor();
m_cachedLastVisibleFloor = getLastVisibleFloor(); m_cachedLastVisibleFloor = calcLastVisibleFloor();
assert(m_cachedFirstVisibleFloor >= 0 && m_cachedLastVisibleFloor >= 0 &&
m_cachedFirstVisibleFloor <= Otc::MAX_Z && m_cachedLastVisibleFloor <= Otc::MAX_Z);
if(m_cachedLastVisibleFloor < m_cachedFirstVisibleFloor) if(m_cachedLastVisibleFloor < m_cachedFirstVisibleFloor)
m_cachedLastVisibleFloor = m_cachedFirstVisibleFloor; m_cachedLastVisibleFloor = m_cachedFirstVisibleFloor;
@ -461,70 +463,81 @@ void MapView::setVisibleDimension(const Size& visibleDimension)
requestVisibleTilesCacheUpdate(); requestVisibleTilesCacheUpdate();
} }
int MapView::getFirstVisibleFloor() int MapView::calcFirstVisibleFloor()
{ {
int z = 7;
// return forced first visible floor // return forced first visible floor
if(m_lockedFirstVisibleFloor != -1) if(m_lockedFirstVisibleFloor != -1) {
return m_lockedFirstVisibleFloor; z = m_lockedFirstVisibleFloor;
} else {
Position cameraPosition = getCameraPosition(); Position cameraPosition = getCameraPosition();
// avoid rendering multifloors in far views
if(m_viewRange >= FAR_VIEW)
return cameraPosition.z;
// if nothing is limiting the view, the first visible floor is 0
int firstFloor = 0;
// limits to underground floors while under sea level
if(cameraPosition.z > Otc::SEA_FLOOR)
firstFloor = std::max(cameraPosition.z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::UNDERGROUND_FLOOR);
// loop in 3x3 tiles around the camera
for(int ix = -1; ix <= 1 && firstFloor < cameraPosition.z; ++ix) {
for(int iy = -1; iy <= 1 && firstFloor < cameraPosition.z; ++iy) {
Position pos = cameraPosition.translated(ix, iy);
// process tiles that we can look through, e.g. windows, doors
if((ix == 0 && iy == 0) || (/*(std::abs(ix) != std::abs(iy)) && */g_map.isLookPossible(pos))) {
Position upperPos = pos;
Position coveredPos = pos;
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
// check tiles physically above
TilePtr tile = g_map.getTile(upperPos);
if(tile && tile->limitsFloorsView()) {
firstFloor = upperPos.z + 1;
break;
}
// check tiles geometrically above // avoid rendering multifloors in far views
tile = g_map.getTile(coveredPos); if(m_viewRange >= FAR_VIEW) {
if(tile && tile->limitsFloorsView()) { z = cameraPosition.z;
firstFloor = coveredPos.z + 1; } else {
break; // if nothing is limiting the view, the first visible floor is 0
int firstFloor = 0;
// limits to underground floors while under sea level
if(cameraPosition.z > Otc::SEA_FLOOR)
firstFloor = std::max(cameraPosition.z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::UNDERGROUND_FLOOR);
// loop in 3x3 tiles around the camera
for(int ix = -1; ix <= 1 && firstFloor < cameraPosition.z; ++ix) {
for(int iy = -1; iy <= 1 && firstFloor < cameraPosition.z; ++iy) {
Position pos = cameraPosition.translated(ix, iy);
// process tiles that we can look through, e.g. windows, doors
if((ix == 0 && iy == 0) || (/*(std::abs(ix) != std::abs(iy)) && */g_map.isLookPossible(pos))) {
Position upperPos = pos;
Position coveredPos = pos;
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
// check tiles physically above
TilePtr tile = g_map.getTile(upperPos);
if(tile && tile->limitsFloorsView()) {
firstFloor = upperPos.z + 1;
break;
}
// check tiles geometrically above
tile = g_map.getTile(coveredPos);
if(tile && tile->limitsFloorsView()) {
firstFloor = coveredPos.z + 1;
break;
}
}
} }
} }
} }
z = firstFloor;
} }
} }
return firstFloor; z = std::min(std::max(z, 0), (int)Otc::MAX_Z);
return z;
} }
int MapView::getLastVisibleFloor() int MapView::calcLastVisibleFloor()
{ {
Position cameraPosition = getCameraPosition(); int z = 7;
Position cameraPosition = getCameraPosition();
// avoid rendering multifloors in far views // avoid rendering multifloors in far views
if(m_viewRange >= FAR_VIEW) if(m_viewRange >= FAR_VIEW) {
return cameraPosition.z; 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;
}
// view only underground floors when below sea level z = std::min(std::max(z, 0), (int)Otc::MAX_Z);
if(cameraPosition.z > Otc::SEA_FLOOR) return z;
return std::min(cameraPosition.z + Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::MAX_Z);
else
return Otc::SEA_FLOOR;
} }
Position MapView::getCameraPosition() Position MapView::getCameraPosition()

@ -77,8 +77,8 @@ public:
bool isFollowingCreature() { return !!m_followingCreature; } bool isFollowingCreature() { return !!m_followingCreature; }
int getFirstVisibleFloor(); int calcFirstVisibleFloor();
int getLastVisibleFloor(); int calcLastVisibleFloor();
Position getCameraPosition(); Position getCameraPosition();
TilePtr getTile(const Point& mousePos, const Rect& mapRect); TilePtr getTile(const Point& mousePos, const Rect& mapRect);
Size getVisibleDimension() { return m_visibleDimension; } Size getVisibleDimension() { return m_visibleDimension; }

Loading…
Cancel
Save