From d9a48a2b5e9e8d311806804258ba56742989c6fa Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 15 Feb 2016 00:24:02 +0000 Subject: [PATCH 1/9] TBTR: Raise clone buttons when vehicle pick aborted. --- src/tbtr_template_gui_create.cpp | 5 +++++ src/tbtr_template_gui_main.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/tbtr_template_gui_create.cpp b/src/tbtr_template_gui_create.cpp index 9e4cce687b..288d511da2 100644 --- a/src/tbtr_template_gui_create.cpp +++ b/src/tbtr_template_gui_create.cpp @@ -273,6 +273,11 @@ public: return true; } + virtual void OnPlaceObjectAbort() + { + this->RaiseButtons(); + } + virtual void DrawWidget(const Rect &r, int widget) const { switch(widget) { diff --git a/src/tbtr_template_gui_main.cpp b/src/tbtr_template_gui_main.cpp index afd63da94c..7f8e6d4f02 100644 --- a/src/tbtr_template_gui_main.cpp +++ b/src/tbtr_template_gui_main.cpp @@ -490,6 +490,11 @@ public: return true; } + virtual void OnPlaceObjectAbort() + { + this->RaiseButtons(); + } + virtual void OnDropdownSelect(int widget, int index) { RailType temp = (RailType) index; From 5850bcf699d48ae1d35f97b28de57ac1cf3705e1 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 15 Feb 2016 02:31:26 +0000 Subject: [PATCH 2/9] TBTR: Fix crash and issues when using a no longer available engine type. Show error messages when cloning a vehicle to a template or virtual vehicle fails. Handle failed clones gracefully. Bypass engine availability check when doing a template edit action. Show correct error message if template replacement fails for a non-money reason. --- src/command.cpp | 4 +-- src/lang/english.txt | 2 ++ src/tbtr_template_gui_create.cpp | 4 +-- src/tbtr_template_gui_main.cpp | 2 +- src/tbtr_template_vehicle_func.h | 2 +- src/train.h | 2 +- src/train_cmd.cpp | 41 +++++++++++++++--------- src/vehicle_cmd.cpp | 54 +++++++++++++++++++++----------- 8 files changed, 71 insertions(+), 40 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index d43b3e5115..9de3a4e11f 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -360,8 +360,8 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdToggleKeepRemainingVehicles, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_TOGGLE_KEEP_REMAINING_VEHICLES DEF_CMD(CmdToggleRefitAsTemplate, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_TOGGLE_REFIT_AS_TEMPLATE - DEF_CMD(CmdVirtualTrainFromTemplateVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE - DEF_CMD(CmdVirtualTrainFromTrain, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_VIRTUAL_TRAIN_FROM_TRAIN + DEF_CMD(CmdVirtualTrainFromTemplateVehicle, CMD_NO_TEST | CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT), // CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE + DEF_CMD(CmdVirtualTrainFromTrain, CMD_NO_TEST | CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT), // CMD_VIRTUAL_TRAIN_FROM_TRAIN DEF_CMD(CmdDeleteVirtualTrain, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_DELETE_VIRTUAL_TRAIN DEF_CMD(CmdBuildVirtualRailVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_BUILD_VIRTUAL_RAIL_VEHICLE DEF_CMD(CmdReplaceTemplateVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_REPLACE_TEMPLATE_VEHICLE diff --git a/src/lang/english.txt b/src/lang/english.txt index cad97b1066..e188672ba3 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -5027,3 +5027,5 @@ STR_TMPL_RPLALLGUI_BUTTON_RPLALL :{BLACK}Replace STR_TMPL_RPLALLGUI_BUTTON_APPLY :{BLACK}Apply STR_TMPL_RPLALLGUI_BUTTON_CANCEL :{BLACK}Cancel STR_TMPL_RPLALLGUI_USE_TIP :{BLACK}Select a vehicle type from each list and press 'Replace All'. If you are happy with the result displayed in the template list, press 'Apply' to actually apply these changes. + +STR_TMPL_CANT_CREATE :{WHITE}Can't create template or virtual vehicle... diff --git a/src/tbtr_template_gui_create.cpp b/src/tbtr_template_gui_create.cpp index 288d511da2..ed35624b31 100644 --- a/src/tbtr_template_gui_create.cpp +++ b/src/tbtr_template_gui_create.cpp @@ -161,7 +161,7 @@ public: this->vehicle_over = INVALID_VEHICLE; if (to_edit) { - DoCommandP(0, to_edit->index, 0, CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE, CcSetVirtualTrain); + DoCommandP(0, to_edit->index, 0, CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE | CMD_MSG(STR_TMPL_CANT_CREATE), CcSetVirtualTrain); } this->resize.step_height = 1; @@ -265,7 +265,7 @@ public: } // create a new one - DoCommandP(0, v->index, 0, CMD_VIRTUAL_TRAIN_FROM_TRAIN, CcSetVirtualTrain); + DoCommandP(0, v->index, 0, CMD_VIRTUAL_TRAIN_FROM_TRAIN | CMD_MSG(STR_TMPL_CANT_CREATE), CcSetVirtualTrain); this->ToggleWidgetLoweredState(TCW_CLONE); ResetObjectToPlace(); this->SetDirty(); diff --git a/src/tbtr_template_gui_main.cpp b/src/tbtr_template_gui_main.cpp index 7f8e6d4f02..23960739ce 100644 --- a/src/tbtr_template_gui_main.cpp +++ b/src/tbtr_template_gui_main.cpp @@ -478,7 +478,7 @@ public: virtual bool OnVehicleSelect(const Vehicle *v) { - bool succeeded = DoCommandP(0, v->index, 0, CMD_CLONE_TEMPLATE_VEHICLE_FROM_TRAIN, NULL); + bool succeeded = DoCommandP(0, v->index, 0, CMD_CLONE_TEMPLATE_VEHICLE_FROM_TRAIN | CMD_MSG(STR_TMPL_CANT_CREATE), NULL); if (!succeeded) return false; diff --git a/src/tbtr_template_vehicle_func.h b/src/tbtr_template_vehicle_func.h index 0e2989ec87..7e3bfa36bf 100644 --- a/src/tbtr_template_vehicle_func.h +++ b/src/tbtr_template_vehicle_func.h @@ -17,7 +17,7 @@ #include "tbtr_template_vehicle.h" -Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv); +Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv, StringID &err); void DrawTemplateVehicle(const TemplateVehicle*, int, int, int, VehicleID, int, VehicleID); diff --git a/src/train.h b/src/train.h index 99b6699dc2..562b704801 100644 --- a/src/train.h +++ b/src/train.h @@ -353,7 +353,7 @@ CommandCost CmdMoveRailVehicle(TileIndex, DoCommandFlag , uint32, uint32, const CommandCost CmdMoveVirtualRailVehicle(TileIndex, DoCommandFlag, uint32, uint32, const char*); Train* CmdBuildVirtualRailWagon(const Engine*); -Train* CmdBuildVirtualRailVehicle(EngineID); +Train* CmdBuildVirtualRailVehicle(EngineID, bool lax_engine_check, StringID &error); #define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 5f8d9ae1f0..eeafb441db 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -4136,19 +4136,19 @@ Train* CmdBuildVirtualRailWagon(const Engine *e) return v; } -/** - * Build a railroad vehicle. - * @param tile tile of the depot where rail-vehicle is built. - * @param flags type of operation. - * @param e the engine to build. - * @param data bit 0 prevents any free cars from being added to the train. - * @param ret[out] the vehicle that has been built. - * @return the cost of this operation or an error. - */ -Train* CmdBuildVirtualRailVehicle(EngineID eid) +Train* CmdBuildVirtualRailVehicle(EngineID eid, bool lax_engine_check, StringID &error) { - if (!IsEngineBuildable(eid, VEH_TRAIN, _current_company)) { - return NULL; + if (lax_engine_check) { + const Engine *e = Engine::GetIfValid(eid); + if (e == NULL || e->type != VEH_TRAIN) { + error = STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + VEH_TRAIN; + return NULL; + } + } else { + if (!IsEngineBuildable(eid, VEH_TRAIN, _current_company)) { + error = STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + VEH_TRAIN; + return NULL; + } } const Engine* e = Engine::Get(eid); @@ -4156,6 +4156,7 @@ Train* CmdBuildVirtualRailVehicle(EngineID eid) int num_vehicles = (e->u.rail.railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + CountArticulatedParts(eid, false); if (!Train::CanAllocateItem(num_vehicles)) { + error = STR_ERROR_TOO_MANY_VEHICLES_IN_GAME; return NULL; } @@ -4229,13 +4230,18 @@ CommandCost CmdBuildVirtualRailVehicle(TileIndex tile, DoCommandFlag flags, uint { EngineID eid = p1; + if (!IsEngineBuildable(eid, VEH_TRAIN, _current_company)) { + return_cmd_error(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + VEH_TRAIN); + } + bool should_execute = (flags & DC_EXEC) != 0; if (should_execute) { - Train* train = CmdBuildVirtualRailVehicle(eid); + StringID err = INVALID_STRING_ID; + Train* train = CmdBuildVirtualRailVehicle(eid, false, err); if (train == NULL) { - return CMD_ERROR; + return_cmd_error(err); } } @@ -4309,7 +4315,12 @@ CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint3 CommandCost buyCost = TestBuyAllTemplateVehiclesInChain(tv, tile); if (!buyCost.Succeeded() || !CheckCompanyHasMoney(buyCost)) { if (!stayInDepot) incoming->vehstatus &= ~VS_STOPPED; - return_cmd_error(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY); + + if (!buyCost.Succeeded() && buyCost.GetErrorMessage() != INVALID_STRING_ID) { + return buyCost; + } else { + return_cmd_error(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY); + } } } diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 622cf0d562..aa36f859d7 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -925,34 +925,41 @@ CommandCost CmdVirtualTrainFromTemplateVehicle(TileIndex tile, DoCommandFlag fla bool should_execute = (flags & DC_EXEC) != 0; if (should_execute) { - Train* train = VirtualTrainFromTemplateVehicle(tv); + StringID err = INVALID_STRING_ID; + Train* train = VirtualTrainFromTemplateVehicle(tv, err); if (train == NULL) { - return CMD_ERROR; + return_cmd_error(err); } } return CommandCost(); } -Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv) +CommandCost CmdDeleteVirtualTrain(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text); + +Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv, StringID &err) { CommandCost c; Train *tmp, *head, *tail; - head = CmdBuildVirtualRailVehicle(tv->engine_type); + head = CmdBuildVirtualRailVehicle(tv->engine_type, true, err); if (!head) return NULL; tail = head; tv = tv->GetNextUnit(); while (tv) { - tmp = CmdBuildVirtualRailVehicle(tv->engine_type); - if (tmp) { - tmp->cargo_type = tv->cargo_type; - tmp->cargo_subtype = tv->cargo_subtype; - CmdMoveRailVehicle(INVALID_TILE, DC_EXEC, (1 << 21) | tmp->index, tail->index, 0); - tail = tmp; + tmp = CmdBuildVirtualRailVehicle(tv->engine_type, true, err); + if (!tmp) { + CmdDeleteVirtualTrain(INVALID_TILE, DC_EXEC, head->index, 0, NULL); + return NULL; } + + tmp->cargo_type = tv->cargo_type; + tmp->cargo_subtype = tv->cargo_subtype; + CmdMoveRailVehicle(INVALID_TILE, DC_EXEC, (1 << 21) | tmp->index, tail->index, 0); + tail = tmp; + tv = tv->GetNextUnit(); } @@ -986,20 +993,25 @@ CommandCost CmdVirtualTrainFromTrain(TileIndex tile, DoCommandFlag flags, uint32 if (should_execute) { CommandCost c; Train *tmp, *head, *tail; + StringID err = INVALID_STRING_ID; - head = CmdBuildVirtualRailVehicle(train->engine_type); - if (!head) return CMD_ERROR; + head = CmdBuildVirtualRailVehicle(train->engine_type, false, err); + if (!head) return_cmd_error(err); tail = head; train = train->GetNextUnit(); while (train) { - tmp = CmdBuildVirtualRailVehicle(train->engine_type); - if (tmp) { - tmp->cargo_type = train->cargo_type; - tmp->cargo_subtype = train->cargo_subtype; - CmdMoveRailVehicle(0, DC_EXEC, (1 << 21) | tmp->index, tail->index, 0); - tail = tmp; + tmp = CmdBuildVirtualRailVehicle(train->engine_type, false, err); + if (!tmp) { + CmdDeleteVirtualTrain(tile, flags, head->index, 0, NULL); + return_cmd_error(err); } + + tmp->cargo_type = train->cargo_type; + tmp->cargo_subtype = train->cargo_subtype; + CmdMoveRailVehicle(0, DC_EXEC, (1 << 21) | tmp->index, tail->index, 0); + tail = tmp; + train = train->GetNextUnit(); } @@ -1121,6 +1133,12 @@ CommandCost CmdTemplateVehicleFromTrain(TileIndex tile, DoCommandFlag flags, uin return CMD_ERROR; } + for (Train *v = clicked; v != NULL; v = v->Next()) { + if (!IsEngineBuildable(v->engine_type, VEH_TRAIN, _current_company)) { + return_cmd_error(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + VEH_TRAIN); + } + } + bool should_execute = (flags & DC_EXEC) != 0; if (should_execute) { From 9132707eb915aea8add4120e57cde33bc2780695 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 15 Feb 2016 02:32:13 +0000 Subject: [PATCH 3/9] TBTR: Fix refitting of template vehicles failing. Fix from KeldorKatarn's tree. --- src/vehicle_cmd.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index aa36f859d7..f6f6c00d5a 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -458,17 +458,15 @@ CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint /* Allow auto-refitting only during loading and normal refitting only in a depot. */ if (!is_virtual_train) { - if (!free_wagon && (!auto_refit || !front->current_order.IsType(OT_LOADING)) && !front->IsStoppedInDepot()) { + if ((flags & DC_QUERY_COST) == 0 && // used by the refit GUI, including the order refit GUI. + !free_wagon && // used by autoreplace/renew + (!auto_refit || !front->current_order.IsType(OT_LOADING)) && // refit inside stations + !front->IsStoppedInDepot()) { // refit inside depots return_cmd_error(STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT + front->type); } + if (front->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_VEHICLE_IS_DESTROYED); } - if ((flags & DC_QUERY_COST) == 0 && // used by the refit GUI, including the order refit GUI. - !free_wagon && // used by autoreplace/renew - (!auto_refit || !front->current_order.IsType(OT_LOADING)) && // refit inside stations - !front->IsStoppedInDepot()) { // refit inside depots - return_cmd_error(STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT + front->type); - } if (front->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_VEHICLE_IS_DESTROYED); From 98fc4493c84f788d00bde5310294ab159b776ba3 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 15 Feb 2016 18:54:37 +0000 Subject: [PATCH 4/9] TBTR: Delete duplicated build vehicle window. Add a virtual train mode to the existing build vehicle window. Simplify some of the inter-window notify logic. Disable all buttons when a new template/edit is in progress. --- projects/openttd_vs100.vcxproj | 2 - projects/openttd_vs100.vcxproj.filters | 6 - projects/openttd_vs140.vcxproj | 2 - projects/openttd_vs140.vcxproj.filters | 6 - projects/openttd_vs80.vcproj | 8 - projects/openttd_vs90.vcproj | 8 - source.list | 2 - src/build_vehicle_gui.cpp | 78 +- src/command_func.h | 2 +- src/tbtr_template_gui_create.cpp | 26 +- src/tbtr_template_gui_create.h | 3 +- src/tbtr_template_gui_create_virtualtrain.cpp | 837 ------------------ src/tbtr_template_gui_create_virtualtrain.h | 19 - src/tbtr_template_gui_main.cpp | 43 +- 14 files changed, 95 insertions(+), 947 deletions(-) delete mode 100644 src/tbtr_template_gui_create_virtualtrain.cpp delete mode 100644 src/tbtr_template_gui_create_virtualtrain.h diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj index 200502ef78..5aa70d072a 100644 --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -293,12 +293,10 @@ - - diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters index 6423835e82..552d9e92c7 100644 --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -108,9 +108,6 @@ Source Files - - Source Files - Source Files @@ -123,9 +120,6 @@ Source Files - - Source Files - Source Files diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj index e55d31ae85..fdce86459d 100644 --- a/projects/openttd_vs140.vcxproj +++ b/projects/openttd_vs140.vcxproj @@ -310,12 +310,10 @@ - - diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters index 6423835e82..552d9e92c7 100644 --- a/projects/openttd_vs140.vcxproj.filters +++ b/projects/openttd_vs140.vcxproj.filters @@ -108,9 +108,6 @@ Source Files - - Source Files - Source Files @@ -123,9 +120,6 @@ Source Files - - Source Files - Source Files diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index dd33150fb5..0ac64562b8 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -442,10 +442,6 @@ RelativePath=".\..\src\tbtr_template_gui_create.cpp" > - - @@ -462,10 +458,6 @@ RelativePath=".\..\src\tbtr_template_gui_create.h" > - - diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index 36e02cb215..9d879d603e 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -439,10 +439,6 @@ RelativePath=".\..\src\tbtr_template_gui_create.cpp" > - - @@ -459,10 +455,6 @@ RelativePath=".\..\src\tbtr_template_gui_create.h" > - - diff --git a/source.list b/source.list index cdf5ab80d3..1c5d0085a4 100644 --- a/source.list +++ b/source.list @@ -1,12 +1,10 @@ # Source Files tbtr_template_gui_main.cpp tbtr_template_gui_create.cpp -tbtr_template_gui_create_virtualtrain.cpp tbtr_template_vehicle.cpp tbtr_template_vehicle_func.cpp tbtr_template_gui_main.h tbtr_template_gui_create.h -tbtr_template_gui_create_virtualtrain.h tbtr_template_vehicle.h tbtr_template_vehicle_func.h diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index bd4bf3b59b..d41b1345d7 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -32,6 +32,7 @@ #include "cargotype.h" #include "core/geometry_func.hpp" #include "autoreplace_func.h" +#include "train.h" #include "widgets/build_vehicle_widget.h" @@ -974,11 +975,16 @@ struct BuildVehicleWindow : Window { byte cargo_filter_criteria; ///< Selected cargo filter int details_height; ///< Minimal needed height of the details panels (found so far). Scrollbar *vscroll; + bool virtual_train_mode; ///< Are we building a virtual train? + Train **virtual_train_out; ///< Virtual train ptr - BuildVehicleWindow(WindowDesc *desc, TileIndex tile, VehicleType type) : Window(desc) + BuildVehicleWindow(WindowDesc *desc, TileIndex tile, VehicleType type, Train **virtual_train_out) : Window(desc) { this->vehicle_type = type; this->window_number = tile == INVALID_TILE ? (int)type : tile; + this->virtual_train_out = virtual_train_out; + this->virtual_train_mode = (virtual_train_out != NULL); + if (this->virtual_train_mode) this->window_number = 0; this->sel_engine = INVALID_ENGINE; @@ -998,7 +1004,7 @@ struct BuildVehicleWindow : Window { break; } - this->listview_mode = (this->window_number <= VEH_END); + this->listview_mode = !(this->virtual_train_mode) && (this->window_number <= VEH_END); this->CreateNestedTree(); @@ -1018,8 +1024,13 @@ struct BuildVehicleWindow : Window { widget->tool_tip = STR_BUY_VEHICLE_TRAIN_HIDE_SHOW_TOGGLE_TOOLTIP + type; widget = this->GetWidget(WID_BV_BUILD); - widget->widget_data = STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_BUTTON + type; - widget->tool_tip = STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP + type; + if (this->virtual_train_mode) { + widget->widget_data = STR_TMPL_CONFIRM; + widget->tool_tip = STR_TMPL_CONFIRM; + } else { + widget->widget_data = STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_BUTTON + type; + widget->tool_tip = STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP + type; + } widget = this->GetWidget(WID_BV_RENAME); widget->widget_data = STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON + type; @@ -1032,7 +1043,7 @@ struct BuildVehicleWindow : Window { this->details_height = ((this->vehicle_type == VEH_TRAIN) ? 10 : 9) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; - this->FinishInitNested(tile == INVALID_TILE ? (int)type : tile); + this->FinishInitNested(this->window_number); this->owner = (tile != INVALID_TILE) ? GetTileOwner(tile) : _local_company; @@ -1116,7 +1127,7 @@ struct BuildVehicleWindow : Window { int num_engines = 0; int num_wagons = 0; - this->filter.railtype = (this->listview_mode) ? RAILTYPE_END : GetRailType(this->window_number); + this->filter.railtype = (this->listview_mode || this->virtual_train_mode) ? RAILTYPE_END : GetRailType(this->window_number); this->eng_list.Clear(); @@ -1308,8 +1319,13 @@ struct BuildVehicleWindow : Window { case WID_BV_BUILD: { EngineID sel_eng = this->sel_engine; if (sel_eng != INVALID_ENGINE) { - CommandCallback *callback = (this->vehicle_type == VEH_TRAIN && RailVehInfo(sel_eng)->railveh_type == RAILVEH_WAGON) ? CcBuildWagon : CcBuildPrimaryVehicle; - DoCommandP(this->window_number, sel_eng, 0, GetCmdBuildVeh(this->vehicle_type), callback); + if (this->virtual_train_mode) { + DoCommandP(0, sel_eng, 0, CMD_BUILD_VIRTUAL_RAIL_VEHICLE, CcAddVirtualEngine); + } else { + CommandCallback *callback = (this->vehicle_type == VEH_TRAIN && RailVehInfo(sel_eng)->railveh_type == RAILVEH_WAGON) + ? CcBuildWagon : CcBuildPrimaryVehicle; + DoCommandP(this->window_number, sel_eng, 0, GetCmdBuildVeh(this->vehicle_type), callback); + } } break; } @@ -1348,7 +1364,7 @@ struct BuildVehicleWindow : Window { { switch (widget) { case WID_BV_CAPTION: - if (this->vehicle_type == VEH_TRAIN && !this->listview_mode) { + if (this->vehicle_type == VEH_TRAIN && !this->listview_mode && !this->virtual_train_mode) { const RailtypeInfo *rti = GetRailTypeInfo(this->filter.railtype); SetDParam(0, rti->strings.build_caption); } else { @@ -1481,8 +1497,34 @@ struct BuildVehicleWindow : Window { { this->vscroll->SetCapacityFromWidget(this, WID_BV_LIST); } + + void AddVirtualEngine(Train *toadd) + { + if (this->virtual_train_out == NULL) return; + + if (*(this->virtual_train_out) == NULL) { + *(this->virtual_train_out) = toadd; + } else { + VehicleID target = (*(this->virtual_train_out))->GetLastUnit()->index; + + DoCommandP(0, (1 << 21) | toadd->index, target, CMD_MOVE_RAIL_VEHICLE); + } + InvalidateWindowClassesData(WC_CREATE_TEMPLATE); + InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN); + } }; +void CcAddVirtualEngine(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2) +{ + if (result.Failed()) return; + + Window* window = FindWindowById(WC_BUILD_VIRTUAL_TRAIN, 0); + if (window) { + Train* train = Train::From(Vehicle::Get(_new_vehicle_id)); + ((BuildVehicleWindow*) window)->AddVirtualEngine(train); + } +} + static WindowDesc _build_vehicle_desc( WDP_AUTO, "build_vehicle", 240, 268, WC_BUILD_VEHICLE, WC_NONE, @@ -1490,6 +1532,13 @@ static WindowDesc _build_vehicle_desc( _nested_build_vehicle_widgets, lengthof(_nested_build_vehicle_widgets) ); +static WindowDesc _build_template_vehicle_desc( + WDP_AUTO, "build_vehicle", 240, 268, + WC_BUILD_VIRTUAL_TRAIN, WC_CREATE_TEMPLATE, + WDF_CONSTRUCTION, + _nested_build_vehicle_widgets, lengthof(_nested_build_vehicle_widgets) +); + void ShowBuildVehicleWindow(TileIndex tile, VehicleType type) { /* We want to be able to open both Available Train as Available Ships, @@ -1502,5 +1551,14 @@ void ShowBuildVehicleWindow(TileIndex tile, VehicleType type) DeleteWindowById(WC_BUILD_VEHICLE, num); - new BuildVehicleWindow(&_build_vehicle_desc, tile, type); + new BuildVehicleWindow(&_build_vehicle_desc, tile, type, NULL); +} + +void ShowTemplateTrainBuildVehicleWindow(Train **virtual_train) +{ + assert(IsCompanyBuildableVehicleType(VEH_TRAIN)); + + DeleteWindowById(WC_BUILD_VIRTUAL_TRAIN, 0); + + new BuildVehicleWindow(&_build_template_vehicle_desc, INVALID_TILE, VEH_TRAIN, virtual_train); } diff --git a/src/command_func.h b/src/command_func.h index d719aba570..416ed45178 100644 --- a/src/command_func.h +++ b/src/command_func.h @@ -130,7 +130,7 @@ CommandCallback CcSetVirtualTrain; CommandCallback CcVirtualTrainWaggonsMoved; CommandCallback CcDeleteVirtualTrain; -/* tbtr_template_gui_create_virtualtrain.cpp */ +/* build_vehicle_gui.cpp */ CommandCallback CcAddVirtualEngine; #endif /* COMMAND_FUNC_H */ diff --git a/src/tbtr_template_gui_create.cpp b/src/tbtr_template_gui_create.cpp index ed35624b31..1e9c174a5d 100644 --- a/src/tbtr_template_gui_create.cpp +++ b/src/tbtr_template_gui_create.cpp @@ -104,6 +104,8 @@ static WindowDesc _template_create_window_desc( _widgets, lengthof(_widgets) // widgets + num widgets ); +void ShowTemplateTrainBuildVehicleWindow(Train **virtual_train); + static void TrainDepotMoveVehicle(const Vehicle *wagon, VehicleID sel, const Vehicle *head) { const Vehicle *v = Vehicle::Get(sel); @@ -130,15 +132,13 @@ private: int line_height; Train* virtual_train; bool editMode; - bool *noticeParent; bool *createWindowOpen; /// used to notify main window of progress (dummy way of disabling 'delete' while editing a template) - bool virtualTrainChangedNotice; VehicleID sel; VehicleID vehicle_over; TemplateVehicle *editTemplate; public: - TemplateCreateWindow(WindowDesc* _wdesc, TemplateVehicle *to_edit, bool *notice, bool *windowOpen, int step_h) : Window(_wdesc) + TemplateCreateWindow(WindowDesc* _wdesc, TemplateVehicle *to_edit, bool *windowOpen, int step_h) : Window(_wdesc) { this->line_height = step_h; this->CreateNestedTree(_wdesc != NULL); @@ -150,9 +150,7 @@ public: this->owner = _local_company; - noticeParent = notice; createWindowOpen = windowOpen; - virtualTrainChangedNotice = false; this->editTemplate = to_edit; editMode = (to_edit != NULL); @@ -181,6 +179,7 @@ public: /* more cleanup */ *createWindowOpen = false; DeleteWindowById(WC_BUILD_VIRTUAL_TRAIN, this->window_number); + InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN); } void SetVirtualTrain(Train* const train) @@ -205,7 +204,7 @@ public: virtual void OnInvalidateData(int data = 0, bool gui_scope = true) { - virtualTrainChangedNotice = true; + this->SetDirty(); UpdateButtonState(); } @@ -218,7 +217,7 @@ public: break; } case TCW_NEW: { - ShowBuildVirtualTrainWindow(&virtual_train, &virtualTrainChangedNotice); + ShowTemplateTrainBuildVehicleWindow(&virtual_train); break; } case TCW_CLONE: { @@ -330,15 +329,6 @@ public: } } - virtual void OnTick() - { - if (virtualTrainChangedNotice) { - this->SetDirty(); - virtualTrainChangedNotice = false; - UpdateButtonState(); - } - } - virtual void OnDragDrop(Point pt, int widget) { switch (widget) { @@ -546,10 +536,10 @@ public: } }; -void ShowTemplateCreateWindow(TemplateVehicle *to_edit, bool *noticeParent, bool *createWindowOpen, int step_h) +void ShowTemplateCreateWindow(TemplateVehicle *to_edit, bool *createWindowOpen, int step_h) { if (BringWindowToFrontById(WC_CREATE_TEMPLATE, VEH_TRAIN) != NULL) return; - new TemplateCreateWindow(&_template_create_window_desc, to_edit, noticeParent, createWindowOpen, step_h); + new TemplateCreateWindow(&_template_create_window_desc, to_edit, createWindowOpen, step_h); } void CcSetVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2) diff --git a/src/tbtr_template_gui_create.h b/src/tbtr_template_gui_create.h index d95cf53bdf..8e267a7303 100644 --- a/src/tbtr_template_gui_create.h +++ b/src/tbtr_template_gui_create.h @@ -13,8 +13,7 @@ #define TEMPLATE_GUI_CREATE #include "tbtr_template_vehicle.h" -#include "tbtr_template_gui_create_virtualtrain.h" -void ShowTemplateCreateWindow(TemplateVehicle*, bool*, bool*, int); +void ShowTemplateCreateWindow(TemplateVehicle*, bool*, int); #endif diff --git a/src/tbtr_template_gui_create_virtualtrain.cpp b/src/tbtr_template_gui_create_virtualtrain.cpp deleted file mode 100644 index de3f537327..0000000000 --- a/src/tbtr_template_gui_create_virtualtrain.cpp +++ /dev/null @@ -1,837 +0,0 @@ -/* $Id$ */ - -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file tbtr_template_gui_create_virtualtrain.cpp Template-based train replacement: template creation vehicle build GUI. */ - -#include "stdafx.h" -#include "engine_base.h" -#include "engine_func.h" -#include "station_base.h" -#include "articulated_vehicles.h" -#include "textbuf_gui.h" -#include "command_func.h" -#include "company_func.h" -#include "vehicle_gui.h" -#include "newgrf_engine.h" -#include "newgrf_text.h" -#include "group.h" -#include "string_func.h" -#include "strings_func.h" -#include "window_func.h" -#include "date_func.h" -#include "vehicle_func.h" -#include "widgets/dropdown_func.h" -#include "engine_gui.h" -#include "cargotype.h" -#include "core/geometry_func.hpp" -#include "vehicle_gui.h" -#include "tbtr_template_gui_create_virtualtrain.h" - -#include "widgets/build_vehicle_widget.h" - -#include "table/strings.h" - -#include "safeguards.h" - -static const NWidgetPart _nested_build_vehicle_widgets[] = { - NWidget(NWID_HORIZONTAL), - NWidget(WWT_CLOSEBOX, COLOUR_GREY), - NWidget(WWT_CAPTION, COLOUR_GREY, WID_BV_CAPTION), SetDataTip(STR_WHITE_STRING, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), - NWidget(WWT_SHADEBOX, COLOUR_GREY), - NWidget(WWT_STICKYBOX, COLOUR_GREY), - EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY), - NWidget(NWID_HORIZONTAL), - NWidget(NWID_VERTICAL), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), SetFill(1, 0), - NWidget(NWID_SPACER), SetFill(1, 1), - EndContainer(), - NWidget(NWID_VERTICAL), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_BV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_BV_CARGO_FILTER_DROPDOWN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA), - EndContainer(), - EndContainer(), - EndContainer(), - /* Vehicle list. */ - NWidget(NWID_HORIZONTAL), - NWidget(WWT_MATRIX, COLOUR_GREY, WID_BV_LIST), SetResize(1, 1), SetFill(1, 0), SetDataTip(0x101, STR_NULL), SetScrollbar(WID_BV_SCROLLBAR), - NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_BV_SCROLLBAR), - EndContainer(), - /* Panel with details. */ - NWidget(WWT_PANEL, COLOUR_GREY, WID_BV_PANEL), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(), - /* Build/rename buttons, resize button. */ - NWidget(NWID_HORIZONTAL), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BV_BUILD), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_TMPL_CONFIRM, STR_TMPL_CONFIRM), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BV_RENAME), SetResize(1, 0), SetFill(1, 0), - NWidget(WWT_RESIZEBOX, COLOUR_GREY), - EndContainer(), -}; - -/** Special cargo filter criteria */ -static const CargoID CF_ANY = CT_NO_REFIT; ///< Show all vehicles independent of carried cargo (i.e. no filtering) -static const CargoID CF_NONE = CT_INVALID; ///< Show only vehicles which do not carry cargo (e.g. train engines) - -static bool _internal_sort_order; ///< false = descending, true = ascending -static byte _last_sort_criteria[] = {0, 0, 0, 0}; -static bool _last_sort_order[] = {false, false, false, false}; -static CargoID _last_filter_criteria[] = {CF_ANY, CF_ANY, CF_ANY, CF_ANY}; - -/** - * Determines order of engines by engineID - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL EngineNumberSorter(const EngineID *a, const EngineID *b) -{ - int r = Engine::Get(*a)->list_position - Engine::Get(*b)->list_position; - - return _internal_sort_order ? -r : r; -} - -/** - * Determines order of engines by introduction date - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL EngineIntroDateSorter(const EngineID *a, const EngineID *b) -{ - const int va = Engine::Get(*a)->intro_date; - const int vb = Engine::Get(*b)->intro_date; - const int r = va - vb; - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/** - * Determines order of engines by name - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL EngineNameSorter(const EngineID *a, const EngineID *b) -{ - static EngineID last_engine[2] = { INVALID_ENGINE, INVALID_ENGINE }; - static char last_name[2][64] = { "\0", "\0" }; - - const EngineID va = *a; - const EngineID vb = *b; - - if (va != last_engine[0]) { - last_engine[0] = va; - SetDParam(0, va); - GetString(last_name[0], STR_ENGINE_NAME, lastof(last_name[0])); - } - - if (vb != last_engine[1]) { - last_engine[1] = vb; - SetDParam(0, vb); - GetString(last_name[1], STR_ENGINE_NAME, lastof(last_name[1])); - } - - int r = strnatcmp(last_name[0], last_name[1]); // Sort by name (natural sorting). - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/** - * Determines order of engines by reliability - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL EngineReliabilitySorter(const EngineID *a, const EngineID *b) -{ - const int va = Engine::Get(*a)->reliability; - const int vb = Engine::Get(*b)->reliability; - const int r = va - vb; - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/** - * Determines order of engines by purchase cost - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL EngineCostSorter(const EngineID *a, const EngineID *b) -{ - Money va = Engine::Get(*a)->GetCost(); - Money vb = Engine::Get(*b)->GetCost(); - int r = ClampToI32(va - vb); - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/** - * Determines order of engines by speed - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL EngineSpeedSorter(const EngineID *a, const EngineID *b) -{ - int va = Engine::Get(*a)->GetDisplayMaxSpeed(); - int vb = Engine::Get(*b)->GetDisplayMaxSpeed(); - int r = va - vb; - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/** - * Determines order of engines by power - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL EnginePowerSorter(const EngineID *a, const EngineID *b) -{ - int va = Engine::Get(*a)->GetPower(); - int vb = Engine::Get(*b)->GetPower(); - int r = va - vb; - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/** - * Determines order of engines by tractive effort - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL EngineTractiveEffortSorter(const EngineID *a, const EngineID *b) -{ - int va = Engine::Get(*a)->GetDisplayMaxTractiveEffort(); - int vb = Engine::Get(*b)->GetDisplayMaxTractiveEffort(); - int r = va - vb; - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/** - * Determines order of engines by running costs - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL EngineRunningCostSorter(const EngineID *a, const EngineID *b) -{ - Money va = Engine::Get(*a)->GetRunningCost(); - Money vb = Engine::Get(*b)->GetRunningCost(); - int r = ClampToI32(va - vb); - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/** - * Determines order of engines by running costs - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL EnginePowerVsRunningCostSorter(const EngineID *a, const EngineID *b) -{ - const Engine *e_a = Engine::Get(*a); - const Engine *e_b = Engine::Get(*b); - - /* Here we are using a few tricks to get the right sort. - * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int, - * we will actually calculate cunning cost/power (to make it more than 1). - * Because of this, the return value have to be reversed as well and we return b - a instead of a - b. - * Another thing is that both power and running costs should be doubled for multiheaded engines. - * Since it would be multipling with 2 in both numerator and denumerator, it will even themselves out and we skip checking for multiheaded. */ - Money va = (e_a->GetRunningCost()) / max(1U, (uint)e_a->GetPower()); - Money vb = (e_b->GetRunningCost()) / max(1U, (uint)e_b->GetPower()); - int r = ClampToI32(vb - va); - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/* Train sorting functions */ - -/** - * Determines order of train engines by capacity - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL TrainEngineCapacitySorter(const EngineID *a, const EngineID *b) -{ - const RailVehicleInfo *rvi_a = RailVehInfo(*a); - const RailVehicleInfo *rvi_b = RailVehInfo(*b); - - int va = GetTotalCapacityOfArticulatedParts(*a) * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); - int vb = GetTotalCapacityOfArticulatedParts(*b) * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); - int r = va - vb; - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/** - * Determines order of train engines by engine / wagon - * @param *a first engine to compare - * @param *b second engine to compare - * @return for descending order: returns < 0 if a < b and > 0 for a > b. Vice versa for ascending order and 0 for equal - */ -static int CDECL TrainEnginesThenWagonsSorter(const EngineID *a, const EngineID *b) -{ - int val_a = (RailVehInfo(*a)->railveh_type == RAILVEH_WAGON ? 1 : 0); - int val_b = (RailVehInfo(*b)->railveh_type == RAILVEH_WAGON ? 1 : 0); - int r = val_a - val_b; - - /* Use EngineID to sort instead since we want consistent sorting */ - if (r == 0) return EngineNumberSorter(a, b); - return _internal_sort_order ? -r : r; -} - -/** Sort functions for the vehicle sort criteria, for each vehicle type. */ -static EngList_SortTypeFunction * const _sorter[][11] = {{ - /* Trains */ - &EngineNumberSorter, - &EngineCostSorter, - &EngineSpeedSorter, - &EnginePowerSorter, - &EngineTractiveEffortSorter, - &EngineIntroDateSorter, - &EngineNameSorter, - &EngineRunningCostSorter, - &EnginePowerVsRunningCostSorter, - &EngineReliabilitySorter, - &TrainEngineCapacitySorter, -}}; - -static const StringID _sort_listing[][12] = {{ - /* Trains */ - STR_SORT_BY_ENGINE_ID, - STR_SORT_BY_COST, - STR_SORT_BY_MAX_SPEED, - STR_SORT_BY_POWER, - STR_SORT_BY_TRACTIVE_EFFORT, - STR_SORT_BY_INTRO_DATE, - STR_SORT_BY_NAME, - STR_SORT_BY_RUNNING_COST, - STR_SORT_BY_POWER_VS_RUNNING_COST, - STR_SORT_BY_RELIABILITY, - STR_SORT_BY_CARGO_CAPACITY, - INVALID_STRING_ID -}}; - -/** Cargo filter functions */ -static bool CDECL CargoFilter(const EngineID *eid, const CargoID cid) -{ - if (cid == CF_ANY) return true; - uint32 refit_mask = GetUnionOfArticulatedRefitMasks(*eid, true); - return (cid == CF_NONE ? refit_mask == 0 : HasBit(refit_mask, cid)); -} - -static GUIEngineList::FilterFunction * const _filter_funcs[] = { - &CargoFilter, -}; - -/** - * Engine drawing loop - * @param type Type of vehicle (VEH_*) - * @param l The left most location of the list - * @param r The right most location of the list - * @param y The top most location of the list - * @param eng_list What engines to draw - * @param min where to start in the list - * @param max where in the list to end - * @param selected_id what engine to highlight as selected, if any - * @param show_count Whether to show the amount of engines or not - * @param selected_group the group to list the engines of - */ -static void DrawEngineList(VehicleType type, int l, int r, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group) -{ - static const int sprite_widths[] = { 60, 60, 76, 67 }; - static const int sprite_y_offsets[] = { -1, -1, -2, -2 }; - - /* Obligatory sanity checks! */ - assert((uint)type < lengthof(sprite_widths)); - assert_compile(lengthof(sprite_y_offsets) == lengthof(sprite_widths)); - assert(max <= eng_list->Length()); - - bool rtl = _current_text_dir == TD_RTL; - int step_size = GetEngineListHeight(type); - int sprite_width = sprite_widths[type]; - - int sprite_x = (rtl ? r - sprite_width / 2 : l + sprite_width / 2) - 1; - int sprite_y_offset = sprite_y_offsets[type] + step_size / 2; - - int text_left = l + (rtl ? WD_FRAMERECT_LEFT : sprite_width); - int text_right = r - (rtl ? sprite_width : WD_FRAMERECT_RIGHT); - - int normal_text_y_offset = (step_size - FONT_HEIGHT_NORMAL) / 2; - int small_text_y_offset = step_size - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 1; - - for (; min < max; min++, y += step_size) { - const EngineID engine = (*eng_list)[min]; - /* Note: num_engines is only used in the autoreplace GUI, so it is correct to use _local_company here. */ - const uint num_engines = GetGroupNumEngines(_local_company, selected_group, engine); - - SetDParam(0, engine); - DrawString(text_left, text_right, y + normal_text_y_offset, STR_ENGINE_NAME, engine == selected_id ? TC_WHITE : TC_BLACK); - DrawVehicleEngine(l, r, sprite_x, y + sprite_y_offset, engine, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_company), EIT_PURCHASE); - if (show_count) { - SetDParam(0, num_engines); - DrawString(text_left, text_right, y + small_text_y_offset, STR_TINY_BLACK_COMA, TC_FROMSTRING, SA_RIGHT); - } - } -} - - -struct BuildVirtualTrainWindow : Window { - VehicleType vehicle_type; - union { - RailTypeByte railtype; - RoadTypes roadtypes; - } filter; - bool descending_sort_order; - byte sort_criteria; - bool listview_mode; - EngineID sel_engine; - EngineID rename_engine; - GUIEngineList eng_list; - CargoID cargo_filter[NUM_CARGO + 2]; ///< Available cargo filters; CargoID or CF_ANY or CF_NONE - StringID cargo_filter_texts[NUM_CARGO + 3]; ///< Texts for filter_cargo, terminated by INVALID_STRING_ID - byte cargo_filter_criteria; ///< Selected cargo filter - int details_height; ///< Minimal needed height of the details panels (found so far). - Scrollbar *vscroll; - Train **virtual_train; ///< the virtual train that is currently being created - bool *noticeParent; - - BuildVirtualTrainWindow(WindowDesc *desc, Train **vt, bool *notice) : Window(desc) - { - this->vehicle_type = VEH_TRAIN; - this->window_number = 0; - - this->sel_engine = INVALID_ENGINE; - - this->sort_criteria = _last_sort_criteria[VEH_TRAIN]; - this->descending_sort_order = _last_sort_order[VEH_TRAIN]; - - this->filter.railtype = RAILTYPE_END; - - this->listview_mode = (this->window_number <= VEH_END); - - this->CreateNestedTree(desc); - - this->vscroll = this->GetScrollbar(WID_BV_SCROLLBAR); - - NWidgetCore *widget = this->GetWidget(WID_BV_LIST); - - widget = this->GetWidget(WID_BV_BUILD); - - widget = this->GetWidget(WID_BV_RENAME); - widget->widget_data = STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON + VEH_TRAIN; - widget->tool_tip = STR_BUY_VEHICLE_TRAIN_RENAME_TOOLTIP + VEH_TRAIN; - - this->details_height = ((this->vehicle_type == VEH_TRAIN) ? 10 : 9) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM; - - this->FinishInitNested(VEH_TRAIN); - - this->owner = _local_company; - - this->eng_list.ForceRebuild(); - this->GenerateBuildList(); - - if (this->eng_list.Length() > 0) this->sel_engine = this->eng_list[0]; - - this->virtual_train = vt; - this->noticeParent = notice; - } - - /** Populate the filter list and set the cargo filter criteria. */ - void SetCargoFilterArray() - { - uint filter_items = 0; - - /* Add item for disabling filtering. */ - this->cargo_filter[filter_items] = CF_ANY; - this->cargo_filter_texts[filter_items] = STR_PURCHASE_INFO_ALL_TYPES; - filter_items++; - - /* Add item for vehicles not carrying anything, e.g. train engines. - * This could also be useful for eyecandy vehicles of other types, but is likely too confusing for joe, */ - if (this->vehicle_type == VEH_TRAIN) { - this->cargo_filter[filter_items] = CF_NONE; - this->cargo_filter_texts[filter_items] = STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE; - filter_items++; - } - - /* Collect available cargo types for filtering. */ - const CargoSpec *cs; - FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) { - this->cargo_filter[filter_items] = cs->Index(); - this->cargo_filter_texts[filter_items] = cs->name; - filter_items++; - } - - /* Terminate the filter list. */ - this->cargo_filter_texts[filter_items] = INVALID_STRING_ID; - - /* If not found, the cargo criteria will be set to all cargoes. */ - this->cargo_filter_criteria = 0; - - /* Find the last cargo filter criteria. */ - for (uint i = 0; i < filter_items; ++i) { - if (this->cargo_filter[i] == _last_filter_criteria[this->vehicle_type]) { - this->cargo_filter_criteria = i; - break; - } - } - - this->eng_list.SetFilterFuncs(_filter_funcs); - this->eng_list.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY); - } - - void OnInit() - { - this->SetCargoFilterArray(); - } - - /** Filter the engine list against the currently selected cargo filter */ - void FilterEngineList() - { - this->eng_list.Filter(this->cargo_filter[this->cargo_filter_criteria]); - if (0 == this->eng_list.Length()) { // no engine passed through the filter, invalidate the previously selected engine - this->sel_engine = INVALID_ENGINE; - } else if (!this->eng_list.Contains(this->sel_engine)) { // previously selected engine didn't pass the filter, select the first engine of the list - this->sel_engine = this->eng_list[0]; - } - } - - /** Filter a single engine */ - bool FilterSingleEngine(EngineID eid) - { - CargoID filter_type = this->cargo_filter[this->cargo_filter_criteria]; - return (filter_type == CF_ANY || CargoFilter(&eid, filter_type)); - } - - /* Figure out what train EngineIDs to put in the list */ - void GenerateBuildTrainList() - { - EngineID sel_id = INVALID_ENGINE; - int num_engines = 0; - int num_wagons = 0; - - this->filter.railtype = (this->listview_mode) ? RAILTYPE_END : GetRailType(this->window_number); - - this->eng_list.Clear(); - - /* Make list of all available train engines and wagons. - * Also check to see if the previously selected engine is still available, - * and if not, reset selection to INVALID_ENGINE. This could be the case - * when engines become obsolete and are removed */ - const Engine *e; - FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) { - EngineID eid = e->index; - const RailVehicleInfo *rvi = &e->u.rail; - - if (this->filter.railtype != RAILTYPE_END && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue; - if (!IsEngineBuildable(eid, VEH_TRAIN, _local_company)) continue; - - /* Filter now! So num_engines and num_wagons is valid */ - if (!FilterSingleEngine(eid)) continue; - - *this->eng_list.Append() = eid; - - if (rvi->railveh_type != RAILVEH_WAGON) { - num_engines++; - } else { - num_wagons++; - } - - if (eid == this->sel_engine) sel_id = eid; - } - - this->sel_engine = sel_id; - - /* make engines first, and then wagons, sorted by ListPositionOfEngine() */ - _internal_sort_order = false; - EngList_Sort(&this->eng_list, TrainEnginesThenWagonsSorter); - - /* and then sort engines */ - _internal_sort_order = this->descending_sort_order; - EngList_SortPartial(&this->eng_list, _sorter[0][this->sort_criteria], 0, num_engines); - - /* and finally sort wagons */ - EngList_SortPartial(&this->eng_list, _sorter[0][this->sort_criteria], num_engines, num_wagons); - } - - /* Generate the list of vehicles */ - void GenerateBuildList() - { - if (!this->eng_list.NeedRebuild()) return; - - this->GenerateBuildTrainList(); - this->eng_list.Compact(); - this->eng_list.RebuildDone(); - return; // trains should not reach the last sorting - - - this->FilterEngineList(); - - _internal_sort_order = this->descending_sort_order; - EngList_Sort(&this->eng_list, _sorter[this->vehicle_type][this->sort_criteria]); - - this->eng_list.Compact(); - this->eng_list.RebuildDone(); - } - - virtual void OnClick(Point pt, int widget, int click_count) - { - switch (widget) { - case WID_BV_SORT_ASCENDING_DESCENDING: - this->descending_sort_order ^= true; - _last_sort_order[this->vehicle_type] = this->descending_sort_order; - this->eng_list.ForceRebuild(); - this->SetDirty(); - break; - - case WID_BV_LIST: { - uint i = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_BV_LIST); - size_t num_items = this->eng_list.Length(); - this->sel_engine = (i < num_items) ? this->eng_list[i] : INVALID_ENGINE; - this->SetDirty(); - if (click_count > 1 && !this->listview_mode) this->OnClick(pt, WID_BV_BUILD, 1); - break; - } - case WID_BV_SORT_DROPDOWN: { // Select sorting criteria dropdown menu - uint32 hidden_mask = 0; - /* Disable sorting by power or tractive effort when the original acceleration model for road vehicles is being used. */ - if (this->vehicle_type == VEH_ROAD && - _settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) { - SetBit(hidden_mask, 3); // power - SetBit(hidden_mask, 4); // tractive effort - SetBit(hidden_mask, 8); // power by running costs - } - /* Disable sorting by tractive effort when the original acceleration model for trains is being used. */ - if (this->vehicle_type == VEH_TRAIN && - _settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) { - SetBit(hidden_mask, 4); // tractive effort - } - ShowDropDownMenu(this, _sort_listing[this->vehicle_type], this->sort_criteria, WID_BV_SORT_DROPDOWN, 0, hidden_mask); - break; - } - - case WID_BV_CARGO_FILTER_DROPDOWN: // Select cargo filtering criteria dropdown menu - ShowDropDownMenu(this, this->cargo_filter_texts, this->cargo_filter_criteria, WID_BV_CARGO_FILTER_DROPDOWN, 0, 0); - break; - - case WID_BV_BUILD: { - EngineID sel_eng = this->sel_engine; - if (sel_eng != INVALID_ENGINE) { - DoCommandP(0, sel_engine, 0, CMD_BUILD_VIRTUAL_RAIL_VEHICLE, CcAddVirtualEngine); - } - break; - } - } - } - - /** - * Some data on this window has become invalid. - * @param data Information about the changed data. - * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details. - */ - virtual void OnInvalidateData(int data = 0, bool gui_scope = true) - { - if (!gui_scope) return; - /* When switching to original acceleration model for road vehicles, clear the selected sort criteria if it is not available now. */ - - this->eng_list.ForceRebuild(); - } - - virtual void SetStringParameters(int widget) const - { - switch (widget) { - case WID_BV_CAPTION: - if (this->vehicle_type == VEH_TRAIN && !this->listview_mode) { - const RailtypeInfo *rti = GetRailTypeInfo(this->filter.railtype); - SetDParam(0, rti->strings.build_caption); - } else { - SetDParam(0, (this->listview_mode ? STR_VEHICLE_LIST_AVAILABLE_TRAINS : STR_BUY_VEHICLE_TRAIN_ALL_CAPTION) + this->vehicle_type); - } - break; - - case WID_BV_SORT_DROPDOWN: - SetDParam(0, _sort_listing[this->vehicle_type][this->sort_criteria]); - break; - - case WID_BV_CARGO_FILTER_DROPDOWN: - SetDParam(0, this->cargo_filter_texts[this->cargo_filter_criteria]); - break; - } - } - - virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) - { - switch (widget) { - case WID_BV_LIST: - resize->height = GetEngineListHeight(this->vehicle_type); - size->height = 3 * resize->height; - break; - - case WID_BV_PANEL: - size->height = this->details_height; - break; - - case WID_BV_SORT_ASCENDING_DESCENDING: { - Dimension d = GetStringBoundingBox(this->GetWidget(widget)->widget_data); - d.width += padding.width + WD_CLOSEBOX_WIDTH * 2; // Doubled since the string is centred and it also looks better. - d.height += padding.height; - *size = maxdim(*size, d); - break; - } - } - } - - virtual void DrawWidget(const Rect &r, int widget) const - { - switch (widget) { - case WID_BV_LIST: - DrawEngineList(this->vehicle_type, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, - &this->eng_list, this->vscroll->GetPosition(), min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), - this->eng_list.Length()), this->sel_engine, false, DEFAULT_GROUP); - break; - - case WID_BV_SORT_ASCENDING_DESCENDING: - this->DrawSortButtonState(WID_BV_SORT_ASCENDING_DESCENDING, this->descending_sort_order ? SBS_DOWN : SBS_UP); - break; - } - } - - virtual void OnPaint() - { - this->GenerateBuildList(); - this->vscroll->SetCount(this->eng_list.Length()); - - this->DrawWidgets(); - - if (!this->IsShaded()) { - int needed_height = this->details_height; - /* Draw details panels. */ - if (this->sel_engine != INVALID_ENGINE) { - NWidgetBase *nwi = this->GetWidget(WID_BV_PANEL); - int text_end = DrawVehiclePurchaseInfo(nwi->pos_x + WD_FRAMETEXT_LEFT, nwi->pos_x + nwi->current_x - WD_FRAMETEXT_RIGHT, - nwi->pos_y + WD_FRAMERECT_TOP, this->sel_engine); - needed_height = max(needed_height, text_end - (int)nwi->pos_y + WD_FRAMERECT_BOTTOM); - } - if (needed_height != this->details_height) { // Details window are not high enough, enlarge them. - int resize = needed_height - this->details_height; - this->details_height = needed_height; - this->ReInit(0, resize); - return; - } - } - } - - virtual void OnQueryTextFinished(char *str) - { - if (str == NULL) return; - - DoCommandP(0, this->rename_engine, 0, CMD_RENAME_ENGINE | CMD_MSG(STR_ERROR_CAN_T_RENAME_TRAIN_TYPE + this->vehicle_type), NULL, str); - } - - virtual void OnDropdownSelect(int widget, int index) - { - switch (widget) { - case WID_BV_SORT_DROPDOWN: - if (this->sort_criteria != index) { - this->sort_criteria = index; - _last_sort_criteria[this->vehicle_type] = this->sort_criteria; - this->eng_list.ForceRebuild(); - } - break; - - case WID_BV_CARGO_FILTER_DROPDOWN: // Select a cargo filter criteria - if (this->cargo_filter_criteria != index) { - this->cargo_filter_criteria = index; - _last_filter_criteria[this->vehicle_type] = this->cargo_filter[this->cargo_filter_criteria]; - /* deactivate filter if criteria is 'Show All', activate it otherwise */ - this->eng_list.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY); - this->eng_list.ForceRebuild(); - } - break; - } - this->SetDirty(); - } - - virtual void OnResize() - { - this->vscroll->SetCapacityFromWidget(this, WID_BV_LIST); - this->GetWidget(WID_BV_LIST)->widget_data = (this->vscroll->GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START); - } - - void AddVirtualEngine(Train *toadd) - { - if (*virtual_train == NULL) { - *virtual_train = toadd; - } else { - VehicleID target = (*(this->virtual_train))->GetLastUnit()->index; - - DoCommandP(0, (1 << 21) | toadd->index, target, CMD_MOVE_RAIL_VEHICLE); - } - *noticeParent = true; - } -}; - -void CcAddVirtualEngine(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2) -{ - if (result.Failed()) return; - - Window* window = FindWindowById(WC_BUILD_VIRTUAL_TRAIN, 0); - if (window) { - Train* train = Train::From(Vehicle::Get(_new_vehicle_id)); - ((BuildVirtualTrainWindow*)window)->AddVirtualEngine(train); - window->InvalidateData(); - } -} - -static WindowDesc _build_vehicle_desc( - WDP_AUTO, // window position - "template create virtual train", // const char* ini_key - 240, 268, // window size - WC_BUILD_VIRTUAL_TRAIN, // window class - WC_CREATE_TEMPLATE, // parent window class - WDF_CONSTRUCTION, // window flags - _nested_build_vehicle_widgets, lengthof(_nested_build_vehicle_widgets) // widgets + num widgets -); - -void ShowBuildVirtualTrainWindow(Train **vt, bool *noticeParent) -{ - // '0' as in VEH_TRAIN = Tile=0 - assert(IsCompanyBuildableVehicleType(VEH_TRAIN)); - - DeleteWindowById(WC_BUILD_VEHICLE, 0); - - new BuildVirtualTrainWindow(&_build_vehicle_desc, vt, noticeParent); -} diff --git a/src/tbtr_template_gui_create_virtualtrain.h b/src/tbtr_template_gui_create_virtualtrain.h deleted file mode 100644 index ee0b4123c3..0000000000 --- a/src/tbtr_template_gui_create_virtualtrain.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $Id$ */ - -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file tbtr_template_gui_create_virtualtrain.cpp Template-based train replacement: template creation vehicle build GUI header. */ - -#ifndef BUILD_VIRTUAL_TRAIN_GUI -#define BUILD_VIRTUAL_TRAIN_GUI - -#include "train.h" - -void ShowBuildVirtualTrainWindow(Train**, bool*); - -#endif diff --git a/src/tbtr_template_gui_main.cpp b/src/tbtr_template_gui_main.cpp index 23960739ce..49afffed50 100644 --- a/src/tbtr_template_gui_main.cpp +++ b/src/tbtr_template_gui_main.cpp @@ -200,7 +200,6 @@ private: short selected_template_index; short selected_group_index; - bool templateNotice; bool editInProgress; public: @@ -235,7 +234,6 @@ public: this->UpdateButtonState(); - this->templateNotice = false; this->editInProgress = false; this->templates.ForceRebuild(); @@ -319,11 +317,6 @@ public: this->BuildGroupList(_local_company); - if (templateNotice) { - BuildTemplateGuiList(&this->templates, vscroll[1], _local_company, this->sel_railtype); - templateNotice = false; - this->SetDirty(); - } /* sets the colour of that art thing */ this->GetWidget(TRW_WIDGET_TRAIN_FLUFF_LEFT)->colour = _company_colours[_local_company]; this->GetWidget(TRW_WIDGET_TRAIN_FLUFF_RIGHT)->colour = _company_colours[_local_company]; @@ -392,14 +385,17 @@ public: break; } case TRW_WIDGET_TMPL_BUTTONS_DEFINE: { - ShowTemplateCreateWindow(0, &templateNotice, &editInProgress, this->line_height); + editInProgress = true; + ShowTemplateCreateWindow(0, &editInProgress, this->line_height); + UpdateButtonState(); break; } case TRW_WIDGET_TMPL_BUTTONS_EDIT: { if ((this->selected_template_index >= 0) && (this->selected_template_index < (short)this->templates.Length())) { editInProgress = true; TemplateVehicle *sel = TemplateVehicle::Get(((this->templates)[selected_template_index])->index); - ShowTemplateCreateWindow(sel, &templateNotice, &editInProgress, this->line_height); + ShowTemplateCreateWindow(sel, &editInProgress, this->line_height); + UpdateButtonState(); } break; } @@ -522,21 +518,12 @@ public: this->vscroll[2]->SetCapacity(nwi3->current_y); } - virtual void OnTick() - { - if (templateNotice) { - BuildTemplateGuiList(&this->templates, this->vscroll[1], this->owner, this->sel_railtype); - this->SetDirty(); - templateNotice = false; - } - - } - virtual void OnInvalidateData(int data = 0, bool gui_scope = true) { this->groups.ForceRebuild(); this->templates.ForceRebuild(); this->UpdateButtonState(); + this->SetDirty(); } /** For a given group (id) find the template that is issued for template replacement for this group and return this template's index @@ -791,14 +778,18 @@ public: g_id = g->index; } - this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_EDIT, !selected_ok); - this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_DELETE, !selected_ok); - this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REUSE, !selected_ok); - this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_KEEP, !selected_ok); - this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REFIT, !selected_ok); + this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_EDIT, this->editInProgress || !selected_ok); + this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_DELETE, this->editInProgress || !selected_ok); + this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REUSE, this->editInProgress || !selected_ok); + this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_KEEP, this->editInProgress ||!selected_ok); + this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REFIT, this->editInProgress ||!selected_ok); - this->SetWidgetDisabledState(TRW_WIDGET_START, !(selected_ok && group_ok && FindTemplateIndexForGroup(g_id) != this->selected_template_index)); - this->SetWidgetDisabledState(TRW_WIDGET_STOP, !(group_ok && GetTemplateReplacementByGroupID(g_id) != NULL)); + this->SetWidgetDisabledState(TRW_WIDGET_START, this->editInProgress || !(selected_ok && group_ok && FindTemplateIndexForGroup(g_id) != this->selected_template_index)); + this->SetWidgetDisabledState(TRW_WIDGET_STOP, this->editInProgress || !(group_ok && GetTemplateReplacementByGroupID(g_id) != NULL)); + + this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_DEFINE, this->editInProgress); + this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CLONE, this->editInProgress); + this->SetWidgetDisabledState(TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN, this->editInProgress); } }; From 5b6560b73b047bd57c1ef4b0d4bd39f7427696de Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 15 Feb 2016 19:28:14 +0000 Subject: [PATCH 5/9] TBTR: Handle template being deleted during edit. --- src/tbtr_template_gui_create.cpp | 37 +++++++++++++++++--------------- src/vehicle_cmd.cpp | 1 + 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/tbtr_template_gui_create.cpp b/src/tbtr_template_gui_create.cpp index 1e9c174a5d..01b4e28848 100644 --- a/src/tbtr_template_gui_create.cpp +++ b/src/tbtr_template_gui_create.cpp @@ -131,14 +131,13 @@ private: Scrollbar *vscroll; int line_height; Train* virtual_train; - bool editMode; - bool *createWindowOpen; /// used to notify main window of progress (dummy way of disabling 'delete' while editing a template) + bool *create_window_open; /// used to notify main window of progress (dummy way of disabling 'delete' while editing a template) VehicleID sel; VehicleID vehicle_over; - TemplateVehicle *editTemplate; + uint32 template_index; public: - TemplateCreateWindow(WindowDesc* _wdesc, TemplateVehicle *to_edit, bool *windowOpen, int step_h) : Window(_wdesc) + TemplateCreateWindow(WindowDesc* _wdesc, TemplateVehicle *to_edit, bool *window_open, int step_h) : Window(_wdesc) { this->line_height = step_h; this->CreateNestedTree(_wdesc != NULL); @@ -150,15 +149,13 @@ public: this->owner = _local_company; - createWindowOpen = windowOpen; - this->editTemplate = to_edit; - - editMode = (to_edit != NULL); + this->create_window_open = window_open; + this->template_index = (to_edit != NULL) ? to_edit->index : INVALID_VEHICLE; this->sel = INVALID_VEHICLE; this->vehicle_over = INVALID_VEHICLE; - if (to_edit) { + if (to_edit != NULL) { DoCommandP(0, to_edit->index, 0, CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE | CMD_MSG(STR_TMPL_CANT_CREATE), CcSetVirtualTrain); } @@ -177,7 +174,7 @@ public: SetWindowClassesDirty(WC_TRAINS_LIST); /* more cleanup */ - *createWindowOpen = false; + *create_window_open = false; DeleteWindowById(WC_BUILD_VIRTUAL_TRAIN, this->window_number); InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN); } @@ -204,6 +201,14 @@ public: virtual void OnInvalidateData(int data = 0, bool gui_scope = true) { + if(!gui_scope) return; + + if (this->template_index != INVALID_VEHICLE) { + if (TemplateVehicle::GetIfValid(this->template_index) == NULL) { + delete this; + return; + } + } this->SetDirty(); UpdateButtonState(); } @@ -231,13 +236,11 @@ public: break; } case TCW_OK: { - uint32 templateIndex = (editTemplate != NULL) ? editTemplate->index : INVALID_VEHICLE; - if (virtual_train != NULL) { - DoCommandP(0, templateIndex, virtual_train->index, CMD_REPLACE_TEMPLATE_VEHICLE); + DoCommandP(0, this->template_index, virtual_train->index, CMD_REPLACE_TEMPLATE_VEHICLE); virtual_train = NULL; - } else if (templateIndex != INVALID_VEHICLE) { - DoCommandP(0, templateIndex, 0, CMD_DELETE_TEMPLATE_VEHICLE); + } else if (this->template_index != INVALID_VEHICLE) { + DoCommandP(0, this->template_index, 0, CMD_DELETE_TEMPLATE_VEHICLE); } delete this; break; @@ -536,10 +539,10 @@ public: } }; -void ShowTemplateCreateWindow(TemplateVehicle *to_edit, bool *createWindowOpen, int step_h) +void ShowTemplateCreateWindow(TemplateVehicle *to_edit, bool *create_window_open, int step_h) { if (BringWindowToFrontById(WC_CREATE_TEMPLATE, VEH_TRAIN) != NULL) return; - new TemplateCreateWindow(&_template_create_window_desc, to_edit, createWindowOpen, step_h); + new TemplateCreateWindow(&_template_create_window_desc, to_edit, create_window_open, step_h); } void CcSetVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2) diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index f6f6c00d5a..968a23569a 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -1186,6 +1186,7 @@ CommandCost CmdDeleteTemplateVehicle(TileIndex tile, DoCommandFlag flags, uint32 delete del; + InvalidateWindowClassesData(WC_CREATE_TEMPLATE, 0); InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN, 0); } From 89aeb973f8330b707762db0278a96b498cfff780 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 15 Feb 2016 19:29:00 +0000 Subject: [PATCH 6/9] TBTR: Fix create window not being redrawn when selling vehs in MP. --- src/tbtr_template_gui_create.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/tbtr_template_gui_create.cpp b/src/tbtr_template_gui_create.cpp index 01b4e28848..1b858c8e1c 100644 --- a/src/tbtr_template_gui_create.cpp +++ b/src/tbtr_template_gui_create.cpp @@ -365,7 +365,7 @@ public: virtual_train = (_ctrl_pressed) ? NULL : virtual_train->GetNextUnit(); } - DoCommandP(0, this->sel | (sell_cmd << 20) | (1 << 21), 0, GetCmdSellVeh(VEH_TRAIN)); + DoCommandP(0, this->sel | (sell_cmd << 20) | (1 << 21), 0, GetCmdSellVeh(VEH_TRAIN), CcDeleteVirtualTrain); this->sel = INVALID_VEHICLE; @@ -570,6 +570,10 @@ void CcVirtualTrainWaggonsMoved(const CommandCost &result, TileIndex tile, uint3 void CcDeleteVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2) { - VehicleID virtual_train_id = p2; - DoCommandP(0, virtual_train_id, 0, CMD_DELETE_VIRTUAL_TRAIN); + if (result.Failed()) return; + + Window* window = FindWindowById(WC_CREATE_TEMPLATE, 0); + if (window) { + window->InvalidateData(); + } } From 77ca3269973c85c45866defb480484141673afb5 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 15 Feb 2016 20:36:17 +0000 Subject: [PATCH 7/9] TBTR: Fix main window in double scale mode, and misc alignment issues. --- src/tbtr_template_gui_main.cpp | 51 ++++++++++++++++++------------ src/tbtr_template_vehicle_func.cpp | 3 +- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/tbtr_template_gui_main.cpp b/src/tbtr_template_gui_main.cpp index 49afffed50..2873372b63 100644 --- a/src/tbtr_template_gui_main.cpp +++ b/src/tbtr_template_gui_main.cpp @@ -28,6 +28,7 @@ #include "core/geometry_func.hpp" #include "rail_gui.h" #include "network/network.h" +#include "zoom_func.h" #include "table/sprites.h" #include "table/strings.h" @@ -269,6 +270,9 @@ public: *size = maxdim(*size, d); break; } + default: + size->width = ScaleGUITrad(size->width); + break; } } @@ -615,20 +619,22 @@ public: /* Fill the background of the current cell in a darker tone for the currently selected template */ if (this->selected_group_index == i) { - GfxFillRect(left, y, right, y+(this->line_height) / 2, _colour_gradient[COLOUR_GREY][3]); + GfxFillRect(r.left + 1, y, r.right, y + (this->line_height) / 2, _colour_gradient[COLOUR_GREY][3]); } + int text_y = y + ScaleGUITrad(3); + SetDParam(0, g_id); StringID str = STR_GROUP_NAME; - DrawString(left + 30 + this->indents[i] * 10, right, y + 2, str, TC_BLACK); + DrawString(left + ScaleGUITrad(30 + this->indents[i] * 10), right, text_y, str, TC_BLACK); /* Draw the template in use for this group, if there is one */ short template_in_use = FindTemplateIndexForGroup(g_id); if (template_in_use >= 0) { SetDParam(0, template_in_use); - DrawString (left, right, y + 2, STR_TMPL_GROUP_USES_TEMPLATE, TC_BLACK, SA_HOR_CENTER); + DrawString (left, right, text_y, STR_TMPL_GROUP_USES_TEMPLATE, TC_BLACK, SA_HOR_CENTER); } else if (GetTemplateReplacementByGroupID(g_id)) { /* If there isn't a template applied from the current group, check if there is one for another rail type */ - DrawString (left, right, y + 2, STR_TMPL_TMPLRPL_EX_DIFF_RAILTYPE, TC_SILVER, SA_HOR_CENTER); + DrawString (left, right, text_y, STR_TMPL_TMPLRPL_EX_DIFF_RAILTYPE, TC_SILVER, SA_HOR_CENTER); } /* Draw the number of trains that still need to be treated by the currently selected template replacement */ @@ -639,7 +645,7 @@ public: // Draw text TextColour color = TC_GREY; if (num_trains) color = TC_BLACK; - DrawString(left, right - 16, y + 2, STR_TMPL_NUM_TRAINS_NEED_RPL, color, SA_RIGHT); + DrawString(left, right - ScaleGUITrad(16), text_y, STR_TMPL_NUM_TRAINS_NEED_RPL, color, SA_RIGHT); // Draw number if (num_trains ) { color = TC_ORANGE; @@ -647,7 +653,7 @@ public: color = TC_GREY; } SetDParam(0, num_trains); - DrawString(left, right - 4, y + 2, STR_JUST_INT, color, SA_RIGHT); + DrawString(left, right - ScaleGUITrad(4), text_y, STR_JUST_INT, color, SA_RIGHT); } y += line_height / 2; @@ -669,46 +675,49 @@ public: /* Fill the background of the current cell in a darker tone for the currently selected template */ if (this->selected_template_index == (int32) i) { - GfxFillRect(left, y, right, y + this->line_height, _colour_gradient[COLOUR_GREY][3]); + GfxFillRect(left + 1, y, right, y + this->line_height, _colour_gradient[COLOUR_GREY][3]); } + /* Draw the template */ + DrawTemplate(v, left + ScaleGUITrad(50), right, y); + /* Draw a notification string for chains that are not runnable */ if (v->IsFreeWagonChain()) { - DrawString(left, right - 2, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 2, STR_TMPL_WARNING_FREE_WAGON, TC_RED, SA_RIGHT); + DrawString(left, right - ScaleGUITrad(24), y + ScaleGUITrad(2), STR_TMPL_WARNING_FREE_WAGON, TC_RED, SA_RIGHT); } /* Draw the template's length in tile-units */ SetDParam(0, v->GetRealLength()); SetDParam(1, 1); - DrawString(left, right - 4, y + 2, STR_TINY_BLACK_DECIMAL, TC_BLACK, SA_RIGHT); + DrawString(left, right - ScaleGUITrad(4), y + ScaleGUITrad(2), STR_TINY_BLACK_DECIMAL, TC_BLACK, SA_RIGHT); - /* Draw the template */ - DrawTemplate(v, left + 50, right, y); + int bottom_edge = y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - ScaleGUITrad(4); /* Buying cost */ SetDParam(0, CalculateOverallTemplateCost(v)); - DrawString(left + 35, right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 2, STR_TMPL_TEMPLATE_OVR_VALUE_notinyfont, TC_BLUE, SA_LEFT); + DrawString(left + ScaleGUITrad(35), right, bottom_edge, STR_TMPL_TEMPLATE_OVR_VALUE_notinyfont, TC_BLUE, SA_LEFT); /* Index of current template vehicle in the list of all templates for its company */ SetDParam(0, i); - DrawString(left + 5, left + 25, y + 2, STR_BLACK_INT, TC_BLACK, SA_RIGHT); + DrawString(left + ScaleGUITrad(5), left + ScaleGUITrad(25), y + ScaleGUITrad(2), STR_BLACK_INT, TC_BLACK, SA_RIGHT); /* Draw whether the current template is in use by any group */ if (v->NumGroupsUsingTemplate() > 0) { - DrawString(left + 35, right, y + line_height - FONT_HEIGHT_SMALL * 2 - 4 - WD_FRAMERECT_BOTTOM - 2, STR_TMP_TEMPLATE_IN_USE, TC_GREEN, SA_LEFT); + DrawString(left + ScaleGUITrad(35), right, bottom_edge - FONT_HEIGHT_SMALL - ScaleGUITrad(3), + STR_TMP_TEMPLATE_IN_USE, TC_GREEN, SA_LEFT); } /* Draw information about template configuration settings */ TextColour color; color = v->IsSetReuseDepotVehicles() ? TC_LIGHT_BLUE : TC_GREY; - DrawString(right - 225, right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 2, STR_TMPL_CONFIG_USEDEPOT, color, SA_LEFT); + DrawString(right - ScaleGUITrad(225), right, bottom_edge, STR_TMPL_CONFIG_USEDEPOT, color, SA_LEFT); color = v->IsSetKeepRemainingVehicles() ? TC_LIGHT_BLUE : TC_GREY; - DrawString(right - 150, right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 2, STR_TMPL_CONFIG_KEEPREMAINDERS, color, SA_LEFT); + DrawString(right - ScaleGUITrad(150), right, bottom_edge, STR_TMPL_CONFIG_KEEPREMAINDERS, color, SA_LEFT); color = v->IsSetRefitAsTemplate() ? TC_LIGHT_BLUE : TC_GREY; - DrawString(right - 75, right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 2, STR_TMPL_CONFIG_REFIT, color, SA_LEFT); + DrawString(right - ScaleGUITrad(75), right, bottom_edge, STR_TMPL_CONFIG_REFIT, color, SA_LEFT); y += line_height; } @@ -736,11 +745,11 @@ public: SetDParam(1, tmp->power); SetDParam(0, tmp->weight); SetDParam(3, tmp->max_te); - DrawString(8, r.right, 4 - this->vscroll[2]->GetPosition(), STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE); + DrawString(8, r.right, ScaleGUITrad(4) - this->vscroll[2]->GetPosition(), STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE); /* Draw cargo summary */ - short top = 30 - this->vscroll[2]->GetPosition(); - short left = 8; + short top = ScaleGUITrad(30) - this->vscroll[2]->GetPosition(); + short left = ScaleGUITrad(8); short count_columns = 0; short max_columns = 2; @@ -756,7 +765,7 @@ public: SetDParam(1, cargo_caps[i]); SetDParam(2, _settings_game.vehicle.freight_trains); DrawString(x, r.right, top, FreightWagonMult(i) > 1 ? STR_TMPL_CARGO_SUMMARY_MULTI : STR_TMPL_CARGO_SUMMARY, TC_LIGHT_BLUE, SA_LEFT); - x += 250; + x += ScaleGUITrad(250); if (count_columns % max_columns == 0) { x = left; top += this->line_height / 3; diff --git a/src/tbtr_template_vehicle_func.cpp b/src/tbtr_template_vehicle_func.cpp index 7064659296..0c0b8d1050 100644 --- a/src/tbtr_template_vehicle_func.cpp +++ b/src/tbtr_template_vehicle_func.cpp @@ -20,6 +20,7 @@ #include "vehicle_func.h" #include "core/geometry_type.hpp" #include "debug.h" +#include "zoom_func.h" #include "table/sprites.h" #include "table/strings.h" @@ -123,7 +124,7 @@ void DrawTemplate(const TemplateVehicle *tv, int left, int right, int y) while (t) { PaletteID pal = GetEnginePalette(t->engine_type, _current_company); - DrawSprite(t->cur_image, pal, offset, y + 12); + DrawSprite(t->cur_image, pal, offset, y + ScaleGUITrad(11)); offset += t->image_width; t = t->Next(); From d688039a4234231039e7d104f236a5e387344502 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 15 Feb 2016 23:19:41 +0000 Subject: [PATCH 8/9] TBTR: Update template veh sprite IDs when loading savegame/GRFs. --- src/saveload/afterload.cpp | 4 ++++ src/saveload/saveload_internal.h | 2 ++ src/saveload/tbtr_template_veh_sl.cpp | 33 +++++++++++++++++++++++++++ src/tbtr_template_vehicle.h | 1 - src/vehicle_cmd.cpp | 3 +-- 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 9b3b7c27e9..477786cf2e 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2991,6 +2991,9 @@ bool AfterLoadGame() ResetSignalHandlers(); AfterLoadLinkGraphs(); + + AfterLoadTemplateVehiclesUpdateImage(); + return true; } @@ -3028,4 +3031,5 @@ void ReloadNewGRFData() /* redraw the whole screen */ MarkWholeScreenDirty(); CheckTrainsLengths(); + AfterLoadTemplateVehiclesUpdateImage(); } diff --git a/src/saveload/saveload_internal.h b/src/saveload/saveload_internal.h index 67b3038a04..914e833f87 100644 --- a/src/saveload/saveload_internal.h +++ b/src/saveload/saveload_internal.h @@ -48,6 +48,8 @@ void ConnectMultiheadedTrains(); Engine *GetTempDataEngine(EngineID index); void CopyTempEngineData(); +void AfterLoadTemplateVehiclesUpdateImage(); + extern int32 _saved_scrollpos_x; extern int32 _saved_scrollpos_y; extern ZoomLevelByte _saved_scrollpos_zoom; diff --git a/src/saveload/tbtr_template_veh_sl.cpp b/src/saveload/tbtr_template_veh_sl.cpp index 3c6ca9e0b6..60c8b6080b 100644 --- a/src/saveload/tbtr_template_veh_sl.cpp +++ b/src/saveload/tbtr_template_veh_sl.cpp @@ -1,6 +1,8 @@ #include "../stdafx.h" #include "../tbtr_template_vehicle.h" +#include "../tbtr_template_vehicle_func.h" +#include "../train.h" #include "saveload.h" @@ -94,6 +96,37 @@ void AfterLoadTemplateVehicles() } } +void AfterLoadTemplateVehiclesUpdateImage() +{ + TemplateVehicle *tv; + + FOR_ALL_TEMPLATES(tv) { + if (tv->Prev() == NULL) { + StringID err; + Train* t = VirtualTrainFromTemplateVehicle(tv, err); + if (t != NULL) { + int tv_len = 0; + for (TemplateVehicle *u = tv; u != NULL; u = u->Next()) { + tv_len++; + } + int t_len = 0; + for (Train *u = t; u != NULL; u = u->Next()) { + t_len++; + } + if (t_len == tv_len) { + Train *v = t; + for (TemplateVehicle *u = tv; u != NULL; u = u->Next(), v = v->Next()) { + u->spritenum = v->spritenum; + u->cur_image = v->GetImage(DIR_W, EIT_PURCHASE); + u->image_width = v->GetDisplayImageWidth(); + } + } + delete t; + } + } + } +} + extern const ChunkHandler _template_vehicle_chunk_handlers[] = { {'TMPL', Save_TMPLS, Load_TMPLS, Ptrs_TMPLS, NULL, CH_ARRAY | CH_LAST}, }; diff --git a/src/tbtr_template_vehicle.h b/src/tbtr_template_vehicle.h index 0631f85b8d..e4331a1f5a 100644 --- a/src/tbtr_template_vehicle.h +++ b/src/tbtr_template_vehicle.h @@ -92,7 +92,6 @@ public: byte spritenum; SpriteID cur_image; uint32 image_width; - const SpriteGroup *sgroup; TemplateVehicle(VehicleType type = VEH_INVALID, EngineID e = INVALID_ENGINE, byte B = 0, Owner = _local_company); TemplateVehicle(EngineID, RailVehicleInfo*); diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 968a23569a..477c30e10f 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -810,8 +810,7 @@ inline void SetupTemplateVehicleFromVirtual(TemplateVehicle *tmp, TemplateVehicl tmp->spritenum = virt->spritenum; tmp->cur_image = virt->GetImage(DIR_W, EIT_PURCHASE); - Point *p = new Point(); - tmp->image_width = virt->GetDisplayImageWidth(p); + tmp->image_width = virt->GetDisplayImageWidth(); } /** From 4f052d3cadd1162698bbdd59125b8b98aa2da6de Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 16 Feb 2016 21:02:53 +0000 Subject: [PATCH 9/9] Fix clone template from vehicle validation for artic vehicles. --- src/vehicle_cmd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 477c30e10f..3622dbd287 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -1130,7 +1130,7 @@ CommandCost CmdTemplateVehicleFromTrain(TileIndex tile, DoCommandFlag flags, uin return CMD_ERROR; } - for (Train *v = clicked; v != NULL; v = v->Next()) { + for (Train *v = clicked; v != NULL; v = v->GetNextUnit()) { if (!IsEngineBuildable(v->engine_type, VEH_TRAIN, _current_company)) { return_cmd_error(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + VEH_TRAIN); }