Fix redrawing/clearing of vehicle route lines.

Fix new route lines not being (fully) added in a timely manner.
Fix old lines not being (fully) removed until a scroll/zoom.
Fix the screen invalidation algorithm assuming that the terrain is
perfectly flat at at near sea level. (Use of MarkTileDirtyByTile to
clear lines which do not follow tile height contours).
This commit is contained in:
Jonathan G Rennison
2015-10-30 21:05:33 +00:00
parent 6e3b3c04de
commit 129e14d817
2 changed files with 88 additions and 8 deletions

View File

@@ -704,11 +704,12 @@ private:
/* When networking, move one order lower */ /* When networking, move one order lower */
int selected = this->selected_order + (int)_networking; int selected = this->selected_order + (int)_networking;
MarkAllRoutePathsDirty(this->vehicle);
MarkAllRouteStepsDirty(this); MarkAllRouteStepsDirty(this);
if (DoCommandP(this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), CMD_DELETE_ORDER | CMD_MSG(STR_ERROR_CAN_T_DELETE_THIS_ORDER))) { if (DoCommandP(this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), CMD_DELETE_ORDER | CMD_MSG(STR_ERROR_CAN_T_DELETE_THIS_ORDER))) {
this->selected_order = selected >= this->vehicle->GetNumOrders() ? -1 : selected; this->selected_order = selected >= this->vehicle->GetNumOrders() ? -1 : selected;
this->UpdateButtonState(); this->UpdateButtonState();
MarkAllRoutePathsDirty(this->vehicle);
MarkAllRouteStepsDirty(this);
} }
} }

View File

