Allow selecting individual ship parts in refit window
Add callback to name ship parts in refit window
This commit is contained in:
@@ -83,6 +83,14 @@
|
||||
Additional ship parts may be refitted individually.
|
||||
<p>This requires the <span class="code">multi_part_ships</span> feature.</p>
|
||||
</p>
|
||||
<p>
|
||||
Added callback: <span class="code">refit_part_name</span><br />
|
||||
This callback is called on the primary vehicle to get the name of each part of the ship (e.g. the name of each cargo hold) in the refit window.<br />
|
||||
This is not called for ships of only one part.<br />
|
||||
The callback handler should return a string or CB_RESULT_NO_TEXT.<br />
|
||||
If this callback is not handled or if CB_RESULT_NO_TEXT is returned, a default name is used.<br />
|
||||
<span class="code">getbits(extra_callback_info1, 0, 8)</span> contains the index of the part of the ship. The first/primary part is 0, each subsequent part increases the value by 1.
|
||||
</p>
|
||||
|
||||
<h3 id="railtype-properties"><a href="https://newgrf-specs.tt-wiki.net/wiki/NML:Railtypes#Railtype_properties">Railtype properties</a></h3>
|
||||
<table>
|
||||
|
@@ -901,6 +901,18 @@
|
||||
Additional ship parts may be refitted individually.
|
||||
</p>
|
||||
<p>This is indicated by the feature name: <font face="monospace">multi_part_ships</font>, version 1</p>
|
||||
<p><b>Callback EC008002 - Ship part name for refit window</b><br />
|
||||
This callback is called on the primary vehicle to get the name of each part of the ship (e.g. the name of each cargo hold) in the refit window.<br />
|
||||
This is not called for ships of only one part.<br />
|
||||
If this callback is not handled, a default name is used.<br />
|
||||
Bits 0 - 7 of variable 10 contains the index of the part of the ship. The first/primary part is 0, each subsequent part increases the value by 1.
|
||||
</p>
|
||||
<p>
|
||||
The return value should be the number of a D0xx text to be displayed. The contents of registers 100h..105h are copied onto the text reference stack and can be used with string codes 80/81 to show texts from the D8xx range as well, extending the available unique strings.<br />
|
||||
You can return 400 to use the default name (instead of failing the callback).<br />
|
||||
(This is the same return format as callbacks: 23, 38, 3A, 14D, 15C, 161).
|
||||
</p>
|
||||
<p>This is indicated by the feature name: <font face="monospace">multi_part_ships</font>, version 1</p>
|
||||
<br />
|
||||
<br />
|
||||
<h3 id="a3objects"><a href="https://newgrf-specs.tt-wiki.net/wiki/Action3">Action 3 - Objects</a></h3>
|
||||
|
@@ -2022,3 +2022,7 @@ STR_MODIFIER_TOGGLE_SHIFT_TOOLTIP :{BLACK}Click to
|
||||
STR_MODIFIER_TOGGLE_CTRL_TOOLTIP :{BLACK}Click to invert state of Ctrl key
|
||||
|
||||
STR_ERROR_TUNNEL_DISALLOWED_ROAD :{WHITE}Tunnels not allowed for this road type
|
||||
|
||||
STR_REFIT_SHIP_PART_DROPDOWN_TOOLTIP :{BLACK}Select which part of this ship to refit
|
||||
STR_REFIT_WHOLE_SHIP :Whole ship
|
||||
STR_REFIT_SHIP_PART :Part {NUM}
|
||||
|
@@ -287,6 +287,9 @@ enum CallbackID {
|
||||
|
||||
/** Called to set town zones */
|
||||
XCBID_TOWN_ZONES = 0xEC008001,
|
||||
|
||||
/** Called to get the name of the part of a ship for the refit window */
|
||||
XCBID_SHIP_REFIT_PART_NAME = 0xEC008002,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1656,6 +1656,7 @@ const char *GetNewGRFCallbackName(CallbackID cbid)
|
||||
CBID(CBID_VEHICLE_SPAWN_VISUAL_EFFECT)
|
||||
CBID(CBID_VEHICLE_NAME)
|
||||
CBID(XCBID_TOWN_ZONES)
|
||||
CBID(XCBID_SHIP_REFIT_PART_NAME)
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
@@ -692,6 +692,7 @@ struct RefitWindow : public Window {
|
||||
uint8 num_vehicles; ///< Number of selected vehicles.
|
||||
bool auto_refit; ///< Select cargo for auto-refitting.
|
||||
bool is_virtual_train; ///< TemplateReplacement, whether the selected vehicle is virtual
|
||||
mutable std::map<VehicleID, std::string> ship_part_names; ///< Ship part name strings
|
||||
|
||||
/**
|
||||
* Collects all (cargo, subcargo) refit options of a vehicle chain.
|
||||
@@ -707,6 +708,7 @@ struct RefitWindow : public Window {
|
||||
|
||||
do {
|
||||
if (v->type == VEH_TRAIN && std::find(vehicles_to_refit.begin(), vehicles_to_refit.end(), v->index) == vehicles_to_refit.end()) continue;
|
||||
if (v->type == VEH_SHIP && this->num_vehicles == 1 && v->index != this->selected_vehicle) continue;
|
||||
const Engine *e = v->GetEngine();
|
||||
CargoTypes cmask = e->info.refit_mask;
|
||||
byte callback_mask = e->info.callback_mask;
|
||||
@@ -798,7 +800,7 @@ struct RefitWindow : public Window {
|
||||
}
|
||||
current_index++;
|
||||
}
|
||||
} while (v->IsGroundVehicle() && (v = v->Next()) != nullptr);
|
||||
} while (v->IsArticulatedCallbackVehicleType() && (v = v->Next()) != nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -885,7 +887,15 @@ struct RefitWindow : public Window {
|
||||
NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_VR_REFIT);
|
||||
nwi->widget_data = STR_REFIT_TRAIN_REFIT_BUTTON + v->type;
|
||||
nwi->tool_tip = STR_REFIT_TRAIN_REFIT_TOOLTIP + v->type;
|
||||
this->GetWidget<NWidgetStacked>(WID_VR_SHOW_HSCROLLBAR)->SetDisplayedPlane(v->IsGroundVehicle() ? 0 : SZSP_HORIZONTAL);
|
||||
int hscrollbar_pane;
|
||||
if (v->IsGroundVehicle()) {
|
||||
hscrollbar_pane = 0;
|
||||
} else if (v->type == VEH_SHIP && v->Next() != nullptr && this->order == INVALID_VEH_ORDER_ID) {
|
||||
hscrollbar_pane = 1;
|
||||
} else {
|
||||
hscrollbar_pane = SZSP_HORIZONTAL;
|
||||
}
|
||||
this->GetWidget<NWidgetStacked>(WID_VR_SHOW_HSCROLLBAR)->SetDisplayedPlane(hscrollbar_pane);
|
||||
this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY)->tool_tip = (v->type == VEH_TRAIN) ? STR_REFIT_SELECT_VEHICLES_TOOLTIP : STR_NULL;
|
||||
|
||||
this->FinishInitNested(v->index);
|
||||
@@ -998,9 +1008,45 @@ struct RefitWindow : public Window {
|
||||
}
|
||||
}
|
||||
|
||||
const std::string &GetShipPartName(const Vehicle *v) const
|
||||
{
|
||||
std::string &name = this->ship_part_names[v->index];
|
||||
if (name.empty()) {
|
||||
char buffer[128] = "";
|
||||
const Vehicle *front = v->First();
|
||||
uint offset = 0;
|
||||
for (const Vehicle *u = front; u != v; u = u->Next()) offset++;
|
||||
uint16 callback = GetVehicleCallback(XCBID_SHIP_REFIT_PART_NAME, offset, 0, front->engine_type, front);
|
||||
if (callback != CALLBACK_FAILED && callback < 0x400) {
|
||||
const GRFFile *grffile = v->GetGRF();
|
||||
assert(grffile != nullptr);
|
||||
|
||||
StartTextRefStackUsage(grffile, 6);
|
||||
char *end = GetString(buffer, GetGRFStringID(grffile->grfid, 0xD000 + callback), lastof(buffer));
|
||||
StopTextRefStackUsage();
|
||||
|
||||
name.assign(buffer, end - buffer);
|
||||
} else {
|
||||
SetDParam(0, offset + 1);
|
||||
char *end = GetString(buffer, STR_REFIT_SHIP_PART, lastof(buffer));
|
||||
name.assign(buffer, end - buffer);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
void SetStringParameters(int widget) const override
|
||||
{
|
||||
if (widget == WID_VR_CAPTION) SetDParam(0, Vehicle::Get(this->window_number)->index);
|
||||
|
||||
if (widget == WID_VR_VEHICLE_DROPDOWN) {
|
||||
if (this->num_vehicles == 1) {
|
||||
SetDParam(0, STR_JUST_RAW_STRING);
|
||||
SetDParamStr(1, this->GetShipPartName(Vehicle::Get(this->selected_vehicle)));
|
||||
} else {
|
||||
SetDParam(0, STR_REFIT_WHOLE_SHIP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1147,6 +1193,7 @@ struct RefitWindow : public Window {
|
||||
Vehicle *v = Vehicle::Get(this->window_number);
|
||||
this->selected_vehicle = v->index;
|
||||
this->num_vehicles = UINT8_MAX;
|
||||
this->ship_part_names.clear();
|
||||
FALLTHROUGH;
|
||||
}
|
||||
|
||||
@@ -1246,6 +1293,29 @@ struct RefitWindow : public Window {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnDropdownSelect(int widget, int index) override
|
||||
{
|
||||
if (widget != WID_VR_VEHICLE_DROPDOWN) return;
|
||||
|
||||
const Vehicle *v = Vehicle::Get(this->window_number);
|
||||
|
||||
if (index > 0) {
|
||||
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
|
||||
if (index == 1) {
|
||||
this->selected_vehicle = u->index;
|
||||
this->num_vehicles = 1;
|
||||
this->InvalidateData(2);
|
||||
return;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
}
|
||||
|
||||
this->selected_vehicle = v->index;
|
||||
this->num_vehicles = UINT8_MAX;
|
||||
this->InvalidateData(2);
|
||||
}
|
||||
|
||||
void OnClick(Point pt, int widget, int click_count) override
|
||||
{
|
||||
switch (widget) {
|
||||
@@ -1288,6 +1358,26 @@ struct RefitWindow : public Window {
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WID_VR_VEHICLE_DROPDOWN: {
|
||||
const Vehicle *v = Vehicle::Get(this->window_number);
|
||||
if (v->type != VEH_SHIP) break;
|
||||
|
||||
DropDownList dlist;
|
||||
int selected = 0;
|
||||
dlist.emplace_back(new DropDownListStringItem(STR_REFIT_WHOLE_SHIP, 0, false));
|
||||
|
||||
int offset = 1;
|
||||
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
|
||||
if (u->index == this->selected_vehicle && this->num_vehicles == 1) selected = offset;
|
||||
DropDownListCharStringItem *item = new DropDownListCharStringItem(this->GetShipPartName(u), offset, false);
|
||||
dlist.emplace_back(item);
|
||||
offset++;
|
||||
}
|
||||
|
||||
ShowDropDownList(this, std::move(dlist), selected, WID_VR_VEHICLE_DROPDOWN, 0, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1336,6 +1426,7 @@ static const NWidgetPart _nested_vehicle_refit_widgets[] = {
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_VR_VEHICLE_PANEL_DISPLAY), SetMinimalSize(228, 14), SetResize(1, 0), SetScrollbar(WID_VR_HSCROLLBAR), EndContainer(),
|
||||
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VR_SHOW_HSCROLLBAR),
|
||||
NWidget(NWID_HSCROLLBAR, COLOUR_GREY, WID_VR_HSCROLLBAR),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VR_VEHICLE_DROPDOWN), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_JUST_STRING1, STR_REFIT_SHIP_PART_DROPDOWN_TOOLTIP),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_VR_SELECT_HEADER), SetDataTip(STR_REFIT_TITLE, STR_NULL), SetResize(1, 0),
|
||||
|
@@ -36,6 +36,7 @@ enum VehicleRefitWidgets {
|
||||
WID_VR_VEHICLE_PANEL_DISPLAY, ///< Display with a representation of the vehicle to refit.
|
||||
WID_VR_SHOW_HSCROLLBAR, ///< Selection widget for the horizontal scrollbar.
|
||||
WID_VR_HSCROLLBAR, ///< Horizontal scrollbar or the vehicle display.
|
||||
WID_VR_VEHICLE_DROPDOWN, ///< Dropdown for the vehicle display.
|
||||
WID_VR_SELECT_HEADER, ///< Header with question about the cargo to carry.
|
||||
WID_VR_MATRIX, ///< Options to refit to.
|
||||
WID_VR_SCROLLBAR, ///< Scrollbar for the refit options.
|
||||
|
Reference in New Issue
Block a user