# HG changeset patch # User smatz # Date 2010-09-06 14:14:09 # Node ID f8b5963745b72fe2fbf41c5c367a560b5daf8da2 # Parent 533aca9c35420546f5515c800197b07f21b23d48 (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 diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -486,12 +486,6 @@ struct DepotWindow : Window { 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 @@ struct DepotWindow : Window { 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 @@ struct DepotWindow : Window { 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 @@ struct DepotWindow : Window { } } - /** - * 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 @@ struct DepotWindow : Window { 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 @@ struct DepotWindow : Window { 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 @@ struct DepotWindow : Window { 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; diff --git a/src/group_gui.cpp b/src/group_gui.cpp --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -441,6 +441,7 @@ public: 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 @@ public: 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; diff --git a/src/order_gui.cpp b/src/order_gui.cpp --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -497,28 +497,6 @@ private: 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 @@ private: 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 @@ public: 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 @@ public: } } + 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 @@ public: } } - 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) { diff --git a/src/tilehighlight_type.h b/src/tilehighlight_type.h --- 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) */ diff --git a/src/vehicle.cpp b/src/vehicle.cpp --- 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? diff --git a/src/vehicle_func.h b/src/vehicle_func.h --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -162,7 +162,6 @@ CommandCost EnsureNoTrainOnTrackBits(Til 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; diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp --- 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 @@ public: 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 @@ void ShowVehicleViewWindow(const Vehicle AllocateWindowDescFront((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); diff --git a/src/vehicle_gui.h b/src/vehicle_gui.h --- a/src/vehicle_gui.h +++ b/src/vehicle_gui.h @@ -107,6 +107,7 @@ static inline WindowClass GetWindowClass /* 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); diff --git a/src/viewport.cpp b/src/viewport.cpp --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1805,14 +1805,19 @@ static bool CheckClickOnLandscape(const 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 @@ void UpdateTileSelection() _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; diff --git a/src/window.cpp b/src/window.cpp --- a/src/window.cpp +++ b/src/window.cpp @@ -2204,13 +2204,11 @@ static void MouseLoop(MouseClick click, 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(); } diff --git a/src/window_gui.h b/src/window_gui.h --- a/src/window_gui.h +++ b/src/window_gui.h @@ -636,6 +636,12 @@ public: 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() {}