Beispiel #1
0
        public override void OnUpdate()
        {
            if (enablingVariable == null)
            {
                return;
            }

            RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);

            if (enablingVariable.IsInRange(comp))
            {
                base.OnUpdate();
                Quaternion post       = navBall.rotation;
                float      deltaAngle = Quaternion.Angle(lastOrientation, post);
                float      maxAngle   = maxAngleChange * Time.deltaTime;

                // If the rotation angle exceeds what we can do, slow it down
                if (deltaAngle > maxAngle)
                {
                    Quaternion newRotation = Quaternion.Slerp(lastOrientation, post, maxAngle / deltaAngle);
                    lastOrientation  = newRotation;
                    navBall.rotation = newRotation;
                }
                else
                {
                    lastOrientation = post;
                }
            }
        }
        public override void OnUpdate()
        {
            if (!JUtil.UserIsInPod(part))
            {
                StopPlaying();
                return;
            }

            if (needsElectricCharge)
            {
                soundCheckCountdown--;
                if (soundCheckCountdown <= 0)
                {
                    RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                    soundCheckCountdown   = soundCheckRate;
                    electricChargeReserve = comp.ProcessVariable(resourceName).MassageToFloat();
                    if (electricChargeReserve < 0.01f)
                    {
                        StopPlaying();
                        return;
                    }
                }
            }

            StartPlaying();
        }
        /// <summary>
        /// Evaluate the variable, returning it in destination.
        /// </summary>
        /// <param name="destination"></param>
        /// <param name="comp"></param>
        /// <returns></returns>
        public bool Get(out double destination, RPMVesselComputer comp)
        {
            if (type == VoNType.ConstantString)
            {
                destination = 0.0;
                return(false);
            }
            else if (type == VoNType.VariableValue)
            {
                numericValue = comp.ProcessVariable(variableName).MassageToDouble();
                if (double.IsNaN(numericValue) || double.IsInfinity(numericValue))
                {
                    if (!warningMade)
                    {
                        JUtil.LogMessage(this, "Warning: {0} can fail to produce a usable number.", variableName);
                        warningMade = true;
                    }
                    destination = numericValue;
                    return(false);
                }
            }

            destination = numericValue;
            return(true);
        }
Beispiel #4
0
        private void UpdateMethods()
        {
            RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);

            GetSmartassMode      = (Func <int>)comp.GetMethod("JSIMechJeb:GetSmartassMode", internalProp, typeof(Func <int>));
            SetSmartassMode      = (Action <JSIMechJeb.Target>)comp.GetMethod("JSIMechJeb:SetSmartassMode", internalProp, typeof(Action <JSIMechJeb.Target>));
            SetForceRoll         = (Action <bool, double>)comp.GetMethod("JSIMechJeb:ForceRoll", internalProp, typeof(Action <bool, double>));
            GetModuleExists      = (Func <string, bool>)comp.GetMethod("JSIMechJeb:GetModuleExists", internalProp, typeof(Func <string, bool>));
            CircularizeAt        = (Action <double>)comp.GetMethod("JSIMechJeb:CircularizeAt", internalProp, typeof(Action <double>));
            PositionTargetExists = (Func <bool>)comp.GetMethod("JSIMechJeb:PositionTargetExists", internalProp, typeof(Func <bool>));
            AutopilotEnabled     = (Func <bool>)comp.GetMethod("JSIMechJeb:AutopilotEnabled", internalProp, typeof(Func <bool>));
            GetForceRollAngle    = (Func <double>)comp.GetMethod("JSIMechJeb:GetForceRollAngle", internalProp, typeof(Func <double>));

            AscentAP      = (Action <bool>)comp.GetMethod("JSIMechJeb:ButtonAscentGuidance", internalProp, typeof(Action <bool>));
            AscentAPState = (Func <bool>)comp.GetMethod("JSIMechJeb:ButtonAscentGuidanceState", internalProp, typeof(Func <bool>));

            LandingAP      = (Action <bool>)comp.GetMethod("JSIMechJeb:ButtonLandingGuidance", internalProp, typeof(Action <bool>));
            LandingAPState = (Func <bool>)comp.GetMethod("JSIMechJeb:ButtonLandingGuidanceState", internalProp, typeof(Func <bool>));

            DockingAP      = (Action <bool>)comp.GetMethod("JSIMechJeb:ButtonDockingGuidance", internalProp, typeof(Action <bool>));
            DockingAPState = (Func <bool>)comp.GetMethod("JSIMechJeb:ButtonDockingGuidanceState", internalProp, typeof(Func <bool>));

            ForceRoll      = (Action <bool>)comp.GetMethod("JSIMechJeb:ButtonForceRoll", internalProp, typeof(Action <bool>));
            ForceRollState = (Func <bool>)comp.GetMethod("JSIMechJeb:ButtonForceRollState", internalProp, typeof(Func <bool>));

            ExecuteNextNode      = (Action <bool>)comp.GetMethod("JSIMechJeb:ButtonNodeExecute", internalProp, typeof(Action <bool>));
            ExecuteNextNodeState = (Func <bool>)comp.GetMethod("JSIMechJeb:ButtonNodeExecuteState", internalProp, typeof(Func <bool>));
        }
