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); } } }
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++) { if (SemaphorePos != SemaphoreTarget && SignalTypeData.LightsSemaphoreChange[i]) continue; if (!SignalTypeData.DrawAspects[DisplayState].DrawLights[i]) continue; if (SignalTypeData.DrawAspects[DisplayState].FlashLights[i] && (CumulativeTime > SignalTypeData.FlashTimeOn)) continue; var xnaMatrix = Matrix.CreateTranslation(SignalTypeData.Lights[i].Position); foreach (int MatrixIndex in MatrixIndices) { Matrix.Multiply(ref xnaMatrix, ref SignalShape.XNAMatrices[MatrixIndex], out xnaMatrix); } Matrix.Multiply(ref xnaMatrix, ref xnaTileTranslation, out xnaMatrix); frame.AddPrimitive(SignalTypeData.Material, SignalTypeData.Lights[i], RenderPrimitiveGroup.Lights, ref xnaMatrix); if (Viewer.Settings.SignalLightGlow) frame.AddPrimitive(SignalTypeData.GlowMaterial, SignalTypeData.Lights[i], RenderPrimitiveGroup.Lights, ref xnaMatrix); } 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); } } }