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:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user