Beispiel #5
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);
            }
        }
        public static string ProcessString(string input, RPMVesselComputer comp, int propID = -1)
        {
            try
            {
                if (input.IndexOf(JUtil.VariableListSeparator[0], StringComparison.Ordinal) >= 0)
                {
                    string[] tokens = input.Split(JUtil.VariableListSeparator, StringSplitOptions.RemoveEmptyEntries);
                    if (tokens.Length != 2)
                    {
                        return("FORMAT ERROR");
                    }
                    else
                    {
                        string[] vars = tokens[1].Split(JUtil.VariableSeparator, StringSplitOptions.RemoveEmptyEntries);

                        var variables = new object[vars.Length];
                        for (int i = 0; i < vars.Length; i++)
                        {
                            variables[i] = comp.ProcessVariable(vars[i], propID);
                        }
                        string output = string.Format(fp, tokens[0], variables);
                        return(output.TrimEnd());
                    }
                }
            }
            catch (Exception e)
            {
                JUtil.LogMessage(comp, "Bad format on string {0}", input);
                throw e;
            }
            return(input.TrimEnd());
        }
Beispiel #7
0
        public void Start()
        {
            JUtil.LogMessage(this, "Setting RasterPropMonitor debugging to {0}", debugLogging);
            JUtil.debugLoggingEnabled = debugLogging;

            if (!HighLogic.LoadedSceneIsEditor)
            {
                RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                comp.SetVesselDescription(vesselDescription);

                // Make sure we have the description strings parsed.
                string[] descriptionStrings = vesselDescription.UnMangleConfigText().Split(JUtil.LineSeparator, StringSplitOptions.None);
                for (int i = 0; i < descriptionStrings.Length; i++)
                {
                    if (descriptionStrings[i].StartsWith("AG", StringComparison.Ordinal) && descriptionStrings[i][3] == '=')
                    {
                        uint groupID;
                        if (uint.TryParse(descriptionStrings[i][2].ToString(), out groupID))
                        {
                            descriptionStrings[i] = string.Empty;
                        }
                    }
                }
                vesselDescriptionForDisplay = string.Join(Environment.NewLine, descriptionStrings).MangleConfigText();

                // Now let's parse our stored strings...
                if (!string.IsNullOrEmpty(storedStrings))
                {
                    storedStringsArray = storedStrings.Split('|');
                }

                ParseData();
            }
        }
Beispiel #8
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);
            }
        }
Beispiel #9
0
        /// <summary>
        /// This intermediary will cache the results so that multiple variable
        /// requests within the frame would not result in duplicated code.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public object ProcessVariable(string input, RPMVesselComputer comp)
        {
            input = input.Trim();

            if (RPMGlobals.debugShowVariableCallCount)
            {
                debug_callCount[input] = debug_callCount[input] + 1;
            }

            if (comp == null)
            {
                comp = RPMVesselComputer.Instance(vid);
            }

            if (!variableCache.ContainsKey(input))
            {
                AddVariable(input);
            }

            VariableCache vc = variableCache[input];

            if (vc.cacheable)
            {
                return(vc.value.Get());
            }
            else
            {
                return(vc.evaluator(input, comp));
            }
        }
        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);
        }
        public void Click()
        {
            activeLabel++;

            if (activeLabel == labelsEx.Count)
            {
                activeLabel = 0;
            }

            if (labelsEx[activeLabel].hasColor)
            {
                colorShiftRenderer.material.SetColor(colorName, labelsEx[activeLabel].color);
            }

            if (labelsEx[activeLabel].hasText)
            {
                RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                textObj.text.Text = StringProcessor.ProcessString(labelsEx[activeLabel].label, comp);
            }

            // Force an update.
            updateCountdown = 0;

            if (audioOutput != null && (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA ||
                                        CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal))
            {
                audioOutput.audio.Play();
            }
        }
        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));
        }
Beispiel #13
0
        /// <summary>
        /// Callback for button presses.
        /// </summary>
        public void Click()
        {
            RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
            bool switchEnabled     = true;

            if (!forcedShutdown)
            {
                if (masterVariable != null)
                {
                    switchEnabled = masterVariable.IsInRange(comp);
                }
            }
            if (!switchEnabled)
            {
                // If the master switch is 'off' and we're not here because
                // of a forced shutdown, don't allow this switch to work.
                // early return
                return;
            }

            for (int i = 0; i < action.Count; ++i)
            {
                action[i].Click(vessel, null, comp);
            }
        }
