Пример #1
0
        internal void Update(RPMVesselComputer comp)
        {
            float value;

            if (enablingVariable != null)
            {
                if (!enablingVariable.IsInRange(comp))
                {
                    return;
                }
            }

            if (variable.Get(out value, comp))
            {
                if (useLog10)
                {
                    value = JUtil.PseudoLog10(value);
                }
                float xOffset = JUtil.DualLerp(textureLimit, scale, value);

                MeshFilter meshFilter = barObject.GetComponent <MeshFilter>();

                meshFilter.mesh.uv = new[]
                {
                    new Vector2(xOffset - textureSize, 0.0f),
                    new Vector2(xOffset + textureSize, 0.0f),
                    new Vector2(xOffset - textureSize, 1.0f),
                    new Vector2(xOffset + textureSize, 1.0f)
                };

                JUtil.ShowHide(true, barObject);
            }
        }
Пример #2
0
            public void Draw(Rect screenRect, double time)
            {
                double mintime = time - horizontalSpan;

                if (floatingMin && points.Count > 0)
                {
                    verticalSpan.x = (float)points[0].y;
                    foreach (Vector2d dataPoint in points)
                    {
                        verticalSpan.x = (float)Math.Min(dataPoint.y, verticalSpan.x);
                    }
                }
                if (floatingMax && points.Count > 0)
                {
                    verticalSpan.y = (float)points[0].y;
                    foreach (Vector2d dataPoint in points)
                    {
                        verticalSpan.y = (float)Math.Max(dataPoint.y, verticalSpan.y);
                    }
                }
                var actualXY = new List <Vector2>();

                foreach (Vector2d dataPoint in points)
                {
                    if (dataPoint.x > mintime)
                    {
                        actualXY.Add(new Vector2(
                                         (float)JUtil.DualLerp(screenRect.xMin, screenRect.xMax, mintime, time, dataPoint.x),
                                         (float)JUtil.DualLerp(screenRect.yMin, screenRect.yMax, verticalSpan.x, verticalSpan.y, dataPoint.y)
                                         ));
                    }
                }
                DrawVector(actualXY, lineColor);
            }
Пример #3
0
        internal void Update()
        {
            if (enablingVariable != null)
            {
                if (!enablingVariable.IsInRange())
                {
                    return;
                }
            }

            float value = variable.AsFloat();

            if (useLog10)
            {
                value = JUtil.PseudoLog10(value);
            }
            float yOffset = JUtil.DualLerp(textureLimit, scale, value);

            MeshFilter meshFilter = barObject.GetComponent <MeshFilter>();

            meshFilter.mesh.uv = new[]
            {
                new Vector2(0.0f, yOffset - textureSize),
                new Vector2(1.0f, yOffset - textureSize),
                new Vector2(0.0f, yOffset + textureSize),
                new Vector2(1.0f, yOffset + textureSize)
            };

            JUtil.ShowHide(true, barObject);
        }
Пример #4
0
        /// <summary>
        /// Update the compass / heading bar
        /// </summary>
        private void UpdateHeading(Quaternion rotationVesselSurface, RPMVesselComputer comp)
        {
            float heading = rotationVesselSurface.eulerAngles.y / 360.0f;

            MeshFilter meshFilter = headingMesh.GetComponent <MeshFilter>();

            meshFilter.mesh.uv = new[]
            {
                new Vector2(heading - headingBarTextureWidth, 0.0f),
                new Vector2(heading + headingBarTextureWidth, 0.0f),
                new Vector2(heading - headingBarTextureWidth, 1.0f),
                new Vector2(heading + headingBarTextureWidth, 1.0f)
            };

            if (progradeHeadingIcon != null)
            {
                float slipAngle = comp.Sideslip;
                float slipTC    = JUtil.DualLerp(0f, 1f, 0f, 360f, rotationVesselSurface.eulerAngles.y + slipAngle);
                float slipIconX = JUtil.DualLerp(progradeHeadingIconOrigin - 0.5f * headingBarPosition.z, progradeHeadingIconOrigin + 0.5f * headingBarPosition.z, heading - headingBarTextureWidth, heading + headingBarTextureWidth, slipTC);

                Vector3 position = progradeHeadingIcon.transform.position;
                position.x = slipIconX;
                progradeHeadingIcon.transform.position = position;

                JUtil.ShowHide(true, progradeHeadingIcon);
            }
        }
