Tracerestrict: Add a group membership conditional.

pull/8/head
Jonathan G Rennison 8 years ago
parent 4d94470d08
commit 213b0e7e3a

@ -21,6 +21,7 @@
#include "company_func.h"
#include "core/pool_func.hpp"
#include "order_backup.h"
#include "tracerestrict.h"
#include "table/strings.h"
@ -341,6 +342,9 @@ CommandCost CmdDeleteGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
VehicleType vt = g->vehicle_type;
/* notify tracerestrict that group is about to be deleted */
TraceRestrictRemoveGroupID(g->index);
/* Delete the Replace Vehicle Windows */
DeleteWindowById(WC_REPLACE_VEHICLE, g->vehicle_type);
delete g;

@ -95,6 +95,29 @@ static const NWidgetPart _nested_group_widgets[] = {
EndContainer(),
};
/** Sort the groups by their name */
int CDECL GroupNameSorter(const Group * const *a, const Group * const *b)
{
static const Group *last_group[2] = { NULL, NULL };
static char last_name[2][64] = { "", "" };
if (*a != last_group[0]) {
last_group[0] = *a;
SetDParam(0, (*a)->index);
GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0]));
}
if (*b != last_group[1]) {
last_group[1] = *b;
SetDParam(0, (*b)->index);
GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1]));
}
int r = strnatcmp(last_name[0], last_name[1]); // Sort by name (natural sorting).
if (r == 0) return (*a)->index - (*b)->index;
return r;
}
class VehicleGroupWindow : public BaseVehicleListWindow {
private:
/* Columns in the group list */
@ -132,29 +155,6 @@ private:
}
}
/** Sort the groups by their name */
static int CDECL GroupNameSorter(const Group * const *a, const Group * const *b)
{
static const Group *last_group[2] = { NULL, NULL };
static char last_name[2][64] = { "", "" };
if (*a != last_group[0]) {
last_group[0] = *a;
SetDParam(0, (*a)->index);
GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0]));
}
if (*b != last_group[1]) {
last_group[1] = *b;
SetDParam(0, (*b)->index);
GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1]));
}
int r = strnatcmp(last_name[0], last_name[1]); // Sort by name (natural sorting).
if (r == 0) return (*a)->index - (*b)->index;
return r;
}
/**
* (Re)Build the group list.
*

@ -2395,7 +2395,9 @@ STR_TRACE_RESTRICT_VARIABLE_CARGO :cargo
STR_TRACE_RESTRICT_VARIABLE_ENTRY_DIRECTION :entry direction
STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL :PBS entry signal
STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL_LONG :entered signal of PBS block
STR_TRACE_RESTRICT_VARIABLE_TRAIN_GROUP :train group
STR_TRACE_RESTRICT_VARIABLE_UNDEFINED :undefined
STR_TRACE_RESTRICT_VARIABLE_UNDEFINED_RED :{RED}undefined
STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_INTEGER :{STRING} {STRING} {STRING} {COMMA} then
STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_SPEED :{STRING} {STRING} {STRING} {VELOCITY} then
STR_TRACE_RESTRICT_CONDITIONAL_ORDER_STATION :{STRING} {STRING} {STRING} {STATION} then
@ -2405,6 +2407,8 @@ STR_TRACE_RESTRICT_CONDITIONAL_CARGO :{STRING} train
STR_TRACE_RESTRICT_CONDITIONAL_ENTRY_DIRECTION :{STRING} train {STRING} entering from {STRING} tile edge then
STR_TRACE_RESTRICT_CONDITIONAL_ENTRY_SIGNAL_FACE :{STRING} train {STRING} entering from {STRING} of signal then
STR_TRACE_RESTRICT_CONDITIONAL_TILE_INDEX :{STRING} {STRING} {STRING} at {NUM} x {NUM} then
STR_TRACE_RESTRICT_CONDITIONAL_GROUP :{STRING} train {STRING} in group: {GROUP} then
STR_TRACE_RESTRICT_CONDITIONAL_GROUP_STR :{STRING} train {STRING} in group: {STRING} {BLACK}{STRING}then
STR_TRACE_RESTRICT_CONDITIONAL_UNDEFINED :{STRING} {STRING} {STRING} {RED}undefined {BLACK}{STRING}then
STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_UNDEFINED :{STRING} {RED}undefined {BLACK}{STRING}then
STR_TRACE_RESTRICT_PF_PENALTY_ITEM :Add pathfinder penalty: {COMMA}

@ -18,6 +18,7 @@
#include "window_func.h"
#include "order_base.h"
#include "cargotype.h"
#include "group.h"
#include "pathfinder/yapf/yapf_cache.h"
#include <vector>
@ -343,6 +344,11 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
break;
}
case TRIT_COND_TRAIN_GROUP: {
result = TestBinaryConditionCommon(item, GroupIsInGroup(v->group_id, GetTraceRestrictValue(item)));
break;
}
default:
NOT_REACHED();
}
@ -479,6 +485,7 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
case TRIT_COND_CARGO:
case TRIT_COND_ENTRY_DIRECTION:
case TRIT_COND_PBS_ENTRY_SIGNAL:
case TRIT_COND_TRAIN_GROUP:
break;
default:
@ -577,6 +584,11 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp
SetTraceRestrictAuxField(item, TRPPAF_PRESET);
break;
case TRVT_GROUP_INDEX:
SetTraceRestrictValue(item, INVALID_GROUP);
SetTraceRestrictAuxField(item, 0);
break;
default:
NOT_REACHED();
break;
@ -1110,3 +1122,25 @@ void TraceRestrictRemoveDestinationID(TraceRestrictOrderCondAuxField type, uint1
// update windows
InvalidateWindowClassesData(WC_TRACE_RESTRICT);
}
/**
* This is called when a group is about to be deleted
* Scan program pool and change any references to it to the invalid group ID, to avoid dangling references
*/
void TraceRestrictRemoveGroupID(GroupID index)
{
TraceRestrictProgram *prog;
FOR_ALL_TRACE_RESTRICT_PROGRAMS(prog) {
for (size_t i = 0; i < prog->items.size(); i++) {
TraceRestrictItem &item = prog->items[i]; // note this is a reference,
if (GetTraceRestrictType(item) == TRIT_COND_TRAIN_GROUP && GetTraceRestrictValue(item) == index) {
SetTraceRestrictValueDefault(item, TRVT_GROUP_INDEX); // this updates the instruction in-place
}
if (IsTraceRestrictDoubleItem(item)) i++;
}
}
// update windows
InvalidateWindowClassesData(WC_TRACE_RESTRICT);
}

