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;
        }
Exemple #2
0
        /// <summary>
        /// Set the refresh rate (number of Update() calls per triggered update).
        /// The lower of the current data rate and the new data rate is used.
        /// </summary>
        /// <param name="newDataRate">New data rate</param>
        internal void UpdateDataRefreshRate(int newDataRate)
        {
            refreshDataRate = Math.Max(RPMGlobals.minimumRefreshRate, Math.Min(newDataRate, refreshDataRate));

            RPMVesselComputer comp = null;

            if (RPMVesselComputer.TryGetInstance(vessel, ref comp))
            {
                comp.UpdateDataRefreshRate(newDataRate);
            }
        }
 public void Start()
 {
     textObjTransform = internalProp.FindModelTransform(transformName);
     textObj          = InternalComponents.Instance.CreateText(fontName, fontSize, textObjTransform, string.Empty);
     // Force oneshot if there's no variables:
     oneshot     |= !labelText.Contains("$&$");
     sourceString = labelText.UnMangleConfigText();
     if (!oneshot)
     {
         RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
         comp.UpdateDataRefreshRate(refreshRate);
     }
 }
Exemple #4
0
        public void Start()
        {
            RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);

            Transform textObjTransform = internalProp.FindModelTransform(transformName);

            textObj = InternalComponents.Instance.CreateText(fontName, fontSize, textObjTransform, string.Empty);
            // Force oneshot if there's no variables:
            oneshot |= !labelText.Contains("$&$");
            string sourceString = labelText.UnMangleConfigText();

            // Alow a " character to escape leading whitespace
            if (sourceString[0] == '"')
            {
                sourceString = sourceString.Substring(1);
            }
            spf = new StringProcessorFormatter(sourceString);

            if (!oneshot)
            {
                comp.UpdateDataRefreshRate(refreshRate);
            }

            if (!(string.IsNullOrEmpty(variableName) || string.IsNullOrEmpty(positiveColor) || string.IsNullOrEmpty(negativeColor) || string.IsNullOrEmpty(zeroColor)))
            {
                positiveColorValue = ConfigNode.ParseColor32(positiveColor);
                negativeColorValue = ConfigNode.ParseColor32(negativeColor);
                zeroColorValue     = ConfigNode.ParseColor32(zeroColor);
                del = (Action <RPMVesselComputer, float>)Delegate.CreateDelegate(typeof(Action <RPMVesselComputer, float>), this, "OnCallback");
                comp.RegisterCallback(variableName, del);

                // Initialize the text color.
                float value = comp.ProcessVariable(variableName).MassageToFloat();
                if (value < 0.0f)
                {
                    textObj.text.Color = negativeColorValue;
                }
                else if (value > 0.0f)
                {
                    textObj.text.Color = positiveColorValue;
                }
                else
                {
                    textObj.text.Color = zeroColorValue;
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Callback to tell us our vessel was modified (and we thus need to
        /// re-examine some values.
        /// </summary>
        /// <param name="who"></param>
        private void onVesselWasModified(Vessel who)
        {
            if (who.id == vessel.id)
            {
                vid = vessel.id;
                //JUtil.LogMessage(this, "onVesselWasModified(): RPMCid {0} / vessel {1}", RPMCid, vid;)
                ClearVariables();
                UpdateLocalCrew();

                for (int i = 0; i < installedModules.Count; ++i)
                {
                    installedModules[i].vessel = vessel;
                }

                RPMVesselComputer comp = null;
                if (RPMVesselComputer.TryGetInstance(vessel, ref comp))
                {
                    comp.UpdateDataRefreshRate(refreshDataRate);
                }
            }
        }
        public void Start()
        {
            // If we're not in the correct location, there's no point doing anything.
            if (!InstallationPathWarning.Warn())
            {
                return;
            }

            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            try
            {
                // Install the calculator module.
                RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                comp.UpdateDataRefreshRate(refreshDataRate);

                persistence = new PersistenceAccessor(internalProp);

                // Loading the font...
                List <Texture2D> fontTexture = new List <Texture2D>();
                fontTexture.Add(LoadFont(this, internalProp, fontTransform));

                // Damn KSP's config parser!!!
                if (!string.IsNullOrEmpty(emptyColor))
                {
                    emptyColorValue = ConfigNode.ParseColor32(emptyColor);
                }
                if (!string.IsNullOrEmpty(defaultFontTint))
                {
                    defaultFontTintValue = ConfigNode.ParseColor32(defaultFontTint);
                }

                if (!string.IsNullOrEmpty(fontDefinition))
                {
                    JUtil.LogMessage(this, "Loading font definition from {0}", fontDefinition);
                    fontDefinitionString = File.ReadAllLines(KSPUtil.ApplicationRootPath + "GameData/" + fontDefinition.EnforceSlashes(), Encoding.UTF8)[0];
                }

                // Now that is done, proceed to setting up the screen.

                screenTexture = new RenderTexture(screenPixelWidth, screenPixelHeight, 24, RenderTextureFormat.ARGB32);
                screenMat     = internalProp.FindModelTransform(screenTransform).renderer.material;
                foreach (string layerID in textureLayerID.Split())
                {
                    screenMat.SetTexture(layerID.Trim(), screenTexture);
                }

                if (GameDatabase.Instance.ExistsTexture(noSignalTextureURL.EnforceSlashes()))
                {
                    noSignalTexture = GameDatabase.Instance.GetTexture(noSignalTextureURL.EnforceSlashes(), false);
                }

                // Create camera instance...
                cameraStructure = new FlyingCamera(part, screenTexture, cameraAspect);

                // The neat trick. IConfigNode doesn't work. No amount of kicking got it to work.
                // Well, we don't need it. GameDatabase, gimme config nodes for all props!
                foreach (ConfigNode node in GameDatabase.Instance.GetConfigNodes("PROP"))
                {
                    // Now, we know our own prop name.
                    if (node.GetValue("name") == internalProp.propName)
                    {
                        // So this is the configuration of our prop in memory. Nice place.
                        // We know it contains at least one MODULE node, us.
                        // And we know our moduleID, which is the number in order of being listed in the prop.
                        // Therefore the module by that number is our module's own config node.

                        ConfigNode   moduleConfig = node.GetNodes("MODULE")[moduleID];
                        ConfigNode[] pageNodes    = moduleConfig.GetNodes("PAGE");

                        // Which we can now parse for page definitions.
                        for (int i = 0; i < pageNodes.Length; i++)
                        {
                            // Mwahahaha.
                            try
                            {
                                var newPage = new MonitorPage(i, pageNodes[i], this);
                                activePage = activePage ?? newPage;
                                if (newPage.isDefault)
                                {
                                    activePage = newPage;
                                }
                                pages.Add(newPage);
                            }
                            catch (ArgumentException e)
                            {
                                JUtil.LogMessage(this, "Warning - {0}", e);
                            }
                        }

                        // Now that all pages are loaded, we can use the moment in the loop to suck in all the extra fonts.
                        foreach (string value in moduleConfig.GetValues("extraFont"))
                        {
                            fontTexture.Add(LoadFont(this, internalProp, value));
                        }

                        break;
                    }
                }
                JUtil.LogMessage(this, "Done setting up pages, {0} pages ready.", pages.Count);

                textRenderer = new TextRenderer(fontTexture, new Vector2((float)fontLetterWidth, (float)fontLetterHeight), fontDefinitionString, 17, screenPixelWidth, screenPixelHeight);

                // Load our state from storage...
                persistentVarName = "activePage" + internalProp.propID;
                int activePageID = persistence.GetVar(persistentVarName, pages.Count);
                if (activePageID < pages.Count)
                {
                    activePage = pages[activePageID];
                }
                activePage.Active(true);

                // If we have global buttons, set them up.
                if (!string.IsNullOrEmpty(globalButtons))
                {
                    string[] tokens = globalButtons.Split(',');
                    for (int i = 0; i < tokens.Length; i++)
                    {
                        string buttonName = tokens[i].Trim();
                        // Notice that holes in the global button list ARE legal.
                        if (!string.IsNullOrEmpty(buttonName))
                        {
                            SmarterButton.CreateButton(internalProp, buttonName, i, GlobalButtonClick, GlobalButtonRelease);
                        }
                    }
                }

                audioOutput = JUtil.SetupIVASound(internalProp, buttonClickSound, buttonClickVolume, false);

                // One last thing to make sure of: If our pod is transparent, we're always active.
                ourPodIsTransparent = JUtil.IsPodTransparent(part);

                // And if the try block never completed, startupComplete will never be true.
                startupComplete = true;
            }
            catch
            {
                JUtil.AnnoyUser(this);
                startupFailed = true;
                // We can also disable ourselves, that should help.
                enabled = false;
                // And now that we notified the user that config is borked, we rethrow the exception so that
                // it gets logged and we can debug.
                throw;
            }
        }
Exemple #7
0
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            try
            {
                RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);

                if (!groupList.ContainsKey(actionName) && !customGroupList.ContainsKey(actionName))
                {
                    JUtil.LogErrorMessage(this, "Action \"{0}\" is not supported.", actionName);
                    return;
                }

                // Parse the needs-electric-charge here.
                if (!string.IsNullOrEmpty(needsElectricCharge))
                {
                    switch (needsElectricCharge.ToLowerInvariant().Trim())
                    {
                    case "true":
                    case "yes":
                    case "1":
                        needsElectricChargeValue = true;
                        break;

                    case "false":
                    case "no":
                    case "0":
                        needsElectricChargeValue = false;
                        break;
                    }
                }

                // Now parse consumeOnToggle and consumeWhileActive...
                if (!string.IsNullOrEmpty(consumeOnToggle))
                {
                    string[] tokens = consumeOnToggle.Split(',');
                    if (tokens.Length == 3)
                    {
                        consumeOnToggleName = tokens[0].Trim();
                        if (!(PartResourceLibrary.Instance.GetDefinition(consumeOnToggleName) != null &&
                              float.TryParse(tokens[1].Trim(), NumberStyles.Any, CultureInfo.InvariantCulture,
                                             out consumeOnToggleAmount)))
                        {
                            JUtil.LogErrorMessage(this, "Could not parse \"{0}\"", consumeOnToggle);
                        }
                        switch (tokens[2].Trim().ToLower())
                        {
                        case "on":
                            consumingOnToggleUp = true;
                            break;

                        case "off":
                            consumingOnToggleDown = true;
                            break;

                        case "both":
                            consumingOnToggleUp   = true;
                            consumingOnToggleDown = true;
                            break;

                        default:
                            JUtil.LogErrorMessage(this, "So should I consume resources when turning on, turning off, or both in \"{0}\"?", consumeOnToggle);
                            break;
                        }
                    }
                }

                if (!string.IsNullOrEmpty(consumeWhileActive))
                {
                    string[] tokens = consumeWhileActive.Split(',');
                    if (tokens.Length == 2)
                    {
                        consumeWhileActiveName = tokens[0].Trim();
                        if (!(PartResourceLibrary.Instance.GetDefinition(consumeWhileActiveName) != null &&
                              float.TryParse(tokens[1].Trim(),
                                             NumberStyles.Any, CultureInfo.InvariantCulture,
                                             out consumeWhileActiveAmount)))
                        {
                            JUtil.LogErrorMessage(this, "Could not parse \"{0}\"", consumeWhileActive);
                        }
                        else
                        {
                            consumingWhileActive = true;
                            JUtil.LogMessage(this, "Switch in prop {0} prop id {1} will consume {2} while active at a rate of {3}", internalProp.propName,
                                             internalProp.propID, consumeWhileActiveName, consumeWhileActiveAmount);
                        }
                    }
                }

                if (groupList.ContainsKey(actionName))
                {
                    kspAction    = groupList[actionName];
                    currentState = vessel.ActionGroups[kspAction];
                    // action group switches may not belong to a radio group
                    switchGroupIdentifier = -1;
                }
                else
                {
                    isCustomAction = true;
                    switch (actionName)
                    {
                    case "intlight":
                        persistentVarName = internalLightName;
                        if (!string.IsNullOrEmpty(internalLightName))
                        {
                            Light[] availableLights = internalModel.FindModelComponents <Light>();
                            if (availableLights != null && availableLights.Length > 0)
                            {
                                List <Light> lights = new List <Light>(availableLights);
                                for (int i = lights.Count - 1; i >= 0; --i)
                                {
                                    if (lights[i].name != internalLightName)
                                    {
                                        lights.RemoveAt(i);
                                    }
                                }
                                if (lights.Count > 0)
                                {
                                    lightObjects              = lights.ToArray();
                                    needsElectricChargeValue |= string.IsNullOrEmpty(needsElectricCharge) || needsElectricChargeValue;
                                }
                                else
                                {
                                    actionName = "dummy";
                                }
                            }
                        }
                        else
                        {
                            actionName = "dummy";
                        }
                        break;

                    case "plugin":
                        persistentVarName = string.Empty;
                        comp.UpdateDataRefreshRate(refreshRate);

                        foreach (ConfigNode node in GameDatabase.Instance.GetConfigNodes("PROP"))
                        {
                            if (node.GetValue("name") == internalProp.propName)
                            {
                                foreach (ConfigNode pluginConfig in node.GetNodes("MODULE")[moduleID].GetNodes("PLUGINACTION"))
                                {
                                    if (pluginConfig.HasValue("name") && pluginConfig.HasValue("actionMethod"))
                                    {
                                        string action = pluginConfig.GetValue("name").Trim() + ":" + pluginConfig.GetValue("actionMethod").Trim();
                                        actionHandler = (Action <bool>)comp.GetMethod(action, internalProp, typeof(Action <bool>));

                                        if (actionHandler == null)
                                        {
                                            JUtil.LogErrorMessage(this, "Failed to instantiate action handler {0}", action);
                                        }
                                        else
                                        {
                                            if (pluginConfig.HasValue("stateMethod"))
                                            {
                                                string state = pluginConfig.GetValue("name").Trim() + ":" + pluginConfig.GetValue("stateMethod").Trim();
                                                stateVariable = "PLUGIN_" + state;
                                            }
                                            else if (pluginConfig.HasValue("stateVariable"))
                                            {
                                                stateVariable = pluginConfig.GetValue("stateVariable").Trim();
                                            }
                                            isPluginAction = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if (actionHandler == null)
                        {
                            actionName = "dummy";
                            JUtil.LogMessage(this, "Plugin handlers did not start, reverting to dummy mode.");
                        }
                        break;

                    case "transfer":
                        persistentVarName = string.Empty;
                        comp.UpdateDataRefreshRate(refreshRate);

                        foreach (ConfigNode node in GameDatabase.Instance.GetConfigNodes("PROP"))
                        {
                            if (node.GetValue("name") == internalProp.propName)
                            {
                                foreach (ConfigNode pluginConfig in node.GetNodes("MODULE")[moduleID].GetNodes("TRANSFERACTION"))
                                {
                                    if ((pluginConfig.HasValue("name") || pluginConfig.HasValue("getVariable")) && pluginConfig.HasValue("perPodPersistenceName"))
                                    {
                                        transferPersistentName = pluginConfig.GetValue("perPodPersistenceName").Trim();
                                        if (pluginConfig.HasValue("stateMethod"))
                                        {
                                            string state = pluginConfig.GetValue("name").Trim() + ":" + pluginConfig.GetValue("stateMethod").Trim();
                                            stateVariable = "PLUGIN_" + state;
                                        }
                                        else if (pluginConfig.HasValue("stateVariable"))
                                        {
                                            stateVariable = pluginConfig.GetValue("stateVariable").Trim();
                                        }
                                        if (pluginConfig.HasValue("setMethod"))
                                        {
                                            string action = pluginConfig.GetValue("name").Trim() + ":" + pluginConfig.GetValue("setMethod").Trim();
                                            transferSetter = (Action <double>)comp.GetMethod(action, internalProp, typeof(Action <double>));

                                            if (transferSetter == null)
                                            {
                                                JUtil.LogErrorMessage(this, "Failed to instantiate transfer handler {0}", pluginConfig.GetValue("name"));
                                            }
                                            else
                                            {
                                                //JUtil.LogMessage(this, "Got setter {0}", action);
                                                break;
                                            }
                                        }
                                        else if (pluginConfig.HasValue("getMethod"))
                                        {
                                            string action = pluginConfig.GetValue("name").Trim() + ":" + pluginConfig.GetValue("getMethod").Trim();
                                            var    getter = (Func <double>)comp.GetMethod(action, internalProp, typeof(Func <double>));

                                            if (getter == null)
                                            {
                                                JUtil.LogErrorMessage(this, "Failed to instantiate transfer handler {0}", pluginConfig.GetValue("name"));
                                            }
                                            else
                                            {
                                                transferGetter = "PLUGIN_" + action;
                                                //JUtil.LogMessage(this, "Got getter {0}", action);
                                                break;
                                            }
                                        }
                                        else if (pluginConfig.HasValue("getVariable"))
                                        {
                                            transferGetter = pluginConfig.GetValue("getVariable").Trim();
                                        }
                                    }
                                }
                            }
                        }
                        if (string.IsNullOrEmpty(transferGetter) && transferSetter == null)
                        {
                            actionName    = "dummy";
                            stateVariable = string.Empty;
                            JUtil.LogMessage(this, "Transfer handlers did not start, reverting to dummy mode.");
                        }
                        break;

                    default:
                        persistentVarName = "switch" + internalProp.propID + "_" + moduleID;
                        break;
                    }
                    if (!string.IsNullOrEmpty(perPodPersistenceName))
                    {
                        persistentVarName = perPodPersistenceName;
                    }
                    else
                    {
                        // If there's no persistence name, there's no valid group id for this switch
                        switchGroupIdentifier = -1;
                    }
                }

                if (customGroupList.ContainsKey(actionName))
                {
                    customAction = customGroupList[actionName];
                }

                if (needsElectricChargeValue || !string.IsNullOrEmpty(persistentVarName) || !string.IsNullOrEmpty(perPodMasterSwitchName) || !string.IsNullOrEmpty(masterVariableName) ||
                    !string.IsNullOrEmpty(transferGetter) || transferSetter != null)
                {
                    rpmComp = RasterPropMonitorComputer.Instantiate(internalProp);

                    comp.UpdateDataRefreshRate(refreshRate);

                    if (!string.IsNullOrEmpty(masterVariableName))
                    {
                        string[] range = masterVariableRange.Split(',');
                        if (range.Length == 2)
                        {
                            masterVariable = new VariableOrNumberRange(masterVariableName, range[0], range[1]);
                        }
                        else
                        {
                            masterVariable = null;
                        }
                    }
                }

                // set up the toggle switch
                if (!string.IsNullOrEmpty(switchTransform))
                {
                    if (momentarySwitch)
                    {
                        SmarterButton.CreateButton(internalProp, switchTransform, Click, Click);
                    }
                    else
                    {
                        SmarterButton.CreateButton(internalProp, switchTransform, Click);
                    }
                }

                if (isCustomAction)
                {
                    if (isPluginAction && !string.IsNullOrEmpty(stateVariable))
                    {
                        try
                        {
                            currentState = (comp.ProcessVariable(stateVariable, -1).MassageToInt()) > 0;
                        }
                        catch
                        {
                            // no-op
                        }
                    }
                    else
                    {
                        if (rpmComp != null && !string.IsNullOrEmpty(persistentVarName))
                        {
                            if (switchGroupIdentifier >= 0)
                            {
                                int activeSwitch = rpmComp.GetVar(persistentVarName, 0);

                                currentState = customGroupState = (switchGroupIdentifier == activeSwitch);
                            }
                            else
                            {
                                currentState = customGroupState = rpmComp.GetBool(persistentVarName, initialState);
                            }

                            if (customAction == CustomActions.IntLight)
                            {
                                // We have to restore lighting after reading the
                                // persistent variable.
                                SetInternalLights(customGroupState);
                            }
                        }
                    }
                }

                if (rpmComp != null && !rpmComp.HasVar(persistentVarName))
                {
                    if (switchGroupIdentifier >= 0)
                    {
                        if (currentState)
                        {
                            rpmComp.SetVar(persistentVarName, switchGroupIdentifier);
                        }
                    }
                    else
                    {
                        rpmComp.SetVar(persistentVarName, currentState);
                    }
                }

                if (!string.IsNullOrEmpty(animationName))
                {
                    // Set up the animation
                    Animation[] animators = animateExterior ? part.FindModelAnimators(animationName) : internalProp.FindModelAnimators(animationName);
                    if (animators.Length > 0)
                    {
                        anim = animators[0];
                    }
                    else
                    {
                        JUtil.LogErrorMessage(this, "Could not find animation \"{0}\" on {2} \"{1}\"",
                                              animationName, animateExterior ? part.name : internalProp.name, animateExterior ? "part" : "prop");
                        return;
                    }
                    anim[animationName].wrapMode = WrapMode.Once;

                    if (currentState ^ reverse)
                    {
                        anim[animationName].speed          = float.MaxValue;
                        anim[animationName].normalizedTime = 0;
                    }
                    else
                    {
                        anim[animationName].speed          = float.MinValue;
                        anim[animationName].normalizedTime = 1;
                    }
                    anim.Play(animationName);
                }
                else if (!string.IsNullOrEmpty(coloredObject))
                {
                    // Set up the color shift.
                    Renderer colorShiftRenderer = internalProp.FindModelComponent <Renderer>(coloredObject);
                    disabledColorValue = ConfigNode.ParseColor32(disabledColor);
                    enabledColorValue  = ConfigNode.ParseColor32(enabledColor);
                    colorShiftMaterial = colorShiftRenderer.material;
                    colorShiftMaterial.SetColor(colorName, (currentState ^ reverse ? enabledColorValue : disabledColorValue));
                }
                else
                {
                    JUtil.LogMessage(this, "Warning, neither color nor animation are defined in prop {0} #{1} (this may be okay).", internalProp.propName, internalProp.propID);
                }

                audioOutput = JUtil.SetupIVASound(internalProp, switchSound, switchSoundVolume, false);

                if (!string.IsNullOrEmpty(loopingSound) && loopingSoundVolume > 0.0f)
                {
                    loopingOutput = JUtil.SetupIVASound(internalProp, loopingSound, loopingSoundVolume, true);
                }

                startupComplete = true;
            }
            catch
            {
                JUtil.AnnoyUser(this);
                enabled = false;
                throw;
            }
        }
Exemple #8
0
        /// <summary>
        /// Configure the switch.
        /// </summary>
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            if (string.IsNullOrEmpty(switchTransform))
            {
                throw new Exception("JSISwitch failed to configure: no switchTransform specified in prop " + internalProp.propName);
            }

            if (momentarySwitch)
            {
                SmarterButton.CreateButton(internalProp, switchTransform, Click, Click);
            }
            else
            {
                SmarterButton.CreateButton(internalProp, switchTransform, Click);
            }

            if (!string.IsNullOrEmpty(switchSound))
            {
                switchAudio = JUtil.SetupIVASound(internalProp, switchSound, switchSoundVolume, false);
            }

            if (!string.IsNullOrEmpty(animationName))
            {
                // Set up the animation
                Animation[] animators = internalProp.FindModelAnimators(animationName);
                //Animation[] animators = animateExterior ? part.FindModelAnimators(animationName) : internalProp.FindModelAnimators(animationName);
                if (animators.Length > 0)
                {
                    anim = animators[0];
                }
                else
                {
                    JUtil.LogErrorMessage(this, "Could not find animation \"{0}\" on {2} \"{1}\"",
                                          animationName, internalProp.name, "prop");
                    //JUtil.LogErrorMessage(this, "Could not find animation \"{0}\" on {2} \"{1}\"",
                    //    animationName, animateExterior ? part.name : internalProp.name, animateExterior ? "part" : "prop");
                    return;
                }
                anim[animationName].wrapMode = WrapMode.Once;

                if (currentState ^ reverse)
                {
                    anim[animationName].speed          = float.MaxValue;
                    anim[animationName].normalizedTime = 0.0f;
                }
                else
                {
                    anim[animationName].speed          = float.MinValue;
                    anim[animationName].normalizedTime = 1.0f;
                }
                anim.Play(animationName);
            }

            // Now parse consumeOnToggle and consumeWhileActive...
            if (!string.IsNullOrEmpty(consumeOnToggle))
            {
                string[] tokens = consumeOnToggle.Split(',');
                if (tokens.Length == 3)
                {
                    consumeOnToggleName = tokens[0].Trim();
                    if (!(PartResourceLibrary.Instance.GetDefinition(consumeOnToggleName) != null &&
                          float.TryParse(tokens[1].Trim(), NumberStyles.Any, CultureInfo.InvariantCulture,
                                         out consumeOnToggleAmount)))
                    {
                        JUtil.LogErrorMessage(this, "Could not parse \"{0}\"", consumeOnToggle);
                    }
                    switch (tokens[2].Trim().ToLower())
                    {
                    case "on":
                        consumingOnToggleUp = true;
                        break;

                    case "off":
                        consumingOnToggleDown = true;
                        break;

                    case "both":
                        consumingOnToggleUp   = true;
                        consumingOnToggleDown = true;
                        break;

                    default:
                        JUtil.LogErrorMessage(this, "So should I consume resources when turning on, turning off, or both in \"{0}\"?", consumeOnToggle);
                        break;
                    }
                }
            }

            if (!string.IsNullOrEmpty(consumeWhileActive))
            {
                string[] tokens = consumeWhileActive.Split(',');
                if (tokens.Length == 2)
                {
                    consumeWhileActiveName = tokens[0].Trim();
                    if (!(PartResourceLibrary.Instance.GetDefinition(consumeWhileActiveName) != null &&
                          float.TryParse(tokens[1].Trim(),
                                         NumberStyles.Any, CultureInfo.InvariantCulture,
                                         out consumeWhileActiveAmount)))
                    {
                        JUtil.LogErrorMessage(this, "Could not parse \"{0}\"", consumeWhileActive);
                    }
                    else
                    {
                        consumingWhileActive = true;
                        JUtil.LogMessage(this, "Switch in prop {0} prop id {1} will consume {2} while active at a rate of {3}", internalProp.propName,
                                         internalProp.propID, consumeWhileActiveName, consumeWhileActiveAmount);
                    }
                }
            }

            RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);

            comp.UpdateDataRefreshRate(refreshRate);

            if (!string.IsNullOrEmpty(masterVariableName))
            {
                string[] range = masterVariableRange.Split(',');
                if (range.Length == 2)
                {
                    masterVariable = new VariableOrNumberRange(masterVariableName, range[0], range[1]);
                }
                else
                {
                    masterVariable = null;
                }
            }

            ConfigNode[] nodes = GameDatabase.Instance.GetConfigNodes("PROP");
            for (int i = 0; i < nodes.Length; ++i)
            {
                if (nodes[i].GetValue("name") == internalProp.propName)
                {
                    ConfigNode[] pluginNodes = nodes[i].GetNodes("MODULE")[moduleID].GetNodes("ACTION");
                    for (int j = 0; j < pluginNodes.Length; ++j)
                    {
                        try
                        {
                            IJSIAction newAction = AddAction(pluginNodes[j]);
                            action.Add(newAction);
                            if (newAction.IsMasterAction && masterActionIndex == -1)
                            {
                                masterActionIndex = action.Count - 1;
                            }
                        }
                        catch (Exception e)
                        {
                            JUtil.LogErrorMessage(this, "Failed to create JSIAction: {0}", e);
                        }
                    }
                }
            }

            if (action.Count == 0)
            {
                JUtil.LogErrorMessage(this, "No actions were created for JSIAction in prop {0}", internalProp.propName);
                return;
            }

            if (masterActionIndex == -1)
            {
                masterActionIndex = 0;
            }
            JUtil.LogMessage(this, "Selected action {0} as the master action", masterActionIndex);

            startupComplete = true;
        }
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            try
            {
                ConfigNode moduleConfig = null;
                foreach (ConfigNode node in GameDatabase.Instance.GetConfigNodes("PROP"))
                {
                    if (node.GetValue("name") == internalProp.propName)
                    {
                        moduleConfig = node.GetNodes("MODULE")[moduleID];
                        ConfigNode[] variableNodes = moduleConfig.GetNodes("VARIABLESET");

                        for (int i = 0; i < variableNodes.Length; i++)
                        {
                            try
                            {
                                variableSets.Add(new VariableAnimationSet(variableNodes[i], internalProp));
                            }
                            catch (ArgumentException e)
                            {
                                JUtil.LogMessage(this, "Error in building prop number {1} - {0}", e.Message, internalProp.propID);
                            }
                        }
                        break;
                    }
                }

                // Fallback: If there are no VARIABLESET blocks, we treat the module configuration itself as a variableset block.
                if (variableSets.Count < 1 && moduleConfig != null)
                {
                    try
                    {
                        variableSets.Add(new VariableAnimationSet(moduleConfig, internalProp));
                    }
                    catch (ArgumentException e)
                    {
                        JUtil.LogMessage(this, "Error in building prop number {1} - {0}", e.Message, internalProp.propID);
                    }
                }
                if (JUtil.debugLoggingEnabled)
                {
                    JUtil.LogMessage(this, "Configuration complete in prop {1}, supporting {0} variable indicators.", variableSets.Count, internalProp.propID);
                }
                foreach (VariableAnimationSet thatSet in variableSets)
                {
                    alwaysActive |= thatSet.alwaysActive;
                }
                RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                comp.UpdateDataRefreshRate(refreshRate);
                persistence     = new PersistenceAccessor(internalProp);
                startupComplete = true;
            }
            catch
            {
                JUtil.AnnoyUser(this);
                enabled = false;
                throw;
            }
        }