Пример #5
0
        public double Evaluate(RPMVesselComputer comp, PersistenceAccessor persistence)
        {
            float result = comp.ProcessVariable(sourceVariable, persistence).MassageToFloat();

            Vector2 sourceRange;

            if (!string.IsNullOrEmpty(sourceMinStr))
            {
                sourceRange.x = comp.ProcessVariable(sourceMinStr, persistence).MassageToFloat();
            }
            else
            {
                sourceRange.x = sourceMin;
            }

            if (!string.IsNullOrEmpty(sourceMaxStr))
            {
                sourceRange.y = comp.ProcessVariable(sourceMaxStr, persistence).MassageToFloat();
            }
            else
            {
                sourceRange.y = sourceMax;
            }

            return(JUtil.DualLerp(mappedRange, sourceRange, result));
        }
        // This is honestly very badly written code, probably the worst of what I have in this project.
        // Much of it dictated by the fact that I barely, if at all, understand what am I doing in vector mathematics,
        // the rest is because the problem is all built out of special cases.
        // Sorry. :)
        public bool RenderPFD(RenderTexture screen, float aspect)
        {
            if (screen == null || !startupComplete || HighLogic.LoadedSceneIsEditor)
            {
                return(false);
            }

            // Analysis disable once CompareOfFloatsByEqualityOperator
            if (aspect != cameraAspect)
            {
                cameraAspect      = aspect;
                ballCamera.aspect = cameraAspect;
            }
            GL.Clear(true, true, backgroundColorValue);

            ballCamera.targetTexture = screen;


            Vector3d coM = vessel.findWorldCenterOfMass();
            Vector3d up  = (coM - vessel.mainBody.position).normalized;
            Vector3d velocityVesselOrbit       = vessel.orbit.GetVel();
            Vector3d velocityVesselOrbitUnit   = velocityVesselOrbit.normalized;
            Vector3d velocityVesselSurface     = velocityVesselOrbit - vessel.mainBody.getRFrmVel(coM);
            Vector3d velocityVesselSurfaceUnit = velocityVesselSurface.normalized;
            Vector3d radialPlus = Vector3d.Exclude(velocityVesselOrbit, up).normalized;
            Vector3d normalPlus = -Vector3d.Cross(radialPlus, velocityVesselOrbitUnit);

            //Vector3d targetDirection = -FlightGlobals.fetch.vesselTargetDirection.normalized;
            Vector3d targetDirection = FlightGlobals.ship_tgtVelocity.normalized;

            navBall.transform.rotation = MirrorX(stockNavBall.navBall.rotation);

            if (heading != null)
            {
                Vector3d   north                 = Vector3d.Exclude(up, (vessel.mainBody.position + (Vector3d)vessel.mainBody.transform.up * vessel.mainBody.Radius) - coM).normalized;
                Quaternion rotationSurface       = Quaternion.LookRotation(north, up);
                Quaternion rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.GetTransform().rotation) * rotationSurface);
                heading.renderer.material.SetTextureOffset("_MainTex",
                                                           new Vector2(JUtil.DualLerp(0f, 1f, 0f, 360f, rotationVesselSurface.eulerAngles.y) - headingSpan / 2f, 0));
            }

            Quaternion gymbal = stockNavBall.attitudeGymbal;

            switch (FlightUIController.speedDisplayMode)
            {
            case FlightUIController.SpeedDisplayModes.Surface:
                MoveMarker(markerPrograde, velocityVesselSurfaceUnit, progradeColorValue, gymbal);
                MoveMarker(markerRetrograde, -velocityVesselSurfaceUnit, progradeColorValue, gymbal);
                break;

            case FlightUIController.SpeedDisplayModes.Target:
                MoveMarker(markerPrograde, targetDirection, progradeColorValue, gymbal);
                MoveMarker(markerRetrograde, -targetDirection, progradeColorValue, gymbal);
                break;

            case FlightUIController.SpeedDisplayModes.Orbit:
                MoveMarker(markerPrograde, velocityVesselOrbitUnit, progradeColorValue, gymbal);
                MoveMarker(markerRetrograde, -velocityVesselOrbitUnit, progradeColorValue, gymbal);
                break;
            }
            MoveMarker(markerNormal, normalPlus, normalColorValue, gymbal);
            MoveMarker(markerNormalMinus, -normalPlus, normalColorValue, gymbal);

            MoveMarker(markerRadial, radialPlus, radialColorValue, gymbal);
            MoveMarker(markerRadialMinus, -radialPlus, radialColorValue, gymbal);

            if (vessel.patchedConicSolver != null && vessel.patchedConicSolver.maneuverNodes.Count > 0)
            {
                Vector3d burnVector = vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(vessel.orbit);
                MoveMarker(markerManeuver, burnVector.normalized, maneuverColorValue, gymbal);
                MoveMarker(markerManeuverMinus, -burnVector.normalized, maneuverColorValue, gymbal);
                ShowHide(true, markerManeuver, markerManeuverMinus);
            }

            ITargetable target = FlightGlobals.fetch.VesselTarget;

            if (target != null)
            {
                Vector3 targetSeparation = (vessel.GetTransform().position - target.GetTransform().position).normalized;
                MoveMarker(markerTarget, targetSeparation, targetColorValue, gymbal);
                MoveMarker(markerTargetMinus, -targetSeparation, targetColorValue, gymbal);
                var targetPort = target as ModuleDockingNode;
                if (targetPort != null)
                {
                    // Thanks to Michael Enßlin
                    Transform targetTransform         = targetPort.transform;
                    Transform selfTransform           = vessel.ReferenceTransform;
                    Vector3   targetOrientationVector = -targetTransform.up.normalized;

                    Vector3 v1    = Vector3.Cross(selfTransform.up, targetTransform.forward);
                    Vector3 v2    = Vector3.Cross(selfTransform.up, selfTransform.forward);
                    float   angle = Vector3.Angle(v1, v2);
                    if (Vector3.Dot(selfTransform.up, Vector3.Cross(v1, v2)) < 0)
                    {
                        angle = -angle;
                    }
                    MoveMarker(markerDockingAlignment, targetOrientationVector, dockingColorValue, gymbal);
                    markerDockingAlignment.transform.Rotate(Vector3.up, -angle);
                    ShowHide(true, markerDockingAlignment);
                }
                ShowHide(true, markerTarget, markerTargetMinus);
            }


            // This dirty hack reduces the chance that the ball might get affected by internal cabin lighting.
            int backupQuality = QualitySettings.pixelLightCount;

            QualitySettings.pixelLightCount = 0;

            ShowHide(true,
                     cameraBody, navBall, overlay, heading, markerPrograde, markerRetrograde,
                     markerNormal, markerNormalMinus, markerRadial, markerRadialMinus);
            ballCamera.Render();
            QualitySettings.pixelLightCount = backupQuality;
            ShowHide(false,
                     cameraBody, navBall, overlay, heading, markerPrograde, markerRetrograde,
                     markerManeuver, markerManeuverMinus, markerTarget, markerTargetMinus,
                     markerNormal, markerNormalMinus, markerRadial, markerRadialMinus, markerDockingAlignment);

            return(true);
        }