@ -17,6 +17,7 @@
#include "command_func.h"
#include "rail_map.h"
#include "tile_type.h"
#include "group_type.h"
#include <map>
#include <vector>
@ -111,6 +112,7 @@ enum TraceRestrictItemType {
TRIT_COND_CARGO = 15, ///< Test if train can carry cargo type
TRIT_COND_ENTRY_DIRECTION = 16, ///< Test which side of signal/signal tile is being entered from
TRIT_COND_PBS_ENTRY_SIGNAL = 17, ///< Test tile and PBS-state of previous signal
TRIT_COND_TRAIN_GROUP = 18, ///< Test train group membership
//TRIT_COND_TRAIN_OWNER = 24, ///< Test train owner: reserved for future use
/* space up to 31 */
};
@ -411,6 +413,7 @@ enum TraceRestrictValueType {
TRVT_PF_PENALTY = 9, ///< takes a pathfinder penalty value or preset index, as per the auxiliary field as type: TraceRestrictPathfinderPenaltyAuxField
TRVT_RESERVE_THROUGH = 10,///< takes a value 0 = reserve through, 1 = cancel previous reserve through
TRVT_LONG_RESERVE = 11,///< takes a value 0 = long reserve, 1 = cancel previous long reserve
TRVT_GROUP_INDEX = 12,///< takes a GroupID
};
/**
@ -472,6 +475,11 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR
out.cond_type = TRCOT_BINARY;
break;
case TRIT_COND_TRAIN_GROUP:
out.value_type = TRVT_GROUP_INDEX;
out.cond_type = TRCOT_BINARY;
break;
default:
NOT_REACHED();
break;
@ -565,5 +573,6 @@ CommandCost CmdProgramSignalTraceRestrictProgMgmt(TileIndex tile, DoCommandFlag
void ShowTraceRestrictProgramWindow(TileIndex tile, Track track);
void TraceRestrictRemoveDestinationID(TraceRestrictOrderCondAuxField type, uint16 index);
void TraceRestrictRemoveGroupID(GroupID index);
#endif /* TRACERESTRICT_H */

