Merge branch 'progsig-sx' into jgrpp
Conflicts: src/command.cpp
This commit is contained in:
@@ -205,6 +205,7 @@ CommandProc CmdProgramSignalTraceRestrict;
|
|||||||
CommandProc CmdInsertSignalInstruction;
|
CommandProc CmdInsertSignalInstruction;
|
||||||
CommandProc CmdModifySignalInstruction;
|
CommandProc CmdModifySignalInstruction;
|
||||||
CommandProc CmdRemoveSignalInstruction;
|
CommandProc CmdRemoveSignalInstruction;
|
||||||
|
CommandProc CmdSignalProgramMgmt;
|
||||||
|
|
||||||
CommandProc CmdAddPlan;
|
CommandProc CmdAddPlan;
|
||||||
CommandProc CmdAddPlanLine;
|
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(CmdInsertSignalInstruction, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_INSERT_SIGNAL_INSTRUCTION
|
||||||
DEF_CMD(CmdModifySignalInstruction, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_MODIFY_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(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(CmdAddPlan, 0, CMDT_OTHER_MANAGEMENT ), // CMD_ADD_PLAN
|
||||||
DEF_CMD(CmdAddPlanLine, 0, CMDT_OTHER_MANAGEMENT ), // CMD_ADD_PLAN_LINE
|
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_INSERT_SIGNAL_INSTRUCTION, ///< insert a signal instruction
|
||||||
CMD_MODIFY_SIGNAL_INSTRUCTION, ///< modifies a signal instruction
|
CMD_MODIFY_SIGNAL_INSTRUCTION, ///< modifies a signal instruction
|
||||||
CMD_REMOVE_SIGNAL_INSTRUCTION, ///< removes 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,
|
||||||
CMD_ADD_PLAN_LINE,
|
CMD_ADD_PLAN_LINE,
|
||||||
|
@@ -476,7 +476,7 @@ CommandCost CmdInsertSignalInstruction(TileIndex tile, DoCommandFlag flags, uint
|
|||||||
SignalProgram *prog = GetExistingSignalProgram(SignalReference(tile, track));
|
SignalProgram *prog = GetExistingSignalProgram(SignalReference(tile, track));
|
||||||
if (!prog)
|
if (!prog)
|
||||||
return_cmd_error(STR_ERR_PROGSIG_NOT_THERE);
|
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);
|
return_cmd_error(STR_ERR_PROGSIG_INVALID_INSTRUCTION);
|
||||||
|
|
||||||
bool exec = (flags & DC_EXEC) != 0;
|
bool exec = (flags & DC_EXEC) != 0;
|
||||||
@@ -700,3 +700,130 @@ CommandCost CmdRemoveSignalInstruction(TileIndex tile, DoCommandFlag flags, uint
|
|||||||
InvalidateWindowData(WC_SIGNAL_PROGRAM, (tile << 3) | track);
|
InvalidateWindowData(WC_SIGNAL_PROGRAM, (tile << 3) | track);
|
||||||
return CommandCost();
|
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;
|
class SignalSpecial;
|
||||||
typedef SmallVector<SignalInstruction*, 4> InstructionList;
|
typedef SmallVector<SignalInstruction*, 4> InstructionList;
|
||||||
|
|
||||||
|
enum SignalProgramMgmtCode {
|
||||||
|
SPMC_REMOVE, ///< Remove program
|
||||||
|
SPMC_CLONE, ///< Clone program
|
||||||
|
};
|
||||||
|
|
||||||
/** The actual programmable signal information */
|
/** The actual programmable signal information */
|
||||||
struct SignalProgram {
|
struct SignalProgram {
|
||||||
SignalProgram(TileIndex tile, Track track, bool raw = false);
|
SignalProgram(TileIndex tile, Track track, bool raw = false);
|
||||||
@@ -212,7 +217,6 @@ class SignalStateCondition: public SignalCondition {
|
|||||||
SignalReference this_sig;
|
SignalReference this_sig;
|
||||||
TileIndex sig_tile;
|
TileIndex sig_tile;
|
||||||
Trackdir sig_track;
|
Trackdir sig_track;
|
||||||
SignalState state;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// -- Instructions
|
// -- Instructions
|
||||||
|
@@ -256,8 +256,7 @@ public:
|
|||||||
|
|
||||||
case PROGRAM_WIDGET_REMOVE: {
|
case PROGRAM_WIDGET_REMOVE: {
|
||||||
SignalInstruction *ins = GetSelected();
|
SignalInstruction *ins = GetSelected();
|
||||||
if (this->GetOwner() != _local_company || !ins)
|
if (ins == NULL) return;
|
||||||
return;
|
|
||||||
|
|
||||||
uint32 p1 = 0;
|
uint32 p1 = 0;
|
||||||
SB(p1, 0, 3, this->track);
|
SB(p1, 0, 3, this->track);
|
||||||
@@ -336,15 +335,13 @@ public:
|
|||||||
ScrollMainWindowToTile(this->tile);
|
ScrollMainWindowToTile(this->tile);
|
||||||
// this->RaiseWidget(PROGRAM_WIDGET_GOTO_SIGNAL);
|
// this->RaiseWidget(PROGRAM_WIDGET_GOTO_SIGNAL);
|
||||||
} break;
|
} 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();
|
this->RebuildInstructionList();
|
||||||
} break;
|
} break;
|
||||||
case PROGRAM_WIDGET_COPY_PROGRAM: {
|
|
||||||
|
|
||||||
|
case PROGRAM_WIDGET_COPY_PROGRAM: {
|
||||||
this->ToggleWidgetLoweredState(PROGRAM_WIDGET_COPY_PROGRAM);
|
this->ToggleWidgetLoweredState(PROGRAM_WIDGET_COPY_PROGRAM);
|
||||||
this->SetWidgetDirty(PROGRAM_WIDGET_COPY_PROGRAM);
|
this->SetWidgetDirty(PROGRAM_WIDGET_COPY_PROGRAM);
|
||||||
if (this->IsWidgetLowered(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
|
virtual void OnPlaceObject(Point pt, TileIndex tile1) OVERRIDE
|
||||||
{
|
{
|
||||||
if (this->IsWidgetLowered(PROGRAM_WIDGET_COPY_PROGRAM)) {
|
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);
|
ShowErrorMessage(STR_ERROR_INVALID_SIGNAL, STR_ERROR_NOT_AN_EXIT_SIGNAL, WL_INFO);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
program->first_instruction->Remove();
|
DoCommandP(this->tile, this->track | (SPMC_CLONE << 3) | (track1 << 7), tile1, CMD_SIGNAL_PROGRAM_MGMT | CMD_MSG(STR_ERROR_CAN_T_INSERT_INSTRUCTION));
|
||||||
this->RebuildInstructionList();
|
|
||||||
|
|
||||||
SignalInstruction *si = ((SignalSpecial*)sp->first_instruction)->next;
|
|
||||||
InsertInstruction(si, program->last_instruction->Id());
|
|
||||||
ResetObjectToPlace();
|
ResetObjectToPlace();
|
||||||
this->RaiseWidget(PROGRAM_WIDGET_COPY_PROGRAM);
|
this->RaiseWidget(PROGRAM_WIDGET_COPY_PROGRAM);
|
||||||
|
this->RebuildInstructionList();
|
||||||
//OnPaint(); // this appears to cause visual artefacts
|
//OnPaint(); // this appears to cause visual artefacts
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user