Exemplo n.º 1
0
        public Interpolator(STFReader stf)
        {
            List <float> list = new List <float>();

            stf.MustMatch("(");
            while (!stf.EndOfBlock())
            {
                list.Add(stf.ReadFloat(STFReader.UNITS.Any, null));
            }
            if (list.Count % 2 == 1)
            {
                STFException.TraceWarning(stf, "Ignoring extra odd value in Interpolator list.");
            }
            int n = list.Count / 2;

            if (n < 2)
            {
                STFException.TraceWarning(stf, "Interpolator must have at least two value pairs.");
            }
            X    = new float[n];
            Y    = new float[n];
            Size = n;
            for (int i = 0; i < n; i++)
            {
                X[i] = list[2 * i];
                Y[i] = list[2 * i + 1];
                if (i > 0 && X[i - 1] >= X[i])
                {
                    STFException.TraceWarning(stf, "Interpolator x values must be increasing.");
                }
            }
        }
Exemplo n.º 2
0
        public Interpolator2D(STFReader stf)
        {
            List <float>        xlist = new List <float>();
            List <Interpolator> ilist = new List <Interpolator>();

            stf.MustMatch("(");
            while (!stf.EndOfBlock())
            {
                xlist.Add(stf.ReadFloat(STFReader.UNITS.Any, null));
                ilist.Add(new Interpolator(stf));
            }
            stf.SkipRestOfBlock();
            int n = xlist.Count;

            if (n < 2)
            {
                STFException.TraceWarning(stf, "Interpolator must have at least two x values.");
            }
            X    = new float[n];
            Y    = new Interpolator[n];
            Size = n;
            for (int i = 0; i < n; i++)
            {
                X[i] = xlist[i];
                Y[i] = ilist[i];
                if (i > 0 && X[i - 1] >= X[i])
                {
                    STFException.TraceWarning(stf, " Interpolator x values must be increasing.");
                }
            }
        }
Exemplo n.º 3
0
        public static Interpolator CreateInterpolator(this STFReader reader)
        {
            List <double> list = new List <double>();

            reader.MustMatchBlockStart();
            while (!reader.EndOfBlock())
            {
                list.Add(reader.ReadFloat(STFReader.Units.Any, null));
            }
            if (list.Count % 2 == 1)
            {
                STFException.TraceWarning(reader, "Ignoring extra odd value in Interpolator list.");
            }
            int n = list.Count / 2;

            if (n < 2)
            {
                STFException.TraceWarning(reader, "Interpolator must have at least two value pairs.");
            }
            double[] xArray = new double[n];
            double[] yArray = new double[n];
            for (int i = 0; i < n; i++)
            {
                xArray[i] = list[2 * i];
                yArray[i] = list[2 * i + 1];
                if (i > 0 && xArray[i - 1] >= xArray[i])
                {
                    STFException.TraceWarning(reader, "Interpolator x values must be increasing.");
                }
            }
            return(new Interpolator(xArray, yArray));
        }
Exemplo n.º 4
0
        public static Interpolator2D CreateInterpolator2D(this STFReader stf)
        {
            List <double>       xlist = new List <double>();
            List <Interpolator> ilist = new List <Interpolator>();

            stf.MustMatchBlockStart();
            while (!stf.EndOfBlock())
            {
                xlist.Add(stf.ReadFloat(STFReader.Units.Any, null));
                ilist.Add(stf.CreateInterpolator());
            }
            stf.SkipRestOfBlock();
            int n = xlist.Count;

            if (n < 2)
            {
                STFException.TraceWarning(stf, "Interpolator must have at least two x values.");
            }
            double[]       xArray = new double[n];
            Interpolator[] yArray = new Interpolator[n];
            for (int i = 0; i < n; i++)
            {
                xArray[i] = xlist[i];
                yArray[i] = ilist[i];
                if (i > 0 && xArray[i - 1] >= xArray[i])
                {
                    STFException.TraceWarning(stf, " Interpolator x values must be increasing.");
                }
            }
            return(new Interpolator2D(xArray, yArray));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Default constructor used during file parsing.
        /// </summary>
        /// <param name="stf">The STFreader containing the file stream</param>
        public SignalLight(STFReader stf)
        {
            stf.MustMatchBlockStart();
            Index = stf.ReadInt(null);
            Name  = stf.ReadString().ToLowerInvariant();
            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("radius", () => { Radius = stf.ReadFloatBlock(STFReader.Units.None, null); }),
                new STFReader.TokenProcessor("position", () => {
                    stf.MustMatchBlockStart();
                    position = new Vector3(stf.ReadFloat(null), stf.ReadFloat(null), stf.ReadFloat(null));
                    stf.SkipRestOfBlock();
                }),
                new STFReader.TokenProcessor("signalflags", () => {
                    stf.MustMatchBlockStart();
                    while (!stf.EndOfBlock())
                    {
                        switch (stf.ReadString().ToLower())
                        {
                        case "semaphore_change":
                            SemaphoreChange = true;
                            break;

                        default:
                            stf.StepBackOneItem();
                            STFException.TraceInformation(stf, "Skipped unknown SignalLight flag " + stf.ReadString());
                            break;
                        }
                    }
                }),
            });
        }
Exemplo n.º 6
0
            // SigSubJnLinkIf is not supported

            /// <summary>
            /// Default constructor used during file parsing.
            /// </summary>
            /// <param name="stf">The STFreader containing the file stream</param>
            public SignalSubObj(STFReader stf)
            {
                SignalSubType = -1; // not (yet) specified
                stf.MustMatch("(");
                Index       = stf.ReadInt(null);
                MatrixName  = stf.ReadString().ToUpper();
                Description = stf.ReadString();
                stf.ParseBlock(new STFReader.TokenProcessor[] {
                    new STFReader.TokenProcessor("sigsubtype", () => { SignalSubType = SignalSubTypes.IndexOf(stf.ReadStringBlock(null).ToUpper()); }),
                    new STFReader.TokenProcessor("sigsubstype", () => { SignalSubSignalType = stf.ReadStringBlock(null).ToLowerInvariant(); }),
                    new STFReader.TokenProcessor("signalflags", () => {
                        stf.MustMatch("(");
                        while (!stf.EndOfBlock())
                        {
                            switch (stf.ReadString().ToLower())
                            {
                            case "optional": Optional = true; break;

                            case "default": Default = true; break;

                            case "back_facing": BackFacing = true; break;

                            case "jn_link": JunctionLink = true; break;

                            default: stf.StepBackOneItem(); STFException.TraceInformation(stf, "Skipped unknown SignalSubObj flag " + stf.ReadString()); break;
                            }
                        }
                    }),
                });
            }
Exemplo n.º 7
0
 public Initial_Trigger(STFReader f)
 {
     f.MustMatch("(");
     while (!f.EndOfBlock())
     {
         ParsePlayCommand(f, f.ReadString().ToLower());
     }
 }
Exemplo n.º 8
0
 public Discrete_Trigger(STFReader f)
 {
     f.MustMatch("(");
     TriggerID = f.ReadInt(null);
     while (!f.EndOfBlock())
     {
         ParsePlayCommand(f, f.ReadString().ToLower());
     }
 }
