Пример #1
0
        // Analysis disable once UnusedParameter
        public bool RenderGraphs(RenderTexture screen, float cameraAspect)
        {
            if (backgroundTexture != null)
            {
                Graphics.Blit(backgroundTexture, screen);
            }
            GL.Clear(true, (backgroundTexture == null), backgroundColorValue);

            if (!startupComplete)
            {
                JUtil.AnnoyUser(this);
            }

            GL.PushMatrix();
            // This way 0,0 is in bottom left corner, which is what we want this time.
            GL.LoadPixelMatrix(0, screen.width, 0, screen.height);
            double time = Planetarium.GetUniversalTime();

            foreach (GraphLine graph in graphs)
            {
                graph.Draw(graphSpace, time);
            }
            if (borders > 0)
            {
                GraphLine.DrawVector(borderVertices, borderColorValue);
            }

            GL.PopMatrix();
            return(true);
        }
 public void LateUpdate()
 {
     if (vessel != null && JUtil.VesselIsInIVA(vessel) && !startupComplete)
     {
         JUtil.AnnoyUser(this);
         enabled = false;
     }
 }
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }
            try
            {
                rpmComp = RasterPropMonitorComputer.Instantiate(internalProp, true);

                if (string.IsNullOrEmpty(layout))
                {
                    throw new ArgumentNullException("layout");
                }

                foreach (ConfigNode node in GameDatabase.Instance.GetConfigNodes("RPM_GRAPHING_BACKGROUND"))
                {
                    if (node.GetValue("layout") == layout)
                    {
                        if (!node.HasValue("backgroundColor"))
                        {
                            JUtil.LogErrorMessage(this, "?!? no backgroundColor");
                        }
                        string s = node.GetValue("backgroundColor");
                        if (string.IsNullOrEmpty(s))
                        {
                            JUtil.LogErrorMessage(this, "backgroundColor is missing?");
                        }
                        backgroundColorValue = ConfigNode.ParseColor32(node.GetValue("backgroundColor"));

                        ConfigNode[] dataNodes = node.GetNodes("DATA_SET");

                        for (int i = 0; i < dataNodes.Length; i++)
                        {
                            try
                            {
                                dataSets.Add(new DataSet(dataNodes[i], rpmComp));
                            }
                            catch (ArgumentException e)
                            {
                                JUtil.LogErrorMessage(this, "Error in building prop number {1} - {0}", e.Message, internalProp.propID);
                                throw;
                            }
                        }
                        break;
                    }
                }

                startupComplete = true;
            }

            catch
            {
                JUtil.AnnoyUser(this);
                throw;
            }
        }
Пример #4
0
 public void LateUpdate()
 {
     if (JUtil.IsActiveVessel(vessel) && !startupComplete)
     {
         JUtil.AnnoyUser(this);
         // And disable ourselves.
         enabled = false;
     }
 }
        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)
                    {
                        if (string.IsNullOrEmpty(variableName))
                        {
                            JUtil.LogErrorMessage(this, "Configuration failed in prop {0} ({1}), no variableName.", internalProp.propID, internalProp.propName);
                            throw new ArgumentNullException();
                        }

                        moduleConfig = node.GetNodes("MODULE")[moduleID];
                        ConfigNode[] variableNodes = moduleConfig.GetNodes("VARIABLESET");

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


                RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                del = (Action <RPMVesselComputer, float>)Delegate.CreateDelegate(typeof(Action <RPMVesselComputer, float>), this, "OnCallback");
                float value = comp.ProcessVariable(variableName).MassageToFloat();
                for (int i = 0; i < variableSets.Count; ++i)
                {
                    variableSets[i].Update(comp, value);
                }
                comp.RegisterCallback(variableName, del);
                JUtil.LogMessage(this, "Configuration complete in prop {1} ({2}), supporting {0} callback animators.", variableSets.Count, internalProp.propID, internalProp.propName);
            }
            catch
            {
                JUtil.AnnoyUser(this);
                enabled = false;
                throw;
            }
        }
Пример #6
0
        /// <summary>
        /// Update the text mesh if it's changed.
        /// </summary>
        public void Update()
        {
            if (!string.IsNullOrEmpty(text_))
            {
                if (invalidated)
                {
                    if (font_ == null)
                    {
                        if (!fontNag)
                        {
                            JUtil.LogErrorMessage(this, "Font was not initialized");
                            JUtil.AnnoyUser(this);
                            fontNag = true;
                        }
                        return;
                    }

                    if (text_.Contains("["))
                    {
                        richText = true;
                        GenerateRichText();
                    }
                    else
                    {
                        richText = false;
                        GenerateText();
                    }

                    invalidated      = false;
                    invalidatedColor = false;
                }
                else if (invalidatedColor)
                {
                    if (richText)
                    {
                        GenerateRichText();
                    }
                    else
                    {
                        if (meshFilter_.mesh.colors32.Length > 0)
                        {
                            Color32[] newColor = new Color32[meshFilter_.mesh.colors32.Length];
                            for (int idx = 0; idx < newColor.Length; ++idx)
                            {
                                newColor[idx] = color_;
                            }
                            meshFilter_.mesh.colors32 = newColor;
                            meshFilter_.mesh.UploadMeshData(false);
                        }
                    }

                    invalidatedColor = false;
                }
            }
        }
Пример #7
0
        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);
                    }
                }
                JUtil.LogMessage(this, "Configuration complete in prop {1}, supporting {0} variable indicators.", variableSets.Count, internalProp.propID);
                foreach (VariableAnimationSet thatSet in variableSets)
                {
                    alwaysActive |= thatSet.alwaysActive;
                }
                startupComplete = true;
            } catch {
                JUtil.AnnoyUser(this);
                enabled = false;
                throw;
            }
        }
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }
            try
            {
                backgroundColorValue = ConfigNode.ParseColor32(backgroundColor);

                cameraBody                 = new GameObject();
                cameraBody.name            = "RPMPFD" + cameraBody.GetInstanceID();
                cameraBody.layer           = drawingLayer;
                hudCamera                  = cameraBody.AddComponent <Camera>();
                hudCamera.enabled          = false;
                hudCamera.orthographic     = true;
                hudCamera.eventMask        = 0;
                hudCamera.farClipPlane     = 3f;
                hudCamera.orthographicSize = 1.0f;
                hudCamera.cullingMask      = 1 << drawingLayer;
                // does this actually work?
                hudCamera.backgroundColor      = backgroundColorValue;
                hudCamera.clearFlags           = CameraClearFlags.Depth | CameraClearFlags.Color;
                hudCamera.transparencySortMode = TransparencySortMode.Orthographic;
                hudCamera.transform.position   = Vector3.zero;
                hudCamera.transform.LookAt(new Vector3(0.0f, 0.0f, 1.5f), Vector3.up);

                if (!string.IsNullOrEmpty(progradeColor))
                {
                    progradeColorValue = ConfigNode.ParseColor32(progradeColor);
                }

                persistence = new PersistenceAccessor(internalProp);
            }
            catch (Exception e)
            {
                JUtil.LogErrorMessage(this, "Start() failed with an exception: {0}", e);
                JUtil.AnnoyUser(this);
                throw;
            }

            startupComplete = true;
        }
Пример #9
0
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            try
            {
                rpmComp = RasterPropMonitorComputer.Instantiate(internalProp, true);

                if (lineMaterial == null)
                {
                    lineMaterial = JUtil.DrawLineMaterial();
                }

                if (!string.IsNullOrEmpty(borderColor))
                {
                    borderColorValue = ConfigNode.ParseColor32(borderColor);
                }
                if (!string.IsNullOrEmpty(backgroundColor))
                {
                    backgroundColorValue = ConfigNode.ParseColor32(backgroundColor);
                }

                //comp = RasterPropMonitorComputer.Instantiate(internalProp);
                graphSpace      = new Rect();
                graphSpace.xMin = graphRect.x;
                graphSpace.yMin = graphRect.y;
                graphSpace.xMax = graphRect.z;
                graphSpace.yMax = graphRect.w;
                xGraphSpan      = xSpan;
                interval        = secondsBetweenSamples;
                if (GameDatabase.Instance.ExistsTexture(backgroundTextureURL.EnforceSlashes()))
                {
                    backgroundTexture = GameDatabase.Instance.GetTexture(backgroundTextureURL.EnforceSlashes(), false);
                }

                var bottomLeft  = new Vector2(graphSpace.xMin, graphSpace.yMin);
                var bottomRight = new Vector2(graphSpace.xMax, graphSpace.yMin);
                var topLeft     = new Vector2(graphSpace.xMin, graphSpace.yMax);
                var topRight    = new Vector2(graphSpace.xMax, graphSpace.yMax);


                switch (borders)
                {
                case 2:
                    borderVertices.Add(bottomRight);
                    borderVertices.Add(bottomLeft);
                    borderVertices.Add(topLeft);
                    break;

                case 4:
                    borderVertices.Add(bottomLeft);
                    borderVertices.Add(topLeft);
                    borderVertices.Add(topRight);
                    borderVertices.Add(bottomRight);
                    borderVertices.Add(bottomLeft);
                    break;
                }

                foreach (ConfigNode node in GameDatabase.Instance.GetConfigNodes("JSIGRAPHSET"))
                {
                    if (node.HasValue("name") && node.GetValue("name") == graphSet)
                    {
                        foreach (ConfigNode graphNode in node.GetNodes("GRAPH"))
                        {
                            graphs.Add(new GraphLine(graphNode, rpmComp, xGraphSpan, ySpan, interval));
                        }
                    }
                }
                JUtil.LogMessage(this, "Graphing {0} values.", graphs.Count);
                startupComplete = true;
            }
            catch
            {
                JUtil.AnnoyUser(this);
                throw;
            }
        }