Beispiel #14
0
        private IJSIAction AddAction(ConfigNode node)
        {
            if (!node.HasValue("name"))
            {
                throw new Exception("JSIAction ACTION node is missing a name");
            }

            string            name = node.GetValue("name");
            RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);

            if (JSIActionGroupSwitch.groupList.ContainsKey(name))
            {
                return(new JSIKSPAction(name, node));
            }
            else if (name == "intlight")
            {
                return(new JSIIntLight(node, comp, internalModel));
            }
            else if (name == "dummy")
            {
                return(new JSIDummy(node, comp));
            }
            else if (name == "plugin")
            {
                return(new JSIPlugin(node));
            }

            throw new NotImplementedException("No IJSIAction for " + name);
        }
        public void Start()
        {
            if (string.IsNullOrEmpty(soundURL))
            {
                JUtil.LogMessage(this, "JSIInternalBackgroundNoise called with no soundURL");
                Destroy(this);
                return;
            }

            if (needsElectricCharge)
            {
                RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                comp.UpdateDataRefreshRate(soundCheckRate);
                electricChargeReserve = comp.ProcessVariable(resourceName).MassageToFloat();
            }
            audioOutput            = new FXGroup("RPM" + internalModel.internalName + vessel.id);
            audioOutput.audio      = internalModel.gameObject.AddComponent <AudioSource>();
            audioOutput.audio.clip = GameDatabase.Instance.GetAudioClip(soundURL.EnforceSlashes());
            audioOutput.audio.Stop();
            audioOutput.audio.volume       = GameSettings.SHIP_VOLUME * soundVolume;
            audioOutput.audio.rolloffMode  = AudioRolloffMode.Logarithmic;
            audioOutput.audio.maxDistance  = 10f;
            audioOutput.audio.minDistance  = 8f;
            audioOutput.audio.dopplerLevel = 0f;
            audioOutput.audio.panStereo    = 0f;
            audioOutput.audio.playOnAwake  = false;
            audioOutput.audio.priority     = 255;
            audioOutput.audio.loop         = true;
            audioOutput.audio.pitch        = 1f;
        }
Beispiel #16
0
            internal JSIDummy(ConfigNode node, RPMVesselComputer comp)
                : base(node)
            {
                if (!node.HasValue("perPodPersistenceName"))
                {
                    throw new Exception("Trying to create Dummy JSIAction with no perPodPersistenceName");
                }

                perPodPersistenceName = node.GetValue("perPodPersistenceName");
                if (string.IsNullOrEmpty(perPodPersistenceName))
                {
                    throw new Exception("Invalid perPodPersistenceName supplied for Dummy JSIAction");
                }

                if (node.HasValue("initialState"))
                {
                    if (!bool.TryParse(node.GetValue("initialState"), out currentState))
                    {
                        currentState = false;
                    }
                }
                else
                {
                    currentState = false;
                }

                currentState = comp.GetPersistentVariable(perPodPersistenceName, currentState);
                comp.SetPersistentVariable(perPodPersistenceName, currentState);
            }
Beispiel #17
0
        // I don't like this mess of copypaste, but how can I improve it away?...
        public override void OnUpdate()
        {
            if (!pageActiveState || !initialized || !JUtil.VesselIsInIVA(vessel) || !UpdateCheck())
            {
                return;
            }

            RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);

            if (legacyRange != null)
            {
                float scaledValue;
                if (!legacyRange.InverseLerp(comp, out scaledValue))
                {
                    activePage = 1;
                    return;
                }

                activePage = (scaledValue >= threshold.x && scaledValue <= threshold.y) ? 0 : 1;
            }
            else
            {
                activePage = 0;
                for (activePage = 0; activePage < range.Count; ++activePage)
                {
                    if (range[activePage].IsInRange(comp))
                    {
                        break;
                    }
                }
            }
        }
Beispiel #18
0
        /// <summary>
        /// Return the persistent variable, pre-treated as a boolean.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="defaultValue"></param>
        /// <param name="broadcast">Broadcast the request to other parts of the same craft?</param>
        /// <returns></returns>
        internal bool GetPersistentVariable(string name, bool defaultValue, bool broadcast)
        {
            object val;

            if (persistentVars.ContainsKey(name))
            {
                val = persistentVars[name];
            }
            else if (broadcast)
            {
                RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                val = comp.GetPersistentVariable(name, defaultValue);
                if (val.GetType() == typeof(System.Boolean))
                {
                    persistentVars[name] = val;
                }
            }
            else
            {
                val = defaultValue;
                persistentVars[name] = defaultValue;
            }

            return((val.GetType() == typeof(System.Boolean)) ? (bool)val : false);
        }
Beispiel #19
0
        public static string ProcessString(string input, RasterPropMonitorComputer rpmComp)
        {
            try
            {
                if (input.IndexOf(JUtil.VariableListSeparator[0], StringComparison.Ordinal) >= 0)
                {
                    string[] tokens = input.Split(JUtil.VariableListSeparator, StringSplitOptions.RemoveEmptyEntries);
                    if (tokens.Length != 2)
                    {
                        return("FORMAT ERROR");
                    }
                    else
                    {
                        RPMVesselComputer comp = RPMVesselComputer.Instance(rpmComp.vessel);
                        string[]          vars = tokens[1].Split(JUtil.VariableSeparator, StringSplitOptions.RemoveEmptyEntries);

                        var variables = new object[vars.Length];
                        for (int i = 0; i < vars.Length; i++)
                        {
                            variables[i] = rpmComp.ProcessVariable(vars[i].Trim(), comp);
                        }
                        string output = string.Format(fp, tokens[0], variables);
                        return(output.TrimEnd());
                    }
                }
            }
            catch (Exception e)
            {
                JUtil.LogErrorMessage(rpmComp, "Bad format on string {0}: {1}", input, e);
            }

            return(input.TrimEnd());
        }