Пример #7
0
        private void UpdateOdometer()
        {
            double thisUpdate = Planetarium.GetUniversalTime();
            float  dT         = (float)(thisUpdate - lastUpdate) * odometerRotationScalar;

            RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
            float             value;

            if (!string.IsNullOrEmpty(perPodPersistenceName))
            {
                bool state = rpmComp.GetBool(perPodPersistenceName, false);
                value = comp.ProcessVariable((state) ? altVariable : variable).MassageToFloat();
            }
            else
            {
                value = comp.ProcessVariable(variable).MassageToFloat();
            }
            // Make sure the value isn't going to be a problem.
            if (float.IsNaN(value))
            {
                value = 0.0f;
            }

            if (value < 0.0f)
            {
                signGoalCoord = 0.625f;
            }
            else if (value > 0.0f)
            {
                signGoalCoord = 0.875f;
            }
            else
            {
                signGoalCoord = 0.75f;
            }

            signCurrentCoord = JUtil.DualLerp(signCurrentCoord, signGoalCoord, 0.0f, 1.0f, dT);

            value = Mathf.Abs(value);

            if (oMode == OdometerMode.SI)
            {
                float leadingDigitExponent;
                if (value < 0.001f)
                {
                    leadingDigitExponent = -3.0f;
                }
                else
                {
                    leadingDigitExponent = Mathf.Floor(Mathf.Log10(value));
                }

                // siExponent is the location relative to the original decimal of
                // the SI prefix.  Is is always the greatest multiple-of-3 less
                // than the leadingDigitExponent.
                int siIndex = (int)Mathf.Floor(leadingDigitExponent / 3.0f);
                if (siIndex > 3)
                {
                    siIndex = 3;
                }
                int siExponent = siIndex * 3;

                prefixGoalCoord    = (float)(siIndex + 1) * 0.125f;
                prefixCurrentCoord = JUtil.DualLerp(prefixCurrentCoord, prefixGoalCoord, 0.0f, 1.0f, dT);

                float scaledValue = value / Mathf.Pow(10.0f, (float)(siExponent - 3));
                int   intValue    = (int)(scaledValue);

                for (int i = 5; i >= 0; --i)
                {
                    float thisCoord = (float)(intValue % 10) / 10.0f;
                    if (i == 5)
                    {
                        // So we can display fractional values:
                        // However, we also quantize it to make it easier to
                        // read during the transition from 9 to 0.
                        thisCoord = Mathf.Floor((scaledValue % 10.0f) * 2.0f) / 20.0f;
                    }
                    intValue          = intValue / 10;
                    goalCoordinate[i] = thisCoord;
                }
            }
            else if (oMode == OdometerMode.TIME_HHHMMSS)
            {
                // Clamp the value
                value = Mathf.Min(value, 59.0f + 59.0f * 60.0f + 999.0f * 60.0f * 24.0f);

                // seconds
                float thisCoord = Mathf.Floor((value % 10.0f) * 2.0f) / 20.0f;
                goalCoordinate[6] = thisCoord;
                int intValue = (int)(value) / 10;

                // tens of seconds
                thisCoord         = (float)(intValue % 6) / 10.0f;
                goalCoordinate[5] = thisCoord;
                intValue         /= 6;

                // minutes
                thisCoord         = (float)(intValue % 10) / 10.0f;
                goalCoordinate[4] = thisCoord;
                intValue         /= 10;

                // tens of minutes
                thisCoord         = (float)(intValue % 6) / 10.0f;
                goalCoordinate[3] = thisCoord;
                intValue         /= 6;

                for (int i = 2; i >= 0; --i)
                {
                    thisCoord         = (float)(intValue % 10) / 10.0f;
                    intValue          = intValue / 10;
                    goalCoordinate[i] = thisCoord;
                }
            }
            else
            {
                int intValue = (int)(value);

                for (int i = 7; i >= 0; --i)
                {
                    float thisCoord = (float)(intValue % 10) / 10.0f;
                    if (i == 7)
                    {
                        thisCoord = Mathf.Floor((value % 10.0f) * 2.0f) / 20.0f;
                    }
                    intValue          = intValue / 10;
                    goalCoordinate[i] = thisCoord;
                }
            }

            // Update interpolants
            for (int i = 0; i < 8; ++i)
            {
                if (currentCoordinate[i] != goalCoordinate[i])
                {
                    float startingPoint;
                    float endingPoint;
                    if (Mathf.Abs(currentCoordinate[i] - goalCoordinate[i]) <= 0.5f)
                    {
                        startingPoint = currentCoordinate[i];
                        endingPoint   = goalCoordinate[i];
                    }
                    else if (goalCoordinate[i] < currentCoordinate[i])
                    {
                        startingPoint = currentCoordinate[i];
                        endingPoint   = goalCoordinate[i] + 1.0f;
                    }
                    else
                    {
                        startingPoint = currentCoordinate[i] + 1.0f;
                        endingPoint   = goalCoordinate[i];
                    }

                    // This lerp causes a rotation that starts quickly but
                    // slows down close to the goal.  It actually looks
                    // pretty good for typical incrementing counts, while the
                    // rapid spinning of small values is chaotic enough that
                    // you can't really tell what's going on, anyway.
                    float goal = JUtil.DualLerp(startingPoint, endingPoint, 0.0f, 1.0f, dT);
                    if (goal > 1.0f)
                    {
                        goal -= 1.0f;
                    }
                    currentCoordinate[i] = goal;
                }
            }
            lastUpdate = thisUpdate;
        }
        public void Update(RPMVesselComputer comp, PersistenceAccessor persistence)
        {
            var scaleResults = new float[3];

            for (int i = 0; i < 3; i++)
            {
                if (!scaleEnds[i].Get(out scaleResults[i], comp, persistence))
                {
                    return;
                }
            }
            float scaledValue = Mathf.InverseLerp(scaleResults[0], scaleResults[1], scaleResults[2]);

            if (thresholdMode)
            {
                if (scaledValue >= threshold.x && scaledValue <= threshold.y)
                {
                    if (flashingDelay > 0)
                    {
                        if (lastStateChange < Planetarium.GetUniversalTime() - flashingDelay)
                        {
                            if (currentState)
                            {
                                TurnOff();
                            }
                            else
                            {
                                TurnOn();
                            }
                        }
                    }
                    else
                    {
                        TurnOn();
                    }
                    if (audioOutput != null && !alarmActive)
                    {
                        audioOutput.audio.Play();
                        alarmActive = true;
                    }
                }
                else
                {
                    TurnOff();
                    if (audioOutput != null && alarmActive)
                    {
                        if (!alarmMustPlayOnce)
                        {
                            audioOutput.audio.Stop();
                        }
                        alarmActive = false;
                    }
                }
                // Resetting the audio volume in case it was muted while the ship was out of IVA.
                if (alarmActive && audioOutput != null)
                {
                    audioOutput.audio.volume = alarmSoundVolume * GameSettings.SHIP_VOLUME;
                }
            }
            else
            {
                switch (mode)
                {
                case Mode.Rotation:
                    Quaternion newRotation = longPath ? Quaternion.Euler(Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue)) :
                                             Quaternion.Slerp(reverse ? rotationEnd : rotationStart, reverse ? rotationStart : rotationEnd, scaledValue);
                    controlledTransform.localRotation = initialRotation * newRotation;
                    break;

                case Mode.Translation:
                    controlledTransform.localPosition = initialPosition + Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue);
                    break;

                case Mode.Scale:
                    controlledTransform.localScale = initialScale + Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue);
                    break;

                case Mode.Color:
                    colorShiftRenderer.material.SetColor(colorName, Color.Lerp(reverse ? activeColor : passiveColor, reverse ? passiveColor : activeColor, scaledValue));
                    break;

                case Mode.TextureShift:
                    foreach (string token in textureLayer.Split(','))
                    {
                        affectedMaterial.SetTextureOffset(token.Trim(),
                                                          Vector2.Lerp(reverse ? textureShiftEnd : textureShiftStart, reverse ? textureShiftStart : textureShiftEnd, scaledValue));
                    }
                    break;

                case Mode.TextureScale:
                    foreach (string token in textureLayer.Split(','))
                    {
                        affectedMaterial.SetTextureScale(token.Trim(),
                                                         Vector2.Lerp(reverse ? textureScaleEnd : textureScaleStart, reverse ? textureScaleStart : textureScaleEnd, scaledValue));
                    }
                    break;

                case Mode.LoopingAnimation:
                // MOARdV TODO: Define what this actually does
                case Mode.Animation:
                    float lerp = JUtil.DualLerp(reverse ? 1f : 0f, reverse ? 0f : 1f, scaleResults[0], scaleResults[1], scaleResults[2]);
                    if (float.IsNaN(lerp) || float.IsInfinity(lerp))
                    {
                        lerp = reverse ? 1f : 0f;
                    }
                    onAnim[animationName].normalizedTime = lerp;
                    break;
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Update the ladder's texture UVs so it's drawn correctly
        /// </summary>
        private void UpdateLadder(Quaternion rotationVesselSurface, RPMVesselComputer comp)
        {
            float pitch = 90.0f - Vector3.Angle(comp.Forward, comp.Up);

            float ladderMidpointCoord;

            if (use360horizon)
            {
                // Straight up is texture coord 0.75;
                // Straight down is TC 0.25;
                ladderMidpointCoord = JUtil.DualLerp(0.25f, 0.75f, -90f, 90f, pitch);
            }
            else
            {
                // Straight up is texture coord 1.0;
                // Straight down is TC 0.0;
                ladderMidpointCoord = JUtil.DualLerp(0.0f, 1.0f, -90f, 90f, pitch);
            }

            // MOARdV TODO: These can be done without manually editing the
            // mesh filter.  I need to look up the game object texture stuff.
            MeshFilter meshFilter = ladderMesh.GetComponent <MeshFilter>();

            meshFilter.mesh.uv = new[]
            {
                new Vector2(0.5f - horizonTextureSize.x, ladderMidpointCoord - horizonTextureSize.y),
                new Vector2(0.5f + horizonTextureSize.x, ladderMidpointCoord - horizonTextureSize.y),
                new Vector2(0.5f - horizonTextureSize.x, ladderMidpointCoord + horizonTextureSize.y),
                new Vector2(0.5f + horizonTextureSize.x, ladderMidpointCoord + horizonTextureSize.y)
            };

            float roll = rotationVesselSurface.eulerAngles.z;

            ladderMesh.transform.Rotate(new Vector3(0.0f, 0.0f, 1.0f), lastRoll - roll);

            lastRoll = roll;

            if (progradeLadderIcon != null)
            {
                float AoA = comp.AbsoluteAoA;
                AoA = (float)JUtil.ClampDegrees180(AoA);
                if (float.IsNaN(AoA))
                {
                    AoA = 0.0f;
                }

                float AoATC;
                if (use360horizon)
                {
                    // Straight up is texture coord 0.75;
                    // Straight down is TC 0.25;
                    AoATC = JUtil.DualLerp(0.25f, 0.75f, -90f, 90f, AoA);
                }
                else
                {
                    // Straight up is texture coord 1.0;
                    // Straight down is TC 0.0;
                    AoATC = JUtil.DualLerp(0.0f, 1.0f, -90f, 90f, AoA);
                }

                float Ypos = JUtil.DualLerp(
                    -horizonSize.y * 0.5f, horizonSize.y * 0.5f,
                    ladderMidpointCoord - horizonTextureSize.y, ladderMidpointCoord + horizonTextureSize.y,
                    AoATC);

                Vector3 position = progradeLadderIcon.transform.position;
                position.x = Ypos * Mathf.Sin(roll * Mathf.Deg2Rad);
                position.y = Ypos * Mathf.Cos(roll * Mathf.Deg2Rad);
                progradeLadderIcon.transform.position = position;

                JUtil.ShowHide(true, progradeLadderIcon);
            }
        }