Пример #10
0
        public void Start()
        {
            // Skip the entire sequence when in editor -- this means we're part of a transparent pod and won't get used anyway.
            if (HighLogic.LoadedSceneIsEditor)
            {
                iconMaterial       = new Material(Shader.Find("KSP/Alpha/Unlit Transparent"));
                iconMaterial.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);
                startupComplete    = true;
                return;
            }

            try {
                if (!string.IsNullOrEmpty(backgroundColor))
                {
                    backgroundColorValue = ConfigNode.ParseColor32(backgroundColor);
                }
                if (!string.IsNullOrEmpty(iconColorSelf))
                {
                    iconColorSelfValue = ConfigNode.ParseColor32(iconColorSelf);
                }
                if (!string.IsNullOrEmpty(orbitColorSelf))
                {
                    orbitColorSelfValue = ConfigNode.ParseColor32(orbitColorSelf);
                }
                else
                {
                    orbitColorSelfValue = MapView.PatchColors[0];
                }
                if (!string.IsNullOrEmpty(iconColorTarget))
                {
                    iconColorTargetValue = ConfigNode.ParseColor32(iconColorTarget);
                }
                if (!string.IsNullOrEmpty(iconColorShadow))
                {
                    iconColorShadowValue = ConfigNode.ParseColor32(iconColorShadow);
                }
                if (!string.IsNullOrEmpty(iconColorAP))
                {
                    iconColorAPValue = ConfigNode.ParseColor32(iconColorAP);
                }
                else
                {
                    iconColorAPValue = MapView.PatchColors[0];
                }
                if (!string.IsNullOrEmpty(iconColorPE))
                {
                    iconColorPEValue = ConfigNode.ParseColor32(iconColorPE);
                }
                else
                {
                    iconColorPEValue = MapView.PatchColors[0];
                }
                if (!string.IsNullOrEmpty(orbitColorNextNode))
                {
                    orbitColorNextNodeValue = ConfigNode.ParseColor32(orbitColorNextNode);
                }
                else
                {
                    orbitColorNextNodeValue = MapView.PatchColors[1];
                }
                if (!string.IsNullOrEmpty(iconColorClosestApproach))
                {
                    iconColorClosestApproachValue = ConfigNode.ParseColor32(iconColorClosestApproach);
                }

                // This mess with shaders has to stop. Maybe we should have a single shader to draw EVERYTHING on the screen...
                iconMaterial       = new Material(Shader.Find("KSP/Alpha/Unlit Transparent"));
                iconMaterial.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);

                startupComplete = true;
            } catch {
                JUtil.AnnoyUser(this);
                throw;
            }
        }
Пример #11
0
        public void Start()
        {
            try {
                comp             = RasterPropMonitorComputer.Instantiate(internalProp);
                textObjTransform = internalProp.FindModelTransform(labelTransform);
                textObj          = InternalComponents.Instance.CreateText(fontName, fontSize, textObjTransform, string.Empty);
                activeLabel      = 0;

                SmarterButton.CreateButton(internalProp, switchTransform, Click);

                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 {
                                labelsEx.Add(new VariableLabelSet(variableNodes[i]));
                            } 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 (labelsEx.Count < 1 && moduleConfig != null)
                {
                    try {
                        labelsEx.Add(new VariableLabelSet(moduleConfig));
                    } catch (ArgumentException e) {
                        JUtil.LogMessage(this, "Error in building prop number {1} - {0}", e.Message, internalProp.propID);
                    }
                }

                if (labelsEx.Count == 0)
                {
                    JUtil.LogMessage(this, "No labels defined.");
                    throw new ArgumentException("No labels defined");
                }

                colorShiftRenderer = internalProp.FindModelComponent <Renderer>(coloredObject);
                if (labelsEx[activeLabel].hasColor)
                {
                    colorShiftRenderer.material.SetColor(colorName, labelsEx[activeLabel].color);
                }
                if (labelsEx[activeLabel].hasText)
                {
                    textObj.text.Text = StringProcessor.ProcessString(labelsEx[activeLabel].labelText, comp);
                }

                audioOutput = JUtil.SetupIVASound(internalProp, switchSound, switchSoundVolume, false);
                JUtil.LogMessage(this, "Configuration complete in prop {1}, supporting {0} variable indicators.", labelsEx.Count, internalProp.propID);
            } catch {
                JUtil.AnnoyUser(this);
                enabled = false;
                throw;
            }
        }
Пример #12
0
        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
            {
                rpmComp = RasterPropMonitorComputer.Instantiate(internalProp, true);
                JUtil.LogMessage(this, "Attaching monitor {2}-{1} to {0}", rpmComp.RPMCid, internalProp.propID, internalProp.internalModel.internalName);

                // Install the calculator module.
                rpmComp.UpdateDataRefreshRate(refreshDataRate);

                // 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).GetComponent <Renderer>().material;

                bool manuallyInvertY = false;
                if (SystemInfo.graphicsDeviceVersion.StartsWith("Direct3D 9") || SystemInfo.graphicsDeviceVersion.StartsWith("Direct3D 11") || SystemInfo.graphicsDeviceVersion.StartsWith("Direct3D 12"))
                {
                    manuallyInvertY = (UnityEngine.QualitySettings.antiAliasing > 0);
                }

                foreach (string layerID in textureLayerID.Split())
                {
                    screenMat.SetTexture(layerID.Trim(), screenTexture);
                    // This code was written for a much older flavor of Unity, and the Unity 2017.1 update broke
                    // some assumptions about who managed the y-inversion issue between OpenGL and DX9.
                    if (manuallyInvertY)
                    {
                        screenMat.SetTextureScale(layerID.Trim(), new Vector2(1.0f, -1.0f));
                        screenMat.SetTextureOffset(layerID.Trim(), new Vector2(0.0f, 1.0f));
                    }
                }

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

                // 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 = rpmComp.GetPersistentVariable(persistentVarName, pages.Count, false).MassageToInt();
                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);

                if (needsElectricCharge)
                {
                    delResourceCallback = (Action <bool>)Delegate.CreateDelegate(typeof(Action <bool>), this, "ResourceDepletedCallback");
                    rpmComp.RegisterResourceCallback(resourceName, delResourceCallback);
                }

                if (needsCommConnection)
                {
                    delCommConnectionCallback = (Action <float>)Delegate.CreateDelegate(typeof(Action <float>), this, "CommConnectionCallback");
                    rpmComp.RegisterVariableCallback("COMMNETVESSELCONTROLSTATE", delCommConnectionCallback);
                }

                // And if the try block never completed, startupComplete will never be true.
                startupComplete = true;
            }
            catch
            {
                JUtil.AnnoyUser(this);
                // 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;
            }
        }
Пример #13
0
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            try
            {
                if (!string.IsNullOrEmpty(odometerMode) && modeList.ContainsKey(odometerMode))
                {
                    oMode = modeList[odometerMode];
                }
                //else if (!string.IsNullOrEmpty(odometerMode)) {
                //	JUtil.LogMessage(this, "found odometerMode {0}, but it's not in the dictionary", odometerMode);
                //}
                //else {
                //	JUtil.LogMessage(this, "Did not find odometerMode");
                //}

                if (string.IsNullOrEmpty(characterTexture) && oMode == OdometerMode.SI)
                {
                    JUtil.LogErrorMessage(this, "Prop configured as SI scaled, but there is no characterTexture");
                    return;
                }

                if (string.IsNullOrEmpty(digitTexture))
                {
                    // We can't do anything without the digit texture
                    JUtil.LogErrorMessage(this, "Prop can not function without a digitTexture");
                    return;
                }

                digitTex = GameDatabase.Instance.GetTexture(digitTexture.EnforceSlashes(), false);
                if (digitTex == null)
                {
                    JUtil.LogErrorMessage(this, "Failed to load digitTexture {0}", digitTexture);
                    return;
                }

                if (!string.IsNullOrEmpty(characterTexture))
                {
                    characterTex = GameDatabase.Instance.GetTexture(characterTexture.EnforceSlashes(), false);
                    if (characterTex == null)
                    {
                        JUtil.LogErrorMessage(this, "Failed to load characterTexture {0}", characterTexture);
                        return;
                    }
                }

                if (!string.IsNullOrEmpty(overlayTexture))
                {
                    overlayTex = GameDatabase.Instance.GetTexture(overlayTexture.EnforceSlashes(), false);
                    if (overlayTex == null)
                    {
                        JUtil.LogErrorMessage(this, "Failed to load overlayTexture {0}", overlayTexture);
                        return;
                    }
                }

                if (string.IsNullOrEmpty(altVariable) != string.IsNullOrEmpty(perPodPersistenceName))
                {
                    JUtil.LogErrorMessage(this, "Both altVariable and perPodPeristenceName must be defined, or neither");
                    return;
                }

                // MOARdV: Which one are we using?  HUD uses the latter, OrbitDisplay, the former.
                Shader unlit = Shader.Find("KSP/Alpha/Unlit Transparent");
                //Shader unlit = Shader.Find("Hidden/Internal-GUITexture");
                digitMaterial = new Material(unlit);

                rpmComp = RasterPropMonitorComputer.Instantiate(internalProp);

                backgroundColorValue = ConfigNode.ParseColor32(backgroundColor);

                lastUpdate = Planetarium.GetUniversalTime();

                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);
                }

                startupComplete = true;
            }
            catch
            {
                JUtil.AnnoyUser(this);
                throw;
            }
        }