@ -23,6 +23,7 @@
#include "company_func.h"
#include "tilehighlight_func.h"
#include "widgets/dropdown_func.h"
#include "widgets/dropdown_type.h"
#include "gui.h"
#include "gfx_func.h"
#include "rail_map.h"
@ -33,6 +34,8 @@
#include "depot_base.h"
#include "error.h"
#include "cargotype.h"
#include "sortlist_type.h"
#include "group.h"
#include "table/sprites.h"
extern uint ConvertSpeedToDisplaySpeed(uint speed);
@ -268,6 +271,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictI
STR_TRACE_RESTRICT_VARIABLE_CARGO,
STR_TRACE_RESTRICT_VARIABLE_ENTRY_DIRECTION,
STR_TRACE_RESTRICT_VARIABLE_PBS_ENTRY_SIGNAL,
STR_TRACE_RESTRICT_VARIABLE_TRAIN_GROUP,
STR_TRACE_RESTRICT_VARIABLE_UNDEFINED,
INVALID_STRING_ID,
};
@ -280,6 +284,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictI
TRIT_COND_CARGO,
TRIT_COND_ENTRY_DIRECTION,
TRIT_COND_PBS_ENTRY_SIGNAL,
TRIT_COND_TRAIN_GROUP,
TRIT_COND_UNDEFINED,
};
static const TraceRestrictDropDownListSet set_cond = {
@ -310,6 +315,43 @@ static const TraceRestrictDropDownListSet *GetSortedCargoTypeDropDownListSet()
return &cargo_list;
}
/**
* Get a DropDownList of the group list
*/
static DropDownList *GetGroupDropDownList(Owner owner, GroupID group_id, int &selected)
{
typedef GUIList<const Group*> GUIGroupList;
extern int CDECL GroupNameSorter(const Group * const *a, const Group * const *b);
GUIGroupList list;
const Group *g;
FOR_ALL_GROUPS(g) {
if (g->owner == owner && g->vehicle_type == VEH_TRAIN) {
*list.Append() = g;
}
}
list.ForceResort();
list.Sort(&GroupNameSorter);
DropDownList *dlist = new DropDownList();
selected = -1;
if (group_id == DEFAULT_GROUP) selected = DEFAULT_GROUP;
*dlist->Append() = new DropDownListStringItem(STR_GROUP_DEFAULT_TRAINS, DEFAULT_GROUP, false);
for (size_t i = 0; i < list.Length(); ++i) {
const Group *g = list[i];
if (group_id == g->index) selected = group_id;
DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_GROUP_NAME, g->index, false);
item->SetParam(0, g->index);
*dlist->Append() = item;
}
return dlist;
}
static const StringID _cargo_cond_ops_str[] = {
STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_CARGO_EQUALS,
STR_TRACE_RESTRICT_CONDITIONAL_COMPARATOR_CARGO_NOT_EQUALS,
@ -633,6 +675,25 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric
break;
}
case TRVT_GROUP_INDEX: {
assert(GetTraceRestrictCondFlags(item) <= TRCF_OR);
SetDParam(0, _program_cond_type[GetTraceRestrictCondFlags(item)]);
SetDParam(1, GetDropDownStringByValue(GetCondOpDropDownListSet(properties), GetTraceRestrictCondOp(item)));
if (GetTraceRestrictValue(item) == INVALID_GROUP) {
instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_GROUP_STR;
SetDParam(2, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED_RED);
SetDParam(3, selected ? STR_TRACE_RESTRICT_WHITE : STR_EMPTY);
} else if (GetTraceRestrictValue(item) == DEFAULT_GROUP) {
instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_GROUP_STR;
SetDParam(2, STR_GROUP_DEFAULT_TRAINS);
SetDParam(3, selected ? STR_TRACE_RESTRICT_WHITE : STR_EMPTY);
} else {
instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_GROUP;
SetDParam(2, GetTraceRestrictValue(item));
}
break;
}
default:
NOT_REACHED();
break;
@ -897,6 +958,13 @@ public:
this->ShowDropDownListWithValue(&_long_reserve_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0);
break;
case TRVT_GROUP_INDEX: {
int selected;
DropDownList *dlist = GetGroupDropDownList(this->GetOwner(), GetTraceRestrictValue(item), selected);
ShowDropDownList(this, dlist, selected, TR_WIDGET_VALUE_DROPDOWN);
break;
}
default:
break;
}
@ -968,6 +1036,12 @@ public:
return;
}
if (widget == TR_WIDGET_VALUE_DROPDOWN && GetTraceRestrictTypeProperties(item).value_type == TRVT_GROUP_INDEX) {
SetTraceRestrictValue(item, index);
TraceRestrictDoCommandP(this->tile, this->track, TRDCT_MODIFY_ITEM, this->selected_instruction - 1, item, STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM);
return;
}
const TraceRestrictDropDownListSet *list_set = this->drop_down_list_mapping[widget];
if (!list_set) {
return;
@ -1295,8 +1369,9 @@ public:
case TR_WIDGET_VALUE_DROPDOWN: {
TraceRestrictItem item = this->GetSelected();
if (GetTraceRestrictTypeProperties(item).value_type == TRVT_PF_PENALTY &&
GetTraceRestrictAuxField(item) == TRPPAF_VALUE) {
if ((GetTraceRestrictTypeProperties(item).value_type == TRVT_PF_PENALTY &&
GetTraceRestrictAuxField(item) == TRPPAF_VALUE)
|| GetTraceRestrictTypeProperties(item).value_type == TRVT_GROUP_INDEX) {
SetDParam(0, GetTraceRestrictValue(item));
}
break;
@ -1649,6 +1724,24 @@ private:
GetTraceRestrictValue(item) ? STR_TRACE_RESTRICT_LONG_RESERVE_CANCEL : STR_TRACE_RESTRICT_LONG_RESERVE;
break;
case TRVT_GROUP_INDEX:
right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN);
this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN);
switch (GetTraceRestrictValue(item)) {
case INVALID_GROUP:
this->GetWidget<NWidgetCore>(TR_WIDGET_VALUE_DROPDOWN)->widget_data = STR_TRACE_RESTRICT_VARIABLE_UNDEFINED;
break;
case DEFAULT_GROUP:
this->GetWidget<NWidgetCore>(TR_WIDGET_VALUE_DROPDOWN)->widget_data = STR_GROUP_DEFAULT_TRAINS;
break;
default:
this->GetWidget<NWidgetCore>(TR_WIDGET_VALUE_DROPDOWN)->widget_data = STR_GROUP_NAME;
break;
}
break;
default:
break;
}
@ -1669,7 +1762,7 @@ private:
void ShowDropDownListWithValue(const TraceRestrictDropDownListSet *list_set, uint value, bool missing_ok,
int button, uint32 disabled_mask, uint32 hidden_mask, uint width)
{
drop_down_list_mapping[button] = list_set;
this->drop_down_list_mapping[button] = list_set;
int selected = GetDropDownListIndexByValue(list_set, value, missing_ok);
ShowDropDownMenu(this, list_set->string_array, selected, button, disabled_mask, hidden_mask, width);
}

Loading…
Cancel
Save