Пример #10
0
        // BAR -- Bar pseudo-formatter that produces a horizontal bar
        // Nice for creating pseudo-bar charts.
        // BAR[<bar character>[<empty character>]],<total length>[,<minimum>[,<maximum>]]
        // Examples:
        // BAR,10,10000,200000
        // BAR= ,10,0,200
        // BAR~,10,0,200
        // BAR,10
        private static string BARFormat(string format, double value)
        {
            char   fullChar    = '=';
            char   emptyChar   = ' ';
            string trailerChar = string.Empty;
            double maximum     = 1;
            double minimum     = 0;

            string[] tokens = format.Split(',');
            if (tokens.Length < 2)
            {
                return(value.ToString(format));
            }
            if (tokens[0].Length == formatPrefixBAR.Length + 3)
            {
                trailerChar = new string(tokens[0][formatPrefixBAR.Length + 2], 1);
            }
            if (tokens[0].Length == formatPrefixBAR.Length + 2)
            {
                emptyChar = tokens[0][formatPrefixBAR.Length + 1];
            }
            if (tokens[0].Length >= formatPrefixBAR.Length + 1)
            {
                fullChar = tokens[0][formatPrefixBAR.Length];
            }
            int  outputLength = 0;
            bool reverse      = false;

            try
            {
                if (tokens.Length > 1)
                {
                    outputLength = int.Parse(tokens[1]);
                    if (outputLength < 0)
                    {
                        outputLength = Math.Abs(outputLength);
                        reverse      = true;
                    }
                }
                if (tokens.Length > 2)
                {
                    minimum = double.Parse(tokens[2]);
                }
                if (tokens.Length > 3)
                {
                    maximum = double.Parse(tokens[3]);
                }
            }
            catch
            {
                return(value.ToString(format));
            }
            if (double.IsNaN(value))
            {
                value = 0.0;
            }
            if (double.IsInfinity(value))
            {
                value = maximum;
            }

            int    filledLength = (int)JUtil.DualLerp(0, outputLength, minimum, maximum, value);
            string filledPart   = string.Empty;

            if (!string.IsNullOrEmpty(trailerChar))
            {
                if (filledLength > 0)
                {
                    if (filledLength == 1)
                    {
                        filledPart = trailerChar;
                    }
                    else
                    {
                        filledPart = string.Empty.PadRight(filledLength - 1, fullChar);
                        filledPart = reverse ? trailerChar + filledPart : filledPart + trailerChar;
                    }
                }
            }
            else
            {
                filledPart = string.Empty.PadRight(filledLength, fullChar);
            }
            return(reverse ? filledPart.PadLeft(outputLength, emptyChar) : filledPart.PadRight(outputLength, emptyChar));
        }