Exemplo n.º 9
0
        public Variable_Trigger(STFReader f)
        {
            f.MustMatch("(");

            string eventString = f.ReadString();

            Threshold = f.ReadFloat(STFReader.UNITS.None, null);

            switch (eventString.ToLower())
            {
            case "speed_inc_past": Event = Events.Speed_Inc_Past; break;

            case "speed_dec_past": Event = Events.Speed_Dec_Past; break;

            case "distance_inc_past":
            {
                Event     = Events.Distance_Inc_Past;
                Threshold = Threshold * Threshold;
                break;
            }

            case "distance_dec_past":
            {
                Event     = Events.Distance_Dec_Past;
                Threshold = Threshold * Threshold;
                break;
            }

            case "variable1_inc_past": Event = Events.Variable1_Inc_Past; break;

            case "variable1_dec_past": Event = Events.Variable1_Dec_Past; break;

            case "variable2_inc_past": Event = Events.Variable2_Inc_Past; break;

            case "variable2_dec_past": Event = Events.Variable2_Dec_Past; break;

            case "variable3_inc_past": Event = Events.Variable3_Inc_Past; break;

            case "variable3_dec_past": Event = Events.Variable3_Dec_Past; break;

            case "brakecyl_inc_past": Event = Events.BrakeCyl_Inc_Past; break;

            case "brakecyl_dec_past": Event = Events.BrakeCyl_Dec_Past; break;

            case "curveforce_inc_past": Event = Events.CurveForce_Inc_Past; break;

            case "curveforce_dec_past": Event = Events.CurveForce_Dec_Past; break;
            }



            while (!f.EndOfBlock())
            {
                ParsePlayCommand(f, f.ReadString().ToLower());
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Default constructor used during file parsing.
        /// </summary>
        /// <param name="stf">The STFreader containing the file stream</param>
        /// <param name="ORTSMode">Process SignalType for ORTS mode (always set NumClearAhead_ORTS only)</param>
        public SignalType(STFReader stf, bool ORTSMode)
            : this()
        {
            stf.MustMatch("(");
            Name = stf.ReadString().ToLowerInvariant();
            int numClearAhead = -2;
            int numdefs       = 0;

            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("signalfntype", () => { FnType = ReadFnType(stf); }),  //[Rob Roeterdink] value was not passed
                new STFReader.TokenProcessor("signallighttex", () => { LightTextureName = stf.ReadStringBlock("").ToLowerInvariant(); }),
                new STFReader.TokenProcessor("signallights", () => { Lights = ReadLights(stf); }),
                new STFReader.TokenProcessor("signaldrawstates", () => { DrawStates = ReadDrawStates(stf); }),
                new STFReader.TokenProcessor("signalaspects", () => { Aspects = ReadAspects(stf); }),
                new STFReader.TokenProcessor("approachcontrolsettings", () => { ApproachControlDetails = ReadApproachControlDetails(stf); }),
                new STFReader.TokenProcessor("signalnumclearahead", () => { numClearAhead = numClearAhead >= -1 ? numClearAhead : stf.ReadIntBlock(null); numdefs++; }),
                new STFReader.TokenProcessor("semaphoreinfo", () => { SemaphoreInfo = stf.ReadFloatBlock(STFReader.UNITS.None, null); }),
                new STFReader.TokenProcessor("sigflashduration", () => {
                    stf.MustMatch("(");
                    FlashTimeOn  = stf.ReadFloat(STFReader.UNITS.None, null);
                    FlashTimeOff = stf.ReadFloat(STFReader.UNITS.None, null);
                    stf.SkipRestOfBlock();
                }),
                new STFReader.TokenProcessor("signalflags", () => {
                    stf.MustMatch("(");
                    while (!stf.EndOfBlock())
                    {
                        switch (stf.ReadString().ToLower())
                        {
                        case "abs": Abs = true; break;

                        case "no_gantry": NoGantry = true; break;

                        case "semaphore": Semaphore = true; break;

                        default: stf.StepBackOneItem(); STFException.TraceInformation(stf, "Skipped unknown SignalType flag " + stf.ReadString()); break;
                        }
                    }
                }),
            });

            if (ORTSMode)
            {
                // In ORTS mode : always set value for NumClearAhead_ORTS
                NumClearAhead_MSTS = -2;
                NumClearAhead_ORTS = numClearAhead;
            }
            else
            {
                // In MSTS mode : if one line for SignalNumClearAhead defined, set value for NumClearAhead_MSTS, otherwise set value for NumClearAhead_ORTS
                NumClearAhead_MSTS = numdefs == 1 ? numClearAhead : -2;
                NumClearAhead_ORTS = numdefs == 2 ? numClearAhead : -2;
            }
        }
Exemplo n.º 11
0
        protected void ParsePosition(STFReader stf)
        {
            stf.MustMatchBlockStart();
            bounds = new Rectangle(stf.ReadInt(null), stf.ReadInt(null), stf.ReadInt(null), stf.ReadInt(null));

            // skipping additional values in between
            while (!stf.EndOfBlock())
            {
                STFException.TraceWarning(stf, "Ignored additional positional parameters");
                bounds.Width  = bounds.Height;
                bounds.Height = stf.ReadInt(null);
            }
        }
Exemplo n.º 12
0
        protected virtual (Color[] Colors, float TriggerValue) ParseControlColors(STFReader stf)
        {
            float        trigger = 0f;
            List <Color> colors  = new List <Color>(stf.ReadInt(0));

            if (!stf.EndOfBlock())
            {
                stf.ParseBlock(new STFReader.TokenProcessor[] {
                    new STFReader.TokenProcessor("controlcolour", () => { colors.Add(ParseControlColor(stf)); }),
                    new STFReader.TokenProcessor("switchval", () => { trigger = ParseSwitchVal(stf); })
                });
            }
            return(colors.ToArray(), trigger);
        }
Exemplo n.º 13
0
        public Random_Trigger(STFReader f)
        {
            f.MustMatch("(");
            while (!f.EndOfBlock())
            {
                string lowtok = f.ReadString().ToLower();
                switch (lowtok)
                {
                case "delay_min_max": f.MustMatch("("); Delay_Min = f.ReadFloat(STFReader.UNITS.None, null); Delay_Max = f.ReadFloat(STFReader.UNITS.None, null); f.SkipRestOfBlock(); break;

                case "volume_min_max": f.MustMatch("("); Volume_Min = f.ReadFloat(STFReader.UNITS.None, null); Volume_Max = f.ReadFloat(STFReader.UNITS.None, null); f.SkipRestOfBlock(); break;

                default: ParsePlayCommand(f, lowtok); break;
                }
            }
        }
Exemplo n.º 14
0
        protected void ParsePosition(STFReader stf)
        {
            stf.MustMatch("(");
            PositionX = stf.ReadDouble(null);
            PositionY = stf.ReadDouble(null);
            Width     = stf.ReadDouble(null);
            Height    = stf.ReadDouble(null);

            // Handling middle values
            while (!stf.EndOfBlock())
            {
                STFException.TraceWarning(stf, "Ignored additional positional parameters");
                Width  = Height;
                Height = stf.ReadInt(null);
            }
        }