Beispiel #20
0
        public override void OnUpdate()
        {
            if (!JUtil.UserIsInPod(part))
            {
                StopPlaying();
                return;
            }

            if (needsElectricCharge)
            {
                soundCheckCountdown--;
                if (soundCheckCountdown <= 0)
                {
                    RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                    soundCheckCountdown   = soundCheckRate;
                    electricChargeReserve = (float)comp.ProcessVariable("SYSR_ELECTRICCHARGE");
                    if (electricChargeReserve < 0.01f)
                    {
                        StopPlaying();
                        return;
                    }
                }
            }

            StartPlaying();
        }
        public static string ProcessString(string input, RPMVesselComputer comp, PersistenceAccessor persistence)
        {
            try
            {
                if (input.IndexOf(JUtil.VariableListSeparator[0], StringComparison.Ordinal) >= 0)
                {
                    string[] tokens = input.Split(JUtil.VariableListSeparator, StringSplitOptions.RemoveEmptyEntries);
                    if (tokens.Length != 2)
                    {
                        return "FORMAT ERROR";
                    }
                    else
                    {
                        string[] vars = tokens[1].Split(JUtil.VariableSeparator, StringSplitOptions.RemoveEmptyEntries);

                        var variables = new object[vars.Length];
                        for (int i = 0; i < vars.Length; i++)
                        {
                            variables[i] = comp.ProcessVariable(vars[i], persistence);
                        }
                        string output = string.Format(fp, tokens[0], variables);
                        return output.TrimEnd();
                    }
                }
            }
            catch (Exception e)
            {
                JUtil.LogMessage(comp, "Bad format on string {0}", input);
                throw e;
            }
            return input.TrimEnd();
        }
 /// <summary>
 /// Toggles thrust reversers
 /// </summary>
 /// <param name="state"></param>
 public void SetThrustReverser(bool state)
 {
     if (vessel != null)
     {
         RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
         for (int i = 0; i < comp.availableThrustReverser.Count; ++i)
         {
             ModuleAnimateGeneric thrustReverser = comp.availableThrustReverser[i].thrustReverser;
             if (thrustReverser != null)
             {
                 if (state)
                 {
                     if (thrustReverser.Progress < 0.5f && thrustReverser.CanMove && thrustReverser.aniState != ModuleAnimateGeneric.animationStates.MOVING)
                     {
                         thrustReverser.Toggle();
                     }
                 }
                 else
                 {
                     if (thrustReverser.Progress > 0.5f && thrustReverser.CanMove && thrustReverser.aniState != ModuleAnimateGeneric.animationStates.MOVING)
                     {
                         thrustReverser.Toggle();
                     }
                 }
             }
         }
     }
 }
        public void Update()
        {
            if (!JUtil.IsActiveVessel(vessel))
            {
                return;
            }

            if (!JUtil.VesselIsInIVA(vessel))
            {
                for (int unit = 0; unit < variableSets.Count; ++unit)
                {
                    variableSets[unit].MuteSoundWhileOutOfIVA();
                }
            }

            if ((!alwaysActive && !JUtil.VesselIsInIVA(vessel)) || !UpdateCheck())
            {
                return;
            }

            RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);

            for (int unit = 0; unit < variableSets.Count; ++unit)
            {
                variableSets[unit].Update(comp, persistence);
            }
        }
        /// <summary>
        /// Sets multi-mode engines to run in primary mode (true) or secondary
        /// mode (false).
        /// </summary>
        /// <param name="newstate"></param>
        public void SetEnginesPrimaryMode(bool newstate)
        {
            try
            {
                RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                for (int i = 0; i < comp.availableMultiModeEngines.Count; ++i)
                {
                    if (comp.availableMultiModeEngines[i].runningPrimary ^ newstate)
                    {
                        if (newstate)
                        {
                            comp.availableMultiModeEngines[i].SetPrimary(true);
                        }
                        else
                        {
                            comp.availableMultiModeEngines[i].SetSecondary(true);
                        }
                        // Revised implementation:
                        //comp.availableMultiModeEngines[i].ModeEvent();

                        // original implementation:
                        //var ev = comp.availableMultiModeEngines[i].Events["ModeEvent"];
                        //if (ev != null)
                        //{
                        //    ev.Invoke();
                        //}
                    }
                }

                // Toggling modes changes which engines are enabled and which
                // are disabled.  Force a reset here.
                comp.InvalidateModuleLists();
            }
            catch { }
        }
 private void CheckForElectricCharge()
 {
     if (needsElectricCharge)
     {
         RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
         electricChargeReserve = comp.ProcessVariable(resourceName).MassageToFloat();
     }
 }
