summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbjarni <bjarni@openttd.org>2006-10-05 12:59:28 +0000
committerbjarni <bjarni@openttd.org>2006-10-05 12:59:28 +0000
commitea075f78e04cc5675e890f82e181276ebc6b6f00 (patch)
tree4a3d21fb89f88716ad9e908b35bbfc8df30e3ed2
parenta9478f810cb260c5f180ece9e38b2d6b4bbc94fe (diff)
downloadopenttd-ea075f78e04cc5675e890f82e181276ebc6b6f00.tar.xz
(svn r6651) -Coding feature: added the windowevent WE_INVALIDATE_DATA
This gives the ability to invalidate some window data and recalculate as needed instead of doing it for each WE_PAINT This event is called right away when using InvalidateWindowData(), so it may be a good idea to set a bool or similar in the window or similar and then act on that bool in WE_PAINT instead of doing a lot of stuff in WE_INVALIDATE_DATA as it might be called more than once before WE_PAINT is called InvalidateWindowData() will not automatically repaint the window, so if you want to repaint it as well, you need to mark it dirty as well. Made the depot windows use WE_INVALIDATE_DATA to set when to generate the engine and wagon lists instead of at each redraw It makes no sense to regenerate the list when say using the scrollbar if we know that no vehicle have entered or left the list NOTE: currently there is a piece of code to generate the list when it's not needed and compare it to the stored list and assert if they mismatch This check is somewhat slow and kills the whole idea of WE_INVALIDATE_DATA, so it's a short lived one to verify that InvalidateWindowData() is used everywhere where it's needed
-rw-r--r--aircraft_cmd.c2
-rw-r--r--depot_gui.c43
-rw-r--r--rail_cmd.c1
-rw-r--r--roadveh_cmd.c2
-rw-r--r--ship_cmd.c2
-rw-r--r--train_cmd.c24
-rw-r--r--vehicle.c9
-rw-r--r--window.c8
-rw-r--r--window.h3
9 files changed, 80 insertions, 14 deletions
diff --git a/aircraft_cmd.c b/aircraft_cmd.c
index 70336c0da..6a1840aee 100644
--- a/aircraft_cmd.c
+++ b/aircraft_cmd.c
@@ -399,6 +399,7 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
}
GetPlayer(_current_player)->num_engines[p1]++;
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
@@ -1432,6 +1433,7 @@ static void AircraftLeaveHangar(Vehicle *v)
VehicleServiceInDepot(v);
SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindowClasses(WC_AIRCRAFT_LIST);
}
diff --git a/depot_gui.c b/depot_gui.c
index d4dab78af..bf3472509 100644
--- a/depot_gui.c
+++ b/depot_gui.c
@@ -618,18 +618,43 @@ static void DepotWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_CREATE:
- WP(w, depot_d).vehicle_list = NULL;
- WP(w, depot_d).wagon_list = NULL;
- WP(w, depot_d).engine_count = 0;
- WP(w, depot_d).wagon_count = 0;
+ WP(w, depot_d).vehicle_list = NULL;
+ WP(w, depot_d).wagon_list = NULL;
+ WP(w, depot_d).engine_count = 0;
+ WP(w, depot_d).wagon_count = 0;
+ WP(w, depot_d).generate_list = true;
+ break;
+
+ case WE_INVALIDATE_DATA:
+ WP(w, depot_d).generate_list = true;
break;
case WE_PAINT:
- /* Generate the vehicle list
- * It's ok to use the wagon pointers for non-trains as they will be ignored */
- BuildDepotVehicleList(WP(w, depot_d).type, w->window_number,
- &WP(w, depot_d).vehicle_list, &WP(w, depot_d).engine_list_length, &WP(w, depot_d).engine_count,
- &WP(w, depot_d).wagon_list, &WP(w, depot_d).wagon_list_length, &WP(w, depot_d).wagon_count);
+ if (WP(w, depot_d).generate_list) {
+ /* Generate the vehicle list
+ * It's ok to use the wagon pointers for non-trains as they will be ignored */
+ BuildDepotVehicleList(WP(w, depot_d).type, w->window_number,
+ &WP(w, depot_d).vehicle_list, &WP(w, depot_d).engine_list_length, &WP(w, depot_d).engine_count,
+ &WP(w, depot_d).wagon_list, &WP(w, depot_d).wagon_list_length, &WP(w, depot_d).wagon_count);
+ WP(w, depot_d).generate_list = false;
+#ifndef NDEBUG
+ } else {
+ /* Here we got a piece of code, that only checks if we got a different number of vehicles in the depot list and the number of vehicles actually being in the depot.
+ * IF they aren't the same, then WE_INVALIDATE_DATA should have been called somewhere, but it wasn't and we got a bug
+ * Since this is a time consuming check and not nice to memory fragmentation, it may not stay for long, but it's a good way to check this
+ * We can turn it on/off by switching between #ifndef NDEBUG and #if 0 */
+ Vehicle **engines = NULL, **wagons = NULL;
+ uint16 engine_count = 0, engine_length = 0;
+ uint16 wagon_count = 0, wagon_length = 0;
+ BuildDepotVehicleList(WP(w, depot_d).type, w->window_number, &engines, &engine_length, &engine_count,
+ &wagons, &wagon_length, &wagon_count);
+
+ assert(engine_count == WP(w, depot_d).engine_count);
+ assert(wagon_count == WP(w, depot_d).wagon_count);
+ free((void*)engines);
+ free((void*)wagons);
+#endif
+ }
DrawDepotWindow(w);
break;
diff --git a/rail_cmd.c b/rail_cmd.c
index 206b9cbad..51b3a979b 100644
--- a/rail_cmd.c
+++ b/rail_cmd.c
@@ -2005,6 +2005,7 @@ static uint32 VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y)
v->u.rail.track = 0x80,
v->vehstatus |= VS_HIDDEN; /* hide it */
v->direction = ReverseDir(v->direction);
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
if (v->next == NULL)
VehicleEnterDepot(v);
v->tile = tile;
diff --git a/roadveh_cmd.c b/roadveh_cmd.c
index f6817de62..a5064b8ff 100644
--- a/roadveh_cmd.c
+++ b/roadveh_cmd.c
@@ -194,6 +194,7 @@ int32 CmdBuildRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
VehiclePositionChanged(v);
GetPlayer(_current_player)->num_engines[p1]++;
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
@@ -1305,6 +1306,7 @@ static void RoadVehController(Vehicle *v)
UpdateRoadVehDeltaXY(v);
SetRoadVehPosition(v,x,y);
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
return;
}
diff --git a/ship_cmd.c b/ship_cmd.c
index 857e1d385..2580ef2cf 100644
--- a/ship_cmd.c
+++ b/ship_cmd.c
@@ -358,6 +358,7 @@ static void CheckShipLeaveDepot(Vehicle *v)
PlayShipSound(v);
VehicleServiceInDepot(v);
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindowClasses(WC_SHIPS_LIST);
}
@@ -882,6 +883,7 @@ int32 CmdBuildShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
VehiclePositionChanged(v);
GetPlayer(_current_player)->num_engines[p1]++;
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
diff --git a/train_cmd.c b/train_cmd.c
index c0727abd6..841d0ffdf 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -615,6 +615,7 @@ static int32 CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 flags)
u->next = v;
} else {
SetFreeWagon(v);
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
}
v->cargo_type = rvi->cargo_type;
@@ -818,6 +819,7 @@ int32 CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
}
GetPlayer(_current_player)->num_engines[p1]++;
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindow(WC_VEHICLE_DEPOT, tile);
RebuildVehicleLists();
InvalidateWindow(WC_COMPANY, v->owner);
@@ -1122,6 +1124,7 @@ int32 CmdMoveRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
while (GetNextVehicle(v) != src) v = GetNextVehicle(v);
GetLastEnginePart(v)->next = NULL;
} else {
+ InvalidateWindowData(WC_VEHICLE_DEPOT, src_head->tile); // We removed a line
src_head = NULL;
}
} else {
@@ -1133,6 +1136,9 @@ int32 CmdMoveRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
}
if (dst == NULL) {
+ /* We make a new line in the depot, so we know already that we invalidate the window data */
+ InvalidateWindowData(WC_VEHICLE_DEPOT, src_head->tile);
+
// move the train to an empty line. for locomotives, we set the type to TS_Front. for wagons, 4.
if (IsTrainEngine(src)) {
if (!IsFrontEngine(src)) {
@@ -1152,9 +1158,12 @@ int32 CmdMoveRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
DeleteVehicleOrders(src);
}
- ClearFrontEngine(src);
- ClearFreeWagon(src);
- src->unitnumber = 0; // doesn't occupy a unitnumber anymore.
+ if (IsFrontEngine(src) || IsFreeWagon(src)) {
+ InvalidateWindowData(WC_VEHICLE_DEPOT, src->tile);
+ ClearFrontEngine(src);
+ ClearFreeWagon(src);
+ src->unitnumber = 0; // doesn't occupy a unitnumber anymore.
+ }
// link in the wagon(s) in the chain.
{
@@ -1640,8 +1649,10 @@ static void ReverseTrainDirection(Vehicle *v)
int l = 0, r = -1;
Vehicle *u;
- if (IsTileDepotType(v->tile, TRANSPORT_RAIL))
+ if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) {
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
+ }
/* Check if we were approaching a rail/road-crossing */
{
@@ -1672,8 +1683,10 @@ static void ReverseTrainDirection(Vehicle *v)
AdvanceWagons(v, false);
- if (IsTileDepotType(v->tile, TRANSPORT_RAIL))
+ if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) {
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
+ }
CLRBIT(v->u.rail.flags, VRF_REVERSING);
}
@@ -2166,6 +2179,7 @@ static bool CheckTrainStayInDepot(Vehicle *v)
VehiclePositionChanged(v);
UpdateSignalsOnSegment(v->tile, DirToDiagDir(v->direction));
UpdateTrainAcceleration(v);
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
return false;
diff --git a/vehicle.c b/vehicle.c
index a5bf75597..fd005da92 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -566,6 +566,10 @@ void DestroyVehicle(Vehicle *v)
DeleteName(v->string_id);
if (v->type == VEH_Road) ClearSlot(v);
+ if (v->type != VEH_Train || (v->type == VEH_Train && (IsFrontEngine(v) || IsFreeWagon(v)))) {
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
+ }
+
UpdateVehiclePosHash(v, INVALID_COORD, 0);
v->next_hash = INVALID_VEHICLE;
if (v->orders != NULL) DeleteVehicleOrders(v);
@@ -2476,6 +2480,11 @@ void VehicleEnterDepot(Vehicle *v)
default: NOT_REACHED();
}
+ if (v->type != VEH_Train) {
+ /* Trains update the vehicle list when the first unit enters the depot and calls VehicleEnterDepot() when the last unit enters.
+ * We only increase the number of vehicles when the first one enters, so we will not need to search for more vehicles in the depot */
+ InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
+ }
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
v->vehstatus |= VS_HIDDEN;
diff --git a/window.c b/window.c
index f2d659649..c4348c907 100644
--- a/window.c
+++ b/window.c
@@ -1563,6 +1563,14 @@ void InvalidateWindowClasses(WindowClass cls)
}
}
+void InvalidateWindowData(WindowClass cls, WindowNumber number)
+{
+ Window *w;
+
+ for (w = _windows; w != _last_window; w++) {
+ if (w->window_class == cls && w->window_number == number) CallWindowEventNP(w, WE_INVALIDATE_DATA);
+ }
+}
void CallWindowTickEvent(void)
{
diff --git a/window.h b/window.h
index 2236771ed..0ae31311e 100644
--- a/window.h
+++ b/window.h
@@ -99,6 +99,7 @@ enum WindowEventCodes {
WE_MESSAGE = 23,
WE_SCROLL = 24,
WE_MOUSEWHEEL = 25,
+ WE_INVALIDATE_DATA = 26,
};
struct WindowEvent {
@@ -397,6 +398,7 @@ assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(replaceveh_d));
typedef struct {
VehicleID sel;
byte type;
+ bool generate_list;
uint16 engine_list_length;
uint16 wagon_list_length;
uint16 engine_count;
@@ -748,6 +750,7 @@ int GetMenuItemIndex(const Window *w, int x, int y);
void InputLoop(void);
void UpdateWindows(void);
void InvalidateWidget(const Window *w, byte widget_index);
+void InvalidateWindowData(WindowClass cls, WindowNumber number);
void RaiseWindowButtons(Window *w);
void RelocateAllWindows(int neww, int newh);
int PositionMainToolbar(Window *w);