fix possible mapview crash
This commit is contained in:
		
							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) {
 | 
				
			||||||
 | 
					            z = cameraPosition.z;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // if nothing is limiting the view, the first visible floor is 0
 | 
				
			||||||
 | 
					            int firstFloor = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // avoid rendering multifloors in far views
 | 
					            // limits to underground floors while under sea level
 | 
				
			||||||
    if(m_viewRange >= FAR_VIEW)
 | 
					            if(cameraPosition.z > Otc::SEA_FLOOR)
 | 
				
			||||||
        return cameraPosition.z;
 | 
					                firstFloor = std::max(cameraPosition.z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::UNDERGROUND_FLOOR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // if nothing is limiting the view, the first visible floor is 0
 | 
					            // loop in 3x3 tiles around the camera
 | 
				
			||||||
    int firstFloor = 0;
 | 
					            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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // limits to underground floors while under sea level
 | 
					                    // process tiles that we can look through, e.g. windows, doors
 | 
				
			||||||
    if(cameraPosition.z > Otc::SEA_FLOOR)
 | 
					                    if((ix == 0 && iy == 0) || (/*(std::abs(ix) != std::abs(iy)) && */g_map.isLookPossible(pos))) {
 | 
				
			||||||
        firstFloor = std::max(cameraPosition.z - Otc::AWARE_UNDEGROUND_FLOOR_RANGE, (int)Otc::UNDERGROUND_FLOOR);
 | 
					                        Position upperPos = pos;
 | 
				
			||||||
 | 
					                        Position coveredPos = pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // loop in 3x3 tiles around the camera
 | 
					                        while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
 | 
				
			||||||
    for(int ix = -1; ix <= 1 && firstFloor < cameraPosition.z; ++ix) {
 | 
					                            // check tiles physically above
 | 
				
			||||||
        for(int iy = -1; iy <= 1 && firstFloor < cameraPosition.z; ++iy) {
 | 
					                            TilePtr tile = g_map.getTile(upperPos);
 | 
				
			||||||
            Position pos = cameraPosition.translated(ix, iy);
 | 
					                            if(tile && tile->limitsFloorsView()) {
 | 
				
			||||||
 | 
					                                firstFloor = upperPos.z + 1;
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // process tiles that we can look through, e.g. windows, doors
 | 
					                            // check tiles geometrically above
 | 
				
			||||||
            if((ix == 0 && iy == 0) || (/*(std::abs(ix) != std::abs(iy)) && */g_map.isLookPossible(pos))) {
 | 
					                            tile = g_map.getTile(coveredPos);
 | 
				
			||||||
                Position upperPos = pos;
 | 
					                            if(tile && tile->limitsFloorsView()) {
 | 
				
			||||||
                Position coveredPos = pos;
 | 
					                                firstFloor = coveredPos.z + 1;
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
                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()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    int z = 7;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Position cameraPosition = getCameraPosition();
 | 
					    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…
	
		Reference in New Issue