Beispiel #26
0
            override internal void Click(bool newState, Vessel vessel, RPMVesselComputer comp)
            {
                currentState = !currentState;

                comp.SetPersistentVariable(persistentVarName, currentState);

                SetInternalLights(currentState);
            }
 public override void OnUpdate()
 {
     if (JUtil.RasterPropMonitorShouldUpdate(vessel) && UpdateCheck())
     {
         RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
         textObj.text.Text = StringProcessor.ProcessString(labelsEx[activeLabel].label, comp);
     }
 }
 /// <summary>
 /// Allows enabling/disabling electric generators (and fuel cells)
 /// </summary>
 /// <param name="state"></param>
 public void ButtonEnableElectricGenerator(bool state)
 {
     if (vessel != null)
     {
         RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
         comp.SetEnableGenerators(state);
     }
 }
 /// <summary>
 /// Toggles engines on the current stage (on/off)
 /// </summary>
 /// <param name="state">"true" for on, "false" for off</param>
 public void ButtonEnableEngines(bool state)
 {
     if (vessel != null)
     {
         RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
         comp.SetEnableEngines(state);
     }
 }
 /// <summary>
 /// Toggles the state of deployable solar panels.
 /// </summary>
 /// <param name="state"></param>
 public void SetDeploySolarPanels(bool state)
 {
     if (vessel != null)
     {
         RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
         comp.SetDeploySolarPanels(state);
     }
 }
 private void CheckForElectricCharge()
 {
     if (needsElectricCharge)
     {
         RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
         electricChargeReserve = (double)comp.ProcessVariable("SYSR_ELECTRICCHARGE", null);
     }
 }
 /// <summary>
 /// Inverse of SolarPanelsDeployable for use with SetDeploySolarPanels
 /// </summary>
 /// <returns></returns>
 public bool GetDeploySolarPanels()
 {
     if (vessel != null)
     {
         RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
         return(comp.solarPanelsState);
     }
     return(true);
 }
 public object Evaluate(RPMVesselComputer comp)
 {
     float lerp;
     if (sourceVariable.InverseLerp(comp, out lerp))
     {
         return Mathf.Lerp(mappedRange.x, mappedRange.y, lerp);
     }
     else
     {
         return 0.0f;
     }
 }
 public object Evaluate(RPMVesselComputer comp)
 {
     float lerp, extent1, extent2;
     if (sourceVariable.InverseLerp(comp, out lerp) && mappedExtent1.Get(out extent1, comp) && mappedExtent2.Get(out extent2, comp))
     {
         return Mathf.Lerp(extent1, extent2, lerp);
     }
     else
     {
         return 0.0f;
     }
 }
        public object Evaluate(RPMVesselComputer comp)
        {
            int i = 0;
            for (; i < sourceVariables.Count; ++i)
            {
                if (sourceVariables[i].IsInRange(comp) ^ reverse[i])
                {
                    break;
                }
            }

            float evaluant = 0.0f;
            result[i].Get(out evaluant, comp);
            return evaluant;
        }
        public object Evaluate(RPMVesselComputer comp, PersistenceAccessor persistence)
        {
            // MOARdV TODO: Reevaluate (SWIDT?) this method if math expressions are added
            bool evaluation = sourceVariables[0].Evaluate(comp, persistence);

            for (int i = 1; i < sourceVariables.Count; ++i)
            {
                bool nextValue = sourceVariables[i].Evaluate(comp, persistence);

                switch (op)
                {
                    case Operator.AND:
                    case Operator.NAND:
                        evaluation = (evaluation) && (nextValue);
                        break;
                    case Operator.OR:
                    case Operator.NOR:
                        evaluation = (evaluation) || (nextValue);
                        break;
                    case Operator.XOR:
                        evaluation = (evaluation) ^ (nextValue);
                        break;
                    default:
                        throw new ArgumentException("CustomVariable.Evaluate was called with an invalid operator?");
                    case Operator.NONE:
                        break;
                }
            }

            if (op == Operator.NAND || op == Operator.NOR)
            {
                evaluation = !evaluation;
            }

            return evaluation.GetHashCode();
        }
        /// <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);
            }
        }
        public object Evaluate(RPMVesselComputer comp)
        {
            if (indexOperator)
            {
                int index = 0;
                float value = 0.0f;
                if (!sourceVariables[0].Get(out value, comp))
                {
                    return 0;
                }

                for (int i = 1; i < sourceVariables.Count; ++i)
                {
                    float operand;
                    if (!sourceVariables[i].Get(out operand, comp))
                    {
                        return 0;
                    }

                    switch (op)
                    {
                        case Operator.MAXINDEX:
                            if (operand > value)
                            {
                                index = i;
                                value = operand;
                            }
                            break;
                        case Operator.MININDEX:
                            if (operand < value)
                            {
                                index = i;
                                value = operand;
                            }
                            break;
                    }
                }

                return index;
            }
            else
            {
                float value = 0.0f;
                if (!sourceVariables[0].Get(out value, comp))
                {
                    return 0.0f;
                }

                for (int i = 1; i < sourceVariables.Count; ++i)
                {
                    float operand;
                    if (!sourceVariables[i].Get(out operand, comp))
                    {
                        return 0.0f;
                    }

                    switch (op)
                    {
                        case Operator.NONE:
                            break;
                        case Operator.ADD:
                            value += operand;
                            break;
                        case Operator.SUBTRACT:
                            value -= operand;
                            break;
                        case Operator.MULTIPLY:
                            value *= operand;
                            break;
                        case Operator.DIVIDE:
                            value /= operand;
                            break;
                        case Operator.MAX:
                            value = Mathf.Max(value, operand);
                            break;
                        case Operator.MIN:
                            value = Mathf.Min(value, operand);
                            break;
                    }
                }

                return value;
            }
        }
 public bool Evaluate(RPMVesselComputer comp, PersistenceAccessor persistence)
 {
     return range.IsInRange(comp, persistence) ^ reverse;
 }
        /// <summary>
        /// This intermediary will cache the results so that multiple variable
        /// requests within the frame would not result in duplicated code.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public object ProcessVariable(string input, RPMVesselComputer comp)
        {
            input = input.Trim();

            if (RPMGlobals.debugShowVariableCallCount)
            {
                debug_callCount[input] = debug_callCount[input] + 1;
            }

            if (comp == null)
            {
                comp = RPMVesselComputer.Instance(vid);
            }

            if (!variableCache.ContainsKey(input))
            {
                AddVariable(input);
            }

            VariableCache vc = variableCache[input];
            if (vc.cacheable)
            {
                return vc.value.Get();
            }
            else
            {
                return vc.evaluator(input, comp);
            }
        }
 internal void Update(RPMVesselComputer comp)
 {
     bool inRange = variable.IsInRange(comp);
     if (armed)
     {
         if (inRange)
         {
             if (!triggered)
             {
                 JUtil.LogMessage(this, "Event {0} triggered", eventName);
                 triggered = true;
                 armed = oneShot;
                 DoEvent(comp.vessel);
             }
         }
     }
     else if (!inRange)
     {
         JUtil.LogMessage(this, "Event {0} armed", eventName);
         armed = true;
         triggered = false;
     }
 }
        public void RenderData(RenderTexture screen, RPMVesselComputer comp)
        {
            float leftVal, rightVal;
            if (!scale[0].Get(out leftVal, comp) || !scale[1].Get(out rightVal, comp))
            {
                return; // bad values - can't render
            }

            float eval = comp.ProcessVariable(variableName).MassageToFloat();
            if (float.IsInfinity(eval) || float.IsNaN(eval))
            {
                return; // bad value - can't render
            }

            float ratio = Mathf.InverseLerp(leftVal, rightVal, eval);

            if (thresholdMode)
            {
                if (ratio >= threshold.x && ratio <= threshold.y)
                {
                    if (flashingDelay > 0.0f)
                    {
                        if (lastStateChange + flashingDelay < Planetarium.GetUniversalTime())
                        {
                            lastStateChange = Planetarium.GetUniversalTime();
                            lastState = 1.0f - lastState;
                        }

                        ratio = lastState;
                    }
                    else
                    {
                        ratio = 1.0f;
                    }
                }
                else
                {
                    ratio = 0.0f;
                }
            }

            if (reverse)
            {
                ratio = 1.0f - ratio;
            }

            switch (graphType)
            {
                case GraphType.VerticalDown:
                    DrawVerticalDown(ratio);
                    break;
                case GraphType.VerticalUp:
                    DrawVerticalUp(ratio);
                    break;
                case GraphType.VerticalSplit:
                    DrawVerticalSplit(ratio);
                    break;
                case GraphType.HorizontalLeft:
                    DrawHorizontalLeft(ratio);
                    break;
                case GraphType.HorizontalRight:
                    DrawHorizontalRight(ratio);
                    break;
                case GraphType.HorizontalSplit:
                    DrawHorizontalSplit(ratio);
                    break;
                case GraphType.Lamp:
                    DrawLamp(ratio);
                    break;
                default:
                    throw new NotImplementedException("Unimplemented graphType " + graphType.ToString());
            }
        }
        internal object Evaluate(RPMVesselComputer comp)
        {
            // MOARdV TODO: Reevaluate (SWIDT?) this method if math expressions are added
            bool evaluation = sourceVariables[0].IsInRange(comp) ^ reverse[0];

            // Use an optimization on evaluation to speed things up
            bool earlyExit;
            switch (op)
            {
                case Operator.AND:
                case Operator.NAND:
                    earlyExit = !evaluation;
                    break;
                case Operator.OR:
                case Operator.NOR:
                    earlyExit = evaluation;
                    break;
                case Operator.XOR:
                    earlyExit = false;
                    break;
                case Operator.NONE:
                    earlyExit = true;
                    break;
                default:
                    throw new ArgumentException("CustomVariable.Evaluate was called with an invalid operator?");
            }

            for (int i = 1; i < sourceVariables.Count && (earlyExit == false); ++i)
            {
                bool nextValue = sourceVariables[i].IsInRange(comp) ^ reverse[i];

                switch (op)
                {
                    case Operator.AND:
                    case Operator.NAND:
                        evaluation = (evaluation) && (nextValue);
                        earlyExit = !evaluation;
                        break;
                    case Operator.OR:
                    case Operator.NOR:
                        evaluation = (evaluation) || (nextValue);
                        earlyExit = evaluation;
                        break;
                    case Operator.XOR:
                        evaluation = (evaluation) ^ (nextValue);
                        break;
                    case Operator.NONE:
                        break;
                }
            }

            if (op == Operator.NAND || op == Operator.NOR)
            {
                evaluation = !evaluation;
            }

            return evaluation.GetHashCode();
        }
        /// <summary>
        /// Evaluate the variable, returning it in destination.
        /// </summary>
        /// <param name="destination"></param>
        /// <param name="comp"></param>
        /// <returns></returns>
        public bool Get(out float destination, RPMVesselComputer comp)
        {
            if (!string.IsNullOrEmpty(variableName))
            {
                value = comp.ProcessVariable(variableName).MassageToFloat();
                if (float.IsNaN(value) || float.IsInfinity(value))
                {
                    if (!warningMade)
                    {
                        JUtil.LogMessage(this, "Warning: {0} can fail to produce a usable number.", variableName);
                        warningMade = true;
                    }
                    destination = value;
                    return false;
                }
            }

            destination = value;
            return true;
        }
        public void Update(RPMVesselComputer comp, double universalTime)
        {
            float scaledValue;
            if (!variable.InverseLerp(comp, out scaledValue))
            {
                return;
            }

            float delta = Mathf.Abs(scaledValue - lastScaledValue);
            if (delta < float.Epsilon)
            {
                if (thresholdMode && flashingDelay > 0.0 && scaledValue >= threshold.x && scaledValue <= threshold.y)
                {
                    // If we're blinking our lights, they need to keep blinking
                    if (lastStateChange < universalTime - flashingDelay)
                    {
                        if (currentState)
                        {
                            TurnOff(universalTime);
                        }
                        else
                        {
                            TurnOn(universalTime);
                        }
                    }

                    if (alarmActive && audioOutput != null)
                    {
                        audioOutput.audio.volume = alarmSoundVolume * GameSettings.SHIP_VOLUME;
                    }
                }

                if (maxRateChange > 0.0f)
                {
                    lastAnimUpdate = universalTime;
                }
                return;
            }

            if (maxRateChange > 0.0f && lastScaledValue >= 0.0f)
            {
                float maxDelta = (float)(universalTime - lastAnimUpdate) * maxRateChange;

                if (Mathf.Abs(lastScaledValue - scaledValue) > maxDelta)
                {
                    if (scaledValue < lastScaledValue)
                    {
                        scaledValue = lastScaledValue - maxDelta;
                    }
                    else
                    {
                        scaledValue = lastScaledValue + maxDelta;
                    }
                }
            }

            lastScaledValue = scaledValue;
            lastAnimUpdate = universalTime;

            if (thresholdMode)
            {
                if (scaledValue >= threshold.x && scaledValue <= threshold.y)
                {
                    if (flashingDelay > 0)
                    {
                        if (lastStateChange < universalTime - flashingDelay)
                        {
                            if (currentState)
                            {
                                TurnOff(universalTime);
                            }
                            else
                            {
                                TurnOn(universalTime);
                            }
                        }
                    }
                    else
                    {
                        TurnOn(universalTime);
                    }
                    if (audioOutput != null && !alarmActive)
                    {
                        audioOutput.audio.Play();
                        alarmActive = true;
                    }
                }
                else
                {
                    TurnOff(universalTime);
                    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(vectorStart, vectorEnd, scaledValue)) :
                                                 Quaternion.Slerp(rotationStart, rotationEnd, scaledValue);
                        controlledTransform.localRotation = initialRotation * newRotation;
                        break;
                    case Mode.Translation:
                        controlledTransform.localPosition = initialPosition + Vector3.Lerp(vectorStart, vectorEnd, scaledValue);
                        break;
                    case Mode.Scale:
                        controlledTransform.localScale = initialScale + Vector3.Lerp(vectorStart, vectorEnd, scaledValue);
                        break;
                    case Mode.Color:
                        affectedMaterial.SetColor(colorName, Color.Lerp(passiveColor, activeColor, scaledValue));
                        break;
                    case Mode.TextureShift:
                        for (int i = 0; i < textureLayer.Count; ++i)
                        {
                            affectedMaterial.SetTextureOffset(textureLayer[i],
                                Vector2.Lerp(textureShiftStart, textureShiftEnd, scaledValue));
                        }
                        break;
                    case Mode.TextureScale:
                        for (int i = 0; i < textureLayer.Count; ++i)
                        {
                            affectedMaterial.SetTextureScale(textureLayer[i],
                                Vector2.Lerp(textureScaleStart, textureScaleEnd, scaledValue));
                        }
                        break;
                    case Mode.LoopingAnimation:
                    // MOARdV TODO: Define what this actually does
                    case Mode.Animation:
                        float lerp = (reverse) ? (1.0f - scaledValue) : scaledValue;
                        onAnim[animationName].normalizedTime = lerp;
                        break;
                }
            }
        }
 public bool InverseLerp(RPMVesselComputer comp, out float scaledValue)
 {
     float value;
     float low, high;
     if (!(sourceValue.Get(out value, comp) && lowerBound.Get(out low, comp) && upperBound.Get(out high, comp)))
     {
         scaledValue = 0.0f;
         return false;
     }
     else
     {
         scaledValue = Mathf.InverseLerp(low, high, value);
         return true;
     }
 }
        /// <summary>
        /// Provides a simple boolean true/false for whether the named
        /// variable is in range.
        /// </summary>
        /// <param name="comp"></param>
        /// <param name="persistence"></param>
        /// <returns></returns>
        public bool IsInRange(RPMVesselComputer comp)
        {
            float value;
            float low, high;

            if(!(sourceValue.Get(out value, comp) && lowerBound.Get(out low, comp) && upperBound.Get(out high, comp)))
            {
                return false;
            }
            else if (high < low)
            {
                return (value >= high && value <= low);
            }
            else
            {
                return (value >= low && value <= high);
            }
        }
        internal object Evaluate(RPMVesselComputer comp)
        {
            float value = 0.0f;
            if(!sourceVariables[0].Get(out value, comp))
            {
                return 0.0f;
            }

            for (int i = 1; i < sourceVariables.Count; ++i)
            {
                float operand;
                if(!sourceVariables[i].Get(out operand, comp))
                {
                    return 0.0f;
                }

                switch(op)
                {
                    case Operator.NONE:
                        break;
                    case Operator.ADD:
                        value += operand;
                        break;
                    case Operator.SUBTRACT:
                        value -= operand;
                        break;
                    case Operator.MULTIPLY:
                        value *= operand;
                        break;
                    case Operator.DIVIDE:
                        value /= operand;
                        break;
                    case Operator.MAX:
                        value = Mathf.Max(value, operand);
                        break;
                    case Operator.MIN:
                        value = Mathf.Min(value, operand);
                        break;
                }
            }

            return value;
        }
        /// <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);
            }
        }
        public void Update(RPMVesselComputer comp)
        {
            float scaledValue;
            if (!variable.InverseLerp(comp, out scaledValue))
            {
                return;
            }

            // MOARdV TODO: What's a good epsilon here?  .001 may be too
            // precise.  For an RGB lerp, 1/256 (or so) may be the finest
            // precision we can represent.
            if (Mathf.Abs(scaledValue - lastScaledValue) < epsilon)
            {
                if (thresholdMode && flashingDelay > 0.0 && scaledValue >= threshold.x && scaledValue <= threshold.y)
                {
                    // If we're blinking our lights, they need to keep blinking
                    if (lastStateChange < Planetarium.GetUniversalTime() - flashingDelay)
                    {
                        if (currentState)
                        {
                            TurnOff();
                        }
                        else
                        {
                            TurnOn();
                        }
                    }

                    if (alarmActive && audioOutput != null)
                    {
                        audioOutput.audio.volume = alarmSoundVolume * GameSettings.SHIP_VOLUME;
                    }
                }
            }

            lastScaledValue = scaledValue;

            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 = (reverse) ? (1.0f - scaledValue) : scaledValue;
                        onAnim[animationName].normalizedTime = lerp;
                        break;
                }
            }
        }
        internal void Update(RPMVesselComputer comp, PersistenceAccessor persistence)
        {
            float value;
            if (enablingVariable != null)
            {
                if (!enablingVariable.IsInRange(comp, persistence))
                {
                    return;
                }
            }

            if (variable.Get(out value, comp, persistence))
            {
                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);
            }
        }
 public void Update(double time, RPMVesselComputer comp, PersistenceAccessor persistence)
 {
     double value = isFlat ? flatValue : comp.ProcessVariable(variableName, persistence).MassageToDouble();
     if (double.IsNaN(value) || double.IsInfinity(value))
     {
         return;
     }
     points.Add(new Vector2d(time, value));
     if (points.Count > maxPoints)
     {
         points.RemoveRange(0, points.Count - maxPoints);
     }
 }
 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;
         }
     }
 }
            internal TriggeredEvent(TriggeredEventTemplate template, RPMVesselComputer comp)
            {
                eventName = template.eventName;
                if (string.IsNullOrEmpty(eventName))
                {
                    throw new Exception("TriggeredEvent: eventName not valid");
                }

                string[] tokens = template.range.Split(',');
                if (string.IsNullOrEmpty(template.variableName))
                {
                    throw new Exception("TriggeredEvent: variableName not valid");
                }
                if (tokens.Length != 2)
                {
                    throw new Exception("TriggeredEvent: tokens not valid");
                }
                variable = new VariableOrNumberRange(template.variableName, tokens[0], tokens[1]);

                if (JSIActionGroupSwitch.groupList.ContainsKey(template.triggerEvent))
                {
                    isPluginAction = false;
                    action = JSIActionGroupSwitch.groupList[template.triggerEvent];
                }
                else
                {
                    isPluginAction = true;
                    pluginAction = (Action<bool>)comp.GetInternalMethod(template.triggerEvent, typeof(Action<bool>));

                    if (pluginAction == null)
                    {
                        throw new Exception("TriggeredEvent: Unable to initialize pluginAction");
                    }
                }

                if (string.IsNullOrEmpty(template.triggerState))
                {
                    throw new Exception("TriggeredEvent: Unable to initialize triggerState");
                }
                if (bool.TryParse(template.triggerState, out triggerState))
                {
                    toggleAction = false;
                }
                else if (template.triggerState.ToLower() == "toggle")
                {
                    toggleAction = true;

                    if (isPluginAction)
                    {
                        pluginState = (Func<bool>)comp.GetInternalMethod(template.eventState, typeof(Func<bool>));
                        if (pluginState == null)
                        {
                            throw new Exception("TriggeredEvent: Unable to initialize pluginState");
                        }
                    }
                }
                else
                {
                    throw new Exception("TriggeredEvent: Unable to determine triggerState");
                }

                if (!string.IsNullOrEmpty(template.oneShot))
                {
                    if (!bool.TryParse(template.oneShot, out oneShot))
                    {
                        oneShot = false;
                    }
                }
                else
                {
                    oneShot = false;
                }

                JUtil.LogMessage(this, "Triggered Event {0} created", eventName);
            }