Exemplo n.º 15
0
        /// <summary>
        /// Default constructor used during file parsing.
        /// </summary>
        /// <param name="stf">The STFreader containing the file stream</param>
        public SignalAspect(STFReader stf)
        {
            SpeedLimit = -1;
            stf.MustMatchBlockStart();
            string aspectName = stf.ReadString();

            if (!EnumExtension.GetValue(aspectName, out SignalAspectState aspect))
            {
                STFException.TraceInformation(stf, "Skipped unknown signal aspect " + aspectName);
                Aspect = SignalAspectState.Unknown;
            }
            else
            {
                Aspect = aspect;
            }
            DrawStateName = stf.ReadString().ToLowerInvariant();
            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("speedmph", () => { SpeedLimit = (float)Speed.MeterPerSecond.FromMpH(stf.ReadFloatBlock(STFReader.Units.None, 0)); }),
                new STFReader.TokenProcessor("speedkph", () => { SpeedLimit = (float)Speed.MeterPerSecond.FromKpH(stf.ReadFloatBlock(STFReader.Units.None, 0)); }),
                new STFReader.TokenProcessor("signalflags", () => {
                    stf.MustMatchBlockStart();
                    while (!stf.EndOfBlock())
                    {
                        switch (stf.ReadString().ToLower())
                        {
                        case "asap":
                            Asap = true;
                            break;

                        case "or_speedreset":
                            Reset = true;
                            break;

                        case "or_nospeedreduction":
                            NoSpeedReduction = true;
                            break;

                        default:
                            stf.StepBackOneItem();
                            STFException.TraceInformation(stf, "Skipped unknown DrawLight flag " + stf.ReadString());
                            break;
                        }
                    }
                }),
            });
        }
Exemplo n.º 16
0
        public PlayOneShot(STFReader f)
        {
            f.MustMatch("(");
            int count = f.ReadInt(null);

            Files = new string[count];
            int iFile = 0;

            while (!f.EndOfBlock())
            {
                switch (f.ReadString().ToLower())
                {
                case "file":
                    if (iFile < count)
                    {
                        f.MustMatch("(");
                        Files[iFile++] = f.ReadString();
                        f.ReadInt(null);
                        f.SkipRestOfBlock();
                    }
                    else      // MSTS skips extra files
                    {
                        STFException.TraceWarning(f, "Skipped extra File");
                        f.SkipBlock();
                    }
                    break;

                case "selectionmethod":
                    f.MustMatch("(");
                    string s = f.ReadString();
                    switch (s.ToLower())
                    {
                    case "randomselection": SelectionMethod = SelectionMethods.RandomSelection; break;

                    case "sequentialselection": SelectionMethod = SelectionMethods.SequentialSelection; break;

                    default: STFException.TraceWarning(f, "Skipped unknown selection method " + s); break;
                    }
                    f.SkipRestOfBlock();
                    break;

                case "(": f.SkipRestOfBlock(); break;
                }
            }
        }
Exemplo n.º 17
0
            // SigSubJnLinkIf is not supported

            /// <summary>
            /// Default constructor used during file parsing.
            /// </summary>
            /// <param name="stf">The STFreader containing the file stream</param>
            internal SignalSubObject(STFReader stf)
            {
                SignalSubType = SignalSubType.None;
                stf.MustMatchBlockStart();
                Index       = stf.ReadInt(null);
                MatrixName  = stf.ReadString().ToUpperInvariant();
                Description = stf.ReadString();
                stf.ParseBlock(new STFReader.TokenProcessor[] {
                    new STFReader.TokenProcessor("sigsubtype", () => {
                        if (EnumExtension.GetValue(stf.ReadStringBlock(null), out SignalSubType subType))
                        {
                            SignalSubType = subType;
                        }
                    }),
                    new STFReader.TokenProcessor("sigsubstype", () => { SignalSubSignalType = stf.ReadStringBlock(null); }),
                    new STFReader.TokenProcessor("signalflags", () => {
                        stf.MustMatchBlockStart();
                        while (!stf.EndOfBlock())
                        {
                            switch (stf.ReadString().ToUpperInvariant())
                            {
                            case "OPTIONAL":
                                Optional = true;
                                break;

                            case "DEFAULT":
                                Default = true; break;

                            case "BACK_FACING":
                                BackFacing = true;
                                break;

                            case "JN_LINK":
                                JunctionLink = true;
                                break;

                            default:
                                stf.StepBackOneItem();
                                STFException.TraceInformation(stf, "Skipped unknown SignalSubObj flag " + stf.ReadString());
                                break;
                            }
                        }
                    }),
                });
Exemplo n.º 18
0
        /// <summary>
        /// Default constructor used during file parsing.
        /// </summary>
        /// <param name="stf">The STFreader containing the file stream</param>
        public SignalDrawLight(STFReader stf)
        {
            stf.MustMatch("(");
            LightIndex = stf.ReadUInt(null);
            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("signalflags", () => {
                    stf.MustMatch("(");
                    while (!stf.EndOfBlock())
                    {
                        switch (stf.ReadString().ToLower())
                        {
                        case "flashing": Flashing = true; break;

                        default: stf.StepBackOneItem(); STFException.TraceInformation(stf, "Skipped unknown DrawLight flag " + stf.ReadString()); break;
                        }
                    }
                }),
            });
        }
Exemplo n.º 19
0
        public CabViewGaugeControl(STFReader stf, string basePath)
        {
            stf.MustMatchBlockStart();
            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("type", () => { ParseType(stf); }),
                new STFReader.TokenProcessor("position", () => { ParsePosition(stf); }),
                new STFReader.TokenProcessor("scalerange", () => { ParseScaleRange(stf); }),
                new STFReader.TokenProcessor("graphic", () => { ParseGraphic(stf, basePath); }),
                new STFReader.TokenProcessor("style", () => { ParseStyle(stf); }),
                new STFReader.TokenProcessor("units", () => { ParseUnits(stf); }),

                new STFReader.TokenProcessor("zeropos", () => { ZeroPos = stf.ReadIntBlock(null); }),
                new STFReader.TokenProcessor("orientation", () => { Orientation = stf.ReadIntBlock(null); }),
                new STFReader.TokenProcessor("dirincrease", () => { Direction = stf.ReadIntBlock(null); }),
                new STFReader.TokenProcessor("area", () => {
                    stf.MustMatchBlockStart();
                    area = new Rectangle(stf.ReadInt(null), stf.ReadInt(null), stf.ReadInt(null), stf.ReadInt(null));
                    stf.SkipRestOfBlock();
                }),
                new STFReader.TokenProcessor("positivecolour", () => {
                    stf.MustMatchBlockStart();
                    (PositiveColors, PositiveTrigger) = ParseControlColors(stf);
                }),
                new STFReader.TokenProcessor("negativecolour", () => {
                    stf.MustMatchBlockStart();
                    (NegativeColors, NegativeTrigger) = ParseControlColors(stf);
                }),
                new STFReader.TokenProcessor("decreasecolour", () => {
                    stf.MustMatchBlockStart();
                    stf.ReadInt(0);
                    if (!stf.EndOfBlock())
                    {
                        stf.ParseBlock(new STFReader.TokenProcessor[] {
                            new STFReader.TokenProcessor("controlcolour", () => { DecreaseColor = ParseControlColor(stf); })
                        });
                    }
                })
            });