Пример #14
0
        // Analysis disable once UnusedParameter
        public bool RenderOrbit(RenderTexture screen, float cameraAspect)
        {
            if (!startupComplete)
            {
                JUtil.AnnoyUser(this);
            }

            // Make sure the parameters fit on the screen.
            Vector4 displayPosition = orbitDisplayPosition;

            displayPosition.z = Mathf.Min(screen.width - displayPosition.x, displayPosition.z);
            displayPosition.w = Mathf.Min(screen.height - displayPosition.y, displayPosition.w);

            // Here is our pixel budget in each direction:
            double horizPixelSize = displayPosition.z - iconPixelSize;
            double vertPixelSize  = displayPosition.w - iconPixelSize;

            // Find a basis for transforming values into the framework of
            // vessel.orbit.  The rendering framework assumes the periapsis
            // is drawn directly to the right of the mainBody center of mass.
            // It assumes the orbit's prograde direction is "up" (screen
            // relative) at the periapsis, providing a counter-clockwise
            // motion for vessel.
            // Once we have the basic transform, we will add in scalars
            // that will ultimately transform an arbitrary point (relative to
            // the planet's center) into screen space.
            Matrix4x4 screenTransform = Matrix4x4.identity;
            double    now             = Planetarium.GetUniversalTime();
            double    timeAtPe        = vessel.orbit.NextPeriapsisTime(now);

            // Get the 3 direction vectors, based on Pe being on the right of the screen
            // OrbitExtensions provides handy utilities to get these.
            Vector3d right   = vessel.orbit.Up(timeAtPe);
            Vector3d forward = vessel.orbit.SwappedOrbitNormal();
            // MOARdV: OrbitExtensions.Horizontal is unstable.  I've seen it
            // become (0, 0, 0) intermittently in flight.  Instead, use the
            // cross product of the other two.
            // We flip the sign of this vector because we are using an inverted
            // y coordinate system to keep the icons right-side up.
            Vector3d up = -Vector3d.Cross(forward, right);

            //Vector3d up = -vessel.orbit.Horizontal(timeAtPe);

            screenTransform.SetRow(0, new Vector4d(right.x, right.y, right.z, 0.0));
            screenTransform.SetRow(1, new Vector4d(up.x, up.y, up.z, 0.0));
            screenTransform.SetRow(2, new Vector4d(forward.x, forward.y, forward.z, 0.0));

            // Figure out our bounds.  First, make sure the entire planet
            // fits on the screen.  We define the center of the vessel.mainBody
            // as the origin of our coodinate system.
            double maxX = vessel.mainBody.Radius;
            double minX = -maxX;
            double maxY = maxX;
            double minY = -maxX;

            if (vessel.mainBody.atmosphere)
            {
                maxX += vessel.mainBody.maxAtmosphereAltitude;
                minX  = -maxX;
                maxY  = maxX;
                minY  = -maxX;
            }

            // Now make sure the entire orbit fits on the screen.
            Vector3 vesselPos;

            // The PeR, ApR, and semiMinorAxis are all one dimensional, so we
            // can just apply them directly to these values.
            maxX = Math.Max(maxX, vessel.orbit.PeR);
            if (vessel.orbit.eccentricity < 1.0)
            {
                minX = Math.Min(minX, -vessel.orbit.ApR);

                maxY = Math.Max(maxY, vessel.orbit.semiMinorAxis);
                minY = Math.Min(minY, -vessel.orbit.semiMinorAxis);
            }
            else if (vessel.orbit.EndUT > 0.0)
            {
                // If we're hyperbolic, let's get the SoI transition
                vesselPos = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(vessel.orbit.EndUT));
                maxX      = Math.Max(maxX, vesselPos.x);
                minX      = Math.Min(minX, vesselPos.x);
                maxY      = Math.Max(maxY, vesselPos.y);
                minY      = Math.Min(minY, vesselPos.y);
            }

            // Make sure the vessel shows up on-screen.  Since a hyperbolic
            // orbit doesn't have a meaningful ApR, we use this as a proxy for
            // how far we need to extend the bounds to show the vessel.
            vesselPos = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(now));
            maxX      = Math.Max(maxX, vesselPos.x);
            minX      = Math.Min(minX, vesselPos.x);
            maxY      = Math.Max(maxY, vesselPos.y);
            minY      = Math.Min(minY, vesselPos.y);

            // Account for a target vessel
            var targetBody   = FlightGlobals.fetch.VesselTarget as CelestialBody;
            var targetVessel = FlightGlobals.fetch.VesselTarget as Vessel;

            if (targetVessel != null)
            {
                if (targetVessel.mainBody == vessel.mainBody)
                {
                    double tgtPe = targetVessel.orbit.NextPeriapsisTime(now);

                    vesselPos = screenTransform.MultiplyPoint3x4(targetVessel.orbit.SwappedRelativePositionAtUT(tgtPe));
                    maxX      = Math.Max(maxX, vesselPos.x);
                    minX      = Math.Min(minX, vesselPos.x);
                    maxY      = Math.Max(maxY, vesselPos.y);
                    minY      = Math.Min(minY, vesselPos.y);

                    if (targetVessel.orbit.eccentricity < 1.0)
                    {
                        vesselPos = screenTransform.MultiplyPoint3x4(targetVessel.orbit.SwappedRelativePositionAtUT(targetVessel.orbit.NextApoapsisTime(now)));
                        maxX      = Math.Max(maxX, vesselPos.x);
                        minX      = Math.Min(minX, vesselPos.x);
                        maxY      = Math.Max(maxY, vesselPos.y);
                        minY      = Math.Min(minY, vesselPos.y);
                    }

                    vesselPos = screenTransform.MultiplyPoint3x4(targetVessel.orbit.SwappedRelativePositionAtUT(now));
                    maxX      = Math.Max(maxX, vesselPos.x);
                    minX      = Math.Min(minX, vesselPos.x);
                    maxY      = Math.Max(maxY, vesselPos.y);
                    minY      = Math.Min(minY, vesselPos.y);
                }
                else
                {
                    // We only care about tgtVessel if it is in the same SoI.
                    targetVessel = null;
                }
            }

            if (targetBody != null)
            {
                // Validate some values up front, so we don't need to test them later.
                if (targetBody.GetOrbit() == null)
                {
                    targetBody = null;
                }
                else if (targetBody.orbit.referenceBody == vessel.orbit.referenceBody)
                {
                    // If the target body orbits our current world, let's at
                    // least make sure the body's location is visible.
                    vesselPos = screenTransform.MultiplyPoint3x4(targetBody.GetOrbit().SwappedRelativePositionAtUT(now));
                    maxX      = Math.Max(maxX, vesselPos.x);
                    minX      = Math.Min(minX, vesselPos.x);
                    maxY      = Math.Max(maxY, vesselPos.y);
                    minY      = Math.Min(minY, vesselPos.y);
                }
            }

            ManeuverNode node = (vessel.patchedConicSolver.maneuverNodes.Count > 0) ? vessel.patchedConicSolver.maneuverNodes[0] : null;

            if (node != null)
            {
                double nodePe = node.nextPatch.NextPeriapsisTime(now);
                vesselPos = screenTransform.MultiplyPoint3x4(node.nextPatch.SwappedRelativePositionAtUT(nodePe));
                maxX      = Math.Max(maxX, vesselPos.x);
                minX      = Math.Min(minX, vesselPos.x);
                maxY      = Math.Max(maxY, vesselPos.y);
                minY      = Math.Min(minY, vesselPos.y);

                if (node.nextPatch.eccentricity < 1.0)
                {
                    double nodeAp = node.nextPatch.NextApoapsisTime(now);
                    vesselPos = screenTransform.MultiplyPoint3x4(node.nextPatch.SwappedRelativePositionAtUT(nodeAp));
                    maxX      = Math.Max(maxX, vesselPos.x);
                    minX      = Math.Min(minX, vesselPos.x);
                    maxY      = Math.Max(maxY, vesselPos.y);
                    minY      = Math.Min(minY, vesselPos.y);
                }
                else if (node.nextPatch.EndUT > 0.0)
                {
                    // If the next patch is hyperbolic, include the endpoint.
                    vesselPos = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(node.nextPatch.EndUT));
                    maxX      = Math.Max(maxX, vesselPos.x);
                    minX      = Math.Min(minX, vesselPos.x);
                    maxY      = Math.Max(maxY, vesselPos.y);
                    minY      = Math.Min(minY, vesselPos.y);
                }
            }

            // Add translation.  This will ensure that all of the features
            // under consideration above will be displayed.
            screenTransform[0, 3] = -0.5f * (float)(maxX + minX);
            screenTransform[1, 3] = -0.5f * (float)(maxY + minY);

            double neededWidth  = maxX - minX;
            double neededHeight = maxY - minY;

            // Pick a scalar that will fit the bounding box we just created.
            float pixelScalar = (float)Math.Min(horizPixelSize / neededWidth, vertPixelSize / neededHeight);

            screenTransform = Matrix4x4.Scale(new Vector3(pixelScalar, pixelScalar, pixelScalar)) * screenTransform;

            GL.Clear(true, true, backgroundColorValue);
            GL.PushMatrix();
            GL.LoadPixelMatrix(-displayPosition.z * 0.5f, displayPosition.z * 0.5f, displayPosition.w * 0.5f, -displayPosition.w * 0.5f);
            GL.Viewport(new Rect(displayPosition.x, screen.height - displayPosition.y - displayPosition.w, displayPosition.z, displayPosition.w));

            lineMaterial.SetPass(0);
            GL.Begin(GL.LINES);

            // Draw the planet:
            Vector3 focusCenter = screenTransform.MultiplyPoint3x4(new Vector3(0.0f, 0.0f, 0.0f));

            // orbitDriver is null on the sun, so we'll just use white instead.
            GL.Color((vessel.mainBody.orbitDriver == null) ? new Color(1.0f, 1.0f, 1.0f) : vessel.mainBody.orbitDriver.orbitColor);
            DrawCircle(focusCenter.x, focusCenter.y, (float)(vessel.mainBody.Radius * pixelScalar), orbitPoints);
            if (vessel.mainBody.atmosphere)
            {
                // Use the atmospheric ambient to color the atmosphere circle.
                GL.Color(vessel.mainBody.atmosphericAmbientColor);

                DrawCircle(focusCenter.x, focusCenter.y, (float)((vessel.mainBody.Radius + vessel.mainBody.maxAtmosphereAltitude) * pixelScalar), orbitPoints);
            }

            if (targetVessel != null)
            {
                GL.Color(iconColorTargetValue);
                if (!targetVessel.orbit.activePatch && targetVessel.orbit.eccentricity < 1.0 && targetVessel.orbit.referenceBody == vessel.orbit.referenceBody)
                {
                    // For some reason, activePatch is false for targetVessel.
                    // If we have a stable orbit for the target, use a fallback
                    // rendering method:
                    ReallyDrawOrbit(targetVessel.orbit, vessel.orbit.referenceBody, screenTransform, orbitPoints);
                }
                else
                {
                    DrawOrbit(targetVessel.orbit, vessel.orbit.referenceBody, screenTransform, orbitPoints);
                }
            }

            foreach (CelestialBody moon in vessel.orbit.referenceBody.orbitingBodies)
            {
                if (moon != targetBody)
                {
                    GL.Color(moon.orbitDriver.orbitColor);
                    ReallyDrawOrbit(moon.GetOrbit(), vessel.orbit.referenceBody, screenTransform, orbitPoints);
                }
            }

            if (targetBody != null)
            {
                GL.Color(iconColorTargetValue);
                ReallyDrawOrbit(targetBody.GetOrbit(), vessel.orbit.referenceBody, screenTransform, orbitPoints);
            }

            if (node != null)
            {
                GL.Color(orbitColorNextNodeValue);
                DrawOrbit(node.nextPatch, vessel.orbit.referenceBody, screenTransform, orbitPoints);
            }

            if (vessel.orbit.nextPatch != null && vessel.orbit.nextPatch.activePatch)
            {
                GL.Color(orbitColorNextNodeValue);
                DrawOrbit(vessel.orbit.nextPatch, vessel.orbit.referenceBody, screenTransform, orbitPoints);
            }

            // Draw the vessel orbit
            GL.Color(orbitColorSelfValue);
            DrawOrbit(vessel.orbit, vessel.orbit.referenceBody, screenTransform, orbitPoints);

            // Done drawing lines.
            GL.End();

            // Draw target vessel icons.
            Vector3 transformedPosition;

            foreach (CelestialBody moon in vessel.orbit.referenceBody.orbitingBodies)
            {
                if (moon != targetBody)
                {
                    transformedPosition = screenTransform.MultiplyPoint3x4(moon.getTruePositionAtUT(now) - vessel.orbit.referenceBody.getTruePositionAtUT(now));
                    DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, moon.orbitDriver.orbitColor, MapIcons.OtherIcon.PLANET);
                }
            }

            if (targetVessel != null || targetBody != null)
            {
                var orbit = (targetVessel != null) ? targetVessel.GetOrbit() : targetBody.GetOrbit();
                DrawNextPe(orbit, vessel.orbit.referenceBody, now, iconColorTargetValue, screenTransform);

                DrawNextAp(orbit, vessel.orbit.referenceBody, now, iconColorTargetValue, screenTransform);

                if (targetBody != null)
                {
                    transformedPosition = screenTransform.MultiplyPoint3x4(targetBody.getTruePositionAtUT(now) - vessel.orbit.referenceBody.getTruePositionAtUT(now));
                    DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, iconColorTargetValue, MapIcons.OtherIcon.PLANET);
                }
                else
                {
                    transformedPosition = screenTransform.MultiplyPoint3x4(orbit.SwappedRelativePositionAtUT(now));
                    DrawIcon(transformedPosition.x, transformedPosition.y, targetVessel.vesselType, iconColorTargetValue);
                }

                if (vessel.orbit.AscendingNodeExists(orbit))
                {
                    double anTime = vessel.orbit.TimeOfAscendingNode(orbit, now);
                    if (anTime < vessel.orbit.EndUT || (vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ESCAPE && vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ENCOUNTER))
                    {
                        transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(anTime));
                        DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorSelfValue, MapIcons.OtherIcon.AN);
                    }
                }
                if (vessel.orbit.DescendingNodeExists(orbit))
                {
                    double dnTime = vessel.orbit.TimeOfDescendingNode(orbit, now);
                    if (dnTime < vessel.orbit.EndUT || (vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ESCAPE && vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ENCOUNTER))
                    {
                        transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(dnTime));
                        DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorSelfValue, MapIcons.OtherIcon.DN);
                    }
                }

                double tClosestApproach;
                double dClosestApproach = JUtil.GetClosestApproach(vessel.orbit, orbit, out tClosestApproach);
                Orbit  o = GetPatchAtUT(vessel.orbit, tClosestApproach);
                if (o != null)
                {
                    Vector3d encounterPosition = o.SwappedRelativePositionAtUT(tClosestApproach) + o.referenceBody.getTruePositionAtUT(tClosestApproach) - vessel.orbit.referenceBody.getTruePositionAtUT(tClosestApproach);
                    transformedPosition = screenTransform.MultiplyPoint3x4(encounterPosition);
                    DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, iconColorClosestApproachValue, MapIcons.OtherIcon.SHIPATINTERCEPT);
                }

                // Unconditionally try to draw the closest approach point on
                // the target orbit.
                transformedPosition = screenTransform.MultiplyPoint3x4(orbit.SwappedRelativePositionAtUT(tClosestApproach));
                DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, iconColorClosestApproachValue, MapIcons.OtherIcon.TGTATINTERCEPT);
            }
            else
            {
                if (vessel.orbit.AscendingNodeEquatorialExists())
                {
                    double anTime = vessel.orbit.TimeOfAscendingNodeEquatorial(now);
                    if (anTime < vessel.orbit.EndUT || (vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ESCAPE && vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ENCOUNTER))
                    {
                        transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(anTime));
                        DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorSelfValue, MapIcons.OtherIcon.AN);
                    }
                }
                if (vessel.orbit.DescendingNodeEquatorialExists())
                {
                    double dnTime = vessel.orbit.TimeOfDescendingNodeEquatorial(now);
                    if (dnTime < vessel.orbit.EndUT || (vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ESCAPE && vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ENCOUNTER))
                    {
                        transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(dnTime));
                        DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorSelfValue, MapIcons.OtherIcon.DN);
                    }
                }
            }

            // Draw orbital features
            DrawNextPe(vessel.orbit, vessel.orbit.referenceBody, now, iconColorPEValue, screenTransform);

            DrawNextAp(vessel.orbit, vessel.orbit.referenceBody, now, iconColorAPValue, screenTransform);

            if (vessel.orbit.nextPatch != null && vessel.orbit.nextPatch.activePatch)
            {
                transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(vessel.orbit.EndUT));
                DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorSelfValue, MapIcons.OtherIcon.EXITSOI);

                Orbit nextPatch = vessel.orbit.nextPatch.nextPatch;
                if (nextPatch != null && nextPatch.activePatch)
                {
                    transformedPosition = screenTransform.MultiplyPoint3x4(nextPatch.SwappedRelativePositionAtUT(nextPatch.EndUT) + nextPatch.referenceBody.getTruePositionAtUT(nextPatch.EndUT) - vessel.orbit.referenceBody.getTruePositionAtUT(nextPatch.EndUT));
                    DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorNextNodeValue, MapIcons.OtherIcon.EXITSOI);
                }
            }

            if (node != null && node.nextPatch.activePatch)
            {
                DrawNextPe(node.nextPatch, vessel.orbit.referenceBody, now, orbitColorNextNodeValue, screenTransform);

                DrawNextAp(node.nextPatch, vessel.orbit.referenceBody, now, orbitColorNextNodeValue, screenTransform);

                transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(node.UT));
                DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorNextNodeValue, MapIcons.OtherIcon.NODE);
            }

            // Draw ownship icon
            transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(now));
            DrawIcon(transformedPosition.x, transformedPosition.y, vessel.vesselType, iconColorSelfValue);

            GL.PopMatrix();
            GL.Viewport(new Rect(0, 0, screen.width, screen.height));

            return(true);
        }
