changeset 16060:f814822627f3 draft

(svn r20753) -Feature [FS#3999]: make it possible to select vehicle to clone and vehicle to clone orders from directly from vehicle lists and depot window
author smatz <smatz@openttd.org>
date Mon, 06 Sep 2010 14:14:09 +0000
parents 081331e73323
children eea3c81622fe
files src/depot_gui.cpp src/group_gui.cpp src/order_gui.cpp src/tilehighlight_type.h src/vehicle.cpp src/vehicle_func.h src/vehicle_gui.cpp src/vehicle_gui.h src/viewport.cpp src/window.cpp src/window_gui.h
diffstat 11 files changed, 77 insertions(+), 111 deletions(-) [+]
line wrap: on
line diff
--- a/src/depot_gui.cpp
+++ b/src/depot_gui.cpp
@@ -486,12 +486,6 @@
 		const Vehicle *v = NULL;
 		DepotGUIAction mode = this->GetVehicleFromDepotWndPt(x, y, &v, &gdvp);
 
-		/* share / copy orders */
-		if (_thd.place_mode != HT_NONE && mode != MODE_ERROR) {
-			_place_clicked_vehicle = (this->type == VEH_TRAIN ? gdvp.head : v);
-			return;
-		}
-
 		if (this->type == VEH_TRAIN) v = gdvp.wagon;
 
 		switch (mode) {
@@ -499,6 +493,8 @@
 				return;
 
 			case MODE_DRAG_VEHICLE: { // start dragging of vehicle
+				if (v != NULL && VehicleClicked(v)) return;
+
 				VehicleID sel = this->sel;
 
 				if (this->type == VEH_TRAIN && sel != INVALID_VEHICLE) {
@@ -506,10 +502,10 @@
 					TrainDepotMoveVehicle(v, sel, gdvp.head);
 				} else if (v != NULL) {
 					int image = v->GetImage(DIR_W);
+					SetObjectToPlaceWnd(image, GetVehiclePalette(v), HT_DRAG, this);
 
 					this->sel = v->index;
 					this->SetDirty();
-					SetObjectToPlaceWnd(image, GetVehiclePalette(v), HT_DRAG, this);
 
 					switch (v->type) {
 						case VEH_TRAIN:
@@ -541,25 +537,6 @@
 		}
 	}
 
-	/**
-	 * Clones a vehicle
-	 * @param *v is the original vehicle to clone
-	 */
-	void HandleCloneVehClick(const Vehicle *v)
-	{
-		if (v == NULL || !IsCompanyBuildableVehicleType(v)) return;
-
-		if (!v->IsPrimaryVehicle()) {
-			v = v->First();
-			/* Do nothing when clicking on a train in depot with no loc attached */
-			if (v->type == VEH_TRAIN && !Train::From(v)->IsFrontEngine()) return;
-		}
-
-		DoCommandP(this->window_number, v->index, _ctrl_pressed ? 1 : 0, CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN + v->type), CcCloneVehicle);
-
-		ResetObjectToPlace();
-	}
-
 	/* Function to set up vehicle specific widgets (mainly sprites and strings).
 	 * Only use this if it's the same widget, that's used for more than one vehicle type and it needs different text/sprites
 	 * Vehicle specific text/sprites, that's in a widget, that's only shown for one vehicle type (like sell whole train) is set in the nested widget array
@@ -742,8 +719,7 @@
 						SPR_CURSOR_CLONE_SHIP, SPR_CURSOR_CLONE_AIRPLANE
 					};
 
-					_place_clicked_vehicle = NULL;
-					SetObjectToPlaceWnd(clone_icons[this->type], PAL_NONE, HT_RECT, this);
+					SetObjectToPlaceWnd(clone_icons[this->type], PAL_NONE, HT_VEHICLE, this);
 				} else {
 					ResetObjectToPlace();
 				}
@@ -860,11 +836,15 @@
 		return true;
 	}
 
-	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	/**
+	 * Clones a vehicle
+	 * @param v the original vehicle to clone
+	 */
+	virtual void OnVehicleSelect(const Vehicle *v)
 	{
-		const Vehicle *v = CheckMouseOverVehicle();
-
-		if (v != NULL) this->HandleCloneVehClick(v);
+		if (DoCommandP(this->window_number, v->index, _ctrl_pressed ? 1 : 0, CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN + v->type), CcCloneVehicle)) {
+			ResetObjectToPlace();
+		}
 	}
 
 	virtual void OnPlaceObjectAbort()
@@ -879,18 +859,6 @@
 		this->SetWidgetDirty(DEPOT_WIDGET_MATRIX);
 	};
 