Exemplo n.º 20
0
        /// <summary>
        /// Default constructor used during file parsing.
        /// </summary>
        /// <param name="stf">The STFreader containing the file stream</param>
        public SignalAspect(STFReader stf)
        {
            SpeedMpS = -1;
            stf.MustMatch("(");
            string aspectName = stf.ReadString();

            try
            {
                Aspect = (MstsSignalAspect)Enum.Parse(typeof(MstsSignalAspect), aspectName, true);
            }
            catch (ArgumentException)
            {
                STFException.TraceInformation(stf, "Skipped unknown signal aspect " + aspectName);
                Aspect = MstsSignalAspect.UNKNOWN;
            }
            DrawStateName = stf.ReadString().ToLowerInvariant();
            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("speedmph", () => { SpeedMpS = MpS.FromMpH(stf.ReadFloatBlock(STFReader.UNITS.None, 0)); }),
                new STFReader.TokenProcessor("speedkph", () => { SpeedMpS = MpS.FromKpH(stf.ReadFloatBlock(STFReader.UNITS.None, 0)); }),
                new STFReader.TokenProcessor("signalflags", () => {
                    stf.MustMatch("(");
                    while (!stf.EndOfBlock())
                    {
                        switch (stf.ReadString().ToLower())
                        {
                        case "asap": Asap = true; break;

                        case "or_speedreset": Reset = true; break;

                        case "or_nospeedreduction": NoSpeedReduction = true; break;

                        default: stf.StepBackOneItem(); STFException.TraceInformation(stf, "Skipped unknown DrawLight flag " + stf.ReadString()); break;
                        }
                    }
                }),
            });
        }
Exemplo n.º 21
0
        /// <summary>
        /// Default constructor used during file parsing.
        /// </summary>
        /// <param name="stf">The STFreader containing the file stream</param>
        internal SignalDrawLight(STFReader stf)
        {
            stf.MustMatchBlockStart();
            Index = stf.ReadInt(null);
            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("signalflags", () => {
                    stf.MustMatchBlockStart();
                    while (!stf.EndOfBlock())
                    {
                        switch (stf.ReadString().ToUpperInvariant())
                        {
                        case "FLASHING":
                            Flashing = true;
                            break;

                        default:
                            stf.StepBackOneItem();
                            STFException.TraceInformation(stf, "Skipped unknown DrawLight flag " + stf.ReadString());
                            break;
                        }
                    }
                }),
            });
        }
Exemplo n.º 22
0
        /// <summary>
        /// Default constructor used during file parsing.
        /// </summary>
        /// <param name="stf">The STFreader containing the file stream</param>
        /// <param name="orMode">Process SignalType for ORTS mode (always set NumClearAhead_ORTS only)</param>
        public SignalType(STFReader stf, bool orMode)
            : this()
        {
            stf.MustMatchBlockStart();
            Name = stf.ReadString().ToLowerInvariant();
            int    numClearAhead     = -2;
            int    numdefs           = 0;
            string ortsFunctionType  = string.Empty;
            string ortsNormalSubType = string.Empty;

            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("ortsscript", () => { Script = stf.ReadStringBlock("").ToLowerInvariant(); }),
                new STFReader.TokenProcessor("signalfntype", () => {
                    if (orMode)
                    {
                        ortsFunctionType = ReadOrtsFunctionType(stf);
                    }
                    else
                    {
                        FunctionType = ReadFunctionType(stf);
                    }
                }),
                new STFReader.TokenProcessor("signallighttex", () => { LightTextureName = stf.ReadStringBlock("").ToLowerInvariant(); }),
                new STFReader.TokenProcessor("signallights", () => { Lights = ReadLights(stf); }),
                new STFReader.TokenProcessor("signaldrawstates", () => { DrawStates = ReadDrawStates(stf); }),
                new STFReader.TokenProcessor("signalaspects", () => { Aspects = ReadAspects(stf); }),
                new STFReader.TokenProcessor("approachcontrolsettings", () => { ApproachControlDetails = ReadApproachControlDetails(stf); }),
                new STFReader.TokenProcessor("signalnumclearahead", () => { numClearAhead = numClearAhead >= -1 ? numClearAhead : stf.ReadIntBlock(null); numdefs++; }),
                new STFReader.TokenProcessor("semaphoreinfo", () => { SemaphoreInfo = stf.ReadFloatBlock(STFReader.Units.None, null); }),
                new STFReader.TokenProcessor("ortsdayglow", () => { DayGlow = stf.ReadFloatBlock(STFReader.Units.None, null); }),
                new STFReader.TokenProcessor("ortsnightglow", () => { NightGlow = stf.ReadFloatBlock(STFReader.Units.None, null); }),
                new STFReader.TokenProcessor("ortsdaylight", () => { DayLight = stf.ReadBoolBlock(true); }),
                new STFReader.TokenProcessor("ortsnormalsubtype", () => { ortsNormalSubType = ReadOrtsNormalSubType(stf); }),
                new STFReader.TokenProcessor("ortsonofftime", () => { TransitionTime = stf.ReadFloatBlock(STFReader.Units.None, null); }),
                new STFReader.TokenProcessor("sigflashduration", () => {
                    stf.MustMatchBlockStart();
                    FlashTimeOn  = stf.ReadFloat(STFReader.Units.None, null);
                    FlashTimeOff = stf.ReadFloat(STFReader.Units.None, null);
                    stf.SkipRestOfBlock();
                }),
                new STFReader.TokenProcessor("signalflags", () => {
                    stf.MustMatchBlockStart();
                    while (!stf.EndOfBlock())
                    {
                        switch (stf.ReadString().ToLower())
                        {
                        case "abs": Abs = true; break;

                        case "no_gantry": NoGantry = true; break;

                        case "semaphore": Semaphore = true; break;

                        default: stf.StepBackOneItem(); STFException.TraceInformation(stf, "Skipped unknown SignalType flag " + stf.ReadString()); break;
                        }
                    }
                }),
            });

            if (orMode)
            {
                // set related MSTS function type
                OrtsFunctionTypeIndex = OrSignalTypes.Instance.FunctionTypes.FindIndex(i => StringComparer.OrdinalIgnoreCase.Equals(i, ortsFunctionType));
                if (!EnumExtension.GetValue(ortsFunctionType, out SignalFunction functionType))
                {
                    FunctionType = SignalFunction.Info;
                }
                else
                {
                    FunctionType = functionType;
                }

                // set index for Normal Subtype
                OrtsNormalSubTypeIndex = OrSignalTypes.Instance.NormalSubTypes.FindIndex(i => StringComparer.OrdinalIgnoreCase.Equals(i, ortsNormalSubType));

                // set SNCA
                NumClearAhead_MSTS = -2;
                NumClearAhead_ORTS = numClearAhead;
            }
            else
            {
                // set defaulted OR function type
                OrtsFunctionTypeIndex = (int)FunctionType;

                // set SNCA
                NumClearAhead_MSTS = numdefs == 1 ? numClearAhead : -2;
                NumClearAhead_ORTS = numdefs == 2 ? numClearAhead : -2;
            }
        }
