Пример #1
0
            public void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime, Matrix xnaTileTranslation)
            {
                var initialise = DisplayState == -1;

                if (DisplayState != SignalHead.draw_state)
                {
#if DEBUG_SIGNAL_SHAPES
                    Console.WriteLine("{5} {0} signal {1} unit {2} state: {3} --> {4}",
                                      SignalShape.Location, SignalShape.UID, Index, DisplayState,
                                      SignalHead.draw_state, InfoDisplay.FormattedTime(Viewer.Simulator.ClockTime));
#endif
                    DisplayState = SignalHead.draw_state;
                    if (SignalTypeData.DrawAspects.ContainsKey(DisplayState))
                    {
                        SemaphoreTarget = SignalTypeData.DrawAspects[DisplayState].SemaphorePos;
                        SemaphoreSpeed  = SignalTypeData.SemaphoreAnimationTime <= 0 ? 0 : (SemaphoreTarget > SemaphorePos ? +1 : -1) / SignalTypeData.SemaphoreAnimationTime;
                        if (Sound != null)
                        {
                            Sound.HandleEvent(Event.SemaphoreArm);
                        }
                    }
                }

                CumulativeTime += elapsedTime.ClockSeconds;
                while (CumulativeTime > SignalTypeData.FlashTimeTotal)
                {
                    CumulativeTime -= SignalTypeData.FlashTimeTotal;
                }

                if (DisplayState < 0 || !SignalTypeData.DrawAspects.ContainsKey(DisplayState))
                {
                    return;
                }

                if (SignalTypeData.Semaphore)
                {
                    // We reset the animation matrix before preparing the lights, because they need to be positioned
                    // based on the original matrix only.
                    foreach (AnimatedPart SemaphorePart in SemaphoreParts)
                    {
                        SemaphorePart.SetFrameWrap(0);
                    }
                }

                for (var i = 0; i < SignalTypeData.Lights.Count; i++)
                {
                    SignalLightState state         = lightStates[i];
                    bool             semaphoreDark = SemaphorePos != SemaphoreTarget && SignalTypeData.LightsSemaphoreChange[i];
                    bool             constantDark  = !SignalTypeData.DrawAspects[DisplayState].DrawLights[i];
                    bool             flashingDark  = SignalTypeData.DrawAspects[DisplayState].FlashLights[i] && (CumulativeTime > SignalTypeData.FlashTimeOn);
                    state.UpdateIntensity(semaphoreDark || constantDark || flashingDark ? 0 : 1, elapsedTime);
                    if (!state.IsIlluminated())
                    {
                        continue;
                    }

                    bool isDay;
                    if (Viewer.Settings.UseMSTSEnv == false)
                    {
                        isDay = Viewer.World.Sky.solarDirection.Y > 0;
                    }
                    else
                    {
                        isDay = Viewer.World.MSTSSky.mstsskysolarDirection.Y > 0;
                    }
                    bool isPoorVisibility = Viewer.Simulator.Weather.FogDistance < 200;
                    if (!SignalTypeData.DayLight && isDay && !isPoorVisibility)
                    {
                        continue;
                    }

                    var slp       = SignalTypeData.Lights[i];
                    var xnaMatrix = Matrix.CreateTranslation(slp.Position);

                    foreach (int MatrixIndex in MatrixIndices)
                    {
                        Matrix.Multiply(ref xnaMatrix, ref SignalShape.XNAMatrices[MatrixIndex], out xnaMatrix);
                    }
                    Matrix.Multiply(ref xnaMatrix, ref xnaTileTranslation, out xnaMatrix);

                    void renderEffect(Material material)
                    {
                        frame.AddPrimitive(material, slp, RenderPrimitiveGroup.Lights, ref xnaMatrix, ShapeFlags.None, state);
                    }

                    renderEffect(SignalTypeData.Material);
                    if (Viewer.Settings.SignalLightGlow)
                    {
                        renderEffect(SignalTypeData.GlowMaterial);
                    }
                }

                if (SignalTypeData.Semaphore)
                {
                    // Now we update and re-animate the semaphore arm.
                    if (SignalTypeData.SemaphoreAnimationTime <= 0 || initialise)
                    {
                        // No timing (so instant switch) or we're initialising.
                        SemaphorePos   = SemaphoreTarget;
                        SemaphoreSpeed = 0;
                    }
                    else
                    {
                        // Animate slowly to target position.
                        SemaphorePos += SemaphoreSpeed * elapsedTime.ClockSeconds;
                        if (SemaphorePos * Math.Sign(SemaphoreSpeed) > SemaphoreTarget * Math.Sign(SemaphoreSpeed))
                        {
                            SemaphorePos   = SemaphoreTarget;
                            SemaphoreSpeed = 0;
                        }
                    }
                    foreach (AnimatedPart SemaphorePart in SemaphoreParts)
                    {
                        SemaphorePart.SetFrameCycle(SemaphorePos);
                    }
                }
            }