Пример #11
0
        public bool RenderHUD(RenderTexture screen, float cameraAspect)
        {
            if (screen == null || !startupComplete || HighLogic.LoadedSceneIsEditor)
            {
                return(false);
            }

            // Clear the background, if configured.
            GL.Clear(true, true, backgroundColorValue);

            // Configure the camera, if configured.
            // MOARdV: Might be worthwhile to refactor the flying camera so
            // it is created in Start (like new FlyingCamera(part, cameraTransform)),
            // and pass the screen, FoV, and aspect ratio (or just screen and
            // FoV) as Render parameters, so there's no need to test if the
            // camera's been created every render call.
            if (cameraObject == null && !string.IsNullOrEmpty(cameraTransform))
            {
                cameraObject = new FlyingCamera(part, screen, cameraAspect);
                cameraObject.PointCamera(cameraTransform, hudFov);
            }

            // Draw the camera's view, if configured.
            if (cameraObject != null)
            {
                cameraObject.Render();
            }

            // Configure the matrix so that the origin is the center of the screen.
            GL.PushMatrix();

            // Draw the HUD ladder
            // MOARdV note, 2014/03/19: swapping the y values, to invert the
            // coordinates so the prograde icon is right-side up.
            GL.LoadPixelMatrix(-horizonSize.x * 0.5f, horizonSize.x * 0.5f, horizonSize.y * 0.5f, -horizonSize.y * 0.5f);
            GL.Viewport(new Rect((screen.width - horizonSize.x) * 0.5f, (screen.height - horizonSize.y) * 0.5f, horizonSize.x, horizonSize.y));

            Vector3 coM     = vessel.findWorldCenterOfMass();
            Vector3 up      = (coM - vessel.mainBody.position).normalized;
            Vector3 forward = vessel.GetTransform().up;
            Vector3 right   = vessel.GetTransform().right;
            Vector3 top     = Vector3.Cross(right, forward);
            Vector3 north   = Vector3.Exclude(up, (vessel.mainBody.position + (Vector3d)vessel.mainBody.transform.up * vessel.mainBody.Radius) - coM).normalized;

            Vector3d velocityVesselSurface     = vessel.orbit.GetVel() - vessel.mainBody.getRFrmVel(coM);
            Vector3  velocityVesselSurfaceUnit = velocityVesselSurface.normalized;

            if (ladderMaterial)
            {
                // Figure out the texture coordinate scaling for the ladder.
                float ladderTextureOffset = horizonTextureSize.y / ladderMaterial.mainTexture.height;

                float cosUp   = Vector3.Dot(forward, up);
                float cosRoll = Vector3.Dot(top, up);
                float sinRoll = Vector3.Dot(right, up);

                var normalizedRoll = new Vector2(cosRoll, sinRoll);
                normalizedRoll.Normalize();
                if (normalizedRoll.magnitude < 0.99f)
                {
                    // If we're hitting +/- 90 nearly perfectly, the sin and cos will
                    // be too far out of whack to normalize.  Arbitrarily pick
                    // a roll of 0.0.
                    normalizedRoll.x = 1.0f;
                    normalizedRoll.y = 0.0f;
                }
                cosRoll = normalizedRoll.x;
                sinRoll = normalizedRoll.y;

                // Mihara: I'm pretty sure this was negative of what it should actually be, at least according to my mockup.
                float pitch = -(Mathf.Asin(cosUp) * Mathf.Rad2Deg);

                float ladderMidpointCoord;
                if (use360horizon)
                {
                    // Straight up is texture coord 0.75;
                    // Straight down is TC 0.25;
                    ladderMidpointCoord = JUtil.DualLerp(0.25f, 0.75f, -90f, 90f, pitch);
                }
                else
                {
                    // Straight up is texture coord 1.0;
                    // Straight down is TC 0.0;
                    ladderMidpointCoord = JUtil.DualLerp(0.0f, 1.0f, -90f, 90f, pitch);
                }

                ladderMaterial.SetPass(0);
                GL.Begin(GL.QUADS);

                // transform -x -y
                GL.TexCoord2(0.5f + horizonTextureSize.x, ladderMidpointCoord - ladderTextureOffset);
                GL.Vertex3(cosRoll * horizonSize.x + sinRoll * horizonSize.y, -sinRoll * horizonSize.x + cosRoll * horizonSize.y, 0.0f);

                // transform +x -y
                GL.TexCoord2(0.5f - horizonTextureSize.x, ladderMidpointCoord - ladderTextureOffset);
                GL.Vertex3(-cosRoll * horizonSize.x + sinRoll * horizonSize.y, sinRoll * horizonSize.x + cosRoll * horizonSize.y, 0.0f);

                // transform +x +y
                GL.TexCoord2(0.5f - horizonTextureSize.x, ladderMidpointCoord + ladderTextureOffset);
                GL.Vertex3(-cosRoll * horizonSize.x - sinRoll * horizonSize.y, sinRoll * horizonSize.x - cosRoll * horizonSize.y, 0.0f);

                // transform -x +y
                GL.TexCoord2(0.5f + horizonTextureSize.x, ladderMidpointCoord + ladderTextureOffset);
                GL.Vertex3(cosRoll * horizonSize.x - sinRoll * horizonSize.y, -sinRoll * horizonSize.x - cosRoll * horizonSize.y, 0.0f);
                GL.End();

                float AoA = velocityVesselSurfaceUnit.AngleInPlane(right, forward);
                float AoATC;
                if (use360horizon)
                {
                    // Straight up is texture coord 0.75;
                    // Straight down is TC 0.25;
                    AoATC = JUtil.DualLerp(0.25f, 0.75f, -90f, 90f, pitch + AoA);
                }
                else
                {
                    // Straight up is texture coord 1.0;
                    // Straight down is TC 0.0;
                    AoATC = JUtil.DualLerp(0.0f, 1.0f, -90f, 90f, pitch + AoA);
                }

                float Ypos = JUtil.DualLerp(
                    -horizonSize.y, horizonSize.y,
                    ladderMidpointCoord - ladderTextureOffset, ladderMidpointCoord + ladderTextureOffset,
                    AoATC);

                // Placing the icon on the (0, Ypos) location, so simplify the transform.
                DrawIcon(-sinRoll * Ypos, -cosRoll * Ypos, GizmoIcons.GetIconLocation(GizmoIcons.IconType.PROGRADE), progradeColorValue);
            }

            // Draw the rest of the HUD stuff (0,0) is the top left corner of the screen.
            GL.LoadPixelMatrix(0, screen.width, screen.height, 0);
            GL.Viewport(new Rect(0, 0, screen.width, screen.height));

            if (headingMaterial != null)
            {
                Quaternion rotationSurface       = Quaternion.LookRotation(north, up);
                Quaternion rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.GetTransform().rotation) * rotationSurface);
                float      headingTexture        = JUtil.DualLerp(0f, 1f, 0f, 360f, rotationVesselSurface.eulerAngles.y);
                float      headingTextureOffset  = (headingBarWidth / headingMaterial.mainTexture.width) / 2;

                headingMaterial.SetPass(0);
                GL.Begin(GL.QUADS);
                GL.TexCoord2(headingTexture - headingTextureOffset, 1.0f);
                GL.Vertex3(headingBarPosition.x, headingBarPosition.y, 0.0f);
                GL.TexCoord2(headingTexture + headingTextureOffset, 1.0f);
                GL.Vertex3(headingBarPosition.x + headingBarPosition.z, headingBarPosition.y, 0.0f);
                GL.TexCoord2(headingTexture + headingTextureOffset, 0.0f);
                GL.Vertex3(headingBarPosition.x + headingBarPosition.z, headingBarPosition.y + headingBarPosition.w, 0.0f);
                GL.TexCoord2(headingTexture - headingTextureOffset, 0.0f);
                GL.Vertex3(headingBarPosition.x, headingBarPosition.y + headingBarPosition.w, 0.0f);
                GL.End();

                if (showHeadingBarPrograde)
                {
                    float slipAngle = velocityVesselSurfaceUnit.AngleInPlane(up, forward);
                    float slipTC    = JUtil.DualLerp(0f, 1f, 0f, 360f, rotationVesselSurface.eulerAngles.y + slipAngle);
                    float slipIconX = JUtil.DualLerp(headingBarPosition.x, headingBarPosition.x + headingBarPosition.z, headingTexture - headingTextureOffset, headingTexture + headingTextureOffset, slipTC);
                    DrawIcon(slipIconX, headingBarPosition.y + headingBarPosition.w * 0.5f, GizmoIcons.GetIconLocation(GizmoIcons.IconType.PROGRADE), progradeColorValue);
                }
            }

            if (vertBar1Material != null)
            {
                float value = comp.ProcessVariable(vertBar1Variable).MassageToFloat();
                if (float.IsNaN(value))
                {
                    value = 0.0f;
                }

                if (vertBar1UseLog10)
                {
                    value = JUtil.PseudoLog10(value);
                }

                float vertBar1TexCoord = JUtil.DualLerp(vertBar1TextureLimit.x, vertBar1TextureLimit.y, vertBar1Limit.x, vertBar1Limit.y, value);

                vertBar1Material.SetPass(0);
                GL.Begin(GL.QUADS);
                GL.TexCoord2(0.0f, vertBar1TexCoord + vertBar1TextureSize);
                GL.Vertex3(vertBar1Position.x, vertBar1Position.y, 0.0f);
                GL.TexCoord2(1.0f, vertBar1TexCoord + vertBar1TextureSize);
                GL.Vertex3(vertBar1Position.x + vertBar1Position.z, vertBar1Position.y, 0.0f);
                GL.TexCoord2(1.0f, vertBar1TexCoord - vertBar1TextureSize);
                GL.Vertex3(vertBar1Position.x + vertBar1Position.z, vertBar1Position.y + vertBar1Position.w, 0.0f);
                GL.TexCoord2(0.0f, vertBar1TexCoord - vertBar1TextureSize);
                GL.Vertex3(vertBar1Position.x, vertBar1Position.y + vertBar1Position.w, 0.0f);
                GL.End();
            }

            if (vertBar2Material != null)
            {
                float value = comp.ProcessVariable(vertBar2Variable).MassageToFloat();
                if (float.IsNaN(value))
                {
                    value = 0.0f;
                }

                if (vertBar2UseLog10)
                {
                    value = JUtil.PseudoLog10(value);
                }

                float vertBar2TexCoord = JUtil.DualLerp(vertBar2TextureLimit.x, vertBar2TextureLimit.y, vertBar2Limit.x, vertBar2Limit.y, value);

                vertBar2Material.SetPass(0);
                GL.Begin(GL.QUADS);
                GL.TexCoord2(0.0f, vertBar2TexCoord + vertBar2TextureSize);
                GL.Vertex3(vertBar2Position.x, vertBar2Position.y, 0.0f);
                GL.TexCoord2(1.0f, vertBar2TexCoord + vertBar2TextureSize);
                GL.Vertex3(vertBar2Position.x + vertBar2Position.z, vertBar2Position.y, 0.0f);
                GL.TexCoord2(1.0f, vertBar2TexCoord - vertBar2TextureSize);
                GL.Vertex3(vertBar2Position.x + vertBar2Position.z, vertBar2Position.y + vertBar2Position.w, 0.0f);
                GL.TexCoord2(0.0f, vertBar2TexCoord - vertBar2TextureSize);
                GL.Vertex3(vertBar2Position.x, vertBar2Position.y + vertBar2Position.w, 0.0f);
                GL.End();
            }

            if (overlayMaterial != null)
            {
                overlayMaterial.SetPass(0);
                GL.Begin(GL.QUADS);
                GL.TexCoord2(0.0f, 1.0f);
                GL.Vertex3(0.0f, 0.0f, 0.0f);
                GL.TexCoord2(1.0f, 1.0f);
                GL.Vertex3(screen.width, 0.0f, 0.0f);
                GL.TexCoord2(1.0f, 0.0f);
                GL.Vertex3(screen.width, screen.height, 0.0f);
                GL.TexCoord2(0.0f, 0.0f);
                GL.Vertex3(0.0f, screen.height, 0.0f);
                GL.End();
            }

            GL.PopMatrix();

            return(true);
        }
