Merge branch 'progsig-sx' into jgrpp
Conflicts: src/command.cpp
This commit is contained in:
@@ -205,6 +205,7 @@ CommandProc CmdProgramSignalTraceRestrict;
|
||||
CommandProc CmdInsertSignalInstruction;
|
||||
CommandProc CmdModifySignalInstruction;
|
||||
CommandProc CmdRemoveSignalInstruction;
|
||||
CommandProc CmdSignalProgramMgmt;
|
||||
|
||||
CommandProc CmdAddPlan;
|
||||
CommandProc CmdAddPlanLine;
|
||||
@@ -378,6 +379,7 @@ static const Command _command_proc_table[] = {
|
||||
DEF_CMD(CmdInsertSignalInstruction, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_INSERT_SIGNAL_INSTRUCTION
|
||||
DEF_CMD(CmdModifySignalInstruction, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_MODIFY_SIGNAL_INSTRUCTION
|
||||
DEF_CMD(CmdRemoveSignalInstruction, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_REMOVE_SIGNAL_INSTRUCTION
|
||||
DEF_CMD(CmdSignalProgramMgmt, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_SIGNAL_PROGRAM_MGMT
|
||||
|
||||
DEF_CMD(CmdAddPlan, 0, CMDT_OTHER_MANAGEMENT ), // CMD_ADD_PLAN
|
||||
DEF_CMD(CmdAddPlanLine, 0, CMDT_OTHER_MANAGEMENT ), // CMD_ADD_PLAN_LINE
|
||||
|
@@ -336,6 +336,7 @@ enum Commands {
|
||||
CMD_INSERT_SIGNAL_INSTRUCTION, ///< insert a signal instruction
|
||||
CMD_MODIFY_SIGNAL_INSTRUCTION, ///< modifies a signal instruction
|
||||
CMD_REMOVE_SIGNAL_INSTRUCTION, ///< removes a signal instruction
|
||||
CMD_SIGNAL_PROGRAM_MGMT, ///< removes a signal program management command
|
||||
|
||||
CMD_ADD_PLAN,
|
||||
CMD_ADD_PLAN_LINE,
|
||||
|
@@ -476,7 +476,7 @@ CommandCost CmdInsertSignalInstruction(TileIndex tile, DoCommandFlag flags, uint
|
||||
SignalProgram *prog = GetExistingSignalProgram(SignalReference(tile, track));
|
||||
if (!prog)
|
||||
return_cmd_error(STR_ERR_PROGSIG_NOT_THERE);
|
||||
if (instruction_id > prog->instructions.Length())
|
||||
if (instruction_id >= prog->instructions.Length())
|
||||
return_cmd_error(STR_ERR_PROGSIG_INVALID_INSTRUCTION);
|
||||
|
||||
bool exec = (flags & DC_EXEC) != 0;
|
||||
@@ -700,3 +700,130 @@ CommandCost CmdRemoveSignalInstruction(TileIndex tile, DoCommandFlag flags, uint
|
||||
InvalidateWindowData(WC_SIGNAL_PROGRAM, (tile << 3) | track);
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
static void CloneInstructions(SignalProgram *prog, SignalInstruction *insert_before, SignalInstruction *si)
|
||||
{
|
||||
while(true) {
|
||||
if(si == NULL) break;
|
||||
switch(si->Opcode()) {
|
||||
case PSO_SET_SIGNAL: {
|
||||
SignalSet *set = new SignalSet(prog, ((SignalSet*)si)->to_state);
|
||||
set->Insert(insert_before);
|
||||
|
||||
si = ((SignalSet*)si)->next;
|
||||
break;
|
||||
}
|
||||
|
||||
case PSO_IF: {
|
||||
SignalIf *if_ins = new SignalIf(prog);
|
||||
if_ins->Insert(insert_before);
|
||||
|
||||
CloneInstructions(prog, if_ins->if_true, ((SignalIf*)si)->if_true);
|
||||
CloneInstructions(prog, if_ins->if_false, ((SignalIf*)si)->if_false);
|
||||
|
||||
SignalCondition *src_cond = ((SignalIf *) si)->condition;
|
||||
SignalConditionCode code = src_cond->ConditionCode();
|
||||
switch (code) {
|
||||
case PSC_ALWAYS:
|
||||
case PSC_NEVER:
|
||||
if_ins->SetCondition(new SignalSimpleCondition(code));
|
||||
break;
|
||||
|
||||
case PSC_NUM_GREEN:
|
||||
case PSC_NUM_RED: {
|
||||
SignalVariableCondition *cond = new SignalVariableCondition(code);
|
||||
cond->comparator = ((SignalVariableCondition *) src_cond)->comparator;
|
||||
cond->value = ((SignalVariableCondition *) src_cond)->value;
|
||||
if_ins->SetCondition(cond);
|
||||
break;
|
||||
}
|
||||
|
||||
case PSC_SIGNAL_STATE: {
|
||||
SignalStateCondition *src = ((SignalStateCondition *) src_cond);
|
||||
if_ins->SetCondition(new SignalStateCondition(SignalReference(prog->tile, prog->track), src->sig_tile, src->sig_track));
|
||||
break;
|
||||
}
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
|
||||
si = ((SignalIf*)si)->after;
|
||||
break;
|
||||
}
|
||||
|
||||
case PSO_LAST:
|
||||
case PSO_IF_ELSE:
|
||||
case PSO_IF_ENDIF:
|
||||
return;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Insert a signal instruction into the signal program.
|
||||
*
|
||||
* @param tile The Tile on which to perform the operation
|
||||
* @param p1 Flags and information
|
||||
* - Bits 0-2 Which track the signal sits on
|
||||
* - Bits 3-6 Management code
|
||||
* For clone action:
|
||||
* - Bits 7-9 Which track the clone source signal sits on
|
||||
* @param p2
|
||||
* For clone action:
|
||||
* - Tile of clone source signal
|
||||
* @param text unused
|
||||
*/
|
||||
CommandCost CmdSignalProgramMgmt(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
bool exec = (flags & DC_EXEC) != 0;
|
||||
|
||||
Track track = Extract<Track, 0, 3>(p1);
|
||||
SignalProgramMgmtCode mgmt = static_cast<SignalProgramMgmtCode>(GB(p1, 3, 4));
|
||||
|
||||
if (!IsValidTrack(track) || !IsPlainRailTile(tile) || !HasTrack(tile, track)) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (!IsTileOwner(tile, _current_company)) return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
|
||||
|
||||
SignalProgram *prog = GetExistingSignalProgram(SignalReference(tile, track));
|
||||
if (!prog) return_cmd_error(STR_ERR_PROGSIG_NOT_THERE);
|
||||
|
||||
switch (mgmt) {
|
||||
case SPMC_REMOVE:
|
||||
if (exec) {
|
||||
prog->first_instruction->Remove();
|
||||
}
|
||||
break;
|
||||
|
||||
case SPMC_CLONE: {
|
||||
TileIndex src_tile = p2;
|
||||
Track src_track = Extract<Track, 7, 3>(p1);
|
||||
if (!IsValidTrack(src_track) || !IsPlainRailTile(src_tile) || !HasTrack(src_tile, src_track)) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (!IsTileOwner(src_tile, _current_company)) return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
|
||||
|
||||
SignalProgram *src_prog = GetExistingSignalProgram(SignalReference(src_tile, src_track));
|
||||
if (!src_prog) return_cmd_error(STR_ERR_PROGSIG_NOT_THERE);
|
||||
|
||||
if (exec) {
|
||||
prog->first_instruction->Remove();
|
||||
CloneInstructions(prog, prog->last_instruction, ((SignalSpecial*) src_prog->first_instruction)->next);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return CMD_ERROR;
|
||||
}
|
||||
if (exec) {
|
||||
AddTrackToSignalBuffer(tile, track, GetTileOwner(tile));
|
||||
UpdateSignalsInBuffer();
|
||||
InvalidateWindowData(WC_SIGNAL_PROGRAM, (tile << 3) | track);
|
||||
}
|
||||
return CommandCost();
|
||||
}
|
||||
|
@@ -28,6 +28,11 @@ class SignalInstruction;
|
||||
class SignalSpecial;
|
||||
typedef SmallVector<SignalInstruction*, 4> InstructionList;
|
||||
|
||||
enum SignalProgramMgmtCode {
|
||||
SPMC_REMOVE, ///< Remove program
|
||||
SPMC_CLONE, ///< Clone program
|
||||
};
|
||||
|
||||
/** The actual programmable signal information */
|
||||
struct SignalProgram {
|
||||
SignalProgram(TileIndex tile, Track track, bool raw = false);
|
||||
@@ -212,7 +217,6 @@ class SignalStateCondition: public SignalCondition {
|
||||
SignalReference this_sig;
|
||||
TileIndex sig_tile;
|
||||
Trackdir sig_track;
|
||||
SignalState state;
|
||||
};
|
||||
|
||||
// -- Instructions
|
||||
|
@@ -256,8 +256,7 @@ public:
|
||||
|
||||
case PROGRAM_WIDGET_REMOVE: {
|
||||
SignalInstruction *ins = GetSelected();
|
||||
if (this->GetOwner() != _local_company || !ins)
|
||||
return;
|
||||
if (ins == NULL) return;
|
||||
|
||||
uint32 p1 = 0;
|
||||
SB(p1, 0, 3, this->track);
|
||||
@@ -336,15 +335,13 @@ public:
|
||||
ScrollMainWindowToTile(this->tile);
|
||||
// this->RaiseWidget(PROGRAM_WIDGET_GOTO_SIGNAL);
|
||||
} break;
|
||||
case PROGRAM_WIDGET_REMOVE_PROGRAM: {
|
||||
if (this->GetOwner() != _local_company)
|
||||
return;
|
||||
program->first_instruction->Remove();
|
||||
|
||||
case PROGRAM_WIDGET_REMOVE_PROGRAM: {
|
||||
DoCommandP(this->tile, this->track | (SPMC_REMOVE << 3), 0, CMD_SIGNAL_PROGRAM_MGMT | CMD_MSG(STR_ERROR_CAN_T_MODIFY_INSTRUCTION));
|
||||
this->RebuildInstructionList();
|
||||
} break;
|
||||
case PROGRAM_WIDGET_COPY_PROGRAM: {
|
||||
|
||||
case PROGRAM_WIDGET_COPY_PROGRAM: {
|
||||
this->ToggleWidgetLoweredState(PROGRAM_WIDGET_COPY_PROGRAM);
|
||||
this->SetWidgetDirty(PROGRAM_WIDGET_COPY_PROGRAM);
|
||||
if (this->IsWidgetLowered(PROGRAM_WIDGET_COPY_PROGRAM)) {
|
||||
@@ -356,62 +353,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void InsertInstruction(SignalInstruction *si, uint32 next)
|
||||
{
|
||||
uint64 p1 = 0;
|
||||
while(true) {
|
||||
if(si == NULL) break;
|
||||
switch(si->Opcode()) {
|
||||
case PSO_SET_SIGNAL: {
|
||||
SB(p1, 0, 3, this->track);
|
||||
SB(p1, 3, 16, next);
|
||||
SB(p1, 19, 8, si->Opcode());
|
||||
|
||||
DoCommandP(this->tile, p1, 0, CMD_INSERT_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_INSERT_INSTRUCTION));
|
||||
this->RebuildInstructionList();
|
||||
si = ((SignalSet*)si)->next;
|
||||
} break;
|
||||
|
||||
case PSO_IF: {
|
||||
SB(p1, 0, 3, this->track);
|
||||
SB(p1, 3, 16, next);
|
||||
SB(p1, 19, 8, si->Opcode());
|
||||
|
||||
DoCommandP(this->tile, p1, 0, CMD_INSERT_SIGNAL_INSTRUCTION | CMD_MSG(STR_ERROR_CAN_T_INSERT_INSTRUCTION));
|
||||
this->RebuildInstructionList();
|
||||
|
||||
SignalInstruction *s = ((SignalIf*)si)->if_true;
|
||||
while(s->Opcode() != PSO_IF_ELSE) {
|
||||
if(s->Opcode() == PSO_IF) s = ((SignalIf*)s)->after;
|
||||
if(s->Opcode() == PSO_SET_SIGNAL) s = ((SignalSet*)s)->next;
|
||||
else break;
|
||||
}
|
||||
InsertInstruction(((SignalIf*)si)->if_true, s->Id());
|
||||
this->RebuildInstructionList();
|
||||
|
||||
s = ((SignalIf*)si)->if_false;
|
||||
while(s->Opcode() != PSO_IF_ENDIF) {
|
||||
if(s->Opcode() == PSO_IF) s = ((SignalIf*)s)->after;
|
||||
if(s->Opcode() == PSO_SET_SIGNAL) s = ((SignalSet*)s)->next;
|
||||
else break;
|
||||
}
|
||||
InsertInstruction(((SignalIf*)si)->if_false, s->Id());
|
||||
this->RebuildInstructionList();
|
||||
|
||||
si = ((SignalIf*)si)->after;
|
||||
} break;
|
||||
|
||||
case PSO_LAST:
|
||||
case PSO_IF_ELSE:
|
||||
case PSO_IF_ENDIF:
|
||||
return;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnPlaceObject(Point pt, TileIndex tile1) OVERRIDE
|
||||
{
|
||||
if (this->IsWidgetLowered(PROGRAM_WIDGET_COPY_PROGRAM)) {
|
||||
@@ -446,13 +387,10 @@ public:
|
||||
ShowErrorMessage(STR_ERROR_INVALID_SIGNAL, STR_ERROR_NOT_AN_EXIT_SIGNAL, WL_INFO);
|
||||
return;
|
||||
}
|
||||
program->first_instruction->Remove();
|
||||
this->RebuildInstructionList();
|
||||
|
||||
SignalInstruction *si = ((SignalSpecial*)sp->first_instruction)->next;
|
||||
InsertInstruction(si, program->last_instruction->Id());
|
||||
DoCommandP(this->tile, this->track | (SPMC_CLONE << 3) | (track1 << 7), tile1, CMD_SIGNAL_PROGRAM_MGMT | CMD_MSG(STR_ERROR_CAN_T_INSERT_INSTRUCTION));
|
||||
ResetObjectToPlace();
|
||||
this->RaiseWidget(PROGRAM_WIDGET_COPY_PROGRAM);
|
||||
this->RebuildInstructionList();
|
||||
//OnPaint(); // this appears to cause visual artefacts
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user