-	/* check if a vehicle in a depot was clicked.. */
-	virtual void OnMouseLoop()
-	{
-		const Vehicle *v = _place_clicked_vehicle;
-
-		/* since OTTD checks all open depot windows, we will make sure that it triggers the one with a clicked clone button */
-		if (v != NULL && this->IsWidgetLowered(DEPOT_WIDGET_CLONE)) {
-			_place_clicked_vehicle = NULL;
-			this->HandleCloneVehClick(v);
-		}
-	}
-
 	virtual void OnMouseDrag(Point pt, int widget)
 	{
 		if (this->type != VEH_TRAIN || this->sel == INVALID_VEHICLE) return;
--- a/src/group_gui.cpp
+++ b/src/group_gui.cpp
@@ -441,6 +441,7 @@
 				if (id_v >= this->vehicles.Length()) return; // click out of list bound
 
 				const Vehicle *v = this->vehicles[id_v];
+				if (VehicleClicked(v)) break;
 
 				this->vehicle_sel = v->index;
 
@@ -531,7 +532,7 @@
 				if (id_v >= this->vehicles.Length()) return; // click out of list bound
 
 				const Vehicle *v = this->vehicles[id_v];
-				if (vindex == v->index) {
+				if (!VehicleClicked(v) && vindex == v->index) {
 					ShowVehicleViewWindow(v);
 				}
 				break;
--- a/src/order_gui.cpp
+++ b/src/order_gui.cpp
@@ -497,28 +497,6 @@
 		return (sel <= vehicle->GetNumOrders() && sel >= 0) ? sel : INVALID_ORDER;
 	}
 
-	bool HandleOrderVehClick(const Vehicle *u)
-	{
-		if (u->type != this->vehicle->type) return false;
-
-		if (!u->IsPrimaryVehicle()) {
-			u = u->First();
-			if (!u->IsPrimaryVehicle()) return false;
-		}
-
-		/* v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet
-		 * obviously if you press CTRL on a non-empty orders vehicle you know what you are doing */
-		if (this->vehicle->GetNumOrders() != 0 && _ctrl_pressed == 0) return false;
-
-		if (DoCommandP(this->vehicle->tile, this->vehicle->index | (_ctrl_pressed ? CO_SHARE : CO_COPY) << 30, u->index,
-				_ctrl_pressed ? CMD_CLONE_ORDER | CMD_MSG(STR_ERROR_CAN_T_SHARE_ORDER_LIST) : CMD_CLONE_ORDER | CMD_MSG(STR_ERROR_CAN_T_COPY_ORDER_LIST))) {
-			this->selected_order = -1;
-			ResetObjectToPlace();
-		}
-
-		return true;
-	}
-
 	/**
 	 * Handle the click on the goto button.
 	 * @param i Dummy parameter.
@@ -528,8 +506,7 @@
 		this->SetWidgetDirty(ORDER_WIDGET_GOTO);
 		this->ToggleWidgetLoweredState(ORDER_WIDGET_GOTO);
 		if (this->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
-			_place_clicked_vehicle = NULL;
-			SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, HT_RECT, this);
+			SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, HT_RECT | HT_VEHICLE, this);
 			this->goto_type = OPOS_GOTO;
 		} else {
 			ResetObjectToPlace();
@@ -1260,10 +1237,6 @@
 	virtual void OnPlaceObject(Point pt, TileIndex tile)
 	{
 		if (this->goto_type == OPOS_GOTO) {
-			/* check if we're clicking on a vehicle first.. clone orders in that case. */
-			const Vehicle *v = CheckMouseOverVehicle();
-			if (v != NULL && this->HandleOrderVehClick(v)) return;
-
 			const Order cmd = GetOrderCmdFromTile(this->vehicle, tile);
 			if (cmd.IsType(OT_NOTHING)) return;
 
@@ -1274,6 +1247,20 @@
 		}
 	}
 