Exemplo n.º 23
0
        public static Interpolator2D CreateInterpolator2D(this STFReader stf, bool tab)
        {
            List <double>       xlist = new List <double>();
            List <Interpolator> ilist = new List <Interpolator>();

            bool errorFound = false;

            if (tab)
            {
                stf.MustMatchBlockStart();
                int numOfRows = stf.ReadInt(0);
                if (numOfRows < 2)
                {
                    STFException.TraceWarning(stf, "Interpolator must have at least two rows.");
                    errorFound = true;
                }
                int    numOfColumns = stf.ReadInt(0);
                string header       = stf.ReadString().ToLower();
                if (header == "throttle")
                {
                    stf.MustMatchBlockStart();
                    int numOfThrottleValues = 0;
                    while (!stf.EndOfBlock())
                    {
                        xlist.Add(stf.ReadFloat(STFReader.Units.None, 0f));
                        ilist.Add(new Interpolator(numOfRows));
                        numOfThrottleValues++;
                    }
                    if (numOfThrottleValues != (numOfColumns - 1))
                    {
                        STFException.TraceWarning(stf, "Interpolator throttle vs. num of columns mismatch.");
                        errorFound = true;
                    }

                    if (numOfColumns < 3)
                    {
                        STFException.TraceWarning(stf, "Interpolator must have at least three columns.");
                        errorFound = true;
                    }

                    int    numofData  = 0;
                    string tableLabel = stf.ReadString().ToLower();
                    if (tableLabel == "table")
                    {
                        stf.MustMatchBlockStart();
                        for (int i = 0; i < numOfRows; i++)
                        {
                            float x = stf.ReadFloat(STFReader.Units.SpeedDefaultMPH, 0);
                            numofData++;
                            for (int j = 0; j < numOfColumns - 1; j++)
                            {
                                if (j >= ilist.Count)
                                {
                                    STFException.TraceWarning(stf, "Interpolator throttle vs. num of columns mismatch. (missing some throttle values)");
                                    errorFound = true;
                                }
                                ilist[j][x] = stf.ReadFloat(STFReader.Units.Force, 0);
                                numofData++;
                            }
                        }
                        stf.SkipRestOfBlock();
                    }
                    else
                    {
                        STFException.TraceWarning(stf, "Interpolator didn't find a table to load.");
                        errorFound = true;
                    }
                    //check the table for inconsistencies

                    foreach (Interpolator checkMe in ilist)
                    {
                        if (checkMe.Size != numOfRows)
                        {
                            STFException.TraceWarning(stf, "Interpolator has found a mismatch between num of rows declared and num of rows given.");
                            errorFound = true;
                        }
                        double dx = (checkMe.MaxX() - checkMe.MinX()) * 0.1f;
                        if (dx <= 0f)
                        {
                            STFException.TraceWarning(stf, "Interpolator has found X data error - x values must be increasing. (Possible row number mismatch)");
                            errorFound = true;
                        }
                        else
                        {
                            for (double x = checkMe.MinX(); x <= checkMe.MaxX(); x += dx)
                            {
                                if (double.IsNaN(checkMe[x]))
                                {
                                    STFException.TraceWarning(stf, "Interpolator has found X data error - x values must be increasing. (Possible row number mismatch)");
                                    errorFound = true;
                                    break;
                                }
                            }
                        }
                    }

                    if (numofData != (numOfRows * numOfColumns))
                    {
                        STFException.TraceWarning(stf, "Interpolator has found a mismatch: num of data doesn't fit the header information.");
                        errorFound = true;
                    }
                }
                else
                {
                    STFException.TraceWarning(stf, "Interpolator must have a 'throttle' header row.");
                    errorFound = true;
                }
                stf.SkipRestOfBlock();
            }
            else
            {
                stf.MustMatchBlockStart();
                while (!stf.EndOfBlock())
                {
                    xlist.Add(stf.ReadFloat(STFReader.Units.Any, null));
                    ilist.Add(stf.CreateInterpolator());
                }
            }


            int n = xlist.Count;

            if (n < 2)
            {
                STFException.TraceWarning(stf, "Interpolator must have at least two x values.");
                errorFound = true;
            }
            double[]       xArray = new double[n];
            Interpolator[] yArray = new Interpolator[n];
            for (int i = 0; i < n; i++)
            {
                xArray[i] = xlist[i];
                yArray[i] = ilist[i];
                if (i > 0 && xArray[i - 1] >= xArray[i])
                {
                    STFException.TraceWarning(stf, "Interpolator x values must be increasing.");
                }
            }
            if (errorFound)
            {
                STFException.TraceWarning(stf, "Errors found in the Interpolator definition!!! The Interpolator will not work correctly!");
            }

            Interpolator2D result = new Interpolator2D(xArray, yArray);

            return(result);
        }
Exemplo n.º 24
0
        public InterpolatorDiesel2D(STFReader stf, bool tab)
        {
            // <CSComment> TODO: probably there is some other stf.SkipRestOfBlock() that should be removed </CSComment>
            List <float>        xlist = new List <float>();
            List <Interpolator> ilist = new List <Interpolator>();

            bool errorFound = false;

            if (tab)
            {
                stf.MustMatch("(");
                int numOfRows = stf.ReadInt(0);
                if (numOfRows < 2)
                {
                    STFException.TraceWarning(stf, "Interpolator must have at least two rows.");
                    errorFound = true;
                }
                int    numOfColumns = stf.ReadInt(0);
                string header       = stf.ReadString().ToLower();
                if (header == "throttle")
                {
                    stf.MustMatch("(");
                    int numOfThrottleValues = 0;
                    while (!stf.EndOfBlock())
                    {
                        xlist.Add(stf.ReadFloat(STFReader.UNITS.None, 0f));
                        ilist.Add(new Interpolator(numOfRows));
                        numOfThrottleValues++;
                    }
                    if (numOfThrottleValues != (numOfColumns - 1))
                    {
                        STFException.TraceWarning(stf, "Interpolator throttle vs. num of columns mismatch.");
                        errorFound = true;
                    }

                    if (numOfColumns < 3)
                    {
                        STFException.TraceWarning(stf, "Interpolator must have at least three columns.");
                        errorFound = true;
                    }

                    int    numofData  = 0;
                    string tableLabel = stf.ReadString().ToLower();
                    if (tableLabel == "table")
                    {
                        stf.MustMatch("(");
                        for (int i = 0; i < numOfRows; i++)
                        {
                            float x = stf.ReadFloat(STFReader.UNITS.SpeedDefaultMPH, 0);
                            numofData++;
                            for (int j = 0; j < numOfColumns - 1; j++)
                            {
                                if (j >= ilist.Count)
                                {
                                    STFException.TraceWarning(stf, "Interpolator throttle vs. num of columns mismatch. (missing some throttle values)");
                                    errorFound = true;
                                }
                                ilist[j][x] = stf.ReadFloat(STFReader.UNITS.Force, 0);
                                numofData++;
                            }
                        }
                        stf.SkipRestOfBlock();
                    }
                    else
                    {
                        STFException.TraceWarning(stf, "Interpolator didn't find a table to load.");
                        errorFound = true;
                    }
                    //check the table for inconsistencies

                    foreach (Interpolator checkMe in ilist)
                    {
                        if (checkMe.GetSize() != numOfRows)
                        {
                            STFException.TraceWarning(stf, "Interpolator has found a mismatch between num of rows declared and num of rows given.");
                            errorFound = true;
                        }
                        float dx = (checkMe.MaxX() - checkMe.MinX()) * 0.1f;
                        if (dx <= 0f)
                        {
                            STFException.TraceWarning(stf, "Interpolator has found X data error - x values must be increasing. (Possible row number mismatch)");
                            errorFound = true;
                        }
                        else
                        {
                            for (float x = checkMe.MinX(); x <= checkMe.MaxX(); x += dx)
                            {
                                if ((checkMe[x] == float.NaN))
                                {
                                    STFException.TraceWarning(stf, "Interpolator has found X data error - x values must be increasing. (Possible row number mismatch)");
                                    errorFound = true;
                                    break;
                                }
                            }
                        }
                    }

                    if (numofData != (numOfRows * numOfColumns))
                    {
                        STFException.TraceWarning(stf, "Interpolator has found a mismatch: num of data doesn't fit the header information.");
                        errorFound = true;
                    }
                }
                else
                {
                    STFException.TraceWarning(stf, "Interpolator must have a 'throttle' header row.");
                    errorFound = true;
                }
                stf.SkipRestOfBlock();
            }
            else
            {
                stf.MustMatch("(");
                while (!stf.EndOfBlock())
                {
                    xlist.Add(stf.ReadFloat(STFReader.UNITS.Any, null));
                    ilist.Add(new Interpolator(stf));
                }
            }


            int n = xlist.Count;

            if (n < 2)
            {
                STFException.TraceWarning(stf, "Interpolator must have at least two x values.");
                errorFound = true;
            }
            X    = new float[n];
            Y    = new Interpolator[n];
            Size = n;
            for (int i = 0; i < n; i++)
            {
                X[i] = xlist[i];
                Y[i] = ilist[i];
                if (i > 0 && X[i - 1] >= X[i])
                {
                    STFException.TraceWarning(stf, "Interpolator x values must be increasing.");
                }
            }
            //stf.SkipRestOfBlock();
            if (errorFound)
            {
                STFException.TraceWarning(stf, "Errors found in the Interpolator definition!!! The Interpolator will not work correctly!");
            }
        }