Пример #15
0
        // This is honestly very badly written code, probably the worst of what I have in this project.
        // Much of it dictated by the fact that I barely, if at all, understand what am I doing in vector mathematics,
        // the rest is because the problem is all built out of special cases.
        // Sorry. :)
        public bool RenderPFD(RenderTexture screen, float aspect)
        {
            if (screen == null)
            {
                return(false);
            }

            if (!startupComplete)
            {
                JUtil.AnnoyUser(this);
            }

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

            ballCamera.targetTexture = screen;


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

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

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

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

            Quaternion gymbal = stockNavBall.attitudeGymbal;

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

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

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

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

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

            ITargetable target = FlightGlobals.fetch.VesselTarget;

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

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


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

            QualitySettings.pixelLightCount = 0;

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

            return(true);
        }
Пример #16
0
        /// <summary>
        /// Start and initialize all the things!
        /// </summary>
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            try
            {
                rpmComp = RasterPropMonitorComputer.Instantiate(internalProp, true);

                ConfigNode moduleConfig = null;
                foreach (ConfigNode node in GameDatabase.Instance.GetConfigNodes("PROP"))
                {
                    if (node.GetValue("name") == internalProp.propName)
                    {
                        if (string.IsNullOrEmpty(variableName))
                        {
                            JUtil.LogErrorMessage(this, "Configuration failed in prop {0} ({1}), no variableName.", internalProp.propID, internalProp.propName);
                            throw new ArgumentNullException();
                        }

                        moduleConfig = node.GetNodes("MODULE")[moduleID];
                        ConfigNode[] variableNodes = moduleConfig.GetNodes("VARIABLESET");

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

                if (flashRate > 0.0f)
                {
                    fm = JUtil.InstallFlashModule(part, flashRate);

                    if (fm != null)
                    {
                        fm.flashSubscribers += FlashToggle;
                    }
                }

                del = (Action <float>)Delegate.CreateDelegate(typeof(Action <float>), this, "OnCallback");
                rpmComp.RegisterVariableCallback(variableName, del);
                JUtil.LogMessage(this, "Configuration complete in prop {1} ({2}), supporting {0} callback animators.", variableSets.Count, internalProp.propID, internalProp.propName);
            }
            catch
            {
                JUtil.AnnoyUser(this);
                enabled = false;
                throw;
            }
        }
Пример #17
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;
            }
        }
        public bool RenderHUD(RenderTexture screen, float cameraAspect)
        {
            if (screen == null)
            {
                return(false);
            }

            if (!startupComplete)
            {
                JUtil.AnnoyUser(this);
            }

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

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

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

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

            // Draw the HUD ladder
            GL.LoadPixelMatrix(-horizonSize.x * 0.5f, horizonSize.x * 0.5f, -horizonSize.y * 0.5f, horizonSize.y * 0.5f);
            GL.Viewport(new Rect((screen.width - horizonSize.x) * 0.5f, (screen.height - horizonSize.y) * 0.5f, horizonSize.x, horizonSize.y));

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            GL.PopMatrix();

            return(true);
        }