@@ -98,6 +98,7 @@
#include "gui.h" #include "gui.h"
#include <map> #include <map>
#include <vector>
#include "table/strings.h" #include "table/strings.h"
#include "table/string_colours.h" #include "table/string_colours.h"
@@ -197,6 +198,26 @@ uint _vp_route_step_height_middle = 0;
uint _vp_route_step_height_bottom = 0; uint _vp_route_step_height_bottom = 0;
SubSprite _vp_route_step_subsprite; SubSprite _vp_route_step_subsprite;
struct DrawnPathRouteTileLine {
TileIndex from_tile;
TileIndex to_tile;
bool operator==(const DrawnPathRouteTileLine &other) const
{
return this->from_tile == other.from_tile && this->to_tile == other.to_tile;
}
bool operator!=(const DrawnPathRouteTileLine &other) const
{
return !(*this == other);
}
};
std::vector<DrawnPathRouteTileLine> _vp_route_paths_drawn_dirty;
std::vector<DrawnPathRouteTileLine> _vp_route_paths_last_mark_dirty;
static void MarkRoutePathsDirty(const std::vector<DrawnPathRouteTileLine> &lines);
TileHighlightData _thd; TileHighlightData _thd;
static TileInfo *_cur_ti; static TileInfo *_cur_ti;
bool _draw_bounding_boxes = false; bool _draw_bounding_boxes = false;
@@ -1647,13 +1668,31 @@ static void ViewportMapDrawVehicleRoute(const ViewPort *vp)
{ {
Order *order; Order *order;
const Vehicle *veh = GetVehicleFromWindow(_focused_window); const Vehicle *veh = GetVehicleFromWindow(_focused_window);
if (!veh) return; if (!veh) {
if (!_vp_route_paths_drawn_dirty.empty()) {
// make sure we remove any leftover paths
MarkRoutePathsDirty(_vp_route_paths_drawn_dirty);
_vp_route_paths_drawn_dirty.clear();
DEBUG(misc, 1, "ViewportMapDrawVehicleRoute: redrawing dirty paths 0");
}
return;
}
switch (_settings_client.gui.show_vehicle_route) { switch (_settings_client.gui.show_vehicle_route) {
/* case 0: return; // No */ /* case 0: return; // No */
case 1: { // Simple case 1: { // Simple
TileIndex from_tile = GetLastValidOrderLocation(veh); TileIndex from_tile = GetLastValidOrderLocation(veh);
if (from_tile == INVALID_TILE) return; if (from_tile == INVALID_TILE) {
if (!_vp_route_paths_drawn_dirty.empty()) {
// make sure we remove any leftover paths
MarkRoutePathsDirty(_vp_route_paths_drawn_dirty);
_vp_route_paths_drawn_dirty.clear();
DEBUG(misc, 1, "ViewportMapDrawVehicleRoute: redrawing dirty paths 1");
}
return;
}
std::vector<DrawnPathRouteTileLine> drawn_paths;
DrawPixelInfo *old_dpi = _cur_dpi; DrawPixelInfo *old_dpi = _cur_dpi;
_cur_dpi = &_dpi_for_text; _cur_dpi = &_dpi_for_text;
@@ -1677,10 +1716,26 @@ static void ViewportMapDrawVehicleRoute(const ViewPort *vp)
} }
GfxDrawLine(from_x, from_y, to_x, to_y, (final_order == order) ? PC_WHITE : PC_YELLOW, line_width, _settings_client.gui.dash_level_of_route_lines); GfxDrawLine(from_x, from_y, to_x, to_y, (final_order == order) ? PC_WHITE : PC_YELLOW, line_width, _settings_client.gui.dash_level_of_route_lines);
DrawnPathRouteTileLine path = { from_tile, to_tile };
drawn_paths.push_back(path);
const OrderType ot = order->GetType(); const OrderType ot = order->GetType();
if (ot == OT_GOTO_STATION || ot == OT_GOTO_DEPOT || ot == OT_GOTO_WAYPOINT || ot == OT_IMPLICIT) from_tile = to_tile; if (ot == OT_GOTO_STATION || ot == OT_GOTO_DEPOT || ot == OT_GOTO_WAYPOINT || ot == OT_IMPLICIT) from_tile = to_tile;
} }
if (!_vp_route_paths_drawn_dirty.empty() && _vp_route_paths_drawn_dirty != drawn_paths) {
// make sure we remove any leftover paths
MarkRoutePathsDirty(_vp_route_paths_drawn_dirty);
DEBUG(misc, 1, "ViewportMapDrawVehicleRoute: redrawing dirty paths 2");
}
if (_vp_route_paths_last_mark_dirty != drawn_paths) {
// make sure we're not drawing a partial path
MarkRoutePathsDirty(drawn_paths);
DEBUG(misc, 1, "ViewportMapDrawVehicleRoute: redrawing dirty paths 3");
}
_vp_route_paths_drawn_dirty.swap(drawn_paths); // move
_cur_dpi = old_dpi; _cur_dpi = old_dpi;
break; break;
} }
@@ -2757,10 +2812,15 @@ void MarkTileLineDirty(const TileIndex from_tile, const TileIndex to_tile)
assert(from_tile != INVALID_TILE); assert(from_tile != INVALID_TILE);
assert(to_tile != INVALID_TILE); assert(to_tile != INVALID_TILE);
int x1 = TileX(from_tile); const Point from_pt = RemapCoords2(TileX(from_tile) * TILE_SIZE + TILE_SIZE / 2, TileY(from_tile) * TILE_SIZE + TILE_SIZE / 2);
int y1 = TileY(from_tile); const Point to_pt = RemapCoords2(TileX(to_tile) * TILE_SIZE + TILE_SIZE / 2, TileY(to_tile) * TILE_SIZE + TILE_SIZE / 2);
const int x2 = TileX(to_tile);
const int y2 = TileY(to_tile); const int block_radius = 20;
int x1 = from_pt.x / block_radius;
int y1 = from_pt.y / block_radius;
const int x2 = to_pt.x / block_radius;
const int y2 = to_pt.y / block_radius;
/* http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Simplification */ /* http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Simplification */
const int dx = abs(x2 - x1); const int dx = abs(x2 - x1);
@@ -2769,7 +2829,13 @@ void MarkTileLineDirty(const TileIndex from_tile, const TileIndex to_tile)
const int sy = (y1 < y2) ? 1 : -1; const int sy = (y1 < y2) ? 1 : -1;
int err = dx - dy; int err = dx - dy;
for (;;) { for (;;) {
MarkTileDirtyByTile(TileXY(x1, y1)); MarkAllViewportsDirty(
(x1 - 1) * block_radius,
(y1 - 1) * block_radius,
(x1 + 1) * block_radius,
(y1 + 1) * block_radius,
ZOOM_LVL_END
);
if (x1 == x2 && y1 == y2) break; if (x1 == x2 && y1 == y2) break;
const int e2 = 2 * err; const int e2 = 2 * err;
if (e2 > -dy) { if (e2 > -dy) {
@@ -2783,6 +2849,13 @@ void MarkTileLineDirty(const TileIndex from_tile, const TileIndex to_tile)
} }
} }
static void MarkRoutePathsDirty(const std::vector<DrawnPathRouteTileLine> &lines)
{
for (std::vector<DrawnPathRouteTileLine>::const_iterator it = lines.begin(); it != lines.end(); ++it) {
MarkTileLineDirty(it->from_tile, it->to_tile);
}
}
void MarkAllRoutePathsDirty(const Vehicle *veh) void MarkAllRoutePathsDirty(const Vehicle *veh)
{ {
Order *order; Order *order;
@@ -2792,6 +2865,9 @@ void MarkAllRoutePathsDirty(const Vehicle *veh)
return; return;
case 1: // Simple case 1: // Simple
MarkRoutePathsDirty(_vp_route_paths_drawn_dirty);
_vp_route_paths_drawn_dirty.clear();
std::vector<DrawnPathRouteTileLine> dirtied_paths;
from_tile = GetLastValidOrderLocation(veh); from_tile = GetLastValidOrderLocation(veh);
if (from_tile == INVALID_TILE) return; if (from_tile == INVALID_TILE) return;
FOR_VEHICLE_ORDERS(veh, order) { FOR_VEHICLE_ORDERS(veh, order) {
@@ -2800,8 +2876,11 @@ void MarkAllRoutePathsDirty(const Vehicle *veh)
if (to_tile == INVALID_TILE) continue; if (to_tile == INVALID_TILE) continue;
MarkTileLineDirty(from_tile, to_tile); MarkTileLineDirty(from_tile, to_tile);
const OrderType ot = order->GetType(); const OrderType ot = order->GetType();
DrawnPathRouteTileLine path = { from_tile, to_tile };
dirtied_paths.push_back(path);
if (ot == OT_GOTO_STATION || ot == OT_GOTO_DEPOT || ot == OT_GOTO_WAYPOINT || ot == OT_IMPLICIT) from_tile = to_tile; if (ot == OT_GOTO_STATION || ot == OT_GOTO_DEPOT || ot == OT_GOTO_WAYPOINT || ot == OT_IMPLICIT) from_tile = to_tile;
} }
_vp_route_paths_last_mark_dirty.swap(dirtied_paths);
break; break;
} }
} }