Пример #12
0
        public bool RenderPFD(RenderTexture screen, float aspect)
        {
            if (screen == null || !startupComplete || HighLogic.LoadedSceneIsEditor)
            {
                return(false);
            }

            // Analysis disable once CompareOfFloatsByEqualityOperator
            if (firstRenderComplete == false)
            {
                firstRenderComplete = true;
                ConfigureElements((float)screen.width, (float)screen.height);
                ballCamera.aspect = aspect;
            }

            GL.Clear(true, true, backgroundColorValue);

            ballCamera.targetTexture = screen;

            // Navball is rotated around the Y axis 180 degrees since the
            // original implementation had the camera positioned differently.
            // We still need MirrorX since KSP does something odd with the
            // gimbal
            navBall.transform.rotation = (rotateNavBall * MirrorX(stockNavBall.relativeGymbal));

            RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);

            if (heading != null)
            {
                heading.renderer.material.SetTextureOffset("_MainTex",
                                                           new Vector2(JUtil.DualLerp(0f, 1f, 0f, 360f, comp.RotationVesselSurface.eulerAngles.y) - headingSpan / 2f, 0));
            }

            Quaternion gymbal = stockNavBall.attitudeGymbal;

            if (FlightUIController.speedDisplayMode == FlightUIController.SpeedDisplayModes.Orbit)
            {
                Vector3 velocityVesselOrbitUnit = comp.Prograde;
                Vector3 radialPlus = comp.RadialOut;
                Vector3 normalPlus = comp.NormalPlus;

                MoveMarker(markerPrograde, velocityVesselOrbitUnit, gymbal);
                MoveMarker(markerRetrograde, -velocityVesselOrbitUnit, gymbal);

                MoveMarker(markerNormal, normalPlus, gymbal);
                MoveMarker(markerNormalMinus, -normalPlus, gymbal);

                MoveMarker(markerRadial, radialPlus, gymbal);
                MoveMarker(markerRadialMinus, -radialPlus, gymbal);

                JUtil.ShowHide(true, markerNormal, markerNormalMinus, markerRadial, markerRadialMinus);
            }
            else if (FlightUIController.speedDisplayMode == FlightUIController.SpeedDisplayModes.Surface)
            {
                Vector3 velocityVesselSurfaceUnit = vessel.srf_velocity.normalized;
                MoveMarker(markerPrograde, velocityVesselSurfaceUnit, gymbal);
                MoveMarker(markerRetrograde, -velocityVesselSurfaceUnit, gymbal);
            }
            else // FlightUIController.speedDisplayMode == FlightUIController.SpeedDisplayModes.Target
            {
                Vector3 targetDirection = FlightGlobals.ship_tgtVelocity.normalized;

                MoveMarker(markerPrograde, targetDirection, gymbal);
                MoveMarker(markerRetrograde, -targetDirection, gymbal);
            }

            if (vessel.patchedConicSolver != null && vessel.patchedConicSolver.maneuverNodes.Count > 0)
            {
                Vector3 burnVector = vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(vessel.orbit).normalized;
                MoveMarker(markerManeuver, burnVector, gymbal);
                MoveMarker(markerManeuverMinus, -burnVector, gymbal);
                JUtil.ShowHide(true, markerManeuver, markerManeuverMinus);
            }

            if (FinePrint.WaypointManager.navIsActive() == true)
            {
                // MOARdV: Code for the waypoint marker based on https://github.com/Ninenium/NavHud/blob/master/Source/WaypointMarker.cs
                GameObject navWaypointIndicator = GameObject.Find("NavBall").transform.FindChild("vectorsPivot").FindChild("NavWaypoint").gameObject;
                Material   material             = navWaypointIndicator.renderer.sharedMaterial;
                markerNavWaypoint.renderer.material.mainTexture       = material.mainTexture;
                markerNavWaypoint.renderer.material.mainTextureScale  = Vector2.one;
                markerNavWaypoint.renderer.material.mainTextureOffset = Vector2.zero;
                if (string.IsNullOrEmpty(waypointColor))
                {
                    markerNavWaypoint.renderer.material.SetVector("_Color", material.GetVector("_Color"));
                }

                Vector3d waypointPosition  = vessel.mainBody.GetWorldSurfacePosition(FinePrint.WaypointManager.navWaypoint.latitude, FinePrint.WaypointManager.navWaypoint.longitude, FinePrint.WaypointManager.navWaypoint.altitude);
                Vector3  waypointDirection = (waypointPosition - vessel.CoM).normalized;
                MoveMarker(markerNavWaypoint, waypointDirection, gymbal);
                JUtil.ShowHide(true, markerNavWaypoint);
            }

            ITargetable target = FlightGlobals.fetch.VesselTarget;

            if (target != null)
            {
                Vector3 targetSeparation = comp.TargetSeparation.normalized;
                MoveMarker(markerTarget, targetSeparation, gymbal);
                MoveMarker(markerTargetMinus, -targetSeparation, gymbal);
                var targetPort = target as ModuleDockingNode;
                if (targetPort != null)
                {
                    // Thanks to Michael Enßlin
                    Transform targetTransform         = targetPort.transform;
                    Transform selfTransform           = vessel.ReferenceTransform;
                    Vector3   targetOrientationVector = -targetTransform.up.normalized;

                    Vector3 v1    = Vector3.Cross(selfTransform.up, targetTransform.forward);
                    Vector3 v2    = Vector3.Cross(selfTransform.up, selfTransform.forward);
                    float   angle = Vector3.Angle(v1, v2);
                    if (Vector3.Dot(selfTransform.up, Vector3.Cross(v1, v2)) < 0)
                    {
                        angle = -angle;
                    }
                    MoveMarker(markerDockingAlignment, targetOrientationVector, gymbal);
                    markerDockingAlignment.transform.Rotate(Vector3.up, -angle);
                    JUtil.ShowHide(true, markerDockingAlignment);
                }
                JUtil.ShowHide(true, markerTarget, markerTargetMinus);
            }

            JUtil.ShowHide(true,
                           cameraBody, navBall, overlay, heading, markerPrograde, markerRetrograde);
            ballCamera.Render();
            JUtil.ShowHide(false,
                           cameraBody, navBall, overlay, heading, markerPrograde, markerRetrograde,
                           markerManeuver, markerManeuverMinus, markerTarget, markerTargetMinus,
                           markerNormal, markerNormalMinus, markerRadial, markerRadialMinus, markerDockingAlignment, markerNavWaypoint);

            return(true);
        }