Пример #19
0
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            try
            {
                if (string.IsNullOrEmpty(perPodPersistenceName))
                {
                    JUtil.LogErrorMessage(this, "perPodPersistenceName must be defined");
                    return;
                }
                if (string.IsNullOrEmpty(defaultValue))
                {
                    JUtil.LogErrorMessage(this, "defaultValue must be defined");
                    return;
                }

                if (stepSize < 0.0f)
                {
                    stepSize = 0.0f;
                }

                //JUtil.LogMessage(this, "Start(): {0}, {1}, {2}, {3}, {4}", perPodPersistenceName, defaultValue, minValue, maxValue, stepSize);

                if (!string.IsNullOrEmpty(minValue))
                {
                    minRange = VariableOrNumber.Instantiate(minValue);
                    //JUtil.LogMessage(this, "Created lower bound variable");
                }
                if (!string.IsNullOrEmpty(maxValue))
                {
                    maxRange = VariableOrNumber.Instantiate(maxValue);
                    //JUtil.LogMessage(this, "Created upper bound variable");
                }
                if ((minRange == null || maxRange == null) && loopInput == true)
                {
                    JUtil.LogErrorMessage(this, "Overriding loopInput - minValue or maxValue is missing");
                    loopInput = false;
                }

                RPMVesselComputer comp = RPMVesselComputer.Instance(vessel);
                if (!comp.HasPersistentVariable(perPodPersistenceName))
                {
                    //JUtil.LogMessage(this, "Initializing per pod persistence value {0}", perPodPersistenceName);

                    VariableOrNumber von = VariableOrNumber.Instantiate(defaultValue);
                    float            value;
                    if (von.Get(out value, comp))
                    {
                        if (stepSize > 0.0f)
                        {
                            float remainder = value % stepSize;
                            value -= remainder;
                        }
                        comp.SetPersistentVariable(perPodPersistenceName, value);
                    }
                    else
                    {
                        JUtil.LogErrorMessage(this, "Failed to evaluate default value of {0} for {1}", defaultValue, perPodPersistenceName);
                        return;
                    }
                }

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

                        for (int i = 0; i < inputNodes.Length; i++)
                        {
                            try
                            {
                                numericInputs.Add(new NumericInput(inputNodes[i], internalProp));
                                //JUtil.LogMessage(this, "Added USERINPUTSET {0}", inputNodes[i].GetValue("switchTransform"));
                            }
                            catch (ArgumentException e)
                            {
                                JUtil.LogErrorMessage(this, "Error in building prop number {1} - {0}", e.Message, internalProp.propID);
                            }
                        }
                        break;
                    }
                }

                enabled = true;
            }
            catch
            {
                JUtil.AnnoyUser(this);
                enabled = false;
                throw;
            }
        }