Exemplo n.º 25
0
        public CVCGauge(STFReader stf, string basepath)
        {
            stf.MustMatch("(");
            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("type", () => { ParseType(stf); }),
                new STFReader.TokenProcessor("position", () => { ParsePosition(stf); }),
                new STFReader.TokenProcessor("scalerange", () => { ParseScaleRange(stf); }),
                new STFReader.TokenProcessor("graphic", () => { ParseGraphic(stf, basepath); }),
                new STFReader.TokenProcessor("style", () => { ParseStyle(stf); }),
                new STFReader.TokenProcessor("units", () => { ParseUnits(stf); }),

                new STFReader.TokenProcessor("zeropos", () => { ZeroPos = stf.ReadIntBlock(null); }),
                new STFReader.TokenProcessor("orientation", () => { Orientation = stf.ReadIntBlock(null); }),
                new STFReader.TokenProcessor("dirincrease", () => { Direction = stf.ReadIntBlock(null); }),
                new STFReader.TokenProcessor("area", () => {
                    stf.MustMatch("(");
                    int x      = stf.ReadInt(null);
                    int y      = stf.ReadInt(null);
                    int width  = stf.ReadInt(null);
                    int height = stf.ReadInt(null);
                    Area       = new Rectangle(x, y, width, height);
                    stf.SkipRestOfBlock();
                }),
                new STFReader.TokenProcessor("positivecolour", () => {
                    stf.MustMatch("(");
                    NumPositiveColors = stf.ReadInt(0);
                    if ((stf.EndOfBlock() == false))
                    {
                        List <color> Colorset = new List <color>();
                        stf.ParseBlock(new STFReader.TokenProcessor[] {
                            new STFReader.TokenProcessor("controlcolour", () => { Colorset.Add(ParseControlColor(stf)); }),
                            new STFReader.TokenProcessor("switchval", () => { PositiveSwitchVal = ParseSwitchVal(stf); })
                        });
                        PositiveColor = Colorset [0];
                        if ((NumPositiveColors >= 2) && (Colorset.Count >= 2))
                        {
                            SecondPositiveColor = Colorset [1];
                        }
                    }
                }),
                new STFReader.TokenProcessor("negativecolour", () => {
                    stf.MustMatch("(");
                    NumNegativeColors = stf.ReadInt(0);
                    if ((stf.EndOfBlock() == false))
                    {
                        List <color> Colorset = new List <color>();
                        stf.ParseBlock(new STFReader.TokenProcessor[] {
                            new STFReader.TokenProcessor("controlcolour", () => { Colorset.Add(ParseControlColor(stf)); }),
                            new STFReader.TokenProcessor("switchval", () => { NegativeSwitchVal = ParseSwitchVal(stf); })
                        });
                        NegativeColor = Colorset[0];
                        if ((NumNegativeColors >= 2) && (Colorset.Count >= 2))
                        {
                            SecondNegativeColor = Colorset[1];
                        }
                    }
                }),
                new STFReader.TokenProcessor("decreasecolour", () => {
                    stf.MustMatch("(");
                    stf.ReadInt(0);
                    if (stf.EndOfBlock() == false)
                    {
                        stf.ParseBlock(new STFReader.TokenProcessor[] {
                            new STFReader.TokenProcessor("controlcolour", () => { DecreaseColor = ParseControlColor(stf); })
                        });
                    }
                })
            });
        }