Пример #13
0
        public bool RenderHUD(RenderTexture screen, float cameraAspect)
        {
            if (screen == null || !startupComplete || HighLogic.LoadedSceneIsEditor)
            {
                return(false);
            }
            //屏幕不存在,启动不完全,在编辑器内三种条件下直接返回。

            GL.Clear(true, true, backgroundColorValue);                    //擦除屏幕

            Vector3 coM = vessel.findWorldCenterOfMass();                  //质心位置
            //这里的vessel变量是从InternalModule提取的。
            Vector3 up      = (coM - vessel.mainBody.position).normalized; //质心位置减去几何中心位置,求单位向量
            Vector3 forward = vessel.GetTransform().up;                    //求从正在控制的驾驶舱测得的前向速度
            Vector3 right   = vessel.GetTransform().right;                 //求向右平移速度
            Vector3 top     = Vector3.Cross(right, forward);               //求前两者的叉积,得到向上的方向
            Vector3 north   = Vector3.Exclude(up, (vessel.mainBody.position + (Vector3d)vessel.mainBody.transform.up * vessel.mainBody.Radius) - coM).normalized;

            Vector3d velocityVesselSurface     = vessel.orbit.GetVel() - vessel.mainBody.getRFrmVel(coM); //轨道速度减去行星转速,得到地面速度
            Vector3  velocityVesselSurfaceUnit = velocityVesselSurface.normalized;                        //速度的方向

            float cosUp   = Vector3.Dot(forward, up);                                                     //俯仰的余弦
            float cosRoll = Vector3.Dot(top, up);                                                         //滚转的余弦
            float sinRoll = Vector3.Dot(right, up);                                                       //滚转的正弦

            var normalizedRoll = new Vector2(cosRoll, sinRoll);                                           //滚转角速度的单位向量。

            GL.PushMatrix();                                                                              //保存运行前的状态。第一次运行显然为空



            foreach (InfoGauge gauge in gaugeList)                                                                          //遍历信息条列表
            {
                GL.LoadPixelMatrix(-0.5f * screen.width, 0.5f * screen.width, 0.5f * screen.height, -0.5f * screen.height); //载入屏幕矩阵,准备渲染
                //原点在屏幕中心
                GL.Viewport(new Rect(0, 0, screen.width, screen.height));                                                   //载入视场
                float value = comp.ProcessVariable(gauge.Variable).MassageToFloat();                                        //用来存读入的变量
                if (float.IsNaN(value))
                {
                    value = 0.0f;
                }

                if (gauge.Material != null) //读到信息条用的贴图
                {
                    float   midPointCoord;  //贴图中点坐标。所有信息条统一用原本俯仰条的渲染方法。
                    Vector2 usedTextureSize = new Vector2(gauge.TextureLimit.y - gauge.TextureLimit.x, gauge.TextureLimit.w - gauge.TextureLimit.z);
                    float   textureOffset   = usedTextureSize.x / gauge.Material.mainTexture.height;
                    if (gauge.Use360Horizon)//超过上限之后翻转
                    {
                        midPointCoord = JUtil.DualLerp(gauge.TextureLimit.z + 0.25f * usedTextureSize.y,
                                                       gauge.TextureLimit.w - 0.25f * usedTextureSize.y, gauge.Limit.x,
                                                       gauge.Limit.y, value);
                    }
                    else
                    {
                        midPointCoord = JUtil.DualLerp(gauge.TextureLimit.x, gauge.TextureLimit.y, gauge.Limit.x, gauge.Limit.y, value);
                    }
                    if (gauge.RotateWithVessel)//随载具滚转
                    {
                        gauge.Material.SetPass(0);
                        GL.Begin(GL.QUADS);

                        GL.TexCoord2(0.0f, midPointCoord + gauge.TextureSize);
                        GL.Vertex3((cosRoll * gauge.Position.x + sinRoll * gauge.Position.y), (-sinRoll * gauge.Position.x + cosRoll * gauge.Position.y), 0.0f);
                        GL.TexCoord2(1.0f, midPointCoord + gauge.TextureSize);
                        GL.Vertex3((cosRoll * (gauge.Position.x + gauge.Position.z) + sinRoll * gauge.Position.y), (-sinRoll * (gauge.Position.x + gauge.Position.z) + cosRoll * gauge.Position.y), 0.0f);
                        GL.TexCoord2(1.0f, midPointCoord - gauge.TextureSize);
                        GL.Vertex3((cosRoll * (gauge.Position.x + gauge.Position.z) + sinRoll * (gauge.Position.y + gauge.Position.w)), (-sinRoll * (gauge.Position.x + gauge.Position.z) + cosRoll * (gauge.Position.y + gauge.Position.w)), 0.0f);
                        GL.TexCoord2(0.0f, midPointCoord - gauge.TextureSize);
                        GL.Vertex3((cosRoll * (gauge.Position.x) + sinRoll * (gauge.Position.y + gauge.Position.w)), (-sinRoll * (gauge.Position.x) + cosRoll * (gauge.Position.y + gauge.Position.w)), 0.0f);
                        GL.End();
                    }
                    else
                    {
                        gauge.Material.SetPass(0);
                        GL.Begin(GL.QUADS);
                        GL.TexCoord2(0.0f, midPointCoord + gauge.TextureSize);
                        GL.Vertex3(gauge.Position.x, gauge.Position.y, 0.0f);
                        GL.TexCoord2(1.0f, midPointCoord + gauge.TextureSize);
                        GL.Vertex3(gauge.Position.x + gauge.Position.z, gauge.Position.y, 0.0f);
                        GL.TexCoord2(1.0f, midPointCoord - gauge.TextureSize);
                        GL.Vertex3(gauge.Position.x + gauge.Position.z, gauge.Position.y + gauge.Position.w, 0.0f);
                        GL.TexCoord2(0.0f, midPointCoord - gauge.TextureSize);
                        GL.Vertex3(gauge.Position.x, gauge.Position.y + gauge.Position.w, 0.0f);
                        GL.End();
                    }
                }
                else
                {
                    JUtil.LogErrorMessage(this, "Material is null");
                }
            }
            GL.PopMatrix();//输出上述的矩阵
            return(true);
        }
        public void Update()
        {
            var scaleResults = new float[3];

            for (int i = 0; i < 3; i++)
            {
                if (!scaleEnds[i].Get(out scaleResults[i]))
                {
                    return;
                }
            }
            float scaledValue = Mathf.InverseLerp(scaleResults[0], scaleResults[1], scaleResults[2]);

            if (thresholdMode)
            {
                if (scaledValue >= threshold.x && scaledValue <= threshold.y)
                {
                    if (flashingDelay > 0)
                    {
                        if (lastStateChange < Planetarium.GetUniversalTime() - flashingDelay)
                        {
                            if (currentState)
                            {
                                TurnOff();
                            }
                            else
                            {
                                TurnOn();
                            }
                        }
                    }
                    else
                    {
                        TurnOn();
                    }
                    if (audioOutput != null && !alarmActive)
                    {
                        audioOutput.audio.Play();
                        alarmActive = true;
                    }
                }
                else
                {
                    TurnOff();
                    if (audioOutput != null)
                    {
                        audioOutput.audio.Stop();
                        alarmActive = false;
                    }
                }
            }
            else
            {
                switch (mode)
                {
                case Mode.Rotation:
                    Quaternion newRotation = longPath ? Quaternion.Euler(Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue)) :
                                             Quaternion.Slerp(reverse ? rotationEnd : rotationStart, reverse ? rotationStart : rotationEnd, scaledValue);
                    controlledTransform.localRotation = initialRotation * newRotation;
                    break;

                case Mode.Translation:
                    controlledTransform.localPosition = initialPosition + Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue);
                    break;

                case Mode.Scale:
                    controlledTransform.localScale = initialScale + Vector3.Lerp(reverse ? vectorEnd : vectorStart, reverse ? vectorStart : vectorEnd, scaledValue);
                    break;

                case Mode.Color:
                    colorShiftRenderer.material.SetColor(colorName, Color.Lerp(reverse ? activeColor : passiveColor, reverse ? passiveColor : activeColor, scaledValue));
                    break;

                case Mode.TextureShift:
                    foreach (string token in textureLayer.Split(','))
                    {
                        affectedMaterial.SetTextureOffset(token.Trim(),
                                                          Vector2.Lerp(reverse ? textureShiftEnd : textureShiftStart, reverse ? textureShiftStart : textureShiftEnd, scaledValue));
                    }
                    break;

                case Mode.TextureScale:
                    foreach (string token in textureLayer.Split(','))
                    {
                        affectedMaterial.SetTextureScale(token.Trim(),
                                                         Vector2.Lerp(reverse ? textureScaleEnd : textureScaleStart, reverse ? textureScaleStart : textureScaleEnd, scaledValue));
                    }
                    break;

                case Mode.Animation:
                    float lerp = JUtil.DualLerp(reverse ? 1f : 0f, reverse ? 0f : 1f, scaleResults[0], scaleResults[1], scaleResults[2]);
                    if (float.IsNaN(lerp) || float.IsInfinity(lerp))
                    {
                        lerp = reverse ? 1f : 0f;
                    }
                    anim[animationName].normalizedTime = lerp;
                    break;
                }
            }
        }