+	virtual void OnVehicleSelect(const Vehicle *v)
+	{
+		/* v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet
+		 * obviously if you press CTRL on a non-empty orders vehicle you know what you are doing
+		 * TODO: give a warning message */
+		if (this->vehicle->GetNumOrders() != 0 && _ctrl_pressed == 0) return;
+
+		if (DoCommandP(this->vehicle->tile, this->vehicle->index | (_ctrl_pressed ? CO_SHARE : CO_COPY) << 30, v->index,
+				_ctrl_pressed ? CMD_CLONE_ORDER | CMD_MSG(STR_ERROR_CAN_T_SHARE_ORDER_LIST) : CMD_CLONE_ORDER | CMD_MSG(STR_ERROR_CAN_T_COPY_ORDER_LIST))) {
+			this->selected_order = -1;
+			ResetObjectToPlace();
+		}
+	}
+
 	virtual void OnPlaceObjectAbort()
 	{
 		if (this->goto_type == OPOS_CONDITIONAL) {
@@ -1301,23 +1288,6 @@
 		}
 	}
 
-	virtual void OnMouseLoop()
-	{
-		const Vehicle *v = _place_clicked_vehicle;
-		/*
-		 * Check if we clicked on a vehicle
-		 * and if the GOTO button of this window is pressed
-		 * This is because of all open order windows WE_MOUSELOOP is called
-		 * and if you have 3 windows open, and this check is not done
-		 * the order is copied to the last open window instead of the
-		 * one where GOTO is enabled
-		 */
-		if (v != NULL && this->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
-			_place_clicked_vehicle = NULL;
-			this->HandleOrderVehClick(v);
-		}
-	}
-
 	virtual void OnMouseDrag(Point pt, int widget)
 	{
 		if (this->selected_order != -1 && widget == ORDER_WIDGET_ORDER_LIST) {
--- a/src/tilehighlight_type.h
+++ b/src/tilehighlight_type.h
@@ -19,14 +19,15 @@
 
 /** Highlighting draw styles */
 enum HighLightStyle {
-	HT_NONE      = 0x00, ///< default
-	HT_RECT      = 0x10, ///< rectangle (stations, depots, ...)
-	HT_POINT     = 0x20, ///< point (lower land, raise land, level land, ...)
-	HT_SPECIAL   = 0x30, ///< special mode used for highlighting while dragging (and for tunnels/docks)
-	HT_DRAG      = 0x40, ///< dragging items in the depot windows
-	HT_LINE      = 0x08, ///< used for autorail highlighting (longer streches), lower bits: direction
-	HT_RAIL      = 0x80, ///< autorail (one piece), lower bits: direction
-	HT_DRAG_MASK = 0xF8, ///< masks the drag-type
+	HT_NONE      = 0x000, ///< default
+	HT_RECT      = 0x010, ///< rectangle (stations, depots, ...)
+	HT_POINT     = 0x020, ///< point (lower land, raise land, level land, ...)
+	HT_SPECIAL   = 0x030, ///< special mode used for highlighting while dragging (and for tunnels/docks)
+	HT_DRAG      = 0x040, ///< dragging items in the depot windows
+	HT_LINE      = 0x008, ///< used for autorail highlighting (longer streches), lower bits: direction
+	HT_RAIL      = 0x080, ///< autorail (one piece), lower bits: direction
+	HT_VEHICLE   = 0x100, ///< vehicle is accepted as target as well (bitmask)
+	HT_DRAG_MASK = 0x0F8, ///< masks the drag-type
 
 	/* lower bits (used with HT_LINE and HT_RAIL):
 	 * (see ASCII art in autorail.h for a visual interpretation) */
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -55,7 +55,6 @@
 #define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6))
 
 VehicleID _vehicle_id_ctr_day;
-const Vehicle *_place_clicked_vehicle;
 VehicleID _new_vehicle_id;
 uint16 _returned_refit_capacity;
 byte _age_cargo_skip_counter; ///< Skip aging of cargo?
--- a/src/vehicle_func.h
+++ b/src/vehicle_func.h
@@ -162,7 +162,6 @@
 void StopAllVehicles();
 
 extern VehicleID _vehicle_id_ctr_day;
-extern const Vehicle *_place_clicked_vehicle;
 extern VehicleID _new_vehicle_id;
 extern uint16 _returned_refit_capacity;
 extern byte _age_cargo_skip_counter;
--- a/src/vehicle_gui.cpp
+++ b/src/vehicle_gui.cpp
@@ -39,6 +39,7 @@
 #include "company_base.h"
 #include "engine_func.h"
 #include "station_base.h"
+#include "tilehighlight_func.h"
 
 #include "table/strings.h"
 
@@ -1269,7 +1270,7 @@
 				if (id_v >= this->vehicles.Length()) return; // click out of list bound
 
 				const Vehicle *v = this->vehicles[id_v];
-				ShowVehicleViewWindow(v);
+				if (!VehicleClicked(v)) ShowVehicleViewWindow(v);
 				break;
 			}
 
@@ -2344,6 +2345,23 @@
 	AllocateWindowDescFront<VehicleViewWindow>((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index);
 }
 
+/**
+ * Dispatch a "vehicle selected" event if any window waits for it.
+ * @param v selected vehicle;
+ * @return did any window accept vehicle selection?
+ */
+bool VehicleClicked(const Vehicle *v)
+{
+	assert(v != NULL);
+	if (!(_thd.place_mode & HT_VEHICLE)) return false;
+
+	v = v->First();
+	if (!v->IsPrimaryVehicle()) return false;
+
+	FindWindowById(_thd.window_class, _thd.window_number)->OnVehicleSelect(v);
+	return true;
+}
+
 void StopGlobalFollowVehicle(const Vehicle *v)
 {
 	Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
--- a/src/vehicle_gui.h
+++ b/src/vehicle_gui.h
@@ -107,6 +107,7 @@
 
 /* Unified window procedure */
 void ShowVehicleViewWindow(const Vehicle *v);
+bool VehicleClicked(const Vehicle *v);
 void StartStopVehicle(const Vehicle *v, bool texteffect);
 
 Vehicle *CheckClickOnVehicle(const struct ViewPort *vp, int x, int y);
--- a/src/viewport.cpp
+++ b/src/viewport.cpp
@@ -1805,14 +1805,19 @@
 
 bool HandleViewportClicked(const ViewPort *vp, int x, int y)
 {
-	const Vehicle *v;
+	const Vehicle *v = CheckClickOnVehicle(vp, x, y);
+
+	if (_thd.place_mode & HT_VEHICLE) {
+		if (v != NULL && VehicleClicked(v)) return true;
+	}
+
+	if (_thd.place_mode & HT_DRAG_MASK) return false;
 
 	if (CheckClickOnTown(vp, x, y)) return true;
 	if (CheckClickOnStation(vp, x, y)) return true;
 	if (CheckClickOnSign(vp, x, y)) return true;
 	CheckClickOnLandscape(vp, x, y);
 
-	v = CheckClickOnVehicle(vp, x, y);
 	if (v != NULL) {
 		DEBUG(misc, 2, "Vehicle %d (index %d) at %p", v->unitnumber, v->index, v);
 		if (IsCompanyBuildableVehicleType(v)) {
@@ -1971,7 +1976,7 @@
 			_thd.new_size.y = y2 - y1 + TILE_SIZE;
 			_thd.new_drawstyle = _thd.next_drawstyle;
 		}
-	} else if (_thd.place_mode != HT_NONE) {
+	} else if ((_thd.place_mode & HT_DRAG_MASK) != HT_NONE) {
 		Point pt = GetTileBelowCursor();
 		x1 = pt.x;
 		y1 = pt.y;
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -2204,13 +2204,11 @@
 					return;
 				}
 
-				if (_thd.place_mode == HT_NONE) {
-					if (!HandleViewportClicked(vp, x, y) &&
-							!(w->flags4 & WF_DISABLE_VP_SCROLL) &&
-							_settings_client.gui.left_mouse_btn_scrolling) {
-						_scrolling_viewport = true;
-						_cursor.fix_at = false;
-					}
+				if (!HandleViewportClicked(vp, x, y) &&
+						!(w->flags4 & WF_DISABLE_VP_SCROLL) &&
+						_settings_client.gui.left_mouse_btn_scrolling) {
+					_scrolling_viewport = true;
+					_cursor.fix_at = false;
 				} else {
 					PlaceObject();
 				}
--- a/src/window_gui.h
+++ b/src/window_gui.h
@@ -636,6 +636,12 @@
 	virtual void OnPlaceObject(Point pt, TileIndex tile) {}
 
 	/**
+	 * The user clicked on a vehicle while HT_VEHICLE has been set.
+	 * @param v clicked vehicle. It is guaranteed to be v->IsPrimaryVehicle() == true
+	 */
+	virtual void OnVehicleSelect(const struct Vehicle *v) {}
+
+	/**
 	 * The user cancelled a tile highlight mode that has been set.
 	 */
 	virtual void OnPlaceObjectAbort() {}