Exemplo n.º 26
0
        public CVCDiscrete(STFReader stf, string basepath)
        {
//            try
            {
                stf.MustMatch("(");
                stf.ParseBlock(new STFReader.TokenProcessor[] {
                    new STFReader.TokenProcessor("type", () => { ParseType(stf); }),
                    new STFReader.TokenProcessor("position", () => { ParsePosition(stf); }),
                    new STFReader.TokenProcessor("scalerange", () => { ParseScaleRange(stf); }),
                    new STFReader.TokenProcessor("graphic", () => { ParseGraphic(stf, basepath); }),
                    new STFReader.TokenProcessor("style", () => { ParseStyle(stf); }),
                    new STFReader.TokenProcessor("units", () => { ParseUnits(stf); }),
                    new STFReader.TokenProcessor("mousecontrol", () => { MouseControl = stf.ReadBoolBlock(false); }),
                    new STFReader.TokenProcessor("orientation", () => { Orientation = stf.ReadIntBlock(null); }),
                    new STFReader.TokenProcessor("dirincrease", () => { Direction = stf.ReadIntBlock(null); }),

                    new STFReader.TokenProcessor("numframes", () => {
                        stf.MustMatch("(");
                        FramesCount = stf.ReadInt(null);
                        FramesX     = stf.ReadInt(null);
                        FramesY     = stf.ReadInt(null);
                        stf.SkipRestOfBlock();
                    }),
                    // <CJComment> Would like to revise this, as it is difficult to follow and debug.
                    // Can't do that until interaction of ScaleRange, NumFrames, NumPositions and NumValues is more fully specified.
                    // What is needed is samples of data that must be accommodated.
                    // Some decisions appear unwise but they might be a pragmatic solution to a real problem. </CJComment>
                    //
                    // Code accommodates:
                    // - NumValues before NumPositions or the other way round.
                    // - More NumValues than NumPositions and the other way round - perhaps unwise.
                    // - The count of NumFrames, NumValues and NumPositions is ignored - perhaps unwise.
                    // - Abbreviated definitions so that values at intermediate unspecified positions can be omitted.
                    //   Strangely, these values are set to 0 and worked out later when drawing.
                    // Max and min NumValues which don't match the ScaleRange are ignored - perhaps unwise.
                    new STFReader.TokenProcessor("numpositions", () => {
                        stf.MustMatch("(");
                        // If Positions are not filled before by Values
                        bool shouldFill = (Positions.Count == 0);
                        numPositions    = stf.ReadInt(null); // Number of Positions

                        var minPosition   = 0;
                        var positionsRead = 0;
                        while (!stf.EndOfBlock())
                        {
                            int p = stf.ReadInt(null);

                            minPosition = positionsRead == 0 ? p : Math.Min(minPosition, p);  // used to get correct offset
                            positionsRead++;

                            // If Positions are not filled before by Values
                            if (shouldFill)
                            {
                                Positions.Add(p);
                            }
                        }

                        // If positions do not start at 0, add offset to shift them all so they do.
                        // An example of this is RENFE 400 (from http://www.trensim.com/lib/msts/index.php?act=view&id=186)
                        // which has a COMBINED_CONTROL with:
                        //   NumPositions ( 21 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 )
                        // Also handles definitions with position in reverse order, e.g.
                        //   NumPositions ( 5 8 7 2 1 0 )
                        positionsRead++;

                        if (minPosition < 0)
                        {
                            for (int iPos = 0; iPos <= Positions.Count - 1; iPos++)
                            {
                                Positions[iPos] -= minPosition;
                            }
                        }

                        // This is a hack for SLI locomotives which have the positions listed as "1056964608 0 0 0 ...".
                        if (Positions.Any(p => p > 0xFFFF))
                        {
                            STFException.TraceInformation(stf, "Renumbering cab control positions from zero due to value > 0xFFFF");
                            for (var i = 0; i < Positions.Count; i++)
                            {
                                Positions[i] = i;
                            }
                        }

                        // Check if eligible for filling

                        if (Positions.Count > 1 && Positions[0] != 0)
                        {
                            canFill = false;
                        }
                        else
                        {
                            for (var iPos = 1; iPos <= Positions.Count - 1; iPos++)
                            {
                                if (Positions[iPos] > Positions[iPos - 1])
                                {
                                    continue;
                                }
                                canFill = false;
                                break;
                            }
                        }

                        // This is a protection against GP40 locomotives that erroneously have positions pointing beyond frame count limit.

                        if (Positions.Count > 1 && canFill && Positions.Count < FramesCount && Positions[Positions.Count - 1] >= FramesCount && Positions[0] == 0)
                        {
                            STFException.TraceInformation(stf, "Some NumPositions entries refer to non-exisiting frames, trying to renumber");
                            Positions[Positions.Count - 1] = FramesCount - 1;
                            for (var iPos = Positions.Count - 2; iPos >= 1; iPos--)
                            {
                                if ((Positions[iPos] >= FramesCount || Positions[iPos] >= Positions[iPos + 1]))
                                {
                                    Positions[iPos] = Positions[iPos + 1] - 1;
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }),
                    new STFReader.TokenProcessor("numvalues", () => {
                        stf.MustMatch("(");
                        var numValues = stf.ReadDouble(null); // Number of Values
                        while (!stf.EndOfBlock())
                        {
                            double v = stf.ReadDouble(null);
                            // If the Positions are less than expected add new Position(s)
                            while (Positions.Count <= _ValuesRead)
                            {
                                Positions.Add(_ValuesRead);
                            }
                            // Avoid later repositioning, put every value to its Position
                            // But before resize Values if needed
                            if (numValues != numPositions)
                            {
                                while (Values.Count <= Positions[_ValuesRead])
                                {
                                    Values.Add(0);
                                }
                                // Avoid later repositioning, put every value to its Position
                                Values[Positions[_ValuesRead]] = v;
                            }
                            Values.Add(v);
                            _ValuesRead++;
                        }
                    }),
                });

                // If no ACE, just don't need any fixup
                // Because Values are tied to the image Frame to be shown
                if (string.IsNullOrEmpty(ACEFile))
                {
                    return;
                }

                // Now, we have an ACE.

                // If read any Values, or the control requires Values to control
                //     The twostate, tristate, signal displays are not in these
                // Need check the Values collection for validity
                if (_ValuesRead > 0 || ControlStyle == CABViewControlStyles.SPRUNG || ControlStyle == CABViewControlStyles.NOT_SPRUNG ||
                    FramesCount > 0 || (FramesX > 0 && FramesY > 0))
                {
                    // Check max number of Frames
                    if (FramesCount == 0)
                    {
                        // Check valid Frame information
                        if (FramesX == 0 || FramesY == 0)
                        {
                            // Give up, it won't work
                            // Because later we won't know how to display frames from that
                            Trace.TraceWarning("Invalid Frames information given for ACE {0} in {1}", ACEFile, stf.FileName);
                            ACEFile = "";
                            return;
                        }

                        // Valid frames info, set FramesCount
                        FramesCount = FramesX * FramesY;
                    }

                    // Now we have an ACE and Frames for it.

                    // Only shuffle data in following cases

                    if (Values.Count != Positions.Count || (Values.Count < FramesCount & canFill) || (Values.Count > 0 && Values[0] == Values[Values.Count - 1] && Values[0] == 0))
                    {
                        // Fixup Positions and Values collections first

                        // If the read Positions and Values are not match
                        // Or we didn't read Values but have Frames to draw
                        // Do not test if FramesCount equals Values count, we trust in the creator -
                        //     maybe did not want to display all Frames
                        // (If there are more Values than Frames it will checked at draw time)
                        // Need to fix the whole Values
                        if (Positions.Count != _ValuesRead || (FramesCount > 0 && (Values.Count == 0 || Values.Count == 1)))
                        {
                            //This if clause covers among others following cases:
                            // Case 1 (e.g. engine brake lever of Dash 9):
                            //NumFrames ( 22 11 2 )
                            //NumPositions ( 1 0 )
                            //NumValues ( 1 0 )
                            //Orientation ( 1 )
                            //DirIncrease ( 1 )
                            //ScaleRange ( 0 1 )
                            //
                            // Case 2 (e.g. throttle lever of Acela):
                            //NumFrames ( 25 5 5 )
                            //NumPositions ( 0 )
                            //NumValues ( 0 )
                            //Orientation ( 1 )
                            //DirIncrease ( 1 )
                            //ScaleRange ( 0 1 )
                            //
                            // Clear existing
                            Positions.Clear();
                            Values.Clear();

                            // Add the two sure positions, the two ends
                            Positions.Add(0);
                            // We will need the FramesCount later!
                            // We use Positions only here
                            Positions.Add(FramesCount);

                            // Fill empty Values
                            for (int i = 0; i < FramesCount; i++)
                            {
                                Values.Add(0);
                            }
                            Values[0] = MinValue;

                            Values.Add(MaxValue);
                        }
                        else if (Values.Count == 2 && Values[0] == 0 && Values[1] < MaxValue && Positions[0] == 0 && Positions[1] == 1 && Values.Count < FramesCount)
                        {
                            //This if clause covers among others following cases:
                            // Case 1 (e.g. engine brake lever of gp38):
                            //NumFrames ( 18 2 9 )
                            //NumPositions ( 2 0 1 )
                            //NumValues ( 2 0 0.3 )
                            //Orientation ( 0 )
                            //DirIncrease ( 0 )
                            //ScaleRange ( 0 1 )
                            Positions.Add(FramesCount);
                            // Fill empty Values
                            for (int i = Values.Count; i < FramesCount; i++)
                            {
                                Values.Add(Values[1]);
                            }
                            Values.Add(MaxValue);
                        }

                        else
                        {
                            //This if clause covers among others following cases:
                            // Case 1 (e.g. train brake lever of Acela):
                            //NumFrames ( 12 4 3 )
                            //NumPositions ( 5 0 1 9 10 11 )
                            //NumValues ( 5 0 0.2 0.85 0.9 0.95 )
                            //Orientation ( 1 )
                            //DirIncrease ( 1 )
                            //ScaleRange ( 0 1 )
                            //
                            // Fill empty Values
                            int iValues = 1;
                            for (int i = 1; i < FramesCount && i <= Positions.Count - 1 && Values.Count < FramesCount; i++)
                            {
                                var deltaPos = Positions[i] - Positions[i - 1];
                                while (deltaPos > 1 && Values.Count < FramesCount)
                                {
                                    Values.Insert(iValues, 0);
                                    iValues++;
                                    deltaPos--;
                                }
                                iValues++;
                            }

                            // Add the maximums to the end, the Value will be removed
                            // We use Positions only here
                            if (Values.Count > 0 && Values[0] <= Values[Values.Count - 1])
                            {
                                Values.Add(MaxValue);
                            }
                            else if (Values.Count > 0 && Values[0] > Values[Values.Count - 1])
                            {
                                Values.Add(MinValue);
                            }
                        }

                        // OK, we have a valid size of Positions and Values

                        // Now it is the time for checking holes in the given data
                        if ((Positions.Count < FramesCount - 1 && Values[0] <= Values[Values.Count - 1]) || (Values.Count > 1 && Values[0] == Values[Values.Count - 2] && Values[0] == 0))
                        {
                            int j = 1;
                            int p = 0;
                            // Skip the 0 element, that is the default MinValue
                            for (int i = 1; i < Positions.Count; i++)
                            {
                                // Found a hole
                                if (Positions[i] != p + 1)
                                {
                                    // Iterate to the next valid data and fill the hole
                                    for (j = p + 1; j < Positions[i]; j++)
                                    {
                                        // Extrapolate into the hole
                                        Values[j] = MathHelper.Lerp((float)Values[p], (float)Values[Positions[i]], (float)j / (float)Positions[i]);
                                    }
                                }
                                p = Positions[i];
                            }
                        }

                        // Don't need the MaxValue added before, remove it
                        Values.RemoveAt(Values.Count - 1);
                    }
                }

                // MSTS ignores/overrides various settings by the following exceptional cases:
                if (ControlType == CABViewControlTypes.CP_HANDLE)
                {
                    ControlStyle = CABViewControlStyles.NOT_SPRUNG;
                }
                if (ControlType == CABViewControlTypes.PANTOGRAPH || ControlType == CABViewControlTypes.PANTOGRAPH2)
                {
                    ControlStyle = CABViewControlStyles.ONOFF;
                }
                if (ControlType == CABViewControlTypes.HORN || ControlType == CABViewControlTypes.SANDERS || ControlType == CABViewControlTypes.BELL ||
                    ControlType == CABViewControlTypes.RESET)
                {
                    ControlStyle = CABViewControlStyles.WHILE_PRESSED;
                }
                if (ControlType == CABViewControlTypes.DIRECTION && Orientation == 0)
                {
                    Direction = 1 - Direction;
                }
            }
//            catch (Exception error)
//            {
//                if (error is STFException) // Parsing error, so pass it on
//                    throw;
//                else                       // Unexpected error, so provide a hint
//                    throw new STFException(stf, "Problem with NumPositions/NumValues/NumFrames/ScaleRange");
//            } // End of Need check the Values collection for validity
        } // End of Constructor
Exemplo n.º 27
0
        public CVCDigital(STFReader stf, string basepath)
        {
            // Set white as the default positive colour for digital displays
            color white = new color();

            white.R       = 255f;
            white.G       = 255f;
            white.B       = 255f;
            PositiveColor = white;
            FontSize      = 10;
            FontStyle     = 0;
            FontFamily    = "Courier New";

            stf.MustMatch("(");
            stf.ParseBlock(new STFReader.TokenProcessor[] {
                new STFReader.TokenProcessor("type", () => { ParseType(stf); }),
                new STFReader.TokenProcessor("position", () => { ParsePosition(stf); }),
                new STFReader.TokenProcessor("scalerange", () => { ParseScaleRange(stf); }),
                new STFReader.TokenProcessor("graphic", () => { ParseGraphic(stf, basepath); }),
                new STFReader.TokenProcessor("style", () => { ParseStyle(stf); }),
                new STFReader.TokenProcessor("units", () => { ParseUnits(stf); }),
                new STFReader.TokenProcessor("leadingzeros", () => { ParseLeadingZeros(stf); }),
                new STFReader.TokenProcessor("accuracy", () => { ParseAccuracy(stf); }),
                new STFReader.TokenProcessor("accuracyswitch", () => { ParseAccuracySwitch(stf); }),
                new STFReader.TokenProcessor("justification", () => { ParseJustification(stf); }),
                new STFReader.TokenProcessor("positivecolour", () => {
                    stf.MustMatch("(");
                    NumPositiveColors = stf.ReadInt(0);
                    if ((stf.EndOfBlock() == false))
                    {
                        List <color> Colorset = new List <color>();
                        stf.ParseBlock(new STFReader.TokenProcessor[] {
                            new STFReader.TokenProcessor("controlcolour", () => { Colorset.Add(ParseControlColor(stf)); }),
                            new STFReader.TokenProcessor("switchval", () => { PositiveSwitchVal = ParseSwitchVal(stf); })
                        });
                        PositiveColor = Colorset [0];
                        if ((NumPositiveColors >= 2) && (Colorset.Count >= 2))
                        {
                            SecondPositiveColor = Colorset [1];
                        }
                    }
                }),
                new STFReader.TokenProcessor("negativecolour", () => {
                    stf.MustMatch("(");
                    NumNegativeColors = stf.ReadInt(0);
                    if ((stf.EndOfBlock() == false))
                    {
                        List <color> Colorset = new List <color>();
                        stf.ParseBlock(new STFReader.TokenProcessor[] {
                            new STFReader.TokenProcessor("controlcolour", () => { Colorset.Add(ParseControlColor(stf)); }),
                            new STFReader.TokenProcessor("switchval", () => { NegativeSwitchVal = ParseSwitchVal(stf); })
                        });
                        NegativeColor = Colorset[0];
                        if ((NumNegativeColors >= 2) && (Colorset.Count >= 2))
                        {
                            SecondNegativeColor = Colorset[1];
                        }
                    }
                }),
                new STFReader.TokenProcessor("decreasecolour", () => {
                    stf.MustMatch("(");
                    stf.ReadInt(0);
                    if (stf.EndOfBlock() == false)
                    {
                        stf.ParseBlock(new STFReader.TokenProcessor[] {
                            new STFReader.TokenProcessor("controlcolour", () => { DecreaseColor = ParseControlColor(stf); })
                        });
                    }
                }),
                new STFReader.TokenProcessor("ortsfont", () => { ParseFont(stf); })
            });
        }