Пример #2
0
            public SignalShapeHead(Viewer viewer, SignalShape signalShape, int index, SignalHead signalHead,
                                   SignalItem mstsSignalItem, Formats.Msts.SignalShape.SignalSubObj mstsSignalSubObj)
            {
                Viewer      = viewer;
                SignalShape = signalShape;
#if DEBUG_SIGNAL_SHAPES
                Index = index;
#endif
                SignalHead = signalHead;
                for (int mindex = 0; mindex <= signalShape.SharedShape.MatrixNames.Count - 1; mindex++)
                {
                    string MatrixName = signalShape.SharedShape.MatrixNames[mindex];
                    if (String.Equals(MatrixName, mstsSignalSubObj.MatrixName))
                    {
                        MatrixIndices.Add(mindex);
                    }
                }


                if (!viewer.SIGCFG.SignalTypes.ContainsKey(mstsSignalSubObj.SignalSubSignalType))
                {
                    return;
                }

                var mstsSignalType = viewer.SIGCFG.SignalTypes[mstsSignalSubObj.SignalSubSignalType];

                SignalTypeData = viewer.SignalTypeDataManager.Get(mstsSignalType);

                if (SignalTypeData.Semaphore)
                {
                    // Check whether we have to correct the Semaphore position indexes following the strange rule of MSTS
                    // Such strange rule is that, if there are only two animation steps in the related .s file, MSTS behaves as follows:
                    // a SemaphorePos (2) in sigcfg.dat is executed as SemaphorePos (1)
                    // a SemaphorePos (1) in sigcfg.dat is executed as SemaphorePos (0)
                    // a SemaphorePos (0) in sigcfg.dat is executed as SemaphorePos (0)
                    // First we check if there are only two animation steps
                    if (signalShape.SharedShape.Animations != null && signalShape.SharedShape.Animations.Count != 0 && MatrixIndices.Count > 0 &&
                        signalShape.SharedShape.Animations[0].anim_nodes[MatrixIndices[0]].controllers.Count != 0 &&
                        signalShape.SharedShape.Animations[0].anim_nodes[MatrixIndices[0]].controllers[0].Count == 2)
                    {
                        // OK, now we check if maximum SemaphorePos is 2 (we won't correct if there are only SemaphorePos 1 and 0,
                        // because they would both be executed as SemaphorePos (0) accordingly to above law, therefore leading to a static semaphore)
                        float maxIndex = float.MinValue;
                        foreach (SignalAspectData drAsp in SignalTypeData.DrawAspects.Values)
                        {
                            if (drAsp.SemaphorePos > maxIndex)
                            {
                                maxIndex = drAsp.SemaphorePos;
                            }
                        }
                        if (maxIndex == 2)
                        {
                            // in this case we modify the SemaphorePositions for compatibility with MSTS.
                            foreach (SignalAspectData drAsp in SignalTypeData.DrawAspects.Values)
                            {
                                switch ((int)drAsp.SemaphorePos)
                                {
                                case 2:
                                    drAsp.SemaphorePos = 1;
                                    break;

                                case 1:
                                    drAsp.SemaphorePos = 0;
                                    break;

                                default:
                                    break;
                                }
                            }
                            if (!SignalTypeData.AreSemaphoresReindexed)
                            {
                                Trace.TraceInformation("Reindexing semaphore entries of signal type {0} for compatibility with MSTS", mstsSignalType.Name);
                                SignalTypeData.AreSemaphoresReindexed = true;
                            }
                        }
                    }

                    foreach (int mindex in MatrixIndices)
                    {
                        if (mindex == 0 && (signalShape.SharedShape.Animations == null || signalShape.SharedShape.Animations.Count == 0 ||
                                            signalShape.SharedShape.Animations[0].anim_nodes[mindex].controllers.Count == 0))
                        {
                            continue;
                        }
                        AnimatedPart SemaphorePart = new AnimatedPart(signalShape);
                        SemaphorePart.AddMatrix(mindex);
                        SemaphoreParts.Add(SemaphorePart);
                    }

                    if (Viewer.Simulator.TRK.Tr_RouteFile.DefaultSignalSMS != null)
                    {
                        var soundPath = Viewer.Simulator.RoutePath + @"\\sound\\" + Viewer.Simulator.TRK.Tr_RouteFile.DefaultSignalSMS;
                        try
                        {
                            Sound = new SoundSource(Viewer, SignalShape.Location.WorldLocation, Events.Source.MSTSSignal, soundPath);
                            Viewer.SoundProcess.AddSoundSources(this, new List <SoundSourceBase>()
                            {
                                Sound
                            });
                        }
                        catch (Exception error)
                        {
                            Trace.WriteLine(new FileLoadException(soundPath, error));
                        }
                    }
                }

                lightStates = new SignalLightState[SignalTypeData.Lights.Count];
                for (var i = 0; i < SignalTypeData.Lights.Count; i++)
                {
                    lightStates[i] = new SignalLightState(SignalTypeData.OnOffTimeS);
                }

#if DEBUG_SIGNAL_SHAPES
                Console.Write("  HEAD type={0,-8} lights={1,-2} sem={2}", SignalTypeData.Type, SignalTypeData.Lights.Count, SignalTypeData.Semaphore);
#endif
            }