From b623f5953691b2a0614e6f1f4def86bdbb9a4113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sat, 8 Aug 2020 11:53:00 +0200 Subject: New upstream version 5.2.0Beta2.1 --- app/bin/cmodify.c | 490 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 383 insertions(+), 107 deletions(-) (limited to 'app/bin/cmodify.c') diff --git a/app/bin/cmodify.c b/app/bin/cmodify.c index 11f4c06..8f82012 100644 --- a/app/bin/cmodify.c +++ b/app/bin/cmodify.c @@ -34,6 +34,9 @@ #include "param.h" #include "track.h" #include "utility.h" +#include "drawgeom.h" +#include "common.h" +#include "layout.h" static struct { track_p Trk; @@ -47,10 +50,65 @@ static struct { BOOL_T first; } Dex; +static wMenu_p modPopupM; + +extern wIndex_t selectCmdInx; +extern wIndex_t joinCmdInx; +extern wIndex_t describeCmdInx; + +static dynArr_t anchors_da; +#define anchors(N) DYNARR_N(trkSeg_t,anchors_da,N) static int log_modify; static BOOL_T modifyBezierMode; static BOOL_T modifyCornuMode; +static BOOL_T modifyDrawMode; +static BOOL_T modifyRulerMode; +static BOOL_T modifyExtendMode; + + +static void CreateEndAnchor(coOrd p, wBool_t lock) { + DIST_T d = tempD.scale*0.15; + + DYNARR_APPEND(trkSeg_t,anchors_da,1); + int i = anchors_da.cnt-1; + anchors(i).type = lock?SEG_FILCRCL:SEG_CRVLIN; + anchors(i).color = wDrawColorBlue; + anchors(i).u.c.center = p; + anchors(i).u.c.radius = d/2; + anchors(i).u.c.a0 = 0.0; + anchors(i).u.c.a1 = 360.0; + anchors(i).width = 0; +} + +static void CreateCornuAnchor(coOrd p, wBool_t lock) { + DIST_T d = tempD.scale*0.15; + + DYNARR_APPEND(trkSeg_t,anchors_da,1); + int i = anchors_da.cnt-1; + anchors(i).type = lock?SEG_FILCRCL:SEG_CRVLIN; + anchors(i).color = wDrawColorBlue; + anchors(i).u.c.center = p; + anchors(i).u.c.radius = d/2; + anchors(i).u.c.a0 = 0.0; + anchors(i).u.c.a1 = 360.0; + anchors(i).width = 0; + DYNARR_APPEND(trkSeg_t,anchors_da,1); + i = anchors_da.cnt-1; + anchors(i).type = SEG_CRVLIN; + anchors(i).color = wDrawColorBlue; + anchors(i).u.c.center = p; + anchors(i).u.c.radius = d; + anchors(i).u.c.a0 = 0.0; + anchors(i).u.c.a1 = 360.0; + anchors(i).width = 0; +} + + +static void CreateRadiusAnchor(coOrd p, ANGLE_T a, BOOL_T bi) { + DYNARR_SET(trkSeg_t,anchors_da,anchors_da.cnt+5); + DrawArrowHeads(&DYNARR_N(trkSeg_t,anchors_da,anchors_da.cnt-5),p,a,bi,wDrawColorBlue); +} /* * Call cbezier.c CmdBezModify to alter Bezier Track and Lines. @@ -66,6 +124,7 @@ static STATUS_T ModifyBezier(wAction_t action, coOrd pos) { case C_UP: case C_OK: case C_TEXT: + case wActionMove: trackGauge = (IsTrack(Dex.Trk)?GetTrkGauge(Dex.Trk):0.0); rc = CmdBezModify(Dex.Trk, action, pos, trackGauge); break; @@ -89,12 +148,14 @@ static STATUS_T ModifyCornu(wAction_t action, coOrd pos) { STATUS_T rc = C_CONTINUE; if (Dex.Trk == NULL) return C_ERROR; //No track picked yet! switch (action&0xFF) { + case C_LCLICK: case C_START: case C_DOWN: case C_MOVE: case C_UP: case C_OK: case C_TEXT: + case wActionMove: trackGauge = (IsTrack(Dex.Trk)?GetTrkGauge(Dex.Trk):0.0); rc = CmdCornuModify(Dex.Trk, action, pos, trackGauge); break; @@ -110,7 +171,61 @@ static STATUS_T ModifyCornu(wAction_t action, coOrd pos) { return rc; } -static STATUS_T CmdModify( +/* + * Picking a DRAW will allow point modifications until terminated with "Enter" + */ +static STATUS_T ModifyDraw(wAction_t action, coOrd pos) { + STATUS_T rc = C_CONTINUE; + if (Dex.Trk == NULL) return C_ERROR; //No item picked yet! + switch (action&0xFF) { + case C_START: + case C_DOWN: + case C_MOVE: + case C_UP: + rc = ModifyTrack( Dex.Trk, action, pos ); + break; + case wActionMove: + rc = ModifyTrack( Dex.Trk, action, pos ); + break; + case C_TEXT: + //Delete or '0' - continues + if ((action>>8 !=32) && (action >>8 !=13)) + return ModifyTrack( Dex.Trk, action, pos ); + //Enter/Space does not + if ((action>>8 !=32) && (action>>8 != 13)) return C_CONTINUE; + /*no break*/ + case C_OK: + UndoStart( _("Modify Track"), "Modify( T%d[%d] )", GetTrkIndex(Dex.Trk), Dex.params.ep ); + UndoModify( Dex.Trk ); + rc = ModifyTrack( Dex.Trk, C_TEXT | (13<<8), pos ); + if (rc != C_CONTINUE) modifyDrawMode = FALSE; + UndoEnd(); + break; + case C_CANCEL: + case C_FINISH: + case C_CONFIRM: + case C_TERMINATE: + rc = ModifyTrack( Dex.Trk, action, pos ); + Dex.Trk = NULL; + modifyDrawMode = FALSE; + tempSegs_da.cnt = 0; + rc = C_CONTINUE; + break; + case C_REDRAW: + rc = ModifyTrack( Dex.Trk, action, pos ); + break; + case C_CMDMENU: + menuPos = pos; + rc = ModifyTrack( Dex.Trk, action, pos ); + break; + default: + break; + } + return rc; +} + + +STATUS_T CmdModify( wAction_t action, coOrd pos ) /* @@ -128,7 +243,7 @@ static STATUS_T CmdModify( EPINX_T inx; curveType_e curveType; static BOOL_T changeTrackMode; - static BOOL_T modifyRulerMode; + STATUS_T rc; static DIST_T trackGauge; @@ -143,7 +258,8 @@ static STATUS_T CmdModify( switch (action&0xFF) { case C_START: - InfoMessage( _("Select track to modify") ); + DYNARR_RESET(trkSeg_t,anchors_da); + InfoMessage( _("Select a track to modify, Left-Click change length, Right-Click to add flextrack") ); Dex.Trk = NULL; tempSegs_da.cnt = 0; /*ChangeParameter( &easementPD );*/ @@ -151,21 +267,28 @@ static STATUS_T CmdModify( changeTrackMode = modifyRulerMode = FALSE; modifyBezierMode = FALSE; modifyCornuMode = FALSE; + modifyDrawMode = FALSE; + modifyExtendMode = FALSE; return C_CONTINUE; case C_DOWN: + DYNARR_RESET(trkSeg_t,anchors_da); if (modifyBezierMode) return ModifyBezier(C_DOWN, pos); if (modifyCornuMode) return ModifyCornu(C_DOWN, pos); + if (modifyDrawMode) + return ModifyDraw(C_DOWN, pos); + /*no break*/ + case C_LDOUBLE: DYNARR_SET( trkSeg_t, tempSegs_da, 2 ); tempSegs(0).color = wDrawColorBlack; tempSegs(0).width = 0; tempSegs(1).color = wDrawColorBlack; tempSegs(1).width = 0; tempSegs_da.cnt = 0; - SnapPos( &pos ); Dex.Trk = OnTrack( &pos, TRUE, FALSE ); + //Dex.Trk = trk; if (Dex.Trk == NULL) { if ( ModifyRuler( C_DOWN, pos ) == C_CONTINUE ) modifyRulerMode = TRUE; @@ -173,6 +296,7 @@ static STATUS_T CmdModify( } if (!CheckTrackLayer( Dex.Trk ) ) { Dex.Trk = NULL; + return C_CONTINUE; } trackGauge = (IsTrack(Dex.Trk)?GetTrkGauge(Dex.Trk):0.0); @@ -185,21 +309,38 @@ static STATUS_T CmdModify( } return C_CONTINUE; //That's it } - if (QueryTrack( Dex.Trk, Q_IS_CORNU )) { //Bezier + if (QueryTrack( Dex.Trk, Q_IS_CORNU )) { //Cornu modifyCornuMode = TRUE; if (ModifyCornu(C_START, pos) != C_CONTINUE) { //Call Start with track - modifyCornuMode = FALSE; //Function rejected Bezier + modifyCornuMode = FALSE; //Function rejected Cornu Dex.Trk =NULL; tempSegs_da.cnt = 0; + } return C_CONTINUE; //That's it } - if ( (MyGetKeyState()&WKEY_SHIFT) && + if (QueryTrack( Dex.Trk, Q_IS_DRAW )) { + modifyDrawMode = TRUE; + if (ModifyDraw(C_START, pos) != C_CONTINUE) { + modifyDrawMode = FALSE; + Dex.Trk = NULL; + tempSegs_da.cnt = 0; + } + return C_CONTINUE; + } + + if ((action&0xFF) == C_LDOUBLE) return C_ERROR; + + if ((MyGetKeyState()&WKEY_CTRL)) goto extendTrack; + + + + if ( (MyGetKeyState()&WKEY_SHIFT) && //Free to change radius QueryTrack( Dex.Trk, Q_CAN_MODIFYRADIUS )&& - (inx=PickUnconnectedEndPoint(pos,Dex.Trk)) >= 0 ) { + ((inx=PickUnconnectedEndPoint(pos,Dex.Trk)) >= 0 )) { trk = Dex.Trk; - while ( (trk1=GetTrkEndTrk(trk,1-inx)) && + while ( (trk1=GetTrkEndTrk(trk,1-inx)) && //Means next track to mine even if can be end... QueryTrack(trk1, Q_CANNOT_BE_ON_END) ) { inx = GetEndPtConnectedToMe( trk1, trk ); trk = trk1; @@ -208,7 +349,8 @@ static STATUS_T CmdModify( UndoStart( _("Change Track"), "Change( T%d[%d] )", GetTrkIndex(Dex.Trk), Dex.params.ep ); inx = GetEndPtConnectedToMe( trk1, trk ); Dex.Trk = NULL; - DeleteTrack(trk, TRUE); + UndrawNewTrack( trk ); + DeleteTrack(trk, TRUE); //Get rid of original track if ( !GetTrkEndTrk( trk1, inx ) ) { Dex.Trk = trk1; Dex.pos00 = GetTrkEndPos( Dex.Trk, inx ); @@ -218,16 +360,70 @@ static STATUS_T CmdModify( } ErrorMessage( MSG_CANNOT_CHANGE ); } + ModifyTrack(Dex.Trk, C_START, pos); //Basically trim via Modify... rc = ModifyTrack( Dex.Trk, C_DOWN, pos ); if ( rc != C_CONTINUE ) { Dex.Trk = NULL; rc = C_CONTINUE; } - DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); - MainRedraw(); - MapRedraw(); return rc; + case wActionMove: + DYNARR_RESET(trkSeg_t,anchors_da); + if (modifyCornuMode) return ModifyCornu(wActionMove,pos); + if (modifyDrawMode) return ModifyDraw(wActionMove,pos); + if (modifyBezierMode) return ModifyBezier(wActionMove, pos); + track_p t; + if (((t=OnTrack(&pos,FALSE,TRUE))!= NULL) && CheckTrackLayerSilent( t )) { + EPINX_T ep = PickUnconnectedEndPointSilent(pos, t); + if (QueryTrack( t, Q_IS_CORNU )) { + CreateCornuAnchor(pos,FALSE); + } else if ( QueryTrack( t, Q_CAN_MODIFY_CONTROL_POINTS )) { + CreateRadiusAnchor(pos,NormalizeAngle(GetAngleAtPoint(t,pos,NULL,NULL)+90.0),TRUE); + CreateEndAnchor(pos,FALSE); + } else if (QueryTrack(t,Q_CAN_ADD_ENDPOINTS)){ //Turntable + trackParams_t tp; + if (!GetTrackParams(PARAMS_CORNU, t, pos, &tp)) return C_CONTINUE; + ANGLE_T a = tp.angle; + Translate(&pos,tp.ttcenter,a,tp.ttradius); + CreateRadiusAnchor(pos,a,FALSE); + } else if (QueryTrack(t,Q_CAN_EXTEND)) { + if (ep != -1) { + if (MyGetKeyState()&WKEY_CTRL) { + pos = GetTrkEndPos(t,ep); + CreateEndAnchor(pos,FALSE); + CreateRadiusAnchor(pos,GetTrkEndAngle(t,ep),FALSE); + CreateRadiusAnchor(pos,GetTrkEndAngle(t,ep)+90,TRUE); + } else { + CreateEndAnchor(pos,FALSE); + if ((MyGetKeyState()&WKEY_SHIFT) && //Shift Down + QueryTrack( t, Q_CAN_MODIFYRADIUS ) && // Straight or Curve + ((inx=PickUnconnectedEndPointSilent(pos,t)) >= 0 )) { //Which has an open end + if (GetTrkEndTrk(t,1-inx)) // Has to have a track on other end + CreateRadiusAnchor(pos,NormalizeAngle(GetAngleAtPoint(t,pos,NULL,NULL)+90.0),TRUE); + } + CreateRadiusAnchor(pos,GetAngleAtPoint(t,pos,NULL,NULL),TRUE); + } + } + } else if (ep>=0){ //Turnout + pos = GetTrkEndPos(t, ep); + CreateEndAnchor(pos,TRUE); + if ( (MyGetKeyState()&WKEY_CTRL)) { + CreateRadiusAnchor(pos,NormalizeAngle(GetTrkEndAngle(t,ep)),FALSE); + CreateRadiusAnchor(pos,GetTrkEndAngle(t,ep)+90,TRUE); + CreateEndAnchor(pos,TRUE); + } else { + CreateRadiusAnchor(pos,NormalizeAngle(GetTrkEndAngle(t,ep)),FALSE); + CreateEndAnchor(pos,TRUE); + } + } + } else if (((t=OnTrack(&pos,FALSE,FALSE))!= NULL) + && (!(GetLayerFrozen(GetTrkLayer(t)) && GetLayerModule(GetTrkLayer(t)))) + && (QueryTrack(t, Q_IS_DRAW ) && !QueryTrack(t, Q_IS_TEXT)) ) { + CreateEndAnchor(pos,FALSE); + } + return C_CONTINUE; + case C_MOVE: if ( modifyRulerMode ) return ModifyRuler( C_MOVE, pos ); @@ -237,21 +433,22 @@ static STATUS_T CmdModify( return ModifyBezier(C_MOVE, pos); if ( modifyCornuMode ) return ModifyCornu(C_MOVE, pos); - DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); + if ( modifyDrawMode) + return ModifyDraw(C_MOVE, pos); + if (modifyExtendMode && (MyGetKeyState()&WKEY_CTRL)) + goto extendTrackMove; tempSegs_da.cnt = 0; + SnapPos( &pos ); rc = ModifyTrack( Dex.Trk, C_MOVE, pos ); if ( rc != C_CONTINUE ) { rc = C_CONTINUE; Dex.Trk = NULL; } - DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); - MainRedraw(); - MapRedraw(); return rc; - case C_UP: + DYNARR_RESET(trkSeg_t,anchors_da); if (Dex.Trk == NULL) return C_CONTINUE; if ( modifyRulerMode ) @@ -260,58 +457,71 @@ static STATUS_T CmdModify( return ModifyBezier( C_UP, pos); if (modifyCornuMode) return ModifyCornu(C_UP, pos); - DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); + if (modifyDrawMode) + return ModifyDraw(C_UP, pos); + if ((MyGetKeyState()&WKEY_CTRL)) goto extendTrackUp; + tempSegs_da.cnt = 0; + SnapPos( &pos ); UndoStart( _("Modify Track"), "Modify( T%d[%d] )", GetTrkIndex(Dex.Trk), Dex.params.ep ); UndoModify( Dex.Trk ); rc = ModifyTrack( Dex.Trk, C_UP, pos ); UndoEnd(); - //changeTrackMode = FALSE; Dex.Trk = NULL; - MainRedraw(); - MapRedraw(); return rc; - case C_RDOWN: + case C_RDOWN: //This is same as context menu.... +extendTrack: + DYNARR_RESET(trkSeg_t,anchors_da); changeTrackMode = TRUE; + modifyExtendMode = TRUE; modifyRulerMode = FALSE; modifyBezierMode = FALSE; modifyCornuMode = FALSE; - Dex.Trk = OnTrack( &pos, TRUE, TRUE ); - if (Dex.Trk) { - if (!CheckTrackLayer( Dex.Trk ) ) { - Dex.Trk = NULL; - return C_CONTINUE; - } - trackGauge = GetTrkGauge( Dex.Trk ); - Dex.pos00 = pos; -CHANGE_TRACK: - if (GetTrackParams( PARAMS_EXTEND, Dex.Trk, Dex.pos00, &Dex.params)) { - if (Dex.params.ep == -1) { + modifyDrawMode = FALSE; + Dex.first = FALSE; + if (((action&0xFF) == C_RDOWN) || ((action&0xFF)== C_DOWN)) { + Dex.Trk = OnTrack( &pos, TRUE, TRUE ); + if (Dex.Trk) { + if (!CheckTrackLayer( Dex.Trk ) ) { Dex.Trk = NULL; return C_CONTINUE; - break; } - if (Dex.params.ep == 0) { - Dex.params.arcR = -Dex.params.arcR; + trackGauge = GetTrkGauge( Dex.Trk ); + Dex.pos00 = pos; + CHANGE_TRACK: + if (GetTrackParams( PARAMS_EXTEND, Dex.Trk, Dex.pos00, &Dex.params)) { + if (Dex.params.ep == -1) { + Dex.Trk = NULL; + return C_CONTINUE; + break; + } + if (Dex.params.ep == 0) { + Dex.params.arcR = -Dex.params.arcR; + } + Dex.pos00 = GetTrkEndPos(Dex.Trk,Dex.params.ep); + Dex.angle = GetTrkEndAngle( Dex.Trk,Dex.params.ep); + Translate( &Dex.pos00x, Dex.pos00, Dex.angle, 10.0 ); + LOG( log_modify, 1, ("extend endPt[%d] = [%0.3f %0.3f] A%0.3f\n", + Dex.params.ep, Dex.pos00.x, Dex.pos00.y, Dex.angle ) ) + InfoMessage( _("Drag to add flex track") ); + } else { + return C_ERROR; } - Dex.pos00 = GetTrkEndPos(Dex.Trk,Dex.params.ep); - Dex.angle = GetTrkEndAngle( Dex.Trk,Dex.params.ep); - Translate( &Dex.pos00x, Dex.pos00, Dex.angle, 10.0 ); -LOG( log_modify, 1, ("extend endPt[%d] = [%0.3f %0.3f] A%0.3f\n", - Dex.params.ep, Dex.pos00.x, Dex.pos00.y, Dex.angle ) ) - InfoMessage( _("Drag to create new track segment") ); } else { + InfoMessage ( _("No track to extend")); return C_ERROR; } + Dex.first = TRUE; + } else if (!Dex.Trk) { + InfoMessage ( _("No track selected")); + return C_ERROR; } - Dex.first = TRUE; - MainRedraw(); - MapRedraw(); /* no break */ case C_RMOVE: - DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); +extendTrackMove: + DYNARR_RESET(trkSeg_t,anchors_da); tempSegs_da.cnt = 0; Dex.valid = FALSE; if (Dex.Trk == NULL) return C_CONTINUE; @@ -320,7 +530,8 @@ LOG( log_modify, 1, ("extend endPt[%d] = [%0.3f %0.3f] A%0.3f\n", return C_CONTINUE; Dex.first = FALSE; Dex.pos01 = Dex.pos00; - if (Dex.params.type == curveTypeCornu) { //Restrict Cornu drag out to match end + + if (Dex.params.type == curveTypeCornu) { //Always Restrict Cornu drag out to match end ANGLE_T angle2 = NormalizeAngle(FindAngle(pos, Dex.pos00)-Dex.angle); if (angle2 > 90.0 && angle2 < 270.0) { if (Dex.params.cornuRadius[Dex.params.ep] == 0) { @@ -346,11 +557,6 @@ LOG( log_modify, 1, ("extend endPt[%d] = [%0.3f %0.3f] A%0.3f\n", ErrorMessage( MSG_TRK_TOO_SHORT, "First ", PutDim(fabs(minLength-d)) ); return C_CONTINUE; } - a0 = Dex.angle + (Dex.jointD.negate?-90.0:+90.0); - Translate( &Dex.pos01, Dex.pos00, a0, Dex.jointD.x ); - Translate( &Dex.curveData.pos1, Dex.curveData.pos1, - a0, Dex.jointD.x ); -LOG( log_modify, 2, ("A=%0.3f X=%0.3f\n", a0, Dex.jointD.x ) ) } else { Dex.jointD.d1 = 0.0; } @@ -376,44 +582,55 @@ LOG( log_modify, 2, ("A=%0.3f X=%0.3f\n", a0, Dex.jointD.x ) ) return C_CONTINUE; } else if ( curveType == curveTypeCurve ) { Dex.r1 = Dex.curveData.curveRadius; - if ( easeR > 0.0 && Dex.r1 < easeR ) { - ErrorMessage( MSG_RADIUS_LSS_EASE_MIN, - FormatDistance( Dex.r1 ), FormatDistance( easeR ) ); - return C_CONTINUE; - } - if ( Dex.r1*2.0*M_PI*Dex.curveData.a1/360.0 > mapD.size.x+mapD.size.y ) { - ErrorMessage( MSG_CURVE_TOO_LARGE ); - return C_CONTINUE; - } - if ( NormalizeAngle( FindAngle( Dex.pos00, pos ) - Dex.angle ) > 180.0 ) - Dex.r1 = -Dex.r1; if ( QueryTrack( Dex.Trk, Q_IGNORE_EASEMENT_ON_EXTEND ) ) { - /* Ignore easements when extending turnouts */ + /* Ignore easements when extending turnouts or turntables */ Dex.jointD.x = Dex.jointD.r0 = Dex.jointD.r1 = Dex.jointD.l0 = Dex.jointD.l1 = Dex.jointD.d0 = Dex.jointD.d1 = 0.0; Dex.jointD.flip = Dex.jointD.negate = Dex.jointD.Scurve = FALSE; - } else { - if (ComputeJoint( Dex.params.arcR, Dex.r1, &Dex.jointD ) == E_ERROR) - return C_CONTINUE; - d = Dex.params.len - Dex.jointD.d0; - if (d <= minLength) { - ErrorMessage( MSG_TRK_TOO_SHORT, "First ", PutDim(fabs(minLength-d)) ); - return C_CONTINUE; + d = Dex.curveData.curveRadius * Dex.curveData.a1 * 2.0*M_PI/360.0; + } else { /* Easement code */ + if (easementVal<0.0) { //Cornu Join - need to estimate a "good" easement length + d = Dex.curveData.curveRadius * Dex.curveData.a1 * 2.0*M_PI/360.0; + Dex.jointD.d0 = Dex.jointD.d1 =0.75*72*12/GetTrkScale(Dex.Trk); //Easement 1.5 cars long to start + if (Dex.jointD.d0>(GetTrkLength(Dex.Trk,0,1)/2)) + Dex.jointD.d0 = GetTrkLength(Dex.Trk,0,1)/2; + if (Dex.jointD.d1>d/2) + Dex.jointD.d1 = d/2; + Dex.jointD.negate = DifferenceBetweenAngles(Dex.angle,FindAngle(Dex.pos00,pos))<0.0; + Dex.jointD.x = 2*trackGauge; //Signal an easement present to JoinTracks + } else { + if ( easeR > 0.0 && Dex.r1 < easeR ) { + ErrorMessage( MSG_RADIUS_LSS_EASE_MIN, + FormatDistance( Dex.r1 ), FormatDistance( easeR ) ); + return C_CONTINUE; + } + if ( Dex.r1*2.0*M_PI*Dex.curveData.a1/360.0 > mapD.size.x+mapD.size.y ) { + ErrorMessage( MSG_CURVE_TOO_LARGE ); + return C_CONTINUE; + } + if ( NormalizeAngle( FindAngle( Dex.pos00, pos ) - Dex.angle ) > 180.0 ) + Dex.r1 = - Dex.r1; + if (ComputeJoint( Dex.params.arcR, Dex.r1, &Dex.jointD ) == E_ERROR) + return C_CONTINUE; + d = Dex.params.len - Dex.jointD.d0; + if (d <= minLength) { + ErrorMessage( MSG_TRK_TOO_SHORT, "First ", PutDim(fabs(minLength-d)) ); + return C_CONTINUE; + } } + d -= Dex.jointD.d1; + a0 = Dex.angle + (Dex.jointD.negate?-90.0:+90.0); + Translate( &Dex.pos01, Dex.pos00, a0, Dex.jointD.x ); + Translate( &Dex.curveData.curvePos, Dex.curveData.curvePos, + a0, Dex.jointD.x ); +LOG( log_modify, 2, ("A=%0.3f X=%0.3f\n", a0, Dex.jointD.x ) ) } - d = Dex.curveData.curveRadius * Dex.curveData.a1 * 2.0*M_PI/360.0; - d -= Dex.jointD.d1; if (d <= minLength) { ErrorMessage( MSG_TRK_TOO_SHORT, "Extending ", PutDim(fabs(minLength-d)) ); return C_CONTINUE; } - a0 = Dex.angle + (Dex.jointD.negate?-90.0:+90.0); - Translate( &Dex.pos01, Dex.pos00, a0, Dex.jointD.x ); - Translate( &Dex.curveData.curvePos, Dex.curveData.curvePos, - a0, Dex.jointD.x ); -LOG( log_modify, 2, ("A=%0.3f X=%0.3f\n", a0, Dex.jointD.x ) ) tempSegs(0).type = SEG_CRVTRK; tempSegs(0).width = 0; tempSegs(0).u.c.center = Dex.curveData.curvePos; @@ -421,9 +638,9 @@ LOG( log_modify, 2, ("A=%0.3f X=%0.3f\n", a0, Dex.jointD.x ) ) tempSegs(0).u.c.a0 = Dex.curveData.a0; tempSegs(0).u.c.a1 = Dex.curveData.a1; tempSegs_da.cnt = 1; - d = D2R(Dex.curveData.a1); - if (d < 0.0) - d = 2*M_PI + d; + double da = D2R(Dex.curveData.a1); + if (da < 0.0) + da = 2*M_PI + da; a = NormalizeAngle( Dex.angle - FindAngle( Dex.pos00, Dex.curveData.curvePos ) ); if ( a < 180.0 ) a = NormalizeAngle( Dex.curveData.a0-90 ); @@ -433,17 +650,15 @@ LOG( log_modify, 2, ("A=%0.3f X=%0.3f\n", a0, Dex.jointD.x ) ) if (action != C_RDOWN) InfoMessage( _("Curve Track: Radius=%s Length=%s Angle=%0.3f"), FormatDistance( Dex.curveData.curveRadius ), - FormatDistance( Dex.curveData.curveRadius * d), + FormatDistance( Dex.curveData.curveRadius * da), Dex.curveData.a1 ); } - DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); - MainRedraw(); - MapRedraw(); return C_CONTINUE; case C_RUP: +extendTrackUp: changeTrackMode = FALSE; - DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); + modifyExtendMode = FALSE; tempSegs_da.cnt = 0; if (Dex.Trk == NULL) return C_CONTINUE; if (!Dex.valid) @@ -453,22 +668,24 @@ LOG( log_modify, 2, ("A=%0.3f X=%0.3f\n", a0, Dex.jointD.x ) ) curveType = Dex.curveData.type; if ( curveType == curveTypeStraight ) { - if ( Dex.params.type == curveTypeStraight && Dex.params.len > 0 ) { - //UndrawNewTrack( Dex.Trk ); - UndoModify( Dex.Trk ); - AdjustStraightEndPt( Dex.Trk, Dex.params.ep, Dex.curveData.pos1 ); - UndoEnd(); - DrawNewTrack(Dex.Trk ); - MainRedraw(); - MapRedraw(); - return C_TERMINATE; + if (QueryTrack(Dex.Trk,Q_CAN_EXTEND)) //Check it isn't a turnout end.... + if ( Dex.params.type == curveTypeStraight && + FindDistance(Dex.pos01, Dex.curveData.pos1) > 0 ) { + UndoModify( Dex.Trk ); + AdjustStraightEndPt( Dex.Trk, Dex.params.ep, Dex.curveData.pos1 ); + UndoEnd(); + DrawNewTrack(Dex.Trk ); + return C_TERMINATE; } + if (FindDistance(Dex.pos01, Dex.curveData.pos1) == 0) return C_ERROR; +LOG( log_modify, 1, ("L = %0.3f, P0 = %0.3f, P1 = %0.3f\n", + Dex.params.len, Dex.pos01, Dex.curveData.pos1 ) ) trk = NewStraightTrack( Dex.pos01, Dex.curveData.pos1 ); inx = 0; } else if ( curveType == curveTypeCurve ) { -LOG( log_modify, 1, ("A0 = %0.3f, A1 = %0.3f\n", - Dex.curveData.a0, Dex.curveData.a1 ) ) +LOG( log_modify, 1, ("R = %0.3f, A0 = %0.3f, A1 = %0.3f\n", + Dex.curveData.curveRadius, Dex.curveData.a0, Dex.curveData.a1 ) ) trk = NewCurvedTrack( Dex.curveData.curvePos, Dex.curveData.curveRadius, Dex.curveData.a0, Dex.curveData.a1, 0 ); inx = PickUnconnectedEndPoint( Dex.pos01, trk ); @@ -478,39 +695,86 @@ LOG( log_modify, 1, ("A0 = %0.3f, A1 = %0.3f\n", } else { return C_ERROR; } - //UndrawNewTrack( Dex.Trk ); CopyAttributes( Dex.Trk, trk ); - JoinTracks( Dex.Trk, Dex.params.ep, Dex.pos00, trk, inx, Dex.pos01, &Dex.jointD ); + if (Dex.jointD.d1 == 0) { + DrawEndPt( &mainD, Dex.Trk, Dex.params.ep, wDrawColorWhite ); + ConnectTracks(Dex.Trk, Dex.params.ep, trk, inx); + DrawEndPt( &mainD, Dex.Trk, Dex.params.ep, wDrawColorBlack ); + } else { + UndrawNewTrack( Dex.Trk ); + JoinTracks( Dex.Trk, Dex.params.ep, Dex.pos00, trk, inx, Dex.pos01, &Dex.jointD ); + DrawNewTrack( Dex.Trk ); + } UndoEnd(); + tempSegs_da.cnt = 0; DrawNewTrack( trk ); - DrawNewTrack( Dex.Trk ); - Dex.Trk = NULL; - MainRedraw(); - MapRedraw(); return C_TERMINATE; case C_REDRAW: if (modifyBezierMode) return ModifyBezier(C_REDRAW, pos); if (modifyCornuMode) return ModifyCornu(C_REDRAW, pos); - if ( (!changeTrackMode) && Dex.Trk && !QueryTrack( Dex.Trk, Q_MODIFY_REDRAW_DONT_UNDRAW_TRACK ) ) - UndrawNewTrack( Dex.Trk ); + if (modifyDrawMode) return ModifyDraw(C_REDRAW, pos); DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack ); + if (anchors_da.cnt) + DrawSegs( &tempD, zero, 0.0, &anchors(0), anchors_da.cnt, trackGauge, wDrawColorBlack ); + return C_CONTINUE; case C_TEXT: + if ((action>>8) == 'c') { + panCenter = pos; + LOG( log_pan, 2, ( "PanCenter:Mod-%d %0.3f %0.3f\n", __LINE__, panCenter.x, panCenter.y ) ); + PanHere((void*)0); + return C_CONTINUE; + } + if ((action>>8) == 'e') { + DoZoomExtents(0); + } + if ((action>>8) == '0' || (action>>8 == 'o')) { + PanMenuEnter('o'); + } if ( !Dex.Trk ) return C_CONTINUE; if (modifyBezierMode) return ModifyBezier(action, pos); if (modifyCornuMode) return ModifyCornu(action, pos); + if (modifyDrawMode) + return ModifyDraw(action, pos); + return ModifyTrack( Dex.Trk, action, pos ); + + case C_CMDMENU: + if ( !Dex.Trk ) { + menuPos = pos; + wMenuPopupShow(modPopupM); + return C_CONTINUE; + } + if (modifyBezierMode) + return ModifyBezier(action, pos); + if (modifyCornuMode) + return ModifyCornu(action, pos); + if (modifyDrawMode) + return ModifyDraw(action, pos); return ModifyTrack( Dex.Trk, action, pos ); + case C_LCLICK: + if ( modifyDrawMode) { + rc = ModifyDraw(C_DOWN, pos); + if (rc == C_CONTINUE) + return ModifyDraw(C_UP, pos); + } + if (modifyCornuMode) + return ModifyCornu(action, pos); + /*no break*/ default: if (modifyBezierMode) return ModifyBezier(action, pos); if (modifyCornuMode) return ModifyCornu(action, pos); + if (modifyDrawMode) return ModifyDraw(action, pos); + if (Dex.Trk) + return ModifyTrack( Dex.Trk, action, pos ); return C_CONTINUE; } + return C_CONTINUE; } @@ -521,9 +785,21 @@ LOG( log_modify, 1, ("A0 = %0.3f, A1 = %0.3f\n", */ #include "bitmaps/extend.xpm" +extern wIndex_t panCmdInx; +extern wIndex_t selectCmdInx; +extern wIndex_t describeCmdInx; + void InitCmdModify( wMenu_p menu ) { - modifyCmdInx = AddMenuButton( menu, CmdModify, "cmdModify", _("Modify"), wIconCreatePixMap(extend_xpm), LEVEL0_50, IC_STICKY|IC_POPUP, ACCL_MODIFY, NULL ); + modifyCmdInx = AddMenuButton( menu, CmdModify, "cmdModify", _("Modify"), wIconCreatePixMap(extend_xpm), LEVEL0_50, IC_STICKY|IC_POPUP|IC_WANT_MOVE|IC_CMDMENU, ACCL_MODIFY, NULL ); log_modify = LogFindIndex( "modify" ); + modPopupM = MenuRegister( "Modify Context Menu" ); + wMenuPushCreate(modPopupM, "cmdSelectMode", GetBalloonHelpStr("cmdSelectMode"), 0, DoCommandB, (void*) (intptr_t) selectCmdInx); + wMenuPushCreate(modPopupM, "cmdDescribeMode", GetBalloonHelpStr("cmdDescribeMode"), 0, DoCommandB, (void*) (intptr_t) describeCmdInx); + wMenuPushCreate(modPopupM, "cmdPanMode", GetBalloonHelpStr("cmdPanMode"), 0, DoCommandB, (void*) (intptr_t) panCmdInx); + wMenuSeparatorCreate(modPopupM); + wMenuPushCreate(modPopupM, "", _("Zoom In"), 0,(wMenuCallBack_p) DoZoomUp, (void*) 1); + wMenuPushCreate(modPopupM, "", _("Zoom Out"), 0, (wMenuCallBack_p) DoZoomDown, (void*) 1); + wMenuPushCreate(modPopupM, "", _("Pan center - 'c'"), 0, (wMenuCallBack_p) PanHere, (void*) 3); } -- cgit v1.2.3