Add slot and counter support to programmable pre-signals
This commit is contained in:
@@ -2961,6 +2961,8 @@ STR_PROGSIG_INSERT_TOOLTIP :{BLACK}Insert a
|
|||||||
STR_PROGSIG_REMOVE_TOOLTIP :{BLACK}Remove the selected instruction
|
STR_PROGSIG_REMOVE_TOOLTIP :{BLACK}Remove the selected instruction
|
||||||
STR_PROGSIG_REMOVE_PROGRAM_TOOLTIP :{BLACK}Remove entire program
|
STR_PROGSIG_REMOVE_PROGRAM_TOOLTIP :{BLACK}Remove entire program
|
||||||
STR_PROGSIG_COPY_PROGRAM_TOOLTIP :{BLACK}Copy program from existing signal
|
STR_PROGSIG_COPY_PROGRAM_TOOLTIP :{BLACK}Copy program from existing signal
|
||||||
|
STR_PROGSIG_COND_SLOT_TOOLTIP :{BLACK}Slot to compare occupancy of
|
||||||
|
STR_PROGSIG_COND_COUNTER_TOOLTIP :{BLACK}Counter to compare value of
|
||||||
|
|
||||||
STR_PROGSIG_REMOVE_PROGRAM :{BLACK}Remove program
|
STR_PROGSIG_REMOVE_PROGRAM :{BLACK}Remove program
|
||||||
STR_PROGSIG_COPY_PROGRAM :{BLACK}Copy program
|
STR_PROGSIG_COPY_PROGRAM :{BLACK}Copy program
|
||||||
@@ -2981,7 +2983,16 @@ STR_PROGSIG_SET_SIGNAL :Make signal {ST
|
|||||||
STR_PROGSIG_COND_ALWAYS :always
|
STR_PROGSIG_COND_ALWAYS :always
|
||||||
STR_PROGSIG_COND_NEVER :never
|
STR_PROGSIG_COND_NEVER :never
|
||||||
STR_PROGSIG_COND_COMPARE :{STRING} {STRING} {NUM}
|
STR_PROGSIG_COND_COMPARE :{STRING} {STRING} {NUM}
|
||||||
|
STR_PROGSIG_COND_SLOT_COMPARE :occupancy of {TRSLOT} {STRING} {NUM}
|
||||||
|
STR_PROGSIG_COND_SLOT_COMPARE_INVALID :occupancy of {PUSH_COLOUR}{RED}{STRING}{POP_COLOUR} {STRING} {NUM}
|
||||||
|
STR_PROGSIG_COND_SLOT_REMAINING_COMPARE :occupancy remaining of {TRSLOT} {STRING} {NUM}
|
||||||
|
STR_PROGSIG_COND_SLOT_REMAINING_COMPARE_INVALID :occupancy remaining of {PUSH_COLOUR}{RED}{STRING}{POP_COLOUR} {STRING} {NUM}
|
||||||
|
STR_PROGSIG_COND_COUNTER_COMPARE :value of {TRCOUNTER} {STRING} {NUM}
|
||||||
|
STR_PROGSIG_COND_COUNTER_COMPARE_INVALID :value of {PUSH_COLOUR}{RED}{STRING}{POP_COLOUR} {STRING} {NUM}
|
||||||
STR_PROGSIG_COND_SIGNAL_STATE :signal state
|
STR_PROGSIG_COND_SIGNAL_STATE :signal state
|
||||||
|
STR_PROGSIG_COND_SLOT :slot occupancy
|
||||||
|
STR_PROGSIG_COND_SLOT_REMAINING :slot occupancy remaining
|
||||||
|
STR_PROGSIG_COND_COUNTER :counter value
|
||||||
STR_PROGSIG_CONDVAR_SIGNAL_STATE_SPECIFIED :signal at {NUM} x {NUM} is green
|
STR_PROGSIG_CONDVAR_SIGNAL_STATE_SPECIFIED :signal at {NUM} x {NUM} is green
|
||||||
STR_PROGSIG_CONDVAR_SIGNAL_STATE_UNSPECIFIED :{RED}unspecified signal{STRING} is green
|
STR_PROGSIG_CONDVAR_SIGNAL_STATE_UNSPECIFIED :{RED}unspecified signal{STRING} is green
|
||||||
STR_PROGSIG_CONDVAR_NUM_RED :red signals
|
STR_PROGSIG_CONDVAR_NUM_RED :red signals
|
||||||
|
@@ -80,8 +80,23 @@ SignalSimpleCondition::SignalSimpleCondition(SignalConditionCode code)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SignalConditionComparable::EvaluateComparable(uint32 var_val)
|
||||||
|
{
|
||||||
|
switch (this->comparator) {
|
||||||
|
case SGC_EQUALS: return var_val == this->value;
|
||||||
|
case SGC_NOT_EQUALS: return var_val != this->value;
|
||||||
|
case SGC_LESS_THAN: return var_val < this->value;
|
||||||
|
case SGC_LESS_THAN_EQUALS: return var_val <= this->value;
|
||||||
|
case SGC_MORE_THAN: return var_val > this->value;
|
||||||
|
case SGC_MORE_THAN_EQUALS: return var_val >= this->value;
|
||||||
|
case SGC_IS_TRUE: return var_val != 0;
|
||||||
|
case SGC_IS_FALSE: return !var_val;
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SignalVariableCondition::SignalVariableCondition(SignalConditionCode code)
|
SignalVariableCondition::SignalVariableCondition(SignalConditionCode code)
|
||||||
: SignalCondition(code)
|
: SignalConditionComparable(code)
|
||||||
{
|
{
|
||||||
switch (this->cond_code) {
|
switch (this->cond_code) {
|
||||||
case PSC_NUM_GREEN: comparator = SGC_NOT_EQUALS; break;
|
case PSC_NUM_GREEN: comparator = SGC_NOT_EQUALS; break;
|
||||||
@@ -99,20 +114,158 @@ SignalVariableCondition::SignalVariableCondition(SignalConditionCode code)
|
|||||||
case PSC_NUM_RED: var_val = vm.num_exits - vm.num_green; break;
|
case PSC_NUM_RED: var_val = vm.num_exits - vm.num_green; break;
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
return this->EvaluateComparable(var_val);
|
||||||
|
}
|
||||||
|
|
||||||
switch (this->comparator) {
|
void AddSignalSlotDependency(TraceRestrictSlotID on, SignalReference dep)
|
||||||
case SGC_EQUALS: return var_val == this->value;
|
{
|
||||||
case SGC_NOT_EQUALS: return var_val != this->value;
|
TraceRestrictSlot *slot = TraceRestrictSlot::Get(on);
|
||||||
case SGC_LESS_THAN: return var_val < this->value;
|
assert(slot->owner == GetTileOwner(dep.tile));
|
||||||
case SGC_LESS_THAN_EQUALS: return var_val <= this->value;
|
slot->progsig_dependants.push_back(dep);
|
||||||
case SGC_MORE_THAN: return var_val > this->value;
|
}
|
||||||
case SGC_MORE_THAN_EQUALS: return var_val >= this->value;
|
|
||||||
case SGC_IS_TRUE: return var_val != 0;
|
void RemoveSignalSlotDependency(TraceRestrictSlotID on, SignalReference dep)
|
||||||
case SGC_IS_FALSE: return !var_val;
|
{
|
||||||
|
TraceRestrictSlot *slot = TraceRestrictSlot::Get(on);
|
||||||
|
auto ob = std::find(slot->progsig_dependants.begin(), slot->progsig_dependants.end(), dep);
|
||||||
|
|
||||||
|
if (ob != slot->progsig_dependants.end()) slot->progsig_dependants.erase(ob);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddSignalCounterDependency(TraceRestrictCounterID on, SignalReference dep)
|
||||||
|
{
|
||||||
|
TraceRestrictCounter *ctr = TraceRestrictCounter::Get(on);
|
||||||
|
assert(ctr->owner == GetTileOwner(dep.tile));
|
||||||
|
ctr->progsig_dependants.push_back(dep);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveSignalCounterDependency(TraceRestrictCounterID on, SignalReference dep)
|
||||||
|
{
|
||||||
|
TraceRestrictCounter *ctr = TraceRestrictCounter::Get(on);
|
||||||
|
auto ob = std::find(ctr->progsig_dependants.begin(), ctr->progsig_dependants.end(), dep);
|
||||||
|
|
||||||
|
if (ob != ctr->progsig_dependants.end()) ctr->progsig_dependants.erase(ob);
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalSlotCondition::SignalSlotCondition(SignalConditionCode code, SignalReference this_sig, TraceRestrictSlotID slot_id)
|
||||||
|
: SignalConditionComparable(code), this_sig(this_sig), slot_id(slot_id)
|
||||||
|
{
|
||||||
|
this->comparator = SGC_EQUALS;
|
||||||
|
this->value = 0;
|
||||||
|
if (this->CheckSlotValid()) {
|
||||||
|
AddSignalSlotDependency(this->slot_id, this->this_sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SignalSlotCondition::IsSlotValid() const
|
||||||
|
{
|
||||||
|
return TraceRestrictSlot::IsValidID(this->slot_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SignalSlotCondition::CheckSlotValid()
|
||||||
|
{
|
||||||
|
bool valid = this->IsSlotValid();
|
||||||
|
if (!valid) {
|
||||||
|
this->Invalidate();
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignalSlotCondition::Invalidate()
|
||||||
|
{
|
||||||
|
this->slot_id = INVALID_TRACE_RESTRICT_SLOT_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignalSlotCondition::SetSlot(TraceRestrictSlotID slot_id)
|
||||||
|
{
|
||||||
|
if (this->IsSlotValid()) {
|
||||||
|
RemoveSignalSlotDependency(this->slot_id, this->this_sig);
|
||||||
|
}
|
||||||
|
this->slot_id = slot_id;
|
||||||
|
if (this->CheckSlotValid()) {
|
||||||
|
AddSignalSlotDependency(this->slot_id, this->this_sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ SignalSlotCondition::~SignalSlotCondition()
|
||||||
|
{
|
||||||
|
if (this->IsSlotValid()) {
|
||||||
|
RemoveSignalSlotDependency(this->slot_id, this->this_sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ bool SignalSlotCondition::Evaluate(SignalVM& vm)
|
||||||
|
{
|
||||||
|
if (!this->CheckSlotValid()) {
|
||||||
|
DEBUG(misc, 1, "Signal (%x, %d) has an invalid condition", this->this_sig.tile, this->this_sig.track);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TraceRestrictSlot *slot = TraceRestrictSlot::Get(this->slot_id);
|
||||||
|
switch (this->cond_code) {
|
||||||
|
case PSC_SLOT_OCC: return this->EvaluateComparable(slot->occupants.size());
|
||||||
|
case PSC_SLOT_OCC_REM: return this->EvaluateComparable(slot->max_occupancy > slot->occupants.size() ? slot->max_occupancy - slot->occupants.size() : 0);
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SignalCounterCondition::SignalCounterCondition(SignalReference this_sig, TraceRestrictCounterID ctr_id)
|
||||||
|
: SignalConditionComparable(PSC_COUNTER), this_sig(this_sig), ctr_id(ctr_id)
|
||||||
|
{
|
||||||
|
this->comparator = SGC_EQUALS;
|
||||||
|
this->value = 0;
|
||||||
|
if (this->CheckCounterValid()) {
|
||||||
|
AddSignalCounterDependency(this->ctr_id, this->this_sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SignalCounterCondition::IsCounterValid() const
|
||||||
|
{
|
||||||
|
return TraceRestrictCounter::IsValidID(this->ctr_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SignalCounterCondition::CheckCounterValid()
|
||||||
|
{
|
||||||
|
bool valid = this->IsCounterValid();
|
||||||
|
if (!valid) {
|
||||||
|
this->Invalidate();
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignalCounterCondition::Invalidate()
|
||||||
|
{
|
||||||
|
this->ctr_id = INVALID_TRACE_RESTRICT_COUNTER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignalCounterCondition::SetCounter(TraceRestrictCounterID ctr_id)
|
||||||
|
{
|
||||||
|
if (this->IsCounterValid()) {
|
||||||
|
RemoveSignalCounterDependency(this->ctr_id, this->this_sig);
|
||||||
|
}
|
||||||
|
this->ctr_id = ctr_id;
|
||||||
|
if (this->CheckCounterValid()) {
|
||||||
|
AddSignalCounterDependency(this->ctr_id, this->this_sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ SignalCounterCondition::~SignalCounterCondition()
|
||||||
|
{
|
||||||
|
if (this->IsCounterValid()) {
|
||||||
|
RemoveSignalCounterDependency(this->ctr_id, this->this_sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*virtual*/ bool SignalCounterCondition::Evaluate(SignalVM& vm)
|
||||||
|
{
|
||||||
|
if (!this->CheckCounterValid()) {
|
||||||
|
DEBUG(misc, 1, "Signal (%x, %d) has an invalid condition", this->this_sig.tile, this->this_sig.track);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->EvaluateComparable(TraceRestrictCounter::Get(this->ctr_id)->value);
|
||||||
|
}
|
||||||
|
|
||||||
SignalStateCondition::SignalStateCondition(SignalReference this_sig,
|
SignalStateCondition::SignalStateCondition(SignalReference this_sig,
|
||||||
TileIndex sig_tile, Trackdir sig_track)
|
TileIndex sig_tile, Trackdir sig_track)
|
||||||
: SignalCondition(PSC_SIGNAL_STATE), this_sig(this_sig), sig_tile(sig_tile)
|
: SignalCondition(PSC_SIGNAL_STATE), this_sig(this_sig), sig_tile(sig_tile)
|
||||||
@@ -419,11 +572,52 @@ void RemoveProgramDependencies(SignalReference dependency_target, SignalReferenc
|
|||||||
SignalIf* ifi = static_cast<SignalIf*>(insn);
|
SignalIf* ifi = static_cast<SignalIf*>(insn);
|
||||||
if (ifi->condition->ConditionCode() == PSC_SIGNAL_STATE) {
|
if (ifi->condition->ConditionCode() == PSC_SIGNAL_STATE) {
|
||||||
SignalStateCondition* c = static_cast<SignalStateCondition*>(ifi->condition);
|
SignalStateCondition* c = static_cast<SignalStateCondition*>(ifi->condition);
|
||||||
if(c->sig_tile == dependency_target.tile && TrackdirToTrack(c->sig_track) == dependency_target.track)
|
if (c->sig_tile == dependency_target.tile && TrackdirToTrack(c->sig_track) == dependency_target.track) {
|
||||||
c->Invalidate();
|
c->Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InvalidateWindowData(WC_SIGNAL_PROGRAM, (signal_to_update.tile << 3) | signal_to_update.track);
|
||||||
|
AddTrackToSignalBuffer(signal_to_update.tile, signal_to_update.track, GetTileOwner(signal_to_update.tile));
|
||||||
|
UpdateSignalsInBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveProgramSlotDependencies(TraceRestrictSlotID slot_being_removed, SignalReference signal_to_update)
|
||||||
|
{
|
||||||
|
SignalProgram *prog = GetSignalProgram(signal_to_update);
|
||||||
|
for (SignalInstruction *insn : prog->instructions) {
|
||||||
|
if (insn->Opcode() == PSO_IF) {
|
||||||
|
SignalIf* ifi = static_cast<SignalIf*>(insn);
|
||||||
|
if (ifi->condition->ConditionCode() == PSC_SLOT_OCC || ifi->condition->ConditionCode() == PSC_SLOT_OCC_REM) {
|
||||||
|
SignalSlotCondition* c = static_cast<SignalSlotCondition*>(ifi->condition);
|
||||||
|
if (c->slot_id == slot_being_removed) {
|
||||||
|
c->Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InvalidateWindowData(WC_SIGNAL_PROGRAM, (signal_to_update.tile << 3) | signal_to_update.track);
|
||||||
|
AddTrackToSignalBuffer(signal_to_update.tile, signal_to_update.track, GetTileOwner(signal_to_update.tile));
|
||||||
|
UpdateSignalsInBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveProgramCounterDependencies(TraceRestrictCounterID ctr_being_removed, SignalReference signal_to_update)
|
||||||
|
{
|
||||||
|
SignalProgram *prog = GetSignalProgram(signal_to_update);
|
||||||
|
for (SignalInstruction *insn : prog->instructions) {
|
||||||
|
if (insn->Opcode() == PSO_IF) {
|
||||||
|
SignalIf* ifi = static_cast<SignalIf*>(insn);
|
||||||
|
if (ifi->condition->ConditionCode() == PSC_COUNTER) {
|
||||||
|
SignalCounterCondition* c = static_cast<SignalCounterCondition*>(ifi->condition);
|
||||||
|
if (c->ctr_id == ctr_being_removed) {
|
||||||
|
c->Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InvalidateWindowData(WC_SIGNAL_PROGRAM, (signal_to_update.tile << 3) | signal_to_update.track);
|
InvalidateWindowData(WC_SIGNAL_PROGRAM, (signal_to_update.tile << 3) | signal_to_update.track);
|
||||||
AddTrackToSignalBuffer(signal_to_update.tile, signal_to_update.track, GetTileOwner(signal_to_update.tile));
|
AddTrackToSignalBuffer(signal_to_update.tile, signal_to_update.track, GetTileOwner(signal_to_update.tile));
|
||||||
@@ -586,6 +780,15 @@ CommandCost CmdModifySignalInstruction(TileIndex tile, DoCommandFlag flags, uint
|
|||||||
cond = new SignalStateCondition(SignalReference(tile, track), INVALID_TILE, INVALID_TRACKDIR);
|
cond = new SignalStateCondition(SignalReference(tile, track), INVALID_TILE, INVALID_TRACKDIR);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PSC_SLOT_OCC:
|
||||||
|
case PSC_SLOT_OCC_REM:
|
||||||
|
cond = new SignalSlotCondition(code, SignalReference(tile, track), INVALID_TRACE_RESTRICT_SLOT_ID);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PSC_COUNTER:
|
||||||
|
cond = new SignalCounterCondition(SignalReference(tile, track), INVALID_TRACE_RESTRICT_COUNTER_ID);
|
||||||
|
break;
|
||||||
|
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
si->SetCondition(cond);
|
si->SetCondition(cond);
|
||||||
@@ -623,6 +826,47 @@ CommandCost CmdModifySignalInstruction(TileIndex tile, DoCommandFlag flags, uint
|
|||||||
if (!exec) return CommandCost();
|
if (!exec) return CommandCost();
|
||||||
sc->SetSignal(ti, td);
|
sc->SetSignal(ti, td);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PSC_SLOT_OCC:
|
||||||
|
case PSC_SLOT_OCC_REM: {
|
||||||
|
SignalSlotCondition *sc = static_cast<SignalSlotCondition*>(si->condition);
|
||||||
|
SignalConditionField f = (SignalConditionField) GB(p2, 1, 2);
|
||||||
|
uint32 val = GB(p2, 3, 27);
|
||||||
|
if (f == SCF_COMPARATOR) {
|
||||||
|
if (val > SGC_LAST) return_cmd_error(STR_ERR_PROGSIG_INVALID_COMPARATOR);
|
||||||
|
if (!exec) return CommandCost();
|
||||||
|
sc->comparator = (SignalComparator) val;
|
||||||
|
} else if (f == SCF_VALUE) {
|
||||||
|
if (!exec) return CommandCost();
|
||||||
|
sc->value = val;
|
||||||
|
} else if (f == SCF_SLOT_COUNTER) {
|
||||||
|
if (val != INVALID_TRACE_RESTRICT_SLOT_ID && !TraceRestrictSlot::IsValidID(val)) return CMD_ERROR;
|
||||||
|
if (!exec) return CommandCost();
|
||||||
|
sc->SetSlot((TraceRestrictSlotID) val);
|
||||||
|
} else {
|
||||||
|
return_cmd_error(STR_ERR_PROGSIG_INVALID_CONDITION_FIELD);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PSC_COUNTER: {
|
||||||
|
SignalCounterCondition *sc = static_cast<SignalCounterCondition*>(si->condition);
|
||||||
|
SignalConditionField f = (SignalConditionField) GB(p2, 1, 2);
|
||||||
|
uint32 val = GB(p2, 3, 27);
|
||||||
|
if (f == SCF_COMPARATOR) {
|
||||||
|
if (val > SGC_LAST) return_cmd_error(STR_ERR_PROGSIG_INVALID_COMPARATOR);
|
||||||
|
if (!exec) return CommandCost();
|
||||||
|
sc->comparator = (SignalComparator) val;
|
||||||
|
} else if (f == SCF_VALUE) {
|
||||||
|
if (!exec) return CommandCost();
|
||||||
|
sc->value = val;
|
||||||
|
} else if (f == SCF_SLOT_COUNTER) {
|
||||||
|
if (val != INVALID_TRACE_RESTRICT_COUNTER_ID && !TraceRestrictCounter::IsValidID(val)) return CMD_ERROR;
|
||||||
|
if (!exec) return CommandCost();
|
||||||
|
sc->SetCounter((TraceRestrictCounterID) val);
|
||||||
|
} else {
|
||||||
|
return_cmd_error(STR_ERR_PROGSIG_INVALID_CONDITION_FIELD);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -739,6 +983,25 @@ static void CloneInstructions(SignalProgram *prog, SignalInstruction *insert_bef
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PSC_SLOT_OCC:
|
||||||
|
case PSC_SLOT_OCC_REM: {
|
||||||
|
SignalSlotCondition *src = ((SignalSlotCondition *) src_cond);
|
||||||
|
SignalSlotCondition *cond = new SignalSlotCondition(code, SignalReference(prog->tile, prog->track), src->slot_id);
|
||||||
|
cond->comparator = src->comparator;
|
||||||
|
cond->value = src->value;
|
||||||
|
if_ins->SetCondition(cond);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PSC_COUNTER: {
|
||||||
|
SignalCounterCondition *src = ((SignalCounterCondition *) src_cond);
|
||||||
|
SignalCounterCondition *cond = new SignalCounterCondition(SignalReference(prog->tile, prog->track), src->ctr_id);
|
||||||
|
cond->comparator = src->comparator;
|
||||||
|
cond->value = src->value;
|
||||||
|
if_ins->SetCondition(cond);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#ifndef PROGRAMMABLE_SIGNALS_H
|
#ifndef PROGRAMMABLE_SIGNALS_H
|
||||||
#define PROGRAMMABLE_SIGNALS_H
|
#define PROGRAMMABLE_SIGNALS_H
|
||||||
#include "rail_map.h"
|
#include "rail_map.h"
|
||||||
|
#include "tracerestrict.h"
|
||||||
#include "core/smallvec_type.hpp"
|
#include "core/smallvec_type.hpp"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -129,8 +130,11 @@ enum SignalConditionCode {
|
|||||||
PSC_NUM_GREEN = 2, ///< Number of green signals behind this signal
|
PSC_NUM_GREEN = 2, ///< Number of green signals behind this signal
|
||||||
PSC_NUM_RED = 3, ///< Number of red signals behind this signal
|
PSC_NUM_RED = 3, ///< Number of red signals behind this signal
|
||||||
PSC_SIGNAL_STATE = 4, ///< State of another signal
|
PSC_SIGNAL_STATE = 4, ///< State of another signal
|
||||||
|
PSC_SLOT_OCC = 5, ///< Slot occupancy
|
||||||
|
PSC_SLOT_OCC_REM = 6, ///< Slot occupancy remaining
|
||||||
|
PSC_COUNTER = 7, ///< Counter value
|
||||||
|
|
||||||
PSC_MAX = PSC_SIGNAL_STATE
|
PSC_MAX = PSC_COUNTER
|
||||||
};
|
};
|
||||||
|
|
||||||
class SignalCondition {
|
class SignalCondition {
|
||||||
@@ -178,6 +182,17 @@ enum SignalComparator {
|
|||||||
enum SignalConditionField {
|
enum SignalConditionField {
|
||||||
SCF_COMPARATOR = 0, ///< the comparator (value from SignalComparator enum)
|
SCF_COMPARATOR = 0, ///< the comparator (value from SignalComparator enum)
|
||||||
SCF_VALUE = 1, ///< the value (integer value)
|
SCF_VALUE = 1, ///< the value (integer value)
|
||||||
|
SCF_SLOT_COUNTER = 2, ///< the slot or counter
|
||||||
|
};
|
||||||
|
|
||||||
|
class SignalConditionComparable: public SignalCondition {
|
||||||
|
protected:
|
||||||
|
bool EvaluateComparable(uint32 var_val);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SignalConditionComparable(SignalConditionCode code) : SignalCondition(code) {}
|
||||||
|
SignalComparator comparator;
|
||||||
|
uint32 value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A conditon based upon comparing a variable and a value. This condition can be
|
/** A conditon based upon comparing a variable and a value. This condition can be
|
||||||
@@ -186,15 +201,12 @@ enum SignalConditionField {
|
|||||||
* The variable is specified by the conditon code, the comparison by @p comparator, and
|
* The variable is specified by the conditon code, the comparison by @p comparator, and
|
||||||
* the value to compare against by @p value. The condition returns the result of that value.
|
* the value to compare against by @p value. The condition returns the result of that value.
|
||||||
*/
|
*/
|
||||||
class SignalVariableCondition: public SignalCondition {
|
class SignalVariableCondition: public SignalConditionComparable {
|
||||||
public:
|
public:
|
||||||
/// Constructs a condition refering to the value @p code refers to. Sets the
|
/// Constructs a condition refering to the value @p code refers to. Sets the
|
||||||
/// comparator and value to sane defaults.
|
/// comparator and value to sane defaults.
|
||||||
SignalVariableCondition(SignalConditionCode code);
|
SignalVariableCondition(SignalConditionCode code);
|
||||||
|
|
||||||
SignalComparator comparator;
|
|
||||||
uint32 value;
|
|
||||||
|
|
||||||
/// Evaluates the condition
|
/// Evaluates the condition
|
||||||
virtual bool Evaluate(SignalVM &vm);
|
virtual bool Evaluate(SignalVM &vm);
|
||||||
};
|
};
|
||||||
@@ -217,6 +229,40 @@ class SignalStateCondition: public SignalCondition {
|
|||||||
Trackdir sig_track;
|
Trackdir sig_track;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A condition which is based upon the value of a slot. */
|
||||||
|
class SignalSlotCondition: public SignalConditionComparable {
|
||||||
|
public:
|
||||||
|
SignalSlotCondition(SignalConditionCode code, SignalReference this_sig, TraceRestrictSlotID slot_id);
|
||||||
|
|
||||||
|
void SetSlot(TraceRestrictSlotID slot_id);
|
||||||
|
bool IsSlotValid() const;
|
||||||
|
bool CheckSlotValid();
|
||||||
|
void Invalidate();
|
||||||
|
|
||||||
|
virtual bool Evaluate(SignalVM& vm);
|
||||||
|
virtual ~SignalSlotCondition();
|
||||||
|
|
||||||
|
SignalReference this_sig;
|
||||||
|
TraceRestrictSlotID slot_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A condition which is based upon the value of a counter. */
|
||||||
|
class SignalCounterCondition: public SignalConditionComparable {
|
||||||
|
public:
|
||||||
|
SignalCounterCondition(SignalReference this_sig, TraceRestrictCounterID ctr_id);
|
||||||
|
|
||||||
|
void SetCounter(TraceRestrictCounterID ctr_id);
|
||||||
|
bool IsCounterValid() const;
|
||||||
|
bool CheckCounterValid();
|
||||||
|
void Invalidate();
|
||||||
|
|
||||||
|
virtual bool Evaluate(SignalVM& vm);
|
||||||
|
virtual ~SignalCounterCondition();
|
||||||
|
|
||||||
|
SignalReference this_sig;
|
||||||
|
TraceRestrictCounterID ctr_id;
|
||||||
|
};
|
||||||
|
|
||||||
// -- Instructions
|
// -- Instructions
|
||||||
|
|
||||||
/** The special start and end pseudo instructions.
|
/** The special start and end pseudo instructions.
|
||||||
|
@@ -23,16 +23,21 @@
|
|||||||
#include "rail_map.h"
|
#include "rail_map.h"
|
||||||
#include "tile_cmd.h"
|
#include "tile_cmd.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "scope.h"
|
||||||
|
|
||||||
#include "table/sprites.h"
|
#include "table/sprites.h"
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
|
DropDownList GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &selected);
|
||||||
|
DropDownList GetCounterDropDownList(Owner owner, TraceRestrictCounterID ctr_id, int &selected);
|
||||||
|
|
||||||
enum ProgramWindowWidgets {
|
enum ProgramWindowWidgets {
|
||||||
PROGRAM_WIDGET_CAPTION,
|
PROGRAM_WIDGET_CAPTION,
|
||||||
PROGRAM_WIDGET_INSTRUCTION_LIST,
|
PROGRAM_WIDGET_INSTRUCTION_LIST,
|
||||||
PROGRAM_WIDGET_SCROLLBAR,
|
PROGRAM_WIDGET_SCROLLBAR,
|
||||||
|
|
||||||
PROGRAM_WIDGET_SEL_TOP_LEFT,
|
PROGRAM_WIDGET_SEL_TOP_LEFT,
|
||||||
|
PROGRAM_WIDGET_SEL_TOP_AUX,
|
||||||
PROGRAM_WIDGET_SEL_TOP_MIDDLE,
|
PROGRAM_WIDGET_SEL_TOP_MIDDLE,
|
||||||
PROGRAM_WIDGET_SEL_TOP_RIGHT,
|
PROGRAM_WIDGET_SEL_TOP_RIGHT,
|
||||||
|
|
||||||
@@ -42,6 +47,8 @@ enum ProgramWindowWidgets {
|
|||||||
PROGRAM_WIDGET_COND_VALUE,
|
PROGRAM_WIDGET_COND_VALUE,
|
||||||
PROGRAM_WIDGET_COND_GOTO_SIGNAL,
|
PROGRAM_WIDGET_COND_GOTO_SIGNAL,
|
||||||
PROGRAM_WIDGET_COND_SET_SIGNAL,
|
PROGRAM_WIDGET_COND_SET_SIGNAL,
|
||||||
|
PROGRAM_WIDGET_COND_SLOT,
|
||||||
|
PROGRAM_WIDGET_COND_COUNTER,
|
||||||
|
|
||||||
PROGRAM_WIDGET_GOTO_SIGNAL,
|
PROGRAM_WIDGET_GOTO_SIGNAL,
|
||||||
PROGRAM_WIDGET_INSERT,
|
PROGRAM_WIDGET_INSERT,
|
||||||
@@ -56,6 +63,10 @@ enum PanelWidgets {
|
|||||||
DPL_COND_VARIABLE = 0,
|
DPL_COND_VARIABLE = 0,
|
||||||
DPL_SET_STATE,
|
DPL_SET_STATE,
|
||||||
|
|
||||||
|
// Aux,
|
||||||
|
DPA_SLOT = 0,
|
||||||
|
DPA_COUNTER = 1,
|
||||||
|
|
||||||
// Middle
|
// Middle
|
||||||
DPM_COND_COMPARATOR = 0,
|
DPM_COND_COMPARATOR = 0,
|
||||||
DPM_COND_GOTO_SIGNAL,
|
DPM_COND_GOTO_SIGNAL,
|
||||||
@@ -85,6 +96,9 @@ static bool IsConditionComparator(SignalCondition *cond)
|
|||||||
switch (cond->ConditionCode()) {
|
switch (cond->ConditionCode()) {
|
||||||
case PSC_NUM_GREEN:
|
case PSC_NUM_GREEN:
|
||||||
case PSC_NUM_RED:
|
case PSC_NUM_RED:
|
||||||
|
case PSC_SLOT_OCC:
|
||||||
|
case PSC_SLOT_OCC_REM:
|
||||||
|
case PSC_COUNTER:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -98,6 +112,9 @@ static const StringID _program_condvar[] = {
|
|||||||
/* PSC_NUM_GREEN */ STR_PROGSIG_CONDVAR_NUM_GREEN,
|
/* PSC_NUM_GREEN */ STR_PROGSIG_CONDVAR_NUM_GREEN,
|
||||||
/* PSC_NUM_RED */ STR_PROGSIG_CONDVAR_NUM_RED,
|
/* PSC_NUM_RED */ STR_PROGSIG_CONDVAR_NUM_RED,
|
||||||
/* PSC_SIGNAL_STATE*/ STR_PROGSIG_COND_SIGNAL_STATE,
|
/* PSC_SIGNAL_STATE*/ STR_PROGSIG_COND_SIGNAL_STATE,
|
||||||
|
/* PSC_SLOT_OCC*/ STR_PROGSIG_COND_SLOT,
|
||||||
|
/* PSC_SLOT_OCC_REM*/ STR_PROGSIG_COND_SLOT_REMAINING,
|
||||||
|
/* PSC_COUNTER*/ STR_PROGSIG_COND_COUNTER,
|
||||||
INVALID_STRING_ID
|
INVALID_STRING_ID
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -125,10 +142,30 @@ static const StringID _program_sigstate[] = {
|
|||||||
static char *GetConditionString(SignalCondition *cond, char *buf, char *buflast, bool selected)
|
static char *GetConditionString(SignalCondition *cond, char *buf, char *buflast, bool selected)
|
||||||
{
|
{
|
||||||
StringID string = INVALID_STRING_ID;
|
StringID string = INVALID_STRING_ID;
|
||||||
bool comparator = IsConditionComparator(cond);
|
if (cond->ConditionCode() == PSC_SLOT_OCC || cond->ConditionCode() == PSC_SLOT_OCC_REM) {
|
||||||
|
SignalSlotCondition *scc = static_cast<SignalSlotCondition*>(cond);
|
||||||
if (comparator) {
|
if (scc->IsSlotValid()) {
|
||||||
SignalVariableCondition *cv = static_cast<SignalVariableCondition*>(cond);
|
string = (cond->ConditionCode() == PSC_SLOT_OCC_REM) ? STR_PROGSIG_COND_SLOT_REMAINING_COMPARE : STR_PROGSIG_COND_SLOT_COMPARE;
|
||||||
|
SetDParam(0, scc->slot_id);
|
||||||
|
} else {
|
||||||
|
string = (cond->ConditionCode() == PSC_SLOT_OCC_REM) ? STR_PROGSIG_COND_SLOT_REMAINING_COMPARE_INVALID : STR_PROGSIG_COND_SLOT_COMPARE_INVALID;
|
||||||
|
SetDParam(0, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED_RED);
|
||||||
|
}
|
||||||
|
SetDParam(1, _program_comparator[scc->comparator]);
|
||||||
|
SetDParam(2, scc->value);
|
||||||
|
} else if (cond->ConditionCode() == PSC_COUNTER) {
|
||||||
|
SignalCounterCondition *scc = static_cast<SignalCounterCondition*>(cond);
|
||||||
|
if (scc->IsCounterValid()) {
|
||||||
|
string = STR_PROGSIG_COND_COUNTER_COMPARE;
|
||||||
|
SetDParam(0, scc->ctr_id);
|
||||||
|
} else {
|
||||||
|
string = STR_PROGSIG_COND_COUNTER_COMPARE_INVALID;
|
||||||
|
SetDParam(0, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED_RED);
|
||||||
|
}
|
||||||
|
SetDParam(1, _program_comparator[scc->comparator]);
|
||||||
|
SetDParam(2, scc->value);
|
||||||
|
} else if (IsConditionComparator(cond)) {
|
||||||
|
SignalConditionComparable *cv = static_cast<SignalConditionComparable*>(cond);
|
||||||
string = STR_PROGSIG_COND_COMPARE;
|
string = STR_PROGSIG_COND_COMPARE;
|
||||||
SetDParam(0, _program_condvar[cond->ConditionCode()]);
|
SetDParam(0, _program_condvar[cond->ConditionCode()]);
|
||||||
SetDParam(1, _program_comparator[cv->comparator]);
|
SetDParam(1, _program_comparator[cv->comparator]);
|
||||||
@@ -221,6 +258,8 @@ public:
|
|||||||
|
|
||||||
this->CreateNestedTree(desc);
|
this->CreateNestedTree(desc);
|
||||||
this->vscroll = this->GetScrollbar(PROGRAM_WIDGET_SCROLLBAR);
|
this->vscroll = this->GetScrollbar(PROGRAM_WIDGET_SCROLLBAR);
|
||||||
|
this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_AUX)->SetDisplayedPlane(SZSP_NONE);
|
||||||
|
this->current_aux_plane = SZSP_NONE;
|
||||||
this->FinishInitNested((ref.tile << 3) | ref.track);
|
this->FinishInitNested((ref.tile << 3) | ref.track);
|
||||||
|
|
||||||
program = GetSignalProgram(ref);
|
program = GetSignalProgram(ref);
|
||||||
@@ -278,7 +317,7 @@ public:
|
|||||||
if (!si || si->Opcode() != PSO_IF) return;
|
if (!si || si->Opcode() != PSO_IF) return;
|
||||||
SignalIf *sif = static_cast <SignalIf*>(si);
|
SignalIf *sif = static_cast <SignalIf*>(si);
|
||||||
|
|
||||||
ShowDropDownMenu(this, _program_condvar, sif->condition->ConditionCode(), PROGRAM_WIDGET_COND_VARIABLE, 0, 0, 0);
|
ShowDropDownMenu(this, _program_condvar, sif->condition->ConditionCode(), PROGRAM_WIDGET_COND_VARIABLE, 0, _settings_client.gui.show_adv_tracerestrict_features ? 0 : 0xE0, 0);
|
||||||
this->UpdateButtonState();
|
this->UpdateButtonState();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -287,7 +326,7 @@ public:
|
|||||||
if (!si || si->Opcode() != PSO_IF) return;
|
if (!si || si->Opcode() != PSO_IF) return;
|
||||||
SignalIf *sif = static_cast <SignalIf*>(si);
|
SignalIf *sif = static_cast <SignalIf*>(si);
|
||||||
if (!IsConditionComparator(sif->condition)) return;
|
if (!IsConditionComparator(sif->condition)) return;
|
||||||
SignalVariableCondition *vc = static_cast<SignalVariableCondition*>(sif->condition);
|
SignalConditionComparable *vc = static_cast<SignalConditionComparable*>(sif->condition);
|
||||||
|
|
||||||
ShowDropDownMenu(this, _program_comparator, vc->comparator, PROGRAM_WIDGET_COND_COMPARATOR, 0, _program_comparator_hide_mask, 0);
|
ShowDropDownMenu(this, _program_comparator, vc->comparator, PROGRAM_WIDGET_COND_COMPARATOR, 0, _program_comparator_hide_mask, 0);
|
||||||
} break;
|
} break;
|
||||||
@@ -297,7 +336,7 @@ public:
|
|||||||
if (!si || si->Opcode() != PSO_IF) return;
|
if (!si || si->Opcode() != PSO_IF) return;
|
||||||
SignalIf *sif = static_cast <SignalIf*>(si);
|
SignalIf *sif = static_cast <SignalIf*>(si);
|
||||||
if (!IsConditionComparator(sif->condition)) return;
|
if (!IsConditionComparator(sif->condition)) return;
|
||||||
SignalVariableCondition *vc = static_cast<SignalVariableCondition*>(sif->condition);
|
SignalConditionComparable *vc = static_cast<SignalConditionComparable*>(sif->condition);
|
||||||
|
|
||||||
SetDParam(0, vc->value);
|
SetDParam(0, vc->value);
|
||||||
//ShowQueryString(STR_JUST_INT, STR_PROGSIG_CONDITION_VALUE_CAPT, 5, 100, this, CS_NUMERAL, QSF_NONE);
|
//ShowQueryString(STR_JUST_INT, STR_PROGSIG_CONDITION_VALUE_CAPT, 5, 100, this, CS_NUMERAL, QSF_NONE);
|
||||||
@@ -320,6 +359,30 @@ public:
|
|||||||
// this->RaiseWidget(PROGRAM_WIDGET_COND_GOTO_SIGNAL);
|
// this->RaiseWidget(PROGRAM_WIDGET_COND_GOTO_SIGNAL);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PROGRAM_WIDGET_COND_SLOT: {
|
||||||
|
SignalInstruction *si = this->GetSelected();
|
||||||
|
if (!si || si->Opcode() != PSO_IF) return;
|
||||||
|
SignalIf *sif = static_cast <SignalIf*>(si);
|
||||||
|
if (sif->condition->ConditionCode() != PSC_SLOT_OCC && sif->condition->ConditionCode() != PSC_SLOT_OCC_REM) return;
|
||||||
|
SignalSlotCondition *sc = static_cast<SignalSlotCondition*>(sif->condition);
|
||||||
|
|
||||||
|
int selected;
|
||||||
|
DropDownList list = GetSlotDropDownList(this->GetOwner(), sc->slot_id, selected);
|
||||||
|
if (!list.empty()) ShowDropDownList(this, std::move(list), selected, PROGRAM_WIDGET_COND_SLOT, 0, true);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PROGRAM_WIDGET_COND_COUNTER: {
|
||||||
|
SignalInstruction *si = this->GetSelected();
|
||||||
|
if (!si || si->Opcode() != PSO_IF) return;
|
||||||
|
SignalIf *sif = static_cast <SignalIf*>(si);
|
||||||
|
if (sif->condition->ConditionCode() != PSC_COUNTER) return;
|
||||||
|
SignalCounterCondition *sc = static_cast<SignalCounterCondition*>(sif->condition);
|
||||||
|
|
||||||
|
int selected;
|
||||||
|
DropDownList list = GetCounterDropDownList(this->GetOwner(), sc->ctr_id, selected);
|
||||||
|
if (!list.empty()) ShowDropDownList(this, std::move(list), selected, PROGRAM_WIDGET_COND_COUNTER, 0, true);
|
||||||
|
} break;
|
||||||
|
|
||||||
case PROGRAM_WIDGET_COND_SET_SIGNAL: {
|
case PROGRAM_WIDGET_COND_SET_SIGNAL: {
|
||||||
this->ToggleWidgetLoweredState(PROGRAM_WIDGET_COND_SET_SIGNAL);
|
this->ToggleWidgetLoweredState(PROGRAM_WIDGET_COND_SET_SIGNAL);
|
||||||
this->SetWidgetDirty(PROGRAM_WIDGET_COND_SET_SIGNAL);
|
this->SetWidgetDirty(PROGRAM_WIDGET_COND_SET_SIGNAL);
|
||||||
@@ -523,6 +586,19 @@ public:
|
|||||||
DoCommandP(this->tile, p1, p2, CMD_MODIFY_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_MODIFY_INSTRUCTION));
|
DoCommandP(this->tile, p1, p2, CMD_MODIFY_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_MODIFY_INSTRUCTION));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PROGRAM_WIDGET_COND_SLOT:
|
||||||
|
case PROGRAM_WIDGET_COND_COUNTER: {
|
||||||
|
uint64 p1 = 0, p2 = 0;
|
||||||
|
SB(p1, 0, 3, this->track);
|
||||||
|
SB(p1, 3, 16, ins->Id());
|
||||||
|
|
||||||
|
SB(p2, 0, 1, 1);
|
||||||
|
SB(p2, 1, 2, SCF_SLOT_COUNTER);
|
||||||
|
SB(p2, 3, 27, index);
|
||||||
|
|
||||||
|
DoCommandP(this->tile, p1, p2, CMD_MODIFY_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_MODIFY_INSTRUCTION));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,9 +656,29 @@ public:
|
|||||||
if (!insn || insn->Opcode() != PSO_IF) return;
|
if (!insn || insn->Opcode() != PSO_IF) return;
|
||||||
SignalIf *si = static_cast<SignalIf*>(insn);
|
SignalIf *si = static_cast<SignalIf*>(insn);
|
||||||
if (!IsConditionComparator(si->condition)) return;
|
if (!IsConditionComparator(si->condition)) return;
|
||||||
SignalVariableCondition *vc = static_cast<SignalVariableCondition*>(si->condition);
|
SignalConditionComparable *vc = static_cast<SignalConditionComparable*>(si->condition);
|
||||||
SetDParam(0, vc->value);
|
SetDParam(0, vc->value);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PROGRAM_WIDGET_COND_SLOT: {
|
||||||
|
SetDParam(0, 0);
|
||||||
|
SignalInstruction *insn = this->GetSelected();
|
||||||
|
if (!insn || insn->Opcode() != PSO_IF) return;
|
||||||
|
SignalIf *si = static_cast<SignalIf*>(insn);
|
||||||
|
if (si->condition->ConditionCode() != PSC_SLOT_OCC && si->condition->ConditionCode() != PSC_SLOT_OCC_REM) return;
|
||||||
|
SignalSlotCondition *sc = static_cast<SignalSlotCondition*>(si->condition);
|
||||||
|
SetDParam(0, sc->slot_id);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PROGRAM_WIDGET_COND_COUNTER: {
|
||||||
|
SetDParam(0, 0);
|
||||||
|
SignalInstruction *insn = this->GetSelected();
|
||||||
|
if (!insn || insn->Opcode() != PSO_IF) return;
|
||||||
|
SignalIf *si = static_cast<SignalIf*>(insn);
|
||||||
|
if (si->condition->ConditionCode() != PSC_COUNTER) return;
|
||||||
|
SignalCounterCondition *sc = static_cast<SignalCounterCondition*>(si->condition);
|
||||||
|
SetDParam(0, sc->ctr_id);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,9 +793,17 @@ private:
|
|||||||
this->RaiseWidget(PROGRAM_WIDGET_COND_GOTO_SIGNAL);
|
this->RaiseWidget(PROGRAM_WIDGET_COND_GOTO_SIGNAL);
|
||||||
|
|
||||||
NWidgetStacked *left_sel = this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_LEFT);
|
NWidgetStacked *left_sel = this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_LEFT);
|
||||||
|
NWidgetStacked *aux_sel = this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_AUX);
|
||||||
NWidgetStacked *middle_sel = this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_MIDDLE);
|
NWidgetStacked *middle_sel = this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_MIDDLE);
|
||||||
NWidgetStacked *right_sel = this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_RIGHT);
|
NWidgetStacked *right_sel = this->GetWidget<NWidgetStacked>(PROGRAM_WIDGET_SEL_TOP_RIGHT);
|
||||||
|
|
||||||
|
auto aux_sel_guard = scope_guard([&]() {
|
||||||
|
if (this->current_aux_plane != aux_sel->shown_plane) {
|
||||||
|
this->current_aux_plane = aux_sel->shown_plane;
|
||||||
|
this->ReInit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Disable all the modifier buttons - we will re-enable them if applicable
|
// Disable all the modifier buttons - we will re-enable them if applicable
|
||||||
this->DisableWidget(PROGRAM_WIDGET_SET_STATE);
|
this->DisableWidget(PROGRAM_WIDGET_SET_STATE);
|
||||||
this->DisableWidget(PROGRAM_WIDGET_COND_VARIABLE);
|
this->DisableWidget(PROGRAM_WIDGET_COND_VARIABLE);
|
||||||
@@ -722,6 +826,8 @@ private:
|
|||||||
SignalInstruction *insn = GetSelected();
|
SignalInstruction *insn = GetSelected();
|
||||||
if (!insn) return;
|
if (!insn) return;
|
||||||
|
|
||||||
|
aux_sel->SetDisplayedPlane(SZSP_NONE);
|
||||||
|
|
||||||
switch (insn->Opcode()) {
|
switch (insn->Opcode()) {
|
||||||
case PSO_IF: {
|
case PSO_IF: {
|
||||||
SignalIf *i = static_cast<SignalIf*>(insn);
|
SignalIf *i = static_cast<SignalIf*>(insn);
|
||||||
@@ -734,7 +840,7 @@ private:
|
|||||||
_program_condvar[i->condition->ConditionCode()];
|
_program_condvar[i->condition->ConditionCode()];
|
||||||
|
|
||||||
if (IsConditionComparator(i->condition)) {
|
if (IsConditionComparator(i->condition)) {
|
||||||
SignalVariableCondition *vc = static_cast<SignalVariableCondition*>(i->condition);
|
SignalConditionComparable *vc = static_cast<SignalConditionComparable*>(i->condition);
|
||||||
this->EnableWidget(PROGRAM_WIDGET_COND_COMPARATOR);
|
this->EnableWidget(PROGRAM_WIDGET_COND_COMPARATOR);
|
||||||
this->EnableWidget(PROGRAM_WIDGET_COND_VALUE);
|
this->EnableWidget(PROGRAM_WIDGET_COND_VALUE);
|
||||||
|
|
||||||
@@ -747,6 +853,17 @@ private:
|
|||||||
middle_sel->SetDisplayedPlane(DPM_COND_GOTO_SIGNAL);
|
middle_sel->SetDisplayedPlane(DPM_COND_GOTO_SIGNAL);
|
||||||
right_sel->SetDisplayedPlane(DPR_COND_SET_SIGNAL);
|
right_sel->SetDisplayedPlane(DPR_COND_SET_SIGNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i->condition->ConditionCode() == PSC_SLOT_OCC || i->condition->ConditionCode() == PSC_SLOT_OCC_REM) {
|
||||||
|
SignalSlotCondition *scc = static_cast<SignalSlotCondition*>(i->condition);
|
||||||
|
this->GetWidget<NWidgetCore>(PROGRAM_WIDGET_COND_SLOT)->widget_data = scc->IsSlotValid() ? STR_TRACE_RESTRICT_SLOT_NAME : STR_TRACE_RESTRICT_VARIABLE_UNDEFINED;
|
||||||
|
aux_sel->SetDisplayedPlane(DPA_SLOT);
|
||||||
|
}
|
||||||
|
if (i->condition->ConditionCode() == PSC_COUNTER) {
|
||||||
|
SignalCounterCondition *scc = static_cast<SignalCounterCondition*>(i->condition);
|
||||||
|
this->GetWidget<NWidgetCore>(PROGRAM_WIDGET_COND_COUNTER)->widget_data = scc->IsCounterValid() ? STR_TRACE_RESTRICT_COUNTER_NAME : STR_TRACE_RESTRICT_VARIABLE_UNDEFINED;
|
||||||
|
aux_sel->SetDisplayedPlane(DPA_COUNTER);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case PSO_SET_SIGNAL: {
|
case PSO_SET_SIGNAL: {
|
||||||
@@ -778,6 +895,7 @@ private:
|
|||||||
GuiInstructionList instructions;
|
GuiInstructionList instructions;
|
||||||
int selected_instruction;
|
int selected_instruction;
|
||||||
Scrollbar *vscroll;
|
Scrollbar *vscroll;
|
||||||
|
int current_aux_plane;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const NWidgetPart _nested_program_widgets[] = {
|
static const NWidgetPart _nested_program_widgets[] = {
|
||||||
@@ -792,7 +910,7 @@ static const NWidgetPart _nested_program_widgets[] = {
|
|||||||
|
|
||||||
// Program display
|
// Program display
|
||||||
NWidget(NWID_HORIZONTAL),
|
NWidget(NWID_HORIZONTAL),
|
||||||
NWidget(WWT_PANEL, COLOUR_GREY, PROGRAM_WIDGET_INSTRUCTION_LIST), SetMinimalSize(372, 62), SetDataTip(0x0, STR_PROGSIG_CAPTION), SetResize(1, 1), EndContainer(),
|
NWidget(WWT_PANEL, COLOUR_GREY, PROGRAM_WIDGET_INSTRUCTION_LIST), SetMinimalSize(372, 62), SetDataTip(0x0, STR_NULL), SetResize(1, 1), EndContainer(),
|
||||||
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, PROGRAM_WIDGET_SCROLLBAR),
|
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, PROGRAM_WIDGET_SCROLLBAR),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
|
|
||||||
@@ -805,6 +923,12 @@ static const NWidgetPart _nested_program_widgets[] = {
|
|||||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, PROGRAM_WIDGET_SET_STATE), SetMinimalSize(124, 12), SetFill(1, 0),
|
NWidget(WWT_DROPDOWN, COLOUR_GREY, PROGRAM_WIDGET_SET_STATE), SetMinimalSize(124, 12), SetFill(1, 0),
|
||||||
SetDataTip(STR_NULL, STR_PROGSIG_SIGNAL_STATE_TOOLTIP), SetResize(1, 0),
|
SetDataTip(STR_NULL, STR_PROGSIG_SIGNAL_STATE_TOOLTIP), SetResize(1, 0),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
|
NWidget(NWID_SELECTION, INVALID_COLOUR, PROGRAM_WIDGET_SEL_TOP_AUX),
|
||||||
|
NWidget(WWT_DROPDOWN, COLOUR_GREY, PROGRAM_WIDGET_COND_SLOT), SetMinimalSize(124, 12), SetFill(1, 0),
|
||||||
|
SetDataTip(STR_NULL, STR_PROGSIG_COND_SLOT_TOOLTIP), SetResize(1, 0),
|
||||||
|
NWidget(WWT_DROPDOWN, COLOUR_GREY, PROGRAM_WIDGET_COND_COUNTER), SetMinimalSize(124, 12), SetFill(1, 0),
|
||||||
|
SetDataTip(STR_NULL, STR_PROGSIG_COND_COUNTER_TOOLTIP), SetResize(1, 0),
|
||||||
|
EndContainer(),
|
||||||
NWidget(NWID_SELECTION, INVALID_COLOUR, PROGRAM_WIDGET_SEL_TOP_MIDDLE),
|
NWidget(NWID_SELECTION, INVALID_COLOUR, PROGRAM_WIDGET_SEL_TOP_MIDDLE),
|
||||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, PROGRAM_WIDGET_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0),
|
NWidget(WWT_DROPDOWN, COLOUR_GREY, PROGRAM_WIDGET_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0),
|
||||||
SetDataTip(STR_NULL, STR_PROGSIG_COND_COMPARATOR_TOOLTIP), SetResize(1, 0),
|
SetDataTip(STR_NULL, STR_PROGSIG_COND_COMPARATOR_TOOLTIP), SetResize(1, 0),
|
||||||
|
@@ -72,7 +72,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
|||||||
{ XSLFI_TRACE_RESTRICT_REVERSE, XSCF_NULL, 1, 1, "tracerestrict_reverse", nullptr, nullptr, nullptr },
|
{ XSLFI_TRACE_RESTRICT_REVERSE, XSCF_NULL, 1, 1, "tracerestrict_reverse", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_TRACE_RESTRICT_NEWSCTRL,XSCF_NULL, 1, 1, "tracerestrict_newsctrl", nullptr, nullptr, nullptr },
|
{ XSLFI_TRACE_RESTRICT_NEWSCTRL,XSCF_NULL, 1, 1, "tracerestrict_newsctrl", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_TRACE_RESTRICT_COUNTER, XSCF_NULL, 1, 1, "tracerestrict_counter", nullptr, nullptr, "TRRC" },
|
{ XSLFI_TRACE_RESTRICT_COUNTER, XSCF_NULL, 1, 1, "tracerestrict_counter", nullptr, nullptr, "TRRC" },
|
||||||
{ XSLFI_PROG_SIGS, XSCF_NULL, 1, 1, "programmable_signals", nullptr, nullptr, "SPRG" },
|
{ XSLFI_PROG_SIGS, XSCF_NULL, 2, 2, "programmable_signals", nullptr, nullptr, "SPRG" },
|
||||||
{ XSLFI_ADJACENT_CROSSINGS, XSCF_NULL, 1, 1, "adjacent_crossings", nullptr, nullptr, nullptr },
|
{ XSLFI_ADJACENT_CROSSINGS, XSCF_NULL, 1, 1, "adjacent_crossings", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_SAFER_CROSSINGS, XSCF_NULL, 1, 1, "safer_crossings", nullptr, nullptr, nullptr },
|
{ XSLFI_SAFER_CROSSINGS, XSCF_NULL, 1, 1, "safer_crossings", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_DEPARTURE_BOARDS, XSCF_IGNORABLE_UNKNOWN, 1, 1, "departure_boards", nullptr, nullptr, nullptr },
|
{ XSLFI_DEPARTURE_BOARDS, XSCF_IGNORABLE_UNKNOWN, 1, 1, "departure_boards", nullptr, nullptr, nullptr },
|
||||||
|
@@ -64,6 +64,21 @@ static void WriteCondition(Buffer &b, SignalCondition *c)
|
|||||||
WriteVLI(b, sc->sig_track);
|
WriteVLI(b, sc->sig_track);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case PSC_SLOT_OCC:
|
||||||
|
case PSC_SLOT_OCC_REM: {
|
||||||
|
SignalSlotCondition *cc = static_cast<SignalSlotCondition*>(c);
|
||||||
|
WriteVLI(b, cc->slot_id);
|
||||||
|
WriteVLI(b, cc->comparator);
|
||||||
|
WriteVLI(b, cc->value);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PSC_COUNTER: {
|
||||||
|
SignalCounterCondition *cc = static_cast<SignalCounterCondition*>(c);
|
||||||
|
WriteVLI(b, cc->ctr_id);
|
||||||
|
WriteVLI(b, cc->comparator);
|
||||||
|
WriteVLI(b, cc->value);
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -88,6 +103,25 @@ static SignalCondition *ReadCondition(SignalReference this_sig)
|
|||||||
return new SignalStateCondition(this_sig, ti, td);
|
return new SignalStateCondition(this_sig, ti, td);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PSC_SLOT_OCC:
|
||||||
|
case PSC_SLOT_OCC_REM: {
|
||||||
|
TraceRestrictSlotID slot_id = (TraceRestrictSlotID) ReadVLI();
|
||||||
|
SignalSlotCondition *c = new SignalSlotCondition(code, this_sig, slot_id);
|
||||||
|
c->comparator = (SignalComparator) ReadVLI();
|
||||||
|
if(c->comparator > SGC_LAST) NOT_REACHED();
|
||||||
|
c->value = ReadVLI();
|
||||||
|
return c;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PSC_COUNTER: {
|
||||||
|
TraceRestrictCounterID ctr_id = (TraceRestrictCounterID) ReadVLI();
|
||||||
|
SignalCounterCondition *c = new SignalCounterCondition(this_sig, ctr_id);
|
||||||
|
c->comparator = (SignalComparator) ReadVLI();
|
||||||
|
if(c->comparator > SGC_LAST) NOT_REACHED();
|
||||||
|
c->value = ReadVLI();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return new SignalSimpleCondition(code);
|
return new SignalSimpleCondition(code);
|
||||||
}
|
}
|
||||||
|
@@ -845,18 +845,23 @@ void FreeSignalDependencies()
|
|||||||
_signal_dependencies.clear();
|
_signal_dependencies.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateSignalDependency(SignalReference sr)
|
||||||
|
{
|
||||||
|
Trackdir td = TrackToTrackdir(sr.track);
|
||||||
|
_globset.Add(sr.tile, TrackdirToExitdir(td));
|
||||||
|
_globset.Add(sr.tile, TrackdirToExitdir(ReverseTrackdir(td)));
|
||||||
|
}
|
||||||
|
|
||||||
static void MarkDependencidesForUpdate(SignalReference on)
|
static void MarkDependencidesForUpdate(SignalReference on)
|
||||||
{
|
{
|
||||||
SignalDependencyMap::iterator f = _signal_dependencies.find(on);
|
SignalDependencyMap::iterator f = _signal_dependencies.find(on);
|
||||||
if (f == _signal_dependencies.end()) return;
|
if (f == _signal_dependencies.end()) return;
|
||||||
|
|
||||||
SignalDependencyList &dependencies = f->second;
|
SignalDependencyList &dependencies = f->second;
|
||||||
for (const SignalReference &i : dependencies) {
|
for (const SignalReference &sr : dependencies) {
|
||||||
assert(GetTileOwner(i.tile) == GetTileOwner(on.tile));
|
assert(GetTileOwner(sr.tile) == GetTileOwner(on.tile));
|
||||||
|
|
||||||
Trackdir td = TrackToTrackdir(i.track);
|
UpdateSignalDependency(sr);
|
||||||
_globset.Add(i.tile, TrackdirToExitdir(td));
|
|
||||||
_globset.Add(i.tile, TrackdirToExitdir(ReverseTrackdir(td)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1721,6 +1721,7 @@ bool TraceRestrictSlot::Occupy(VehicleID id, bool force)
|
|||||||
SetBit(Train::Get(id)->flags, VRF_HAVE_SLOT);
|
SetBit(Train::Get(id)->flags, VRF_HAVE_SLOT);
|
||||||
SetWindowDirty(WC_VEHICLE_DETAILS, id);
|
SetWindowDirty(WC_VEHICLE_DETAILS, id);
|
||||||
InvalidateWindowClassesData(WC_TRACE_RESTRICT_SLOTS);
|
InvalidateWindowClassesData(WC_TRACE_RESTRICT_SLOTS);
|
||||||
|
this->UpdateSignals();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1744,6 +1745,7 @@ void TraceRestrictSlot::Vacate(VehicleID id)
|
|||||||
{
|
{
|
||||||
if (container_unordered_remove(this->occupants, id)) {
|
if (container_unordered_remove(this->occupants, id)) {
|
||||||
this->DeIndex(id);
|
this->DeIndex(id);
|
||||||
|
this->UpdateSignals();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1756,6 +1758,13 @@ void TraceRestrictSlot::Clear()
|
|||||||
this->occupants.clear();
|
this->occupants.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TraceRestrictSlot::UpdateSignals() {
|
||||||
|
for (SignalReference sr : this->progsig_dependants) {
|
||||||
|
AddTrackToSignalBuffer(sr.tile, sr.track, GetTileOwner(sr.tile));
|
||||||
|
UpdateSignalsInBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TraceRestrictSlot::DeIndex(VehicleID id)
|
void TraceRestrictSlot::DeIndex(VehicleID id)
|
||||||
{
|
{
|
||||||
auto range = slot_vehicle_index.equal_range(id);
|
auto range = slot_vehicle_index.equal_range(id);
|
||||||
@@ -1833,6 +1842,7 @@ void TraceRestrictRemoveVehicleFromAllSlots(VehicleID vehicle_id)
|
|||||||
for (auto it = range.first; it != range.second; ++it) {
|
for (auto it = range.first; it != range.second; ++it) {
|
||||||
auto slot = TraceRestrictSlot::Get(it->second);
|
auto slot = TraceRestrictSlot::Get(it->second);
|
||||||
container_unordered_remove(slot->occupants, vehicle_id);
|
container_unordered_remove(slot->occupants, vehicle_id);
|
||||||
|
slot->UpdateSignals();
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool anything_to_erase = range.first != range.second;
|
const bool anything_to_erase = range.first != range.second;
|
||||||
@@ -1908,6 +1918,13 @@ void TraceRestrictRemoveSlotID(TraceRestrictSlotID index)
|
|||||||
InvalidateWindowClassesData(WC_VEHICLE_ORDERS);
|
InvalidateWindowClassesData(WC_VEHICLE_ORDERS);
|
||||||
InvalidateWindowClassesData(WC_VEHICLE_TIMETABLE);
|
InvalidateWindowClassesData(WC_VEHICLE_TIMETABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (SignalReference sr : TraceRestrictSlot::Get(index)->progsig_dependants) {
|
||||||
|
if (IsProgrammableSignal(GetSignalType(sr.tile, sr.track))) {
|
||||||
|
extern void RemoveProgramSlotDependencies(TraceRestrictSlotID slot_being_removed, SignalReference signal_to_update);
|
||||||
|
RemoveProgramSlotDependencies(index, sr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsUniqueSlotName(const char *name)
|
static bool IsUniqueSlotName(const char *name)
|
||||||
@@ -2013,6 +2030,7 @@ CommandCost CmdAlterTraceRestrictSlot(TileIndex tile, DoCommandFlag flags, uint3
|
|||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
slot->max_occupancy = p2;
|
slot->max_occupancy = p2;
|
||||||
|
slot->UpdateSignals();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2021,6 +2039,7 @@ CommandCost CmdAlterTraceRestrictSlot(TileIndex tile, DoCommandFlag flags, uint3
|
|||||||
InvalidateWindowClassesData(WC_TRACE_RESTRICT);
|
InvalidateWindowClassesData(WC_TRACE_RESTRICT);
|
||||||
InvalidateWindowClassesData(WC_TRACE_RESTRICT_SLOTS);
|
InvalidateWindowClassesData(WC_TRACE_RESTRICT_SLOTS);
|
||||||
InvalidateWindowClassesData(WC_VEHICLE_ORDERS);
|
InvalidateWindowClassesData(WC_VEHICLE_ORDERS);
|
||||||
|
InvalidateWindowClassesData(WC_SIGNAL_PROGRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
@@ -2082,6 +2101,10 @@ void TraceRestrictCounter::UpdateValue(int32 new_value)
|
|||||||
if (new_value != this->value) {
|
if (new_value != this->value) {
|
||||||
this->value = new_value;
|
this->value = new_value;
|
||||||
InvalidateWindowClassesData(WC_TRACE_RESTRICT_COUNTERS);
|
InvalidateWindowClassesData(WC_TRACE_RESTRICT_COUNTERS);
|
||||||
|
for (SignalReference sr : this->progsig_dependants) {
|
||||||
|
AddTrackToSignalBuffer(sr.tile, sr.track, GetTileOwner(sr.tile));
|
||||||
|
UpdateSignalsInBuffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2125,6 +2148,13 @@ void TraceRestrictRemoveCounterID(TraceRestrictCounterID index)
|
|||||||
InvalidateWindowClassesData(WC_VEHICLE_ORDERS);
|
InvalidateWindowClassesData(WC_VEHICLE_ORDERS);
|
||||||
InvalidateWindowClassesData(WC_VEHICLE_TIMETABLE);
|
InvalidateWindowClassesData(WC_VEHICLE_TIMETABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (SignalReference sr : TraceRestrictCounter::Get(index)->progsig_dependants) {
|
||||||
|
if (IsProgrammableSignal(GetSignalType(sr.tile, sr.track))) {
|
||||||
|
extern void RemoveProgramCounterDependencies(TraceRestrictCounterID ctr_being_removed, SignalReference signal_to_update);
|
||||||
|
RemoveProgramCounterDependencies(index, sr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2230,6 +2260,7 @@ CommandCost CmdAlterTraceRestrictCounter(TileIndex tile, DoCommandFlag flags, ui
|
|||||||
InvalidateWindowClassesData(WC_TRACE_RESTRICT);
|
InvalidateWindowClassesData(WC_TRACE_RESTRICT);
|
||||||
InvalidateWindowClassesData(WC_TRACE_RESTRICT_COUNTERS);
|
InvalidateWindowClassesData(WC_TRACE_RESTRICT_COUNTERS);
|
||||||
InvalidateWindowClassesData(WC_VEHICLE_ORDERS);
|
InvalidateWindowClassesData(WC_VEHICLE_ORDERS);
|
||||||
|
InvalidateWindowClassesData(WC_SIGNAL_PROGRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#include "tile_type.h"
|
#include "tile_type.h"
|
||||||
#include "group_type.h"
|
#include "group_type.h"
|
||||||
#include "vehicle_type.h"
|
#include "vehicle_type.h"
|
||||||
|
#include "signal_type.h"
|
||||||
#include "3rdparty/cpp-btree/btree_map.h"
|
#include "3rdparty/cpp-btree/btree_map.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -873,6 +874,8 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p
|
|||||||
std::string name;
|
std::string name;
|
||||||
Owner owner;
|
Owner owner;
|
||||||
|
|
||||||
|
std::vector<SignalReference> progsig_dependants;
|
||||||
|
|
||||||
static void RebuildVehicleIndex();
|
static void RebuildVehicleIndex();
|
||||||
static bool ValidateVehicleIndex();
|
static bool ValidateVehicleIndex();
|
||||||
static void ValidateSlotOccupants(std::function<void(const char *)> log);
|
static void ValidateSlotOccupants(std::function<void(const char *)> log);
|
||||||
@@ -900,6 +903,7 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p
|
|||||||
bool OccupyDryRun(VehicleID ids);
|
bool OccupyDryRun(VehicleID ids);
|
||||||
void Vacate(VehicleID id);
|
void Vacate(VehicleID id);
|
||||||
void Clear();
|
void Clear();
|
||||||
|
void UpdateSignals();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DeIndex(VehicleID id);
|
void DeIndex(VehicleID id);
|
||||||
@@ -913,6 +917,8 @@ struct TraceRestrictCounter : TraceRestrictCounterPool::PoolItem<&_tracerestrict
|
|||||||
std::string name;
|
std::string name;
|
||||||
Owner owner;
|
Owner owner;
|
||||||
|
|
||||||
|
std::vector<SignalReference> progsig_dependants;
|
||||||
|
|
||||||
TraceRestrictCounter(CompanyID owner = INVALID_COMPANY)
|
TraceRestrictCounter(CompanyID owner = INVALID_COMPANY)
|
||||||
{
|
{
|
||||||
this->owner = owner;
|
this->owner = owner;
|
||||||
|
Reference in New Issue
Block a user