Пример #20
0
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            try
            {
                // Parse bloody KSPField colors.
                if (!string.IsNullOrEmpty(backgroundColor))
                {
                    backgroundColorValue = ConfigNode.ParseColor32(backgroundColor);
                }
                if (!string.IsNullOrEmpty(progradeColor))
                {
                    progradeColorValue = ConfigNode.ParseColor32(progradeColor);
                }
                if (!string.IsNullOrEmpty(maneuverColor))
                {
                    maneuverColorValue = ConfigNode.ParseColor32(maneuverColor);
                }
                if (!string.IsNullOrEmpty(targetColor))
                {
                    targetColorValue = ConfigNode.ParseColor32(targetColor);
                }
                if (!string.IsNullOrEmpty(normalColor))
                {
                    normalColorValue = ConfigNode.ParseColor32(normalColor);
                }
                if (!string.IsNullOrEmpty(radialColor))
                {
                    radialColorValue = ConfigNode.ParseColor32(radialColor);
                }
                if (!string.IsNullOrEmpty(dockingColor))
                {
                    dockingColorValue = ConfigNode.ParseColor32(dockingColor);
                }
                if (!string.IsNullOrEmpty(waypointColor))
                {
                    waypointColorValue = ConfigNode.ParseColor32(waypointColor);
                }

                Shader displayShader = JUtil.LoadInternalShader("RPM-DisplayShader");

                stockNavBall = FlightUIController.fetch.GetComponentInChildren <NavBall>();

                // Non-moving parts...
                cameraBody       = new GameObject();
                cameraBody.name  = "RPMPFD" + cameraBody.GetInstanceID();
                cameraBody.layer = drawingLayer;

                Vector3 navBallPosition = new Vector3(0.0f, 0.0f, 1.5f);

                ballCamera                      = cameraBody.AddComponent <Camera>();
                ballCamera.enabled              = false;
                ballCamera.orthographic         = true;
                ballCamera.eventMask            = 0;
                ballCamera.farClipPlane         = 3f;
                ballCamera.orthographicSize     = 1.0f;
                ballCamera.cullingMask          = 1 << drawingLayer;
                ballCamera.clearFlags           = CameraClearFlags.Depth;
                ballCamera.transparencySortMode = TransparencySortMode.Orthographic;
                ballCamera.transform.position   = Vector3.zero;
                ballCamera.transform.LookAt(navBallPosition, Vector3.up);

                navBall = GameDatabase.Instance.GetModel(navBallModel.EnforceSlashes());
                if (navBall == null)
                {
                    JUtil.LogErrorMessage(this, "Failed to load navball model {0}", navBallModel);
                    // Early return here - if we don't even have a navball, this module is pointless.
                    return;
                }

                Destroy(navBall.collider);
                navBall.name                     = "RPMNB" + navBall.GetInstanceID();
                navBall.layer                    = drawingLayer;
                navBall.transform.parent         = cameraBody.transform;
                navBall.transform.position       = navBallPosition;
                navBall.renderer.material.shader = displayShader;
                Texture2D horizonTex = GameDatabase.Instance.GetTexture(horizonTexture.EnforceSlashes(), false);
                if (horizonTex != null)
                {
                    navBall.renderer.material.mainTexture = horizonTex;
                }
                else
                {
                    JUtil.LogErrorMessage(this, "Failed to load horizon texture {0}", horizonTexture);
                }

                navBall.renderer.material.SetFloat("_Opacity", ballOpacity);

                startupComplete = true;
            }
            catch
            {
                JUtil.AnnoyUser(this);
                throw;
            }
        }
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            try {
                // Parse bloody KSPField colors.
                if (!string.IsNullOrEmpty(backgroundColor))
                {
                    backgroundColorValue = ConfigNode.ParseColor32(backgroundColor);
                }
                if (!string.IsNullOrEmpty(ballColor))
                {
                    ballColorValue = ConfigNode.ParseColor32(ballColor);
                }
                if (!string.IsNullOrEmpty(progradeColor))
                {
                    progradeColorValue = ConfigNode.ParseColor32(progradeColor);
                }
                if (!string.IsNullOrEmpty(maneuverColor))
                {
                    maneuverColorValue = ConfigNode.ParseColor32(maneuverColor);
                }
                if (!string.IsNullOrEmpty(targetColor))
                {
                    targetColorValue = ConfigNode.ParseColor32(targetColor);
                }
                if (!string.IsNullOrEmpty(normalColor))
                {
                    normalColorValue = ConfigNode.ParseColor32(normalColor);
                }
                if (!string.IsNullOrEmpty(radialColor))
                {
                    radialColorValue = ConfigNode.ParseColor32(radialColor);
                }
                if (!string.IsNullOrEmpty(dockingColor))
                {
                    dockingColorValue = ConfigNode.ParseColor32(dockingColor);
                }

                Shader unlit = Shader.Find("KSP/Alpha/Unlit Transparent");
                overlayMaterial             = new Material(unlit);
                overlayMaterial.mainTexture = GameDatabase.Instance.GetTexture(staticOverlay.EnforceSlashes(), false);

                if (!string.IsNullOrEmpty(headingBar))
                {
                    headingMaterial             = new Material(unlit);
                    headingMaterial.mainTexture = GameDatabase.Instance.GetTexture(headingBar.EnforceSlashes(), false);
                }
                horizonTex = GameDatabase.Instance.GetTexture(horizonTexture.EnforceSlashes(), false);

                gizmoTexture = JUtil.GetGizmoTexture();

                // Ahaha, that's clever, does it work?
                stockNavBall = GameObject.Find("NavBall").GetComponent <NavBall>();
                // ...well, it does, but the result is bizarre,
                // apparently, because the stock BALL ITSELF IS MIRRORED.

                navBall = GameDatabase.Instance.GetModel(navBallModel.EnforceSlashes());
                Destroy(navBall.collider);
                navBall.name  = "RPMNB" + navBall.GetInstanceID();
                navBall.layer = drawingLayer;
                navBall.transform.position      = Vector3.zero;
                navBall.transform.rotation      = Quaternion.identity;
                navBall.transform.localRotation = Quaternion.identity;

                if (ballIsEmissive)
                {
                    navBall.renderer.material.shader = Shader.Find("KSP/Emissive/Diffuse");
                    navBall.renderer.material.SetTexture("_MainTex", horizonTex);
                    navBall.renderer.material.SetTextureOffset("_Emissive", navBall.renderer.material.GetTextureOffset("_MainTex"));
                    navBall.renderer.material.SetTexture("_Emissive", horizonTex);
                    navBall.renderer.material.SetColor("_EmissiveColor", ballColorValue);
                }
                else
                {
                    navBall.renderer.material.shader      = Shader.Find("KSP/Unlit");
                    navBall.renderer.material.mainTexture = horizonTex;
                    navBall.renderer.material.color       = ballColorValue;
                }
                navBall.renderer.material.SetFloat("_Opacity", ballOpacity);

                markerPrograde      = BuildMarker(0, 2, progradeColorValue);
                markerRetrograde    = BuildMarker(1, 2, progradeColorValue);
                markerManeuver      = BuildMarker(2, 0, maneuverColorValue);
                markerManeuverMinus = BuildMarker(1, 2, maneuverColorValue);
                markerTarget        = BuildMarker(2, 1, targetColorValue);
                markerTargetMinus   = BuildMarker(2, 2, targetColorValue);
                markerNormal        = BuildMarker(0, 0, normalColorValue);
                markerNormalMinus   = BuildMarker(1, 0, normalColorValue);
                markerRadial        = BuildMarker(1, 1, radialColorValue);
                markerRadialMinus   = BuildMarker(0, 1, radialColorValue);

                markerDockingAlignment = BuildMarker(0, 2, dockingColorValue);

                // Non-moving parts...
                cameraBody                  = new GameObject();
                cameraBody.name             = "RPMPFD" + cameraBody.GetInstanceID();
                cameraBody.layer            = drawingLayer;
                ballCamera                  = cameraBody.AddComponent <Camera>();
                ballCamera.enabled          = false;
                ballCamera.orthographic     = true;
                ballCamera.clearFlags       = CameraClearFlags.Nothing;
                ballCamera.eventMask        = 0;
                ballCamera.farClipPlane     = 3f;
                ballCamera.orthographicSize = cameraSpan;
                ballCamera.cullingMask      = 1 << drawingLayer;
                ballCamera.clearFlags       = CameraClearFlags.Depth;
                // -2,0,0 seems to get the orientation exactly as the ship.
                // But logically, forward is Z+, right?
                // Which means that
                ballCamera.transform.position = new Vector3(0, 0, 2);
                ballCamera.transform.LookAt(Vector3.zero, Vector3.up);
                ballCamera.transform.position = new Vector3(cameraShift.x, cameraShift.y, 2);

                overlay       = CreateSimplePlane("RPMPFDOverlay" + internalProp.propID, 1f, drawingLayer);
                overlay.layer = drawingLayer;
                overlay.transform.position = new Vector3(0, 0, 1.5f);
                overlay.renderer.material  = overlayMaterial;
                overlay.transform.parent   = cameraBody.transform;
                FaceCamera(overlay);

                if (headingMaterial != null)
                {
                    heading       = CreateSimplePlane("RPMPFDHeading" + internalProp.propID, 1f, drawingLayer);
                    heading.layer = drawingLayer;
                    heading.transform.position   = new Vector3(headingBarPosition.x, headingBarPosition.y, headingAboveOverlay ? 1.55f : 1.45f);
                    heading.transform.parent     = cameraBody.transform;
                    heading.transform.localScale = new Vector3(headingBarPosition.z, 0, headingBarPosition.w);
                    heading.renderer.material    = headingMaterial;
                    heading.renderer.material.SetTextureScale("_MainTex", new Vector2(headingSpan, 1f));
                    FaceCamera(heading);
                }

                ShowHide(false, navBall, cameraBody, overlay, heading);
                startupComplete = true;
            } catch {
                JUtil.AnnoyUser(this);
                throw;
            }
        }
        public void Start()
        {
            try {
                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))
                {
                    currentState = vessel.ActionGroups[groupList[actionName]];
                }
                else
                {
                    isCustomAction = true;
                    switch (actionName)
                    {
                    case "intlight":
                        persistentVarName         = internalLightName;
                        lightObjects              = internalModel.FindModelComponents <Light>();
                        needsElectricChargeValue |= string.IsNullOrEmpty(needsElectricCharge) || needsElectricChargeValue;
                        break;

                    case "plugin":
                        persistentVarName = string.Empty;
                        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"))
                                    {
                                        if (!InstantiateHandler(pluginConfig, this, out actionHandler, out stateHandler))
                                        {
                                            JUtil.LogErrorMessage(this, "Failed to instantiate action handler {0}", pluginConfig.GetValue("name"));
                                        }
                                        else
                                        {
                                            isPluginAction = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if (actionHandler == null)
                        {
                            actionName = "dummy";
                            JUtil.LogMessage(this, "Plugin handlers did not start, reverting to dummy mode.");
                        }
                        break;

                    default:
                        persistentVarName = "switch" + internalProp.propID + "_" + moduleID;
                        break;
                    }
                    if (!string.IsNullOrEmpty(perPodPersistenceName))
                    {
                        persistentVarName = perPodPersistenceName;
                    }
                    persistence = new PersistenceAccessor(part);
                }
                if (needsElectricChargeValue)
                {
                    comp = RasterPropMonitorComputer.Instantiate(internalProp);
                    comp.UpdateRefreshRates(lightCheckRate, lightCheckRate);
                }

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

                if (isCustomAction)
                {
                    if (isPluginAction && stateHandler != null)
                    {
                        currentState = stateHandler();
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(persistentVarName))
                        {
                            currentState = customGroupList[actionName] = (persistence.GetBool(persistentVarName) ?? currentState);
                            if (actionName == "intlight")
                            {
                                // We have to restore lighting after reading the
                                // persistent variable.
                                SetInternalLights(customGroupList[actionName]);
                            }
                        }
                    }
                }

                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.
                    colorShiftRenderer = internalProp.FindModelComponent <Renderer>(coloredObject);
                    disabledColorValue = ConfigNode.ParseColor32(disabledColor);
                    enabledColorValue  = ConfigNode.ParseColor32(enabledColor);
                    colorShiftRenderer.material.SetColor(colorName, (currentState ^ reverse ? enabledColorValue : disabledColorValue));
                }
                else
                {
                    JUtil.LogMessage(this, "Warning, neither color nor animation are defined.");
                }

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

                startupComplete = true;
            } catch {
                JUtil.AnnoyUser(this);
                enabled = false;
                throw;
            }
        }
Пример #23
0
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }
            try {
                backgroundColorValue = ConfigNode.ParseColor32(backgroundColor);

                Shader unlit = Shader.Find("Hidden/Internal-GUITexture");
                ladderMaterial       = new Material(unlit);
                ladderMaterial.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);
                if (!String.IsNullOrEmpty(horizonTexture))
                {
                    ladderMaterial.mainTexture = GameDatabase.Instance.GetTexture(horizonTexture.EnforceSlashes(), false);
                    if (ladderMaterial.mainTexture != null)
                    {
                        horizonTextureSize.x = horizonTextureSize.x / ladderMaterial.mainTexture.width;
                        ladderMaterial.mainTexture.wrapMode = TextureWrapMode.Clamp;
                    }
                }

                if (!String.IsNullOrEmpty(headingBar))
                {
                    headingMaterial             = new Material(unlit);
                    headingMaterial.color       = new Color(0.5f, 0.5f, 0.5f, 1.0f);
                    headingMaterial.mainTexture = GameDatabase.Instance.GetTexture(headingBar.EnforceSlashes(), false);
                }

                if (!String.IsNullOrEmpty(staticOverlay))
                {
                    overlayMaterial             = new Material(unlit);
                    overlayMaterial.color       = new Color(0.5f, 0.5f, 0.5f, 1.0f);
                    overlayMaterial.mainTexture = GameDatabase.Instance.GetTexture(staticOverlay.EnforceSlashes(), false);
                }

                if (!String.IsNullOrEmpty(vertBar1Texture) && !String.IsNullOrEmpty(vertBar1Variable))
                {
                    vertBar1Material             = new Material(unlit);
                    vertBar1Material.color       = new Color(0.5f, 0.5f, 0.5f, 1.0f);
                    vertBar1Material.mainTexture = GameDatabase.Instance.GetTexture(vertBar1Texture.EnforceSlashes(), false);
                    if (vertBar1Material.mainTexture != null)
                    {
                        float height = (float)vertBar1Material.mainTexture.height;
                        vertBar1TextureLimit.x = 1.0f - (vertBar1TextureLimit.x / height);
                        vertBar1TextureLimit.y = 1.0f - (vertBar1TextureLimit.y / height);
                        vertBar1TextureSize    = 0.5f * (vertBar1TextureSize / height);
                        vertBar1Material.mainTexture.wrapMode = TextureWrapMode.Clamp;
                    }
                }

                if (!String.IsNullOrEmpty(vertBar2Texture) && !String.IsNullOrEmpty(vertBar2Variable))
                {
                    vertBar2Material             = new Material(unlit);
                    vertBar2Material.color       = new Color(0.5f, 0.5f, 0.5f, 1.0f);
                    vertBar2Material.mainTexture = GameDatabase.Instance.GetTexture(vertBar2Texture.EnforceSlashes(), false);
                    if (vertBar2Material.mainTexture != null)
                    {
                        float height = (float)vertBar2Material.mainTexture.height;
                        vertBar2TextureLimit.x = 1.0f - (vertBar2TextureLimit.x / height);
                        vertBar2TextureLimit.y = 1.0f - (vertBar2TextureLimit.y / height);
                        vertBar2TextureSize    = 0.5f * (vertBar2TextureSize / height);
                        vertBar2Material.mainTexture.wrapMode = TextureWrapMode.Clamp;
                    }
                }

                if (vertBar1UseLog10)
                {
                    vertBar1Limit.x = JUtil.PseudoLog10(vertBar1Limit.x);
                    vertBar1Limit.y = JUtil.PseudoLog10(vertBar1Limit.y);
                }

                if (vertBar2UseLog10)
                {
                    vertBar2Limit.x = JUtil.PseudoLog10(vertBar2Limit.x);
                    vertBar2Limit.y = JUtil.PseudoLog10(vertBar2Limit.y);
                }

                if (!string.IsNullOrEmpty(progradeColor))
                {
                    progradeColorValue = ConfigNode.ParseColor32(progradeColor);
                }

                comp = RasterPropMonitorComputer.Instantiate(internalProp);

                iconMaterial       = new Material(unlit);
                iconMaterial.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);
                gizmoTexture       = JUtil.GetGizmoTexture();

                startupComplete = true;
            } catch {
                JUtil.AnnoyUser(this);
                throw;
            }
        }
Пример #24
0
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }
            try
            {
                backgroundColorValue = ConfigNode.ParseColor32(backgroundColor);
                foreach (ConfigNode propNode in GameDatabase.Instance.GetConfigNodes("PROP"))
                {
                    ConfigNode[] moduleNodes = propNode.GetNodes("MODULE");

                    foreach (ConfigNode moduleNode in moduleNodes)
                    {
                        ConfigNode[] pageNodes = moduleNode.GetNodes("PAGE");

                        foreach (ConfigNode pagenode in pageNodes)
                        {
                            ConfigNode[] bghandlerNodes = pagenode.GetNodes("BACKGROUNDHANDLER");

                            foreach (ConfigNode bghandlerNode in bghandlerNodes)
                            {
                                ConfigNode[] gaugeNodes = bghandlerNode.GetNodes("GAUGE");
                                foreach (ConfigNode node in gaugeNodes)
                                {
                                    InfoGauge gauge = new InfoGauge();
                                    JUtil.LogErrorMessage(this, "one item created");
                                    gauge.Texture = node.GetValue("Texture");
                                    JUtil.LogErrorMessage(this, "texture obtained");
                                    gauge.Position = ConfigNode.ParseVector4(node.GetValue("Position"));
                                    JUtil.LogErrorMessage(this, "position obtained");
                                    gauge.Limit = ConfigNode.ParseVector2(node.GetValue("Limit"));
                                    JUtil.LogErrorMessage(this, "limit obtained");
                                    gauge.TextureLimit = ConfigNode.ParseVector4(node.GetValue("TextureLimit"));
                                    JUtil.LogErrorMessage(this, "texlim obtained");
                                    gauge.TextureSize = float.Parse(node.GetValue("TextureSize"));
                                    JUtil.LogErrorMessage(this, "texsiz obtained");
                                    gauge.VerticalMovement = bool.Parse(node.GetValue("VerticalMovement"));
                                    JUtil.LogErrorMessage(this, "vertmov obtained");
                                    gauge.UseLog10 = bool.Parse(node.GetValue("UseLog10"));
                                    JUtil.LogErrorMessage(this, "uselog obtained");
                                    gauge.Use360Horizon = bool.Parse(node.GetValue("Use360Horizon"));
                                    JUtil.LogErrorMessage(this, "360 obtained");
                                    gauge.RotateWithVessel = bool.Parse(node.GetValue("RotateWithVessel"));
                                    JUtil.LogErrorMessage(this, "rotate obtained");
                                    gauge.Variable = node.GetValue("Variable");
                                    JUtil.LogErrorMessage(this, "variable obtained");
                                    gaugeList.Add(gauge);
                                    JUtil.LogErrorMessage(this, "one item added");
                                }
                            }
                        }
                    }
                }

                Shader unlit = Shader.Find("Hidden/Internal-GUITexture");
                foreach (InfoGauge gauge in gaugeList)
                {
                    if (!String.IsNullOrEmpty(gauge.Texture))
                    {
                        gauge.Material             = new Material(unlit);
                        gauge.Material.color       = new Color(0.0f, 0.0f, 0.0f, 0.0f);
                        gauge.Material.mainTexture = GameDatabase.Instance.GetTexture(gauge.Texture.EnforceSlashes(), false);
                    }
                    if (gauge.Material.mainTexture != null)
                    {
                        float height = (float)gauge.Material.mainTexture.height;
                        float width  = (float)gauge.Material.mainTexture.width;
                        gauge.TextureLimit.x = 1.0f - (gauge.TextureLimit.x / width);
                        gauge.TextureLimit.y = 1.0f - (gauge.TextureLimit.y / width);
                        gauge.TextureLimit.z = 1.0f - (gauge.TextureLimit.z / height);
                        gauge.TextureLimit.w = 1.0f - (gauge.TextureLimit.w / height);
                        gauge.TextureSize    = 0.5f * (gauge.TextureSize / height);//实际调用的时候用的是宽和高的一半。
                        if (gauge.Use360Horizon)
                        {
                            gauge.Material.mainTexture.wrapMode = TextureWrapMode.Repeat;
                        }
                        else
                        {
                            gauge.Material.mainTexture.wrapMode = TextureWrapMode.Clamp;
                        }
                    }
                    if (gauge.UseLog10)
                    {
                        gauge.Limit.x = JUtil.PseudoLog10(gauge.Limit.x);
                        gauge.Limit.y = JUtil.PseudoLog10(gauge.Limit.y);
                    }
                }
                JUtil.LogMessage(this, "material read");
                comp            = RasterPropMonitorComputer.Instantiate(internalProp);
                startupComplete = true;
            }
            catch
            {
                JUtil.AnnoyUser(this);
                throw;
            }
        }
Пример #25
0
        public void Start()
        {
            // Skip the entire sequence when in editor -- this means we're part of a transparent pod and won't get used anyway.
            if (HighLogic.LoadedSceneIsEditor)
            {
                startupComplete = true;
                return;
            }

            try
            {
                if (!string.IsNullOrEmpty(backgroundColor))
                {
                    backgroundColorValue = ConfigNode.ParseColor32(backgroundColor);
                }
                if (!string.IsNullOrEmpty(iconColorSelf))
                {
                    iconColorSelfValue = ConfigNode.ParseColor32(iconColorSelf);
                }
                if (!string.IsNullOrEmpty(orbitColorSelf))
                {
                    orbitColorSelfValue = ConfigNode.ParseColor32(orbitColorSelf);
                }
                else
                {
                    orbitColorSelfValue = MapView.PatchColors[0];
                }
                if (!string.IsNullOrEmpty(iconColorTarget))
                {
                    iconColorTargetValue = ConfigNode.ParseColor32(iconColorTarget);
                }
                if (!string.IsNullOrEmpty(iconColorShadow))
                {
                    iconColorShadowValue = ConfigNode.ParseColor32(iconColorShadow);
                }
                if (!string.IsNullOrEmpty(iconColorAP))
                {
                    iconColorAPValue = ConfigNode.ParseColor32(iconColorAP);
                }
                else
                {
                    iconColorAPValue = MapView.PatchColors[0];
                }
                if (!string.IsNullOrEmpty(iconColorPE))
                {
                    iconColorPEValue = ConfigNode.ParseColor32(iconColorPE);
                }
                else
                {
                    iconColorPEValue = MapView.PatchColors[0];
                }
                if (!string.IsNullOrEmpty(orbitColorNextNode))
                {
                    orbitColorNextNodeValue = ConfigNode.ParseColor32(orbitColorNextNode);
                }
                else
                {
                    orbitColorNextNodeValue = MapView.PatchColors[1];
                }
                if (!string.IsNullOrEmpty(iconColorClosestApproach))
                {
                    iconColorClosestApproachValue = ConfigNode.ParseColor32(iconColorClosestApproach);
                }

                startupComplete = true;
            }
            catch
            {
                JUtil.AnnoyUser(this);
                throw;
            }
        }
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            try
            {
                textObjTransform = internalProp.FindModelTransform(labelTransform);
                textObj          = InternalComponents.Instance.CreateText(fontName, fontSize, textObjTransform, string.Empty);
                activeLabel      = 0;

                SmarterButton.CreateButton(internalProp, switchTransform, Click);

                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
                            {
                                labelsEx.Add(new VariableLabelSet(variableNodes[i]));
                            }
                            catch (ArgumentException e)
                            {
                                JUtil.LogErrorMessage(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 (labelsEx.Count < 1 && moduleConfig != null)
                {
                    try
                    {
                        labelsEx.Add(new VariableLabelSet(moduleConfig));
                    }
                    catch (ArgumentException e)
                    {
                        JUtil.LogErrorMessage(this, "Error in building prop number {1} - {0}", e.Message, internalProp.propID);
                    }
                }

                if (labelsEx.Count == 0)
                {
                    JUtil.LogErrorMessage(this, "No labels defined.");
                    throw new ArgumentException("No labels defined");
                }

                colorShiftRenderer = internalProp.FindModelComponent <Renderer>(coloredObject);
                if (labelsEx[activeLabel].hasColor)
                {
                    colorShiftRenderer.material.SetColor(colorName, labelsEx[activeLabel].color);
                }
                if (labelsEx[activeLabel].hasText)
                {
                    if (labelsEx[activeLabel].oneShot)
                    {
                        // Fetching formatString directly is notionally bad
                        // because there may be formatting stuff, but if
                        // oneShot is true, we already know that this is a
                        // constant string with no formatting.
                        textObj.text.Text = labelsEx[activeLabel].label.formatString;
                    }
                    else
                    {
                        textObj.text.Text = "";
                    }
                }

                audioOutput = JUtil.SetupIVASound(internalProp, switchSound, switchSoundVolume, false);
                JUtil.LogMessage(this, "Configuration complete in prop {1}, supporting {0} variable indicators.", labelsEx.Count, internalProp.propID);
            }
            catch
            {
                JUtil.AnnoyUser(this);
                enabled = false;
                throw;
            }
        }
Пример #27
0
        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;
            }
        }
Пример #28
0
        public void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }
            try
            {
                rpmComp = RasterPropMonitorComputer.Instantiate(internalProp, true);

                backgroundColorValue = ConfigNode.ParseColor32(backgroundColor);

                cameraBody                 = new GameObject();
                cameraBody.name            = "RPMPFD" + cameraBody.GetInstanceID();
                cameraBody.layer           = drawingLayer;
                hudCamera                  = cameraBody.AddComponent <Camera>();
                hudCamera.enabled          = false;
                hudCamera.orthographic     = true;
                hudCamera.eventMask        = 0;
                hudCamera.farClipPlane     = 3f;
                hudCamera.orthographicSize = 1.0f;
                hudCamera.cullingMask      = 1 << drawingLayer;
                // does this actually work?
                hudCamera.backgroundColor      = backgroundColorValue;
                hudCamera.clearFlags           = CameraClearFlags.Depth | CameraClearFlags.Color;
                hudCamera.transparencySortMode = TransparencySortMode.Orthographic;
                hudCamera.transform.position   = Vector3.zero;
                hudCamera.transform.LookAt(new Vector3(0.0f, 0.0f, 1.5f), Vector3.up);

                if (!string.IsNullOrEmpty(progradeColor))
                {
                    progradeColorValue = ConfigNode.ParseColor32(progradeColor);
                }

                if (!string.IsNullOrEmpty(cameraEffectShader))
                {
                    cameraEffectMaterial = new Material(JUtil.LoadInternalShader(cameraEffectShader));

                    if (!string.IsNullOrEmpty(cameraEffectVariables))
                    {
                        try
                        {
                            string[] vars = cameraEffectVariables.Split('|');
                            for (int i = 0; i < vars.Length; ++i)
                            {
                                string[] components = vars[i].Split(',');
                                if (components.Length == 2)
                                {
                                    ShaderEffectVariable sev = new ShaderEffectVariable();
                                    sev.variable = Shader.PropertyToID(components[0].Trim());
                                    sev.value    = rpmComp.InstantiateVariableOrNumber(components[1]);
                                    ceVariables.Add(sev);
                                }
                            }
                        }
                        catch { }
                    }

                    if (!string.IsNullOrEmpty(cameraEffectTextures))
                    {
                        try
                        {
                            string[] vars = cameraEffectTextures.Split('|');
                            for (int i = 0; i < vars.Length; ++i)
                            {
                                string[] components = vars[i].Split(',');
                                if (components.Length == 2)
                                {
                                    Texture tex = GameDatabase.Instance.GetTexture(components[1], false);
                                    cameraEffectMaterial.SetTexture(components[0], tex);
                                }
                            }
                        }
                        catch { }
                    }
                }
            }
            catch (Exception e)
            {
                JUtil.LogErrorMessage(this, "Start() failed with an exception: {0}", e);
                JUtil.AnnoyUser(this);
                throw;
            }

            startupComplete = true;
        }