From: toadicus Date: Tue, 05 May 2015 20:30:50 +0000 Subject: General cleanup of SimManager start-up and calling. X-Git-Tag: 0.18.2 X-Git-Url: http://git.toad.homelinux.net/projects/VOID.git/commitdiff/dbd804b --- General cleanup of SimManager start-up and calling. --- --- /dev/null +++ b/API/Attributes/AVOID_SaveValue.cs @@ -1,1 +1,48 @@ +// VOID +// +// AVOID_SaveValue.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using System; +namespace VOID +{ + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] + public class AVOID_SaveValue : Attribute + { + public string Name + { + get; + private set; + } + + public AVOID_SaveValue(string fieldName) + { + this.Name = fieldName; + } + } +} + + --- /dev/null +++ b/API/Attributes/VOID_GameModesAttribute.cs @@ -1,1 +1,48 @@ +// VOID +// +// VOID_ScenesAttribute.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using System; +namespace VOID +{ + [AttributeUsage(AttributeTargets.Class)] + public class VOID_ScenesAttribute : Attribute + { + public GameScenes[] ValidScenes + { + get; + private set; + } + + public VOID_ScenesAttribute(params GameScenes[] validScenes) + { + this.ValidScenes = validScenes; + } + } +} + + --- /dev/null +++ b/API/Attributes/VOID_ScenesAttribute.cs @@ -1,1 +1,48 @@ +// VOID +// +// VOID_ScenesAttribute.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using System; +namespace VOID +{ + [AttributeUsage(AttributeTargets.Class)] + public class VOID_GameModesAttribute : Attribute + { + public Game.Modes[] ValidModes + { + get; + private set; + } + + public VOID_GameModesAttribute(params Game.Modes[] validModes) + { + this.ValidModes = validModes; + } + } +} + + --- /dev/null +++ b/API/Enums.cs @@ -1,1 +1,25 @@ +// VOID © 2015 toadicus +// +// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a +// copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ +using System; +namespace VOID +{ + public enum VOID_TimeScale : UInt32 + { + KERBIN_TIME = 1, // Earth if 0 + SOLAR_DAY = 4, // Sidereal if 0 + ROUNDED_SCALE = 1024 // Real values if 0 + } + + public enum IconState : UInt32 + { + PowerOff = 1, + PowerOn = 2, + Inactive = 4, + Active = 8 + } +} + + --- /dev/null +++ b/API/IVOID_DataValue.cs @@ -1,1 +1,44 @@ +// VOID +// +// IVOID_DataValue.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using System; +namespace VOID +{ + public interface IVOID_DataValue + { + string Label { get; } + string Units { get; } + object Value { get; } + + void Refresh(); + string ValueUnitString(); + void DoGUIHorizontal(); + } +} + + --- /dev/null +++ b/API/IVOID_Module.cs @@ -1,1 +1,59 @@ +// VOID +// +// IVOID_Module.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using System; + +namespace VOID +{ + public interface IVOID_Module + { + string Name { get; } + bool Active { get; set; } + bool GUIRunning { get; } + bool InValidScene { get; } + bool InValidGame { get; } + + void DrawGUI(); + void StartGUI(); + void StopGUI(); + + void DrawConfigurables(); + + void LoadConfig(); + + void Save(KSP.IO.PluginConfiguration config); + } + + public interface IVOID_BehaviorModule : IVOID_Module + { + void Update(); + void FixedUpdate(); + void OnDestroy(); + } +} + --- /dev/null +++ b/API/IVOID_SaveValue.cs @@ -1,1 +1,40 @@ +// VOID +// +// IVOID_SaveValue.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using System; +namespace VOID +{ + public interface IVOID_SaveValue + { + Type type { get; } + object value { get; } + void SetValue(object v); + } +} + + --- /dev/null +++ b/API/VOIDCore.cs @@ -1,1 +1,90 @@ +// VOID +// +// IVOID_Core.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using KerbalEngineer.VesselSimulator; +using KSP; +using System; +using System.Collections.Generic; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public abstract class VOIDCore : VOID_WindowModule, IVOID_Module + { + public const double Constant_G = 6.674e-11; + public const int CONFIG_VERSION = 2; + + public abstract int ConfigVersion { get; } + public virtual bool configNeedsUpdate { get; set; } + + public abstract int WindowID { get; } + public abstract bool configDirty { get; set; } + public abstract bool powerAvailable { get; protected set; } + + public abstract IList Modules { get; } + + public abstract float UpdateTimer { get; protected set; } + public abstract double UpdatePeriod { get; } + + public virtual float saveTimer { get; protected set; } + + public abstract GUISkin Skin { get; } + + public abstract CelestialBody HomeBody { get; } + public abstract IList AllBodies { get; } + public abstract List SortedBodyList { get; protected set; } + + public abstract VesselType[] AllVesselTypes { get; protected set; } + public abstract Stage LastStage { get; protected set; } + public abstract Stage[] Stages { get; protected set; } + + public abstract VOID_TimeScale TimeScale { get; protected set; } + + public abstract event VOIDEventHandler onApplicationQuit; + public abstract event VOIDEventHandler onSkinChanged; + + public virtual void OnGUI() {} + + public override void LoadConfig() + { + base.LoadConfig(); + } + + public abstract void SaveConfig(); + + public override void Save(KSP.IO.PluginConfiguration config) + { + base.Save(config); + } + } + + public delegate void VOIDEventHandler(object sender); +} + + --- /dev/null +++ b/API/VOIDMaster.cs @@ -1,1 +1,160 @@ +// VOID +// +// VOIDMaster.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// +// +// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors +// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some +// invaluable functions and making your nicely written code available to learn from. +// +/////////////////////////////////////////////////////////////////////////////// +// +// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux. +// Engineer Redux (c) 2013 cybutek +// Used by permission. +// +/////////////////////////////////////////////////////////////////////////////// +using System; +using UnityEngine; +using KerbalEngineer.VesselSimulator; +using ToadicusTools; + +namespace VOID +{ + public abstract class VOIDMaster : MonoBehaviour + where T : VOIDCore_Generic, new() + { + protected T Core; + + public abstract void Awake(); + + public virtual void Update() + { + if (this.Core != null && !this.InValidScene()) + { + this.LogDebug("We have a Core but the scene is not valid for this master. Saving and disposing."); + + this.Core.SaveConfig (); + this.Core.Dispose(); + this.Core = null; + return; + } + + if (this.Core == null && this.InValidScene()) + { + this.LogDebug("We have no Core and the scene is valid for this master; re-trying Awake."); + this.Awake(); + return; + } + + this.Core.Update (); + + if (this.Core.FactoryReset) + { + this.LogDebug("Factory reset is true; deleting config and disposing!"); + + KSP.IO.File.Delete("config.xml"); + this.Core.Dispose(); + this.Core = null; + } + } + + public virtual void FixedUpdate() + { + if (this.Core == null) + { + return; + } + + this.Core.FixedUpdate (); + } + + public virtual void OnGUI() + { + if (this.Core == null) + { + return; + } + + this.Core.OnGUI(); + } + + public virtual void OnDestroy() + { + if (this.Core == null) + { + return; + } + + this.Core.OnDestroy(); + } + + public virtual void OnApplicationQuit() + { + if (this.Core == null) + { + return; + } + + this.Core.OnApplicationQuit(); + } + + protected virtual bool InValidScene() + { + foreach (var attr in this.GetType().GetCustomAttributes(true)) + { + if (attr is KSPAddon) + { + KSPAddon addonAttr = (KSPAddon)attr; + + switch (addonAttr.startup) + { + case KSPAddon.Startup.EveryScene: + return true; + case KSPAddon.Startup.EditorAny: + return HighLogic.LoadedSceneIsEditor; + case KSPAddon.Startup.Flight: + return HighLogic.LoadedSceneIsFlight; + case KSPAddon.Startup.MainMenu: + return HighLogic.LoadedScene == GameScenes.MAINMENU; + case KSPAddon.Startup.SpaceCentre: + return HighLogic.LoadedScene == GameScenes.SPACECENTER; + case KSPAddon.Startup.TrackingStation: + return HighLogic.LoadedScene == GameScenes.TRACKSTATION; + default: + return false; + } + } + } + + return false; + } + } +} + --- /dev/null +++ b/API/VOID_HUDModule.cs @@ -1,1 +1,217 @@ - +// VOID +// +// VOID_HUDModule.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +using KerbalEngineer.VesselSimulator; +using KSP; +using System; +using System.Collections.Generic; +using System.Text; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public abstract class VOID_HUDModule : VOID_Module + { + [AVOID_SaveValue("colorIndex")] + protected VOID_SaveValue _colorIndex; + + protected List textColors; + + [AVOID_SaveValue("positionsLocked")] + protected VOID_SaveValue positionsLocked; + + public virtual int ColorIndex + { + get + { + return this._colorIndex; + } + set + { + if (this._colorIndex >= this.textColors.Count - 1) + { + this._colorIndex.value = 0; + return; + } + + this._colorIndex.value = value; + } + } + + public virtual List Windows + { + get; + protected set; + } + + public VOID_HUDModule() : base() + { + this._colorIndex = (VOID_SaveValue)0; + + this.textColors = new List(); + + this.textColors.Add(Color.green); + this.textColors.Add(Color.black); + this.textColors.Add(Color.white); + this.textColors.Add(Color.red); + this.textColors.Add(Color.blue); + this.textColors.Add(Color.yellow); + this.textColors.Add(Color.gray); + this.textColors.Add(Color.cyan); + this.textColors.Add(Color.magenta); + + this.positionsLocked = (VOID_SaveValue)true; + + this.Windows = new List(); + } + + public override void DrawGUI() + { + VOID_Styles.labelHud.normal.textColor = textColors [ColorIndex]; + + GUI.skin = this.core.Skin; + + if (HighLogic.LoadedSceneIsEditor || + (TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate) + ) + { + SimManager.RequestSimulation(); + } + + foreach (HUDWindow window in this.Windows) + { + window.WindowPos = GUILayout.Window( + this.core.WindowID, + window.WindowPos, + VOID_Tools.GetWindowHandler(window.WindowFunction), + GUIContent.none, + GUIStyle.none + ); + } + } + + public override void DrawConfigurables() + { + base.DrawConfigurables(); + + if (GUILayout.Button (string.Intern("Change HUD color"), GUILayout.ExpandWidth (false))) + { + ++this.ColorIndex; + } + + if (GUILayout.Button(string.Intern("Reset HUD Positions"), GUILayout.ExpandWidth(false))) + { + foreach (HUDWindow window in this.Windows) + { + window.WindowPos = new Rect(window.defaultWindowPos); + } + } + + this.positionsLocked.value = GUITools.Toggle(this.positionsLocked, "Lock HUD Positions"); + } + + public override void LoadConfig() + { + base.LoadConfig(); + + var config = KSP.IO.PluginConfiguration.CreateForType(); + config.load(); + + foreach (HUDWindow window in this.Windows) + { + string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName); + Rect loadedPos = config.GetValue(saveName, window.defaultWindowPos); + + window.WindowPos = loadedPos; + } + } + + public override void Save(KSP.IO.PluginConfiguration config) + { + base.Save(config); + + foreach (HUDWindow window in this.Windows) + { + string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName); + config.SetValue(saveName, window.WindowPos); + } + } + } + + public class HUDWindow + { + public readonly Rect defaultWindowPos; + + private Rect _windowPos; + + public Action WindowFunction + { + get; + private set; + } + + public Rect WindowPos + { + get + { + return this._windowPos; + } + set + { + if (value != this._windowPos) + { + this._windowPos = value; + + if (VOID_Data.Core != null) + { + VOID_Data.Core.configDirty = true; + } + } + } + } + + public string WindowName + { + get; + private set; + } + + private HUDWindow() {} + + public HUDWindow(string name, Action windowFunc, Rect defaultPos) + { + this.WindowName = name; + this.WindowFunction = windowFunc; + this.defaultWindowPos = defaultPos; + this.WindowPos = new Rect(this.defaultWindowPos); + } + } +} + + --- /dev/null +++ b/API/VOID_Module.cs @@ -1,1 +1,550 @@ - +// VOID +// +// VOID_Module.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public abstract class VOID_Module : IVOID_Module + { + /* + * Fields + * */ + [AVOID_SaveValue("Active")] + protected VOID_SaveValue active = (VOID_SaveValue)false; + + protected float lastUpdate = 0; + + private GameScenes[] validScenes; + private Game.Modes[] validModes; + + /* + * Properties + * */ + + public virtual bool Active + { + get + { + return this.active && this.InValidGame && this.InValidScene; + } + set + { + this.active.value = value && this.InValidGame && this.InValidScene; + } + } + + public virtual bool GUIRunning + { + get + { + if ( + RenderingManager.fetch == null || + RenderingManager.fetch.postDrawQueue == null || + RenderingManager.fetch.postDrawQueue.Length < 4 + ) + { + return false; + } + else + { + Delegate callback = RenderingManager.fetch.postDrawQueue[3]; + if (callback == null) + { + return false; + } + + return callback.GetInvocationList().Contains((Callback)this.DrawGUI); + } + } + } + + public virtual bool InValidGame + { + get + { + return this.ValidModes.Contains(HighLogic.CurrentGame.Mode); + } + } + + public virtual bool InValidScene + { + get + { + return this.ValidScenes.Contains(HighLogic.LoadedScene); + } + } + + public virtual string Name + { + get; + protected set; + } + + public virtual Game.Modes[] ValidModes + { + get + { + if (this.validModes == null) + { + Tools.PostDebugMessage(this, "validModes is null when checking inValidGame; fetching attribute."); + foreach (var attr in this.GetType().GetCustomAttributes(false)) + { + if (attr is VOID_GameModesAttribute) + { + VOID_GameModesAttribute addonAttr = (VOID_GameModesAttribute)attr; + + this.validModes = addonAttr.ValidModes; + + Tools.PostDebugMessage("Found VOID_GameModesAttribute; validScenes set."); + + break; + } + } + + if (this.validModes == null) + { + this.validModes = new Game.Modes[] + { + Game.Modes.CAREER, + Game.Modes.SANDBOX, + Game.Modes.SCENARIO, + Game.Modes.SCENARIO_NON_RESUMABLE, + Game.Modes.SCIENCE_SANDBOX + }; + + Tools.PostDebugMessage("No VOID_GameModesAttribute found; validScenes defaulted to flight."); + } + } + + return this.validModes; + } + } + + public virtual GameScenes[] ValidScenes + { + get + { + if (this.validScenes == null) + { + Tools.PostDebugMessage(this, "validScenes is null when checking inValidScene; fetching attribute."); + foreach (var attr in this.GetType().GetCustomAttributes(false)) + { + if (attr is VOID_ScenesAttribute) + { + VOID_ScenesAttribute addonAttr = (VOID_ScenesAttribute)attr; + + this.validScenes = addonAttr.ValidScenes; + + Tools.PostDebugMessage("Found VOID_ScenesAttribute; validScenes set."); + + break; + } + } + + if (this.validScenes == null) + { + this.validScenes = new GameScenes[] { GameScenes.FLIGHT }; + Tools.PostDebugMessage("No VOID_ScenesAttribute found; validScenes defaulted to flight."); + } + } + + return this.validScenes; + } + } + + public virtual Vessel Vessel + { + get + { + return FlightGlobals.ActiveVessel; + } + } + + protected virtual VOIDCore core + { + get + { + return VOID_Data.Core; + } + } + + protected virtual bool timeToUpdate + { + get + { + return ( + (this.core.UpdateTimer - this.lastUpdate) > this.core.UpdatePeriod || + this.lastUpdate > this.core.UpdateTimer + ); + } + } + + /* + * Methods + * */ + public virtual void StartGUI() + { + if (!this.Active || this.GUIRunning) + { + return; + } + + Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name)); + RenderingManager.AddToPostDrawQueue (3, this.DrawGUI); + } + + public virtual void StopGUI() + { + if (!this.GUIRunning) + { + return; + } + Tools.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name)); + RenderingManager.RemoveFromPostDrawQueue (3, this.DrawGUI); + } + + public abstract void DrawGUI(); + + public virtual void DrawConfigurables() {} + + public virtual void LoadConfig() + { + var config = KSP.IO.PluginConfiguration.CreateForType (); + config.load (); + + if (this is VOIDCore) + { + int configVersion = config.GetValue("VOID_Core_configValue", 2); + + if (configVersion < VOIDCore.CONFIG_VERSION) + { + ((VOIDCore)this).configNeedsUpdate = true; + } + } + + foreach (var field in this.GetType().GetMembers( + BindingFlags.NonPublic | + BindingFlags.Public | + BindingFlags.Instance | + BindingFlags.FlattenHierarchy + )) + { + if (!(field is FieldInfo || field is PropertyInfo)) + { + continue; + } + + if (field is PropertyInfo && (field as PropertyInfo).GetIndexParameters().Length > 0) + { + continue; + } + + object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false); + + if (attrs.Length == 0) { + continue; + } + + AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue; + + string fieldName = string.Empty; + + if (this is VOIDCore || this.core.configNeedsUpdate) + { + string typeName = this.GetType().Name;; + + if (this is VOIDCore && ((VOIDCore)this).configNeedsUpdate) + { + if (this is VOIDCore_Flight) + { + typeName = "VOID_Core"; + } + else if (this is VOIDCore_Editor) + { + typeName = "VOID_EditorCore"; + } + } + + fieldName = string.Format("{0}_{1}", typeName, attr.Name); + } + else + { + fieldName = string.Format( + "{0}_{1}_{2}", + this.GetType().Name, + Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene), + attr.Name + ); + } + + Tools.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName)); + + object fieldValue; + + if (field is FieldInfo) + { + fieldValue = (field as FieldInfo).GetValue(this); + } + else + { + fieldValue = (field as PropertyInfo).GetValue(this, null); + } + + bool convertBack = false; + if (fieldValue is IVOID_SaveValue) + { + fieldValue = (fieldValue as IVOID_SaveValue).value; + convertBack = true; + } + + fieldValue = config.GetValue(fieldName, fieldValue); + + if (convertBack) + { + Type type = typeof(VOID_SaveValue<>).MakeGenericType (fieldValue.GetType ()); + IVOID_SaveValue convertValue = Activator.CreateInstance (type) as IVOID_SaveValue; + convertValue.SetValue (fieldValue); + fieldValue = convertValue; + } + + if (field is FieldInfo) + { + (field as FieldInfo).SetValue(this, fieldValue); + } + else + { + (field as PropertyInfo).SetValue(this, fieldValue, null); + } + + Tools.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName)); + } + } + + public virtual void Save(KSP.IO.PluginConfiguration config) + { + foreach (var field in this.GetType().GetMembers( + BindingFlags.Instance | + BindingFlags.NonPublic | + BindingFlags.Public | + BindingFlags.FlattenHierarchy + )) + { + object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false); + + if (attrs.Length == 0) { + continue; + } + + AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue; + + string fieldName; + + if (this is VOIDCore) + { + fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name); + } + else + { + fieldName = string.Format( + "{0}_{1}_{2}", + this.GetType().Name, + Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene), + attr.Name + ); + } + + object fieldValue; + + if (field is FieldInfo) + { + fieldValue = (field as FieldInfo).GetValue(this); + } + else + { + fieldValue = (field as PropertyInfo).GetValue(this, null); + } + + if (fieldValue is IVOID_SaveValue) + { + fieldValue = (fieldValue as IVOID_SaveValue).value; + } + + config.SetValue(fieldName, fieldValue); + + Tools.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName)); + } + } + } + + public abstract class VOID_WindowModule : VOID_Module + { + [AVOID_SaveValue("WindowPos")] + protected Rect WindowPos; + protected float defWidth; + protected float defHeight; + + protected bool decorateWindow; + + protected string inputLockName; + + public VOID_WindowModule() : base() + { + this.defWidth = 250f; + this.defHeight = 50f; + + this.decorateWindow = true; + + this.inputLockName = string.Concat(this.Name, "_edlock"); + + this.WindowPos = new Rect(Screen.width / 2, Screen.height / 2, this.defWidth, this.defHeight); + } + + public virtual void ModuleWindow(int id) + { + GUIStyle buttonStyle = this.core.Skin.button; + RectOffset padding = buttonStyle.padding; + RectOffset border = buttonStyle.border; + + Rect closeRect = new Rect( + 0f, + 0f, + border.left + border.right, + border.top + border.bottom + ); + + closeRect.width = Mathf.Max(closeRect.width, 16f); + closeRect.height = Mathf.Max(closeRect.height, 16f); + + closeRect.x = this.WindowPos.width - closeRect.width - 2f; + closeRect.y = 2f; + + GUI.Button(closeRect, GUIContent.none, buttonStyle); + + if (Event.current.type == EventType.repaint && Input.GetMouseButtonUp(0)) + { + if (closeRect.Contains(Event.current.mousePosition)) + { + this.Active = false; + this.removeUILock(); + } + } + + GUI.DragWindow(); + } + + public override void DrawGUI() + { + GUI.skin = this.core.Skin; + + Rect _Pos = this.WindowPos; + + _Pos = GUILayout.Window( + this.core.WindowID, + _Pos, + VOID_Tools.GetWindowHandler(this.ModuleWindow), + this.Name, + GUILayout.Width(this.defWidth), + GUILayout.Height(this.defHeight) + ); + + bool cursorInWindow = _Pos.Contains(Mouse.screenPos); + + if (cursorInWindow) + { + this.setUILock(); + } + else + { + this.removeUILock(); + } + + if (HighLogic.LoadedSceneIsEditor) + { + _Pos = Tools.ClampRectToEditorPad(_Pos); + } + else + { + _Pos = Tools.ClampRectToScreen(_Pos); + } + + if (_Pos != this.WindowPos) + { + this.WindowPos = _Pos; + this.core.configDirty = true; + } + } + + protected void setUILock() + { + switch (HighLogic.LoadedScene) + { + case GameScenes.EDITOR: + InputLockManager.SetControlLock( + ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK | + ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY, + this.inputLockName + ); + EditorLogic.fetch.Lock(false, false, false, this.inputLockName); + break; + case GameScenes.FLIGHT: + InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName); + break; + case GameScenes.SPACECENTER: + InputLockManager.SetControlLock( + ControlTypes.KSC_FACILITIES | ControlTypes.CAMERACONTROLS, + this.inputLockName + ); + break; + } + } + + protected void removeUILock() + { + switch (HighLogic.LoadedScene) + { + case GameScenes.EDITOR: + EditorLogic.fetch.Unlock(this.inputLockName); + break; + case GameScenes.FLIGHT: + InputLockManager.RemoveControlLock(this.inputLockName); + break; + case GameScenes.SPACECENTER: + InputLockManager.RemoveControlLock(this.inputLockName); + break; + } + } + } +} + + --- /dev/null +++ b/API/VOID_SingletonCore.cs @@ -1,1 +1,69 @@ +// VOID +// +// VOID_SingletonModule.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using System; +namespace VOID +{ + public abstract class VOID_SingletonCore : VOIDCore, IVOID_Module, IDisposable + where T : VOID_Module, new() + { + #region Singleton Members + /* + * Static Members + * */ + protected static bool _initialized = false; + + public static bool Initialized + { + get + { + return _initialized; + } + } + + protected static T _instance; + + public static T Instance + { + get + { + if (_instance == null) + { + _instance = new T(); + _initialized = true; + } + return _instance; + } + } + + public abstract void Dispose(); + #endregion + } +} + + --- /dev/null +++ b/API/VOID_SingletonWindow.cs @@ -1,1 +1,73 @@ +// VOID +// +// VOID_SingletonModule.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using System; +namespace VOID +{ + public abstract class VOID_SingletonWindow : VOID_WindowModule, IVOID_Module, IDisposable + where T : VOID_WindowModule, new() + { + #region Singleton Members + /* + * Static Members + * */ + protected static bool _initialized = false; + + public static bool Initialized + { + get + { + return _initialized; + } + } + + protected static T _instance; + + public static T Instance + { + get + { + if (_instance == null) + { + _instance = new T(); + _initialized = true; + } + return _instance; + } + } + + public virtual void Dispose() + { + _instance = null; + _initialized = false; + } + #endregion + } +} + + --- a/GameData/VOID/Textures/ATM_VOID.cfg +++ b/GameData/VOID/Textures/ATM_VOID.cfg @@ -4,9 +4,9 @@ enabled = true OVERRIDES { - VOID/.* + VOID/Textures/.* { - compress = true + compress = false mipmaps = false scale = 1 max_size = 0 --- a/IVOID_Module.cs +++ /dev/null @@ -1,59 +1,1 @@ -// VOID -// -// IVOID_Module.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using System; - -namespace VOID -{ - public interface IVOID_Module - { - string Name { get; } - bool toggleActive { get; set; } - bool guiRunning { get; } - - void DrawGUI(); - void StartGUI(); - void StopGUI(); - - void DrawConfigurables(); - - void LoadConfig(); - - void _SaveToConfig(KSP.IO.PluginConfiguration config); - } - - public interface IVOID_BehaviorModule : IVOID_Module - { - void Update(); - void FixedUpdate(); - void OnDestroy(); - } - - public interface IVOID_EditorModule : IVOID_Module {} -} - --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -39,7 +39,7 @@ // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion("0.16.4.*")] +[assembly: AssemblyVersion("0.18.1.*")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] --- /dev/null +++ b/Tools/VOID_DataValue.cs @@ -1,1 +1,356 @@ - +// VOID +// +// VOID_DataValue.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +using System; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public class VOID_DataValue : IVOID_DataValue + { + /* + * Static Members + * */ + public static implicit operator T(VOID_DataValue v) + { + return (T)v.Value; + } + + /* + * Instance Members + * */ + /* + * Fields + * */ + protected T cache; + protected Func ValueFunc; + protected float lastUpdate; + + /* + * Properties + * */ + public string Label { get; protected set; } + public string Units { get; protected set; } + + object IVOID_DataValue.Value + { + get + { + return this.Value; + } + } + + public T Value + { + get + { + if ( + (VOID_Data.Core.UpdateTimer - this.lastUpdate > VOID_Data.Core.UpdatePeriod) || + (this.lastUpdate > VOID_Data.Core.UpdateTimer) + ) + { + this.Refresh(); + } + return (T)this.cache; + } + } + + /* + * Methods + * */ + public VOID_DataValue(string Label, Func ValueFunc, string Units = "") + { + this.Label = Label; + this.Units = Units; + this.ValueFunc = ValueFunc; + this.lastUpdate = 0; + + VOID_Data.DataValues[this.GetHashCode()] = this; + } + + public void Refresh() + { + this.cache = this.ValueFunc.Invoke (); + this.lastUpdate = VOID_Data.Core.UpdateTimer; + } + + public T GetFreshValue() + { + this.Refresh (); + return (T)this.cache; + } + + public virtual string ValueUnitString() { + return this.Value.ToString() + this.Units; + } + + public virtual void DoGUIHorizontal() + { + GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true)); + GUILayout.Label (this.Label + ":"); + GUILayout.FlexibleSpace (); + GUILayout.Label (this.ValueUnitString(), GUILayout.ExpandWidth (false)); + GUILayout.EndHorizontal (); + } + + public override int GetHashCode() + { + int hash; + unchecked + { + hash = 79999; + + hash = hash * 104399 + this.Label.GetHashCode(); + hash = hash * 104399 + this.ValueFunc.GetHashCode(); + hash = hash * 104399 + this.Units.GetHashCode(); + } + + return hash; + } + + public override string ToString() + { + return string.Format ( + "{0}: {1}{2}", + this.Label, + this.Value.ToString (), + this.Units + ); + } + } + + public abstract class VOID_NumValue : VOID_DataValue, IFormattable + where T : IFormattable, IConvertible, IComparable + { + public static IFormatProvider formatProvider = Tools.SIFormatter; + + public static implicit operator Double(VOID_NumValue v) + { + return v.ToDouble(); + } + + public static implicit operator Int32(VOID_NumValue v) + { + return v.ToInt32(); + } + + public static implicit operator Single(VOID_NumValue v) + { + return v.ToSingle(); + } + + public VOID_NumValue(string Label, Func ValueFunc, string Units = "") : base(Label, ValueFunc, Units) + { + + } + + public virtual double ToDouble(IFormatProvider provider) + { + return this.Value.ToDouble(provider); + } + + public virtual double ToDouble() + { + return this.ToDouble(formatProvider); + } + + public virtual int ToInt32(IFormatProvider provider) + { + return this.Value.ToInt32(provider); + } + + public virtual int ToInt32() + { + return this.ToInt32(formatProvider); + } + + public virtual float ToSingle(IFormatProvider provider) + { + return this.Value.ToSingle(provider); + } + + public virtual float ToSingle() + { + return this.ToSingle(formatProvider); + } + + public virtual string ToString(string format) + { + return this.ToString(format, formatProvider); + } + + public virtual string ToString(string format, IFormatProvider provider) + { + return string.Format ( + "{0}{1}", + this.Value.ToString(format, provider), + this.Units + ); + } + + public virtual string ToSIString(int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue) + { + return string.Format ( + "{0}{1}", + Tools.MuMech_ToSI (this, digits, MinMagnitude, MaxMagnitude), + this.Units + ); + } + + public virtual string ValueUnitString(string format) + { + return this.Value.ToString(format, formatProvider) + this.Units; + } + + public virtual string ValueUnitString(int digits) { + return string.Format("{0}{1}", SIFormatProvider.ToSI(this, digits), Units); + } + + public virtual string ValueUnitString(int digits, int MinMagnitude, int MaxMagnitude) + { + return Tools.MuMech_ToSI(this, digits, MinMagnitude, MaxMagnitude) + this.Units; + } + + public virtual void DoGUIHorizontal(string format) + { + GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true)); + GUILayout.Label (this.Label + ":"); + GUILayout.FlexibleSpace (); + GUILayout.Label (this.ValueUnitString(format), GUILayout.ExpandWidth (false)); + GUILayout.EndHorizontal (); + } + + public virtual int DoGUIHorizontal(int digits, bool precisionButton = true) + { + if (precisionButton) + { + return this.DoGUIHorizontalPrec(digits); + } + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label(this.Label + ":", GUILayout.ExpandWidth(true)); + GUILayout.FlexibleSpace(); + GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false)); + GUILayout.EndHorizontal(); + + return digits; + } + + public virtual int DoGUIHorizontalPrec(int digits) + { + if (digits < 0 || digits > 8) + { + digits = 5; + } + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label(this.Label + "ⁱ:", GUILayout.ExpandWidth(true)); + GUILayout.FlexibleSpace(); + + GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false)); + + GUILayout.EndHorizontal(); + + if (Event.current.type == EventType.mouseUp) + { + Rect lastRect = GUILayoutUtility.GetLastRect(); + if (lastRect.Contains(Event.current.mousePosition)) + { + Tools.PostDebugMessage(string.Format("{0}: Changing digits from {1}", + this.GetType().Name, + digits + )); + + if (Event.current.button == 0) + { + digits = (digits + 3) % 9; + } + else if (Event.current.button == 1) + { + digits = (digits - 3) % 9; + } + + if (digits < 0) + { + digits += 9; + } + + Tools.PostDebugMessage(string.Format("{0}: Changed digits to {1}.", + this.GetType().Name, + digits + )); + } + } + + return digits; + } + } + + public class VOID_DoubleValue : VOID_NumValue + { + public VOID_DoubleValue(string Label, Func ValueFunc, string Units) : base(Label, ValueFunc, Units) {} + } + + public class VOID_FloatValue : VOID_NumValue + { + public VOID_FloatValue(string Label, Func ValueFunc, string Units) : base(Label, ValueFunc, Units) {} + } + + public class VOID_IntValue : VOID_NumValue + { + public VOID_IntValue(string Label, Func ValueFunc, string Units) : base(Label, ValueFunc, Units) {} + } + + public class VOID_StrValue : VOID_DataValue + { + public VOID_StrValue(string Label, Func ValueFunc) : base(Label, ValueFunc, "") {} + } + + public class VOID_Vector3dValue : VOID_DataValue + { + public VOID_Vector3dValue(string Label, Func ValueFunc, string Units) + : base(Label, ValueFunc, Units) + {} + + public string ToString(string format) + { + return string.Format("{0}: {1}{2}", + this.Label, + this.Value.ToString(format), + this.Units + ); + } + + public string ValueUnitString(string format) { + return this.Value.ToString(format) + this.Units; + } + } +} + + --- /dev/null +++ b/Tools/VOID_Localization.cs @@ -1,1 +1,36 @@ +// VOID +// +// VOID_Localization.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +public static class VOID_Localization +{ + public static string void_primary = "Primary"; + public static string void_altitude_asl = "Altitude (ASL)"; + public static string void_velocity = "Velocity"; + public static string void_apoapsis = "Apoapsis"; + public static string void_periapsis = "Periapsis"; +} --- /dev/null +++ b/Tools/VOID_SaveValue.cs @@ -1,1 +1,127 @@ +// VOID +// +// VOID_SaveValue.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using KSP; +using System; +using System.Collections.Generic; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public struct VOID_SaveValue : IVOID_SaveValue + { + private T _value; + private Type _type; + + private VOIDCore Core + { + get + { + return VOID_Data.Core; + } + } + + object IVOID_SaveValue.value + { + get + { + return this.value; + } + } + + public T value + { + get + { + return this._value; + } + set + { + if (this.Core != null && !System.Object.Equals(this._value, value)) + { + Tools.PostDebugMessage (string.Format ( + "VOID: Dirtying config for type {0}." + + "\n\t Old Value: {2}, New Value: {3}" + + "\n\t Object.Equals(New, Old): {4}\n" + + "{1}", + this._type, + new System.Diagnostics.StackTrace().ToString(), + this._value, + value, + System.Object.Equals(this._value, value) + )); + this.Core.configDirty = true; + } + this._value = value; + } + } + + public Type type + { + get + { + if (this._type == null && this._value != null) + { + this._type = this._value.GetType (); + } + return this._type; + } + set + { + this._type = value; + } + } + + public void SetValue(object v) + { + this.value = (T)v; + } + + public static implicit operator T(VOID_SaveValue v) + { + return (T)v.value; + } + + public static explicit operator VOID_SaveValue(T v) + { + VOID_SaveValue r = new VOID_SaveValue(); + r.type = v.GetType(); + r.value = v; + + return r; + } + + public override string ToString() + { + return this.value.ToString(); + } + } +} + + --- /dev/null +++ b/Tools/VOID_StageExtensions.cs @@ -1,1 +1,38 @@ +// VOID © 2015 toadicus +// +// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a +// copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ +using KerbalEngineer.VesselSimulator; +using KSP; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace VOID +{ + public static class VOID_StageExtensions + { + public static double NominalThrust(this Stage stage) + { + if (stage.actualThrust == 0d) + { + return stage.thrust; + } + else + { + return stage.actualThrust; + } + } + + public static double MassFlow(this Stage stage) + { + double stageIsp = VOID_Data.Core.LastStage.isp; + double stageThrust = stage.NominalThrust(); + + return stageThrust / (stageIsp * VOID_Data.KerbinGee); + } + } +} + + --- /dev/null +++ b/Tools/VOID_Tools.cs @@ -1,1 +1,1099 @@ - +// VOID +// +// VOID_Tools.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +using KSP; +using System; +using System.Collections.Generic; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public static class VOID_Tools + { + #region CelestialBody Utilities + public static bool hasAncestor(this CelestialBody bodyA, CelestialBody bodyB) + { + if (bodyA == null || bodyB == null) + { + return false; + } + + while (bodyA.orbitDriver != null) + { + if (bodyA.orbit.referenceBody == bodyB) + { + return true; + } + + bodyA = bodyA.orbit.referenceBody; + } + + return false; + } + + public static bool NearestRelatedParents(ref CelestialBody bodyA, ref CelestialBody bodyB) + { + if (bodyA == null || bodyB == null || bodyA.orbitDriver == null || bodyB.orbitDriver == null) + { + throw new ArgumentException(string.Concat( + "CelestialBody::FindRelatedParents: ", + "Neither body may be null, and both bodies must have orbits." + )); + } + + CelestialBody a, b; + + a = bodyA; + + while (bodyA.orbitDriver != null) + { + b = bodyB; + + while (b.orbitDriver != null) + { + if (a.orbit.referenceBody == b.orbit.referenceBody) + { + bodyA = a; + bodyB = b; + return true; + } + + b = b.orbit.referenceBody; + } + + a = a.orbit.referenceBody; + } + + return false; + } + #endregion + + #region VESSEL_EXTENSIONS_SCIENCE + public static CBAttributeMapSO.MapAttribute GetBiome(this Vessel vessel) + { + CBAttributeMapSO.MapAttribute mapAttribute; + + try + { + CBAttributeMapSO BiomeMap = vessel.mainBody.BiomeMap; + + double lat = vessel.latitude * Math.PI / 180d; + double lon = vessel.longitude * Math.PI / 180d; + + mapAttribute = BiomeMap.GetAtt(lat, lon); + + /* + lon -= Math.PI / 2d; + + if (lon < 0d) + { + lon += 2d * Math.PI; + } + + float v = (float)(lat / Math.PI) + 0.5f; + float u = (float)(lon / (2d * Math.PI)); + + Color pixelBilinear = BiomeMap.Map.GetPixelBilinear(u, v); + mapAttribute = BiomeMap.defaultAttribute; + + if (BiomeMap.Map != null) + { + if (BiomeMap.exactSearch) + { + for (int i = 0; i < BiomeMap.Attributes.Length; ++i) + { + if (pixelBilinear == BiomeMap.Attributes[i].mapColor) + { + mapAttribute = BiomeMap.Attributes[i]; + } + } + } + else + { + float zero = 0; + float num = 1 / zero; + for (int j = 0; j < BiomeMap.Attributes.Length; ++j) + { + Color mapColor = BiomeMap.Attributes[j].mapColor; + float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude; + if (sqrMagnitude < num) + { + bool testCase = true; + if (BiomeMap.nonExactThreshold != -1) + { + testCase = (sqrMagnitude < BiomeMap.nonExactThreshold); + } + if (testCase) + { + mapAttribute = BiomeMap.Attributes[j]; + num = sqrMagnitude; + } + } + } + } + } + */ + } + catch (NullReferenceException) + { + mapAttribute = new CBAttributeMapSO.MapAttribute(); + mapAttribute.name = "N/A"; + } + + return mapAttribute; + } + + public static ExperimentSituations GetExperimentSituation(this Vessel vessel) + { + if (vessel == null) + { + return ExperimentSituations.SrfSplashed; + } + + Vessel.Situations situation = vessel.situation; + + switch (situation) + { + case Vessel.Situations.PRELAUNCH: + case Vessel.Situations.LANDED: + return ExperimentSituations.SrfLanded; + case Vessel.Situations.SPLASHED: + return ExperimentSituations.SrfSplashed; + case Vessel.Situations.FLYING: + if (vessel.altitude < (double)vessel.mainBody.scienceValues.flyingAltitudeThreshold) + { + return ExperimentSituations.FlyingLow; + } + else + { + return ExperimentSituations.FlyingHigh; + } + } + + if (vessel.altitude < (double)vessel.mainBody.scienceValues.spaceAltitudeThreshold) + { + return ExperimentSituations.InSpaceLow; + } + else + { + return ExperimentSituations.InSpaceHigh; + } + } + + public static string HumanString(this ExperimentSituations situation) + { + switch (situation) + { + case ExperimentSituations.FlyingHigh: + return "Upper Atmosphere"; + case ExperimentSituations.FlyingLow: + return "Flying"; + case ExperimentSituations.SrfLanded: + return "Surface"; + case ExperimentSituations.InSpaceLow: + return "Near in Space"; + case ExperimentSituations.InSpaceHigh: + return "High in Space"; + case ExperimentSituations.SrfSplashed: + return "Splashed Down"; + default: + return "Unknown"; + } + } + #endregion + + #region VESSEL_EXTENSIONS_LAT_LONG + public static string GetLongitudeString(this Vessel vessel, string format = "F4") + { + string dir_long = "W"; + double v_long = vessel.longitude; + + v_long = FixDegreeDomain(v_long); + + if (v_long < -180d) + { + v_long += 360d; + } + if (v_long >= 180) + { + v_long -= 360d; + } + + if (v_long > 0) + dir_long = "E"; + + return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long); + } + + public static string GetLatitudeString(this Vessel vessel, string format = "F4") + { + string dir_lat = "S"; + double v_lat = vessel.latitude; + if (v_lat > 0) + dir_lat = "N"; + + return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat); + } + #endregion + + #region VESSEL_EXTENSIONS_GENERAL + public static double TrueAltitude(Vessel vessel) + { + double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude; + + // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m, + // and water covers the whole surface at 0 m. + if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean) + { + trueAltitude = vessel.orbit.altitude; + } + + return trueAltitude; + } + + public static double Radius(this Vessel vessel) + { + double radius; + + radius = vessel.altitude; + + if (vessel.mainBody != null) + { + radius += vessel.mainBody.Radius; + } + + return radius; + } + #endregion + + #region GEOMETRY_UTILS + public static double FixAngleDomain(double Angle, bool Degrees = false) + { + double Extent = 2d * Math.PI; + if (Degrees) + { + Extent = 360d; + } + + Angle = Angle % (Extent); + if (Angle < 0d) + { + Angle += Extent; + } + + return Angle; + } + + public static double FixDegreeDomain(double Angle) + { + return FixAngleDomain(Angle, true); + } + #endregion + + #region WINDOW_UTILS + private static Dictionary functionCache; + public static UnityEngine.GUI.WindowFunction GetWindowHandler(Action func) + { + if (functionCache == null) + { + functionCache = new Dictionary(); + } + + int hashCode = func.GetHashCode(); + + if (!functionCache.ContainsKey(hashCode)) + { + functionCache[hashCode] = delegate (int id) + { + try + { + func(id); + } + #if DEBUG + catch (ArgumentException) + #else + catch (ArgumentException) + #endif + { + Debug.LogWarning( + string.Format("[{0}]: ArgumentException caught during window call. This is not a bug.", + func.Target.GetType().Name + )); + + /*#if DEBUG + Debug.LogException(ex); + #endif*/ + } + catch (Exception ex) + { + Debug.LogError( + string.Format("[{0}]: {1} caught during window call.\nMessage:\n{2}\nStackTrace:\n{3}", + func.Target.GetType().Name, + ex.GetType().Name, + ex.Message, + ex.StackTrace + )); + } + }; + } + + return functionCache[hashCode]; + } + + public static void UncacheWindow(Action func) + { + if (functionCache != null) + { + int hashCode = func.GetHashCode(); + + if (functionCache.ContainsKey(hashCode)) + { + functionCache.Remove(hashCode); + } + } + } + #endregion + + #region TIME_UTILS + /// + /// Formats the interval given in seconds as a human-friendly + /// time period in [[[[years, ]days, ]hours, ]minutes, and ]seconds. + /// + /// Uses sidereal days, since "6 hours per day" is the Kerbal standard. + /// + /// Human readable interval + /// + public static string FormatInterval(double seconds) + { + return UnpackedTime.FromSeconds(seconds).FormatAsSpan(); + } + + /// + /// Formats the date given in seconds since epoch as a human-friendly + /// date in the format YY, DD, HH:MM:SS + /// + /// The date. + /// Seconds. + public static string FormatDate(double seconds) + { + return UnpackedTime.FromSeconds(seconds).FormatAsDate(); + } + + public class UnpackedTime + { + public const double SecondsPerMinute = 60d; + public const double SecondsPerHour = 3600d; + + public static double SecondsPerDay + { + get + { + VOID_TimeScale flags = VOID_Data.Core.TimeScale & + (VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE); + + switch (flags) + { + // Earth day, sidereal + case 0: + return 86164.1d; + // Earth day, solar (also rounded) + case VOID_TimeScale.ROUNDED_SCALE | VOID_TimeScale.SOLAR_DAY: + case VOID_TimeScale.ROUNDED_SCALE: + case VOID_TimeScale.SOLAR_DAY: + return 86400d; + // Kerbin day, solar + case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY: + return 21650.813d; + // Kerbin day, sidereal (also rounded) + default: + return 21600d; + } + } + } + + public static double SecondsPerYear + { + get + { + VOID_TimeScale flags = VOID_Data.Core.TimeScale & + (VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE); + + switch (flags) + { + // Earth year, rounded + case VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE: + case VOID_TimeScale.ROUNDED_SCALE: + return 60 * 60 * 24 * 365; + // Kerbin year, rounded + case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.SOLAR_DAY | VOID_TimeScale.ROUNDED_SCALE: + case VOID_TimeScale.KERBIN_TIME | VOID_TimeScale.ROUNDED_SCALE: + return 60 * 60 * 6 * 426; + // Earth year, solar time + case VOID_TimeScale.SOLAR_DAY: + return 31556925.2507328; + // Earth year, sidereal time + case 0: + return 31558149.7635456d; + // Kerbin year, solar & sidereal time + default: + return 9203544.61750141d; + } + } + } + + public static UnpackedTime FromSeconds(double seconds) + { + UnpackedTime time = new UnpackedTime(); + + time.years = (int)(seconds / SecondsPerYear); + + seconds %= SecondsPerYear; + + time.days = (int)(seconds / SecondsPerDay); + + seconds %= SecondsPerDay; + + time.hours = (int)(seconds / SecondsPerHour); + + seconds %= SecondsPerHour; + + time.minutes = (int)(seconds / SecondsPerMinute); + + seconds %= SecondsPerMinute; + + time.seconds = seconds; + + return time; + } + + public static explicit operator UnpackedTime(double seconds) + { + return FromSeconds(seconds); + } + + public static implicit operator double(UnpackedTime time) + { + return time.ToSeconds(); + } + + public static UnpackedTime operator+ (UnpackedTime lhs, UnpackedTime rhs) + { + return FromSeconds(lhs.ToSeconds() + rhs.ToSeconds()); + } + + public static UnpackedTime operator- (UnpackedTime lhs, UnpackedTime rhs) + { + return FromSeconds(lhs.ToSeconds() - rhs.ToSeconds()); + } + + public int years; + public int days; + public int hours; + public int minutes; + public double seconds; + + public double ToSeconds() + { + return (double)years * SecondsPerYear + + (double)days * SecondsPerDay + + (double)hours * SecondsPerHour + + (double)minutes * SecondsPerMinute + + seconds; + } + + public string FormatAsSpan() + { + string format_1 = "{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:00.0}s"; + string format_2 = "{0:D1}d {1:D2}h {2:D2}m {3:00.0}s"; + string format_3 = "{0:D2}h {1:D2}m {2:00.0}s"; + string format_4 = "{0:D2}m {1:00.0}s"; + string format_5 = "{0:00.0}s"; + + if (this.years > 0) + { + return string.Format(format_1, this.years, this.days, this.hours, this.minutes, this.seconds); + } + else if (this.days > 0) + { + return string.Format(format_2, this.days, this.hours, this.minutes, this.seconds); + } + else if (this.hours > 0) + { + return string.Format(format_3, this.hours, this.minutes, this.seconds); + } + else if (this.minutes > 0) + { + return string.Format(format_4, this.minutes, this.seconds); + } + else + { + return string.Format(format_5, this.seconds); + } + } + + public string FormatAsDate() + { + string format = "Y{0:#0}, D{1:#0} {2:00}:{3:00}:{4:00.0}s"; + + return string.Format(format, years + 1, days + 1, hours, minutes, seconds); + } + + public UnpackedTime(int years, int days, int hours, int minutes, double seconds) + { + this.years = years; + this.days = days; + this.hours = hours; + this.minutes = minutes; + this.seconds = seconds; + } + + public UnpackedTime() : this(0, 0, 0, 0, 0d) {} + } + #endregion + + public static string UppercaseFirst(string s) + { + if (string.IsNullOrEmpty(s)) + { + return string.Empty; + } + char[] a = s.ToCharArray(); + a[0] = char.ToUpper(a[0]); + return new string(a); + } + + //transfer angles + public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param) + { + r_target /= 1000; + r_current /= 1000; + grav_param /= 1000000000; + + double midpoint = (r_target + r_current) / 2; + + double T_target = (2 * Math.PI) * Math.Sqrt((r_target * r_target * r_target) / grav_param); + double T_transfer = (2 * Math.PI) * Math.Sqrt((midpoint * midpoint * midpoint) / grav_param); + return 360 * (0.5 - (T_transfer / (2 * T_target))); + } + + public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2) + { + /* + def deltaVToGetToOtherBody(mu, r1, r2): + # mu = gravity param of common orbiting body of r1 and r2 + # (e.g. for mun to minmus, mu is kerbin's gravity param + # r1 = initial body's orbit radius + # r2 = target body's orbit radius + + # return value is km/s + sur1 = math.sqrt(mu / r1) + sr1r2 = math.sqrt(float(2*r2)/float(r1+r2)) + mult = sr1r2 - 1 + return sur1 * mult + */ + double sur1, sr1r2, mult; + sur1 = Math.Sqrt(mu / r1); + sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2)); + mult = sr1r2 - 1; + return sur1 * mult; + } + + public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v) + { + /* + def deltaVToExitSOI(mu, r1, r2, v): + # mu = gravity param of current body + # r1 = current orbit radius + # r2 = SOI radius + # v = SOI exit velocity + foo = r2 * (v**2) - 2 * mu + bar = r1 * foo + (2 * r2 * mu) + r = r1*r2 + return math.sqrt(bar / r) + */ + double foo = r2 * (v * v) - 2 * mu; + double bar = r1 * foo + (2 * r2 * mu); + double r = r1 * r2; + return Math.Sqrt(bar / r); + } + + public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu) + { + /* + def transferBurnPoint(r, v, angle, mu): + # r = parking orbit radius + # v = ejection velocity + # angle = phase angle (from function phaseAngle()) + # mu = gravity param of current body. + epsilon = ((v**2)/2) - (mu / r) + h = r * v * math.sin(angle) + e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2))) + theta = math.acos(1.0 / e) + degrees = theta * (180.0 / math.pi) + return 180 - degrees + */ + double epsilon, h, ee, theta, degrees; + epsilon = ((v * v) / 2) - (mu / r); + h = r * v * Math.Sin(angle); + ee = Math.Sqrt(1 + ((2 * epsilon * (h * h)) / (mu * mu))); + theta = Math.Acos(1.0 / ee); + degrees = theta * (180.0 / Math.PI); + return 180 - degrees; + // returns the ejection angle + } + + public static double Adammada_CurrrentPhaseAngle( + double body_LAN, + double body_orbitPct, + double origin_LAN, + double origin_orbitPct + ) + { + double angle = (body_LAN / 360 + body_orbitPct) - (origin_LAN / 360 + origin_orbitPct); + if (angle > 1) + angle = angle - 1; + if (angle < 0) + angle = angle + 1; + if (angle > 0.5) + angle = angle - 1; + angle = angle * 360; + return angle; + } + + public static double Adammada_CurrentEjectionAngle( + double vessel_long, + double origin_rotAngle, + double origin_LAN, + double origin_orbitPct + ) + { + //double eangle = ((FlightGlobals.ActiveVOID.vessel.longitude + orbiting.rotationAngle) - (orbiting.orbit.LAN / 360 + orbiting.orbit.orbitPercent) * 360); + double eangle = ((vessel_long + origin_rotAngle) - (origin_LAN / 360 + origin_orbitPct) * 360); + + while (eangle < 0) + eangle = eangle + 360; + while (eangle > 360) + eangle = eangle - 360; + if (eangle < 270) + eangle = 90 - eangle; + else + eangle = 450 - eangle; + return eangle; + } + + public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body + { + Vector3d vecthis = new Vector3d(); + Vector3d vectarget = new Vector3d(); + vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); + + if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun")) + { + vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); + } + else + { + vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); + } + + vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis); + vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget); + + Vector3d prograde = new Vector3d(); + prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis; + + double phase = Vector3d.Angle(vecthis, vectarget); + + if (Vector3d.Angle(prograde, vectarget) > 90) + phase = 360 - phase; + + return (phase + 360) % 360; + } + + public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase) + { + if (transfer_angle < 0) + { + if (curr_phase > 0) + return (-1 * (360 - curr_phase)); + else if (curr_phase < 0) + return curr_phase; + } + else if (transfer_angle > 0) + { + if (curr_phase > 0) + return curr_phase; + else if (curr_phase < 0) + return (360 + curr_phase); + } + return curr_phase; + } + + public static double adjust_current_ejection_angle(double curr_ejection) + { + //curr_ejection WILL need to be adjusted once for all transfers as it returns values ranging -180 to 180 + // need 0-360 instead + // + // ie i have -17 in the screenshot + // need it to show 343 + // + // do this + // + // if < 0, add curr to 360 // 360 + (-17) = 343 + // else its good as it is + + if (curr_ejection < 0) + return 360 + curr_ejection; + else + return curr_ejection; + + } + + public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase) + { + // if transfer_phase_angle < 0 its a lower transfer + //180 + curr_ejection + // else if transfer_phase_angle > 0 its good as it is + + if (trans_phase < 0) + return 180 + trans_ejection; + else + return trans_ejection; + + } + + public static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel) + { + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label("Phase angle (curr/trans):"); + GUILayout.Label( + VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + VOID_Tools.Nivvy_CalcTransferPhaseAngle( + vessel.orbit.semiMajorAxis, + body.orbit.semiMajorAxis, + vessel.mainBody.gravParameter + ).ToString("F3") + "°", + GUILayout.ExpandWidth(false) + ); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label("Transfer velocity:"); + GUILayout.Label( + (VOID_Tools.Younata_DeltaVToGetToOtherBody( + (vessel.mainBody.gravParameter / 1000000000), + (vessel.orbit.semiMajorAxis / 1000), + (body.orbit.semiMajorAxis / 1000) + ) * 1000).ToString("F2") + "m/s", + GUILayout.ExpandWidth(false) + ); + GUILayout.EndHorizontal(); + } + + public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel) + { + double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( + (vessel.mainBody.referenceBody.gravParameter / 1000000000), + (vessel.mainBody.orbit.semiMajorAxis / 1000), + (body.orbit.semiMajorAxis / 1000) + ); + double dv2 = VOID_Tools.Younata_DeltaVToExitSOI( + (vessel.mainBody.gravParameter / 1000000000), + (vessel.orbit.semiMajorAxis / 1000), + (vessel.mainBody.sphereOfInfluence / 1000), + Math.Abs(dv1) + ); + + double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint( + (vessel.orbit.semiMajorAxis / 1000), + dv2, + (Math.PI / 2.0), + (vessel.mainBody.gravParameter / 1000000000) + ); + double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle( + FlightGlobals.ActiveVessel.longitude, + FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle, + FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, + FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent + ); + + double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( + vessel.mainBody.orbit.semiMajorAxis, + body.orbit.semiMajorAxis, + vessel.mainBody.referenceBody.gravParameter + ) % 360; + double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle( + body.orbit.LAN, + body.orbit.orbitPercent, + FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, + FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent + ); + + double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle); + double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle); + double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label("Phase angle (curr/trans):"); + GUILayout.Label( + adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", + GUILayout.ExpandWidth(false) + ); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label("Ejection angle (curr/trans):"); + GUILayout.Label( + adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°", + GUILayout.ExpandWidth(false) + ); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label("Transfer velocity:"); + GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); + GUILayout.EndHorizontal(); + } + + public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel) + { + double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( + (vessel.mainBody.gravParameter / 1000000000), + (vessel.orbit.semiMajorAxis / 1000), + (body.orbit.semiMajorAxis / 1000) + ); + + double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( + vessel.orbit.semiMajorAxis, + body.orbit.semiMajorAxis, + vessel.mainBody.gravParameter + ); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label("Phase angle (curr/trans):"); + GUILayout.Label( + VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", + GUILayout.ExpandWidth(false) + ); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label("Transfer velocity:"); + GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); + GUILayout.EndHorizontal(); + } + + public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel) + { + double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( + (vessel.mainBody.referenceBody.gravParameter / 1000000000), + (vessel.mainBody.orbit.semiMajorAxis / 1000), + (body.orbit.semiMajorAxis / 1000) + ); + double dv2 = VOID_Tools.Younata_DeltaVToExitSOI( + (vessel.mainBody.gravParameter / 1000000000), + (vessel.orbit.semiMajorAxis / 1000), + (vessel.mainBody.sphereOfInfluence / 1000), + Math.Abs(dv1) + ); + double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint( + (vessel.orbit.semiMajorAxis / 1000), + dv2, + (Math.PI / 2.0), + (vessel.mainBody.gravParameter / 1000000000) + ); + + double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle( + body.orbit.LAN, + body.orbit.orbitPercent, + FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, + FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent + ); + double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle( + FlightGlobals.ActiveVessel.longitude, + FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle, + FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, + FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent + ); + + double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( + vessel.mainBody.orbit.semiMajorAxis, + body.orbit.semiMajorAxis, + vessel.mainBody.referenceBody.gravParameter + ) % 360; + + double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle); + //double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle); + + //new stuff + // + double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle); + double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle); + // + // + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label("Phase angle (curr/trans):"); + GUILayout.Label( + adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", + GUILayout.ExpandWidth(false) + ); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label("Ejection angle (curr/trans):"); + GUILayout.Label( + adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°", + GUILayout.ExpandWidth(false) + ); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + GUILayout.Label("Transfer velocity:"); + GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); + GUILayout.EndHorizontal(); + } + + public static string get_heading_text(double heading) + { + if (heading > 348.75 || heading <= 11.25) + return "N"; + else if (heading > 11.25 && heading <= 33.75) + return "NNE"; + else if (heading > 33.75 && heading <= 56.25) + return "NE"; + else if (heading > 56.25 && heading <= 78.75) + return "ENE"; + else if (heading > 78.75 && heading <= 101.25) + return "E"; + else if (heading > 101.25 && heading <= 123.75) + return "ESE"; + else if (heading > 123.75 && heading <= 146.25) + return "SE"; + else if (heading > 146.25 && heading <= 168.75) + return "SSE"; + else if (heading > 168.75 && heading <= 191.25) + return "S"; + else if (heading > 191.25 && heading <= 213.75) + return "SSW"; + else if (heading > 213.75 && heading <= 236.25) + return "SW"; + else if (heading > 236.25 && heading <= 258.75) + return "WSW"; + else if (heading > 258.75 && heading <= 281.25) + return "W"; + else if (heading > 281.25 && heading <= 303.75) + return "WNW"; + else if (heading > 303.75 && heading <= 326.25) + return "NW"; + else if (heading > 326.25 && heading <= 348.75) + return "NNW"; + else + return ""; + } + } + + public class CBListComparer : IComparer + { + public int Compare(CelestialBody bodyA, CelestialBody bodyB) + { + Tools.PostDebugMessage(this, "got bodyA: {0} & bodyB: {1}", bodyA, bodyB); + + if (bodyA == null && bodyB == null) + { + Tools.PostDebugMessage(this, "both bodies are null, returning 0"); + return 0; + } + if (bodyA == null) + { + Tools.PostDebugMessage(this, "bodyA is null, returning -1"); + return -1; + } + if (bodyB == null) + { + Tools.PostDebugMessage(this, "bodyB is null, returning 1"); + return 1; + } + + Tools.PostDebugMessage(this, "bodies are not null, carrying on"); + + if (object.ReferenceEquals(bodyA, bodyB)) + { + Tools.PostDebugMessage(this, "bodies are equal, returning 0"); + return 0; + } + + Tools.PostDebugMessage(this, "bodies are not equal, carrying on"); + + if (bodyA.orbitDriver == null) + { + Tools.PostDebugMessage(this, "bodyA.orbit is null (bodyA is the sun, returning 1"); + return 1; + } + if (bodyB.orbitDriver == null) + { + Tools.PostDebugMessage(this, "bodyB.orbit is null (bodyB is the sun, returning -1"); + return -1; + } + + Tools.PostDebugMessage(this, "orbits are not null, carrying on"); + + if (bodyA.orbit.referenceBody == bodyB.orbit.referenceBody) + { + Tools.PostDebugMessage(this, "bodies share a parent, comparing SMAs"); + return -bodyA.orbit.semiMajorAxis.CompareTo(bodyB.orbit.semiMajorAxis); + } + + Tools.PostDebugMessage(this, "orbits do not share a parent, carrying on"); + + if (bodyA.hasAncestor(bodyB)) + { + Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning -1"); + return -1; + } + if (bodyB.hasAncestor(bodyA)) + { + Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning 1"); + return 1; + } + + Tools.PostDebugMessage(this, "bodies do not have an obvious relationship, searching for one"); + + if (VOID_Tools.NearestRelatedParents(ref bodyA, ref bodyB)) + { + Tools.PostDebugMessage(this, "good relation {0} and {1}, comparing", bodyA.bodyName, bodyB.bodyName); + return this.Compare(bodyA, bodyB); + } + + Tools.PostDebugMessage(this, "bad relation {0} and {1}, giving up", bodyA.bodyName, bodyB.bodyName); + + return 0; + } + } +} + --- a/VOID.csproj +++ b/VOID.csproj @@ -73,12 +73,7 @@ - - - - - @@ -87,12 +82,7 @@ - - - - - @@ -100,7 +90,32 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -135,5 +150,10 @@ + + + + + --- /dev/null +++ b/VOIDCore_Editor.cs @@ -1,1 +1,46 @@ +// VOID +// +// VOID_EditorCore.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using KerbalEngineer.VesselSimulator; +using KSP; +using System; +using System.Collections.Generic; +using System.Linq; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + [VOID_Scenes(GameScenes.EDITOR)] + public class VOIDCore_Editor : VOIDCore_Generic + { + public override void FixedUpdate() {} + } +} + + --- /dev/null +++ b/VOIDCore_Flight.cs @@ -1,1 +1,51 @@ +// VOID +// +// VOIDCore_Flight.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using KSP; +using System; +using UnityEngine; +using ToadicusTools; + +namespace VOID +{ + [VOID_Scenes(GameScenes.FLIGHT)] + public class VOIDCore_Flight : VOIDCore_Generic + { + public override void DrawConfigurables() + { + if (HighLogic.LoadedSceneIsFlight) + { + this.consumeResource.value = GUITools.Toggle(this.consumeResource, "Consume Resources"); + } + + base.DrawConfigurables(); + } + } +} + + --- /dev/null +++ b/VOIDCore_Generic.cs @@ -1,1 +1,1203 @@ - +// VOID +// +// VOIDCore_Generic.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +using KerbalEngineer.Editor; +using KerbalEngineer.Helpers; +using KerbalEngineer.VesselSimulator; +using KSP; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public abstract class VOIDCore_Generic : VOID_SingletonCore, IVOID_Module, IDisposable + where T : VOID_Module, new() + { + /* + * Fields + * */ + protected string VoidName = "VOID"; + protected string VoidVersion; + + [AVOID_SaveValue("configValue")] + protected VOID_SaveValue configVersion = (VOID_SaveValue)VOIDCore.CONFIG_VERSION; + + protected List modules = new List(); + protected bool modulesLoaded = false; + + protected Texture2D VOIDIconTexture; + protected string VOIDIconOnActivePath; + protected string VOIDIconOnInactivePath; + protected string VOIDIconOffActivePath; + protected string VOIDIconOffInactivePath; + + private bool _useToolbarManager; + + protected GUIStyle iconStyle; + + protected int windowBaseID = -96518722; + protected int windowID = 0; + + protected bool GUIStylesLoaded = false; + + protected CelestialBody homeBody; + + [AVOID_SaveValue("togglePower")] + public VOID_SaveValue togglePower = (VOID_SaveValue)true; + + public override bool powerAvailable { get; protected set; } + + [AVOID_SaveValue("consumeResource")] + protected VOID_SaveValue consumeResource = (VOID_SaveValue)false; + + [AVOID_SaveValue("resourceName")] + protected VOID_SaveValue resourceName = (VOID_SaveValue)"ElectricCharge"; + + [AVOID_SaveValue("resourceRate")] + protected VOID_SaveValue resourceRate = (VOID_SaveValue)0.2f; + + [AVOID_SaveValue("updatePeriod")] + protected VOID_SaveValue updatePeriod = (VOID_SaveValue)(1001f / 15000f); + protected string stringFrequency; + + [AVOID_SaveValue("vesselSimActive")] + protected VOID_SaveValue vesselSimActive; + + [AVOID_SaveValue("timeScaleFlags")] + protected VOID_SaveValue timeScaleFlags; + + // Load-up housekeeping + protected bool vesselTypesLoaded = false; + protected bool simManagerLoaded = false; + + protected string defaultSkin = "KSP window 2"; + + [AVOID_SaveValue("defaultSkin")] + protected VOID_SaveValue skinName; + protected int skinIdx; + + protected Dictionary validSkins; + protected string[] skinNames; + protected string[] forbiddenSkins = + { + "PlaqueDialogSkin", + "FlagBrowserSkin", + "SSUITextAreaDefault", + "ExperimentsDialogSkin", + "ExpRecoveryDialogSkin", + "KSP window 1", + "KSP window 3", + "KSP window 5", + "KSP window 6", + "PartTooltipSkin", + "KSCContextMenuSkin" + }; + protected bool skinsLoaded = false; + + public override bool configDirty { get; set; } + + protected IButton ToolbarButton; + protected ApplicationLauncherButton AppLauncherButton; + protected IconState iconState; + + /* + * Properties + * */ + public override bool Active + { + get + { + return base.Active; + } + set + { + if (value != base.Active) + { + this.SetIconTexture(this.powerState | this.activeState); + } + + base.Active = value; + } + } + public override IList AllBodies + { + get + { + return FlightGlobals.Bodies.AsReadOnly(); + } + } + + public override VesselType[] AllVesselTypes + { + get; + protected set; + } + + public override int ConfigVersion + { + get + { + return this.configVersion; + } + } + + public bool FactoryReset + { + get; + protected set; + } + + public override CelestialBody HomeBody + { + get + { + if (this.homeBody == null) + { + if (Planetarium.fetch != null) + { + this.homeBody = Planetarium.fetch.Home; + } + } + + return this.homeBody; + } + } + + public override IList Modules + { + get + { + return this.modules.AsReadOnly(); + } + } + + public override GUISkin Skin + { + get + { + if (this.skinsLoaded) + { + try + { + return this.validSkins[this.skinName]; + } + catch + { + } + } + + return AssetBase.GetGUISkin(this.defaultSkin); + } + } + + public override List SortedBodyList + { + get; + protected set; + } + + public override double UpdatePeriod + { + get + { + return this.updatePeriod; + } + } + + public override float UpdateTimer + { + get; + protected set; + } + + public override int WindowID + { + get + { + if (this.windowID == 0) + { + this.windowID = this.windowBaseID; + } + return this.windowID++; + } + } + + public override Stage[] Stages + { + get; + protected set; + } + + public override Stage LastStage + { + get; + protected set; + } + + public override VOID_TimeScale TimeScale + { + get + { + return (VOID_TimeScale)this.timeScaleFlags.value; + } + protected set + { + this.timeScaleFlags.value = (UInt32)value; + } + } + + protected IconState activeState + { + get + { + if (this.Active) + { + return IconState.Inactive; + } + else + { + return IconState.Active; + } + + } + } + + protected IconState powerState + { + get + { + if (this.togglePower && this.powerAvailable) + { + return IconState.PowerOn; + } + else + { + return IconState.PowerOff; + } + + } + } + + protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes + { + get + { + return HighLogic.LoadedScene.ToAppScenes(); + } + } + + protected bool useToolbarManager + { + get + { + return _useToolbarManager & ToolbarManager.ToolbarAvailable; + } + set + { + if (_useToolbarManager == value) + { + return; + } + + if (value == false && this.ToolbarButton != null) + { + this.ToolbarButton.Destroy(); + this.ToolbarButton = null; + } + if (value == true) + { + if (this.AppLauncherButton != null) + { + ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton); + this.AppLauncherButton = null; + } + + this.InitializeToolbarButton(); + } + + _useToolbarManager = value; + } + } + + /* + * Events + * */ + public override event VOIDEventHandler onApplicationQuit; + public override event VOIDEventHandler onSkinChanged; + + /* + * Methods + * */ + public override void DrawGUI() + { + this.windowID = this.windowBaseID; + + if (!this.modulesLoaded) + { + this.LoadModulesOfType(); + } + + if (!this.skinsLoaded) + { + this.LoadSkins(); + } + + GUI.skin = this.Skin; + + if (!this.GUIStylesLoaded) + { + this.LoadGUIStyles(); + + Tools.PostDebugMessage( + this, + "ToolbarAvailable: {0}, UseToobarManager: {1}", + ToolbarManager.ToolbarAvailable, + this.useToolbarManager); + } + + if (!this.useToolbarManager) + { + if (this.AppLauncherButton == null) + { + Tools.PostDebugMessage(this, + "UseToolbarManager = false (ToolbarAvailable = {0}) and " + + "AppLauncherButton is null, making AppLauncher button.", + ToolbarManager.ToolbarAvailable + ); + this.InitializeAppLauncherButton(); + } + } + else if (this.ToolbarButton == null) + { + Tools.PostDebugMessage(this, + "UseToolbarManager = true (ToolbarAvailable = {0}) and " + + "ToolbarButton is null, making Toolbar button.", + ToolbarManager.ToolbarAvailable + ); + this.InitializeToolbarButton(); + } + + this.SetIconTexture(); + + if (this.Active) + { + base.DrawGUI(); + } + } + + public virtual void Update() + { + this.LoadBeforeUpdate(); + + if ( + this.vesselSimActive && + ( + this.Vessel != null || + ( + HighLogic.LoadedSceneIsEditor && + EditorLogic.RootPart != null && + EditorLogic.SortedShipList.Count > 0 + ) + ) + ) + { + Tools.PostDebugMessage(this, "Updating SimManager."); + this.UpdateSimManager(); + } + + if (!this.GUIRunning) + { + this.StartGUI(); + } + + foreach (IVOID_Module module in this.modules) + { + if ( + !module.GUIRunning && + module.Active && + module.InValidScene && + ( + !HighLogic.LoadedSceneIsEditor || + (EditorLogic.RootPart != null && EditorLogic.SortedShipList.Count > 0) + ) + ) + { + module.StartGUI(); + } + if ( + module.GUIRunning && + ( + !module.Active || + !this.togglePower || + !module.InValidScene || + this.FactoryReset || + ( + HighLogic.LoadedSceneIsEditor && + (EditorLogic.RootPart == null || EditorLogic.SortedShipList.Count == 0) + ) + ) + ) + { + module.StopGUI(); + } + + if (module is IVOID_BehaviorModule) + { + ((IVOID_BehaviorModule)module).Update(); + } + } + + this.CheckAndSave(); + this.UpdateTimer += Time.deltaTime; + } + + public virtual void FixedUpdate() + { + bool newPowerState = this.powerAvailable; + + if (this.togglePower && this.consumeResource && + this.Vessel.vesselType != VesselType.EVA && + TimeWarp.deltaTime != 0) + { + float powerReceived = this.Vessel.rootPart.RequestResource( + this.resourceName, + this.resourceRate * TimeWarp.fixedDeltaTime + ); + + if (powerReceived > 0) + { + newPowerState = true; + } + else + { + newPowerState = false; + } + + if (this.powerAvailable != newPowerState) + { + this.powerAvailable = newPowerState; + } + } + + foreach (IVOID_Module module in this.modules) + { + if (module is IVOID_BehaviorModule) + { + ((IVOID_BehaviorModule)module).FixedUpdate(); + } + } + } + + public void OnDestroy() + { + foreach (IVOID_Module module in this.modules) + { + if (module is IVOID_BehaviorModule) + { + ((IVOID_BehaviorModule)module).OnDestroy(); + } + } + + this.Dispose(); + } + + public virtual void OnApplicationQuit() + { + if (this.onApplicationQuit != null) + { + this.onApplicationQuit(this); + } + + this.OnDestroy(); + } + + public override void StartGUI() + { + if (!this.GUIRunning) + { + RenderingManager.AddToPostDrawQueue(3, this.DrawGUI); + } + } + + public void ResetGUI() + { + this.StopGUI(); + + foreach (IVOID_Module module in this.modules) + { + module.StopGUI(); + module.StartGUI(); + } + + this.StartGUI(); + } + + public override void ModuleWindow(int id) + { + GUILayout.BeginVertical(); + + if (this.powerAvailable || !HighLogic.LoadedSceneIsFlight) + { + if (!HighLogic.LoadedSceneIsEditor) + { + string str = string.Intern("ON"); + if (togglePower) + str = string.Intern("OFF"); + if (GUILayout.Button("Power " + str)) + { + togglePower.value = !togglePower; + } + } + + if (togglePower || !HighLogic.LoadedSceneIsFlight) + { + foreach (IVOID_Module module in this.modules) + { + if (module is VOID_ConfigWindow) + { + continue; + } + + module.Active = GUITools.Toggle(module.Active, module.Name); + } + } + } + else + { + GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed); + } + + VOID_ConfigWindow.Instance.Active = GUITools.Toggle( + VOID_ConfigWindow.Instance.Active, + "Configuration" + ); + + GUILayout.EndVertical(); + + base.ModuleWindow(id); + } + + public override void DrawConfigurables() + { + GUIContent _content; + + this.useToolbarManager = GUITools.Toggle(this.useToolbarManager, "Use Blizzy's Toolbar If Available"); + + this.vesselSimActive.value = GUITools.Toggle(this.vesselSimActive.value, + "Enable Engineering Calculations"); + + bool useEarthTime = (this.TimeScale & VOID_TimeScale.KERBIN_TIME) == 0u; + bool useSiderealTime = (this.TimeScale & VOID_TimeScale.SOLAR_DAY) == 0u; + bool useRoundedScale = (this.TimeScale & VOID_TimeScale.ROUNDED_SCALE) != 0u; + + useEarthTime = GUITools.Toggle(useEarthTime, "Use Earth Time (changes KSP option)"); + + GameSettings.KERBIN_TIME = !useEarthTime; + + useSiderealTime = GUITools.Toggle( + useSiderealTime, + string.Format( + "Time Scale: {0}", + useSiderealTime ? "Sidereal" : "Solar" + ) + ); + + useRoundedScale = GUITools.Toggle( + useRoundedScale, + string.Format( + "Time Scale: {0}", + useRoundedScale ? "Rounded" : "True" + ) + ); + + if (useEarthTime) + { + this.TimeScale &= ~VOID_TimeScale.KERBIN_TIME; + } + else + { + this.TimeScale |= VOID_TimeScale.KERBIN_TIME; + } + + if (useSiderealTime) + { + this.TimeScale &= ~VOID_TimeScale.SOLAR_DAY; + } + else + { + this.TimeScale |= VOID_TimeScale.SOLAR_DAY; + } + + if (useRoundedScale) + { + this.TimeScale |= VOID_TimeScale.ROUNDED_SCALE; + } + else + { + this.TimeScale &= ~VOID_TimeScale.ROUNDED_SCALE; + } + + GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); + + GUILayout.Label("Skin:", GUILayout.ExpandWidth(false)); + + _content = new GUIContent(); + + _content.text = "◄"; + _content.tooltip = "Select previous skin"; + if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) + { + this.skinIdx--; + Tools.PostDebugMessage(string.Format( + "{0}: new this.skinIdx = {1} :: skin_list.Count = {2}", + this.GetType().Name, + this.skinName, + this.validSkins.Count + )); + } + + _content.text = this.Skin.name; + _content.tooltip = "Current skin"; + GUILayout.Label(_content, VOID_Styles.labelCenter, GUILayout.ExpandWidth(true)); + + _content.text = "►"; + _content.tooltip = "Select next skin"; + if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) + { + this.skinIdx++; + Tools.PostDebugMessage(string.Format( + "{0}: new this.skinIdx = {1} :: skin_list.Count = {2}", + this.GetType().Name, + this.skinName, + this.validSkins.Count + )); + } + + this.skinIdx %= this.skinNames.Length; + if (this.skinIdx < 0) + { + this.skinIdx += this.skinNames.Length; + } + + if (this.skinName != skinNames[this.skinIdx]) + { + this.skinName.value = skinNames[this.skinIdx]; + this.GUIStylesLoaded = false; + } + + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + GUILayout.Label("Update Rate (Hz):"); + if (this.stringFrequency == null) + { + this.stringFrequency = (1f / this.UpdatePeriod).ToString(); + } + this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true)); + + if (GUILayout.Button("Apply")) + { + double updateFreq = 1f / this.UpdatePeriod; + double.TryParse(stringFrequency, out updateFreq); + this.updatePeriod.value = 1 / updateFreq; + } + GUILayout.EndHorizontal(); + + foreach (IVOID_Module mod in this.modules) + { + mod.DrawConfigurables(); + } + + this.FactoryReset = GUITools.Toggle(this.FactoryReset, "Factory Reset"); + } + + protected void UpdateSimManager() + { + if (HighLogic.LoadedSceneIsFlight) + { + double radius = this.Vessel.Radius(); + SimManager.Gravity = this.Vessel.mainBody.gravParameter / (radius * radius); + SimManager.Atmosphere = this.Vessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres; + SimManager.Mach = this.Vessel.mach; + BuildAdvanced.Altitude = this.Vessel.altitude; + CelestialBodies.SelectedBody = this.Vessel.mainBody; + } + + #if DEBUG + SimManager.logOutput = true; + #endif + + SimManager.TryStartSimulation(); + + Tools.PostDebugMessage(this, "Started Engineer simulation with Atmosphere={0} atm and Gravity={1} m/s²", + SimManager.Atmosphere, + SimManager.Gravity + ); + } + + protected void GetSimManagerResults() + { + Tools.PostDebugMessage(this, "VesselSimulator results ready, setting Stages."); + + this.Stages = SimManager.Stages; + + if (this.Stages != null) + { + this.LastStage = this.Stages.Last(); + } + } + + protected void LoadModulesOfType() + { + Tools.DebugLogger sb = Tools.DebugLogger.New(this); + sb.AppendLine("Loading modules..."); + + foreach (AssemblyLoader.LoadedAssembly assy in AssemblyLoader.loadedAssemblies) + { + foreach (Type loadedType in assy.assembly.GetExportedTypes()) + { + if ( + loadedType.IsInterface || + loadedType.IsAbstract || + !typeof(U).IsAssignableFrom(loadedType) || + typeof(VOIDCore).IsAssignableFrom(loadedType) + ) + { + continue; + } + + sb.AppendFormat("Checking IVOID_Module type {0}...", loadedType.Name); + + try + { + this.LoadModule(loadedType); + sb.AppendLine("Success."); + } + catch (Exception ex) + { + sb.AppendFormat("Failed, caught {0}\n", ex.GetType().Name); + + #if DEBUG + Debug.LogException(ex); + #endif + } + } + } + + this.modulesLoaded = true; + + sb.AppendFormat("Loaded {0} modules.\n", this.Modules.Count); + + sb.Print(); + } + + protected void LoadModule(Type T) + { + var existingModules = this.modules.Where(mod => mod.GetType().Name == T.Name); + if (existingModules.Any()) + { + Tools.PostDebugMessage(string.Format( + "{0}: refusing to load {1}: already loaded", + this.GetType().Name, + T.Name + )); + return; + } + + var InstanceProperty = T.GetProperty( + "Instance", + System.Reflection.BindingFlags.Static | + System.Reflection.BindingFlags.Public | + System.Reflection.BindingFlags.FlattenHierarchy + ); + + object modInstance = null; + IVOID_Module module; + + if (InstanceProperty != null) + { + modInstance = InstanceProperty.GetValue(null, null); + } + + if (modInstance != null) + { + module = modInstance as IVOID_Module; + } + else + { + module = Activator.CreateInstance(T) as IVOID_Module; + } + + if (module.InValidGame && module.InValidScene) + { + module.LoadConfig(); + this.modules.Add(module); + + Tools.PostDebugMessage(string.Format( + "{0}: loaded module {1}.", + this.GetType().Name, + T.Name + )); + } + else + { + if (module is IDisposable) + { + (module as IDisposable).Dispose(); + } + } + } + + protected void LoadSkins() + { + Tools.PostDebugMessage("AssetBase has skins: \n" + + string.Join("\n\t", + Resources.FindObjectsOfTypeAll(typeof(GUISkin)) + .Select(s => s.ToString()) + .ToArray() + ) + ); + + this.validSkins = Resources.FindObjectsOfTypeAll(typeof(GUISkin)) + .Where(s => !this.forbiddenSkins.Contains(s.name)) + .Select(s => s as GUISkin) + .GroupBy(s => s.name) + .Select(g => g.First()) + .ToDictionary(s => s.name); + + Tools.PostDebugMessage(string.Format( + "{0}: loaded {1} GUISkins.", + this.GetType().Name, + this.validSkins.Count + )); + + this.skinNames = this.validSkins.Keys.ToArray(); + Array.Sort(this.skinNames); + + int defaultIdx = int.MinValue; + + for (int i = 0; i < this.skinNames.Length; i++) + { + if (this.skinNames[i] == this.skinName) + { + this.skinIdx = i; + } + if (this.skinNames[i] == this.defaultSkin) + { + defaultIdx = i; + } + if (this.skinIdx != int.MinValue && defaultIdx != int.MinValue) + { + break; + } + } + + if (this.skinIdx == int.MinValue) + { + this.skinIdx = defaultIdx; + } + + Tools.PostDebugMessage(string.Format( + "{0}: _skinIdx = {1}.", + this.GetType().Name, + this.skinName.ToString() + )); + + this.skinsLoaded = true; + } + + protected void LoadGUIStyles() + { + VOID_Styles.OnSkinChanged(); + + if (this.onSkinChanged != null) + { + this.onSkinChanged(this); + } + + this.GUIStylesLoaded = true; + } + + protected void LoadVesselTypes() + { + this.AllVesselTypes = Enum.GetValues(typeof(VesselType)).OfType().ToArray(); + this.vesselTypesLoaded = true; + } + + protected void LoadBeforeUpdate() + { + if (!this.vesselTypesLoaded) + { + this.LoadVesselTypes(); + } + + if (this.SortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0) + { + this.SortedBodyList = new List(FlightGlobals.Bodies); + this.SortedBodyList.Sort(new CBListComparer()); + this.SortedBodyList.Reverse(); + + Debug.Log(string.Format("sortedBodyList: {0}", string.Join("\n\t", this.SortedBodyList.Select(b => b.bodyName).ToArray()))); + } + + // SimManager initialization that we don't necessarily want to repeat every Update. + if (!this.simManagerLoaded && this.HomeBody != null) + { + SimManager.Gravity = VOID_Data.KerbinGee; + SimManager.Atmosphere = 0d; + SimManager.Mach = 1d; + CelestialBodies.SelectedBody = this.HomeBody; + BuildAdvanced.Altitude = 0d; + SimManager.OnReady += this.GetSimManagerResults; + + this.simManagerLoaded = true; + } + } + + protected void InitializeToolbarButton() + { + // Do nothing if (the Toolbar is not available. + if (!ToolbarManager.ToolbarAvailable) + { + Tools.PostDebugMessage(this, "Refusing to make a ToolbarButton: ToolbarAvailable = false"); + return; + } + + this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle"); + this.ToolbarButton.Text = this.VoidName; + this.SetIconTexture(this.powerState | this.activeState); + + this.ToolbarButton.Visible = true; + + this.ToolbarButton.OnClick += + (e) => + { + this.ToggleMainWindow(); + }; + + Tools.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name)); + } + + protected void InitializeAppLauncherButton() + { + if (ApplicationLauncher.Ready) + { + this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication( + this.ToggleMainWindow, this.ToggleMainWindow, + this.appIconVisibleScenes, + this.VOIDIconTexture + ); + + Tools.PostDebugMessage( + this, + "AppLauncherButton initialized in {0}", + Enum.GetName( + typeof(GameScenes), + HighLogic.LoadedScene + ) + ); + } + } + + protected void ToggleMainWindow() + { + this.Active = !this.Active; + } + + protected void SetIconTexture() + { + if ( + this.iconState != (this.powerState | this.activeState) || + (this.VOIDIconTexture == null && this.AppLauncherButton != null) + ) + { + this.iconState = this.powerState | this.activeState; + + this.SetIconTexture(this.iconState); + } + } + + protected void SetIconTexture(IconState state) + { + switch (state) + { + case (IconState.PowerOff | IconState.Inactive): + this.SetIconTexture(this.VOIDIconOffInactivePath); + break; + case (IconState.PowerOff | IconState.Active): + this.SetIconTexture(this.VOIDIconOffActivePath); + break; + case (IconState.PowerOn | IconState.Inactive): + this.SetIconTexture(this.VOIDIconOnInactivePath); + break; + case (IconState.PowerOn | IconState.Active): + this.SetIconTexture(this.VOIDIconOnActivePath); + break; + default: + throw new NotImplementedException(); + } + } + + protected void SetIconTexture(string texturePath) + { + if (texturePath == null) + { + return; + } + + if (this.ToolbarButton != null) + { + this.ToolbarButton.TexturePath = texturePath; + } + + if (this.AppLauncherButton != null) + { + this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false); + + this.AppLauncherButton.SetTexture(VOIDIconTexture); + } + } + + protected virtual void CheckAndSave() + { + this.saveTimer += Time.deltaTime; + + if (this.saveTimer > 2f) + { + if (!this.configDirty) + { + return; + } + + Tools.PostDebugMessage(string.Format( + "{0}: Time to save, checking if configDirty: {1}", + this.GetType().Name, + this.configDirty + )); + + this.SaveConfig(); + this.saveTimer = 0; + } + } + + public override void LoadConfig() + { + base.LoadConfig(); + + foreach (IVOID_Module module in this.modules) + { + module.LoadConfig(); + } + + this.TimeScale |= GameSettings.KERBIN_TIME ? VOID_TimeScale.KERBIN_TIME : 0u; + } + + public override void SaveConfig() + { + if (this.configNeedsUpdate && this is VOIDCore_Flight) + { + KSP.IO.File.Delete("config.xml"); + } + + var config = KSP.IO.PluginConfiguration.CreateForType(); + + config.load(); + + this.Save(config); + + foreach (IVOID_Module module in this.modules) + { + module.Save(config); + } + + config.save(); + + this.configDirty = false; + } + + public VOIDCore_Generic() + { + System.Version version = this.GetType().Assembly.GetName().Version; + + this.VoidVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.MajorRevision); + + this.Name = string.Format("VOID {0}", this.VoidVersion.ToString()); + + this.powerAvailable = true; + + this.Active = true; + + this.skinName = (VOID_SaveValue)this.defaultSkin; + this.skinIdx = int.MinValue; + + this.VOIDIconOnActivePath = "VOID/Textures/void_icon_light_glow"; + this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_dark_glow"; + this.VOIDIconOffActivePath = "VOID/Textures/void_icon_light"; + this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_dark"; + + this.saveTimer = 0f; + this.UpdateTimer = 0f; + + this.vesselSimActive = (VOID_SaveValue)true; + + this.useToolbarManager = ToolbarManager.ToolbarAvailable; + + this.LoadConfig(); + + this.configVersion = (VOID_SaveValue)VOIDCore.CONFIG_VERSION; + + this.FactoryReset = false; + } + + public override void Dispose() + { + this.StopGUI(); + + this.onSkinChanged(this); + + if (this.AppLauncherButton != null) + { + ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton); + this.AppLauncherButton = null; + } + if (this.ToolbarButton != null) + { + this.ToolbarButton.Destroy(); + this.ToolbarButton = null; + } + + _instance = null; + _initialized = false; + } + } +} + --- /dev/null +++ b/VOIDCore_SpaceCentre.cs @@ -1,1 +1,39 @@ +// VOID +// +// VOIDCore_SpaceCentre.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using System; +namespace VOID +{ + [VOID_Scenes(GameScenes.SPACECENTER)] + public class VOIDCore_SpaceCentre : VOIDCore_Generic + { + public override void FixedUpdate() {} + } +} + + --- a/VOIDEditorMaster.cs +++ /dev/null @@ -1,130 +1,1 @@ -// VOID -// -// VOIDEditorMaster.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// -// -// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors -// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some -// invaluable functions and making your nicely written code available to learn from. -// -/////////////////////////////////////////////////////////////////////////////// -// -// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux. -// Engineer Redux (c) 2013 cybutek -// Used by permission. -// -/////////////////////////////////////////////////////////////////////////////// -using KerbalEngineer.VesselSimulator; -using KSP; -using System; -using ToadicusTools; -using UnityEngine; - -namespace VOID -{ - [KSPAddon(KSPAddon.Startup.EditorAny, false)] - public class VOIDEditorMaster : MonoBehaviour - { - protected VOID_EditorCore Core; - - public void Awake() - { - Tools.PostDebugMessage ("VOIDEditorMaster: Waking up."); - this.Core = VOID_EditorCore.Instance; - this.Core.ResetGUI (); - Tools.PostDebugMessage ("VOIDEditorMaster: Awake."); - } - - public void Update() - { - if (!HighLogic.LoadedSceneIsEditor && this.Core != null) - { - this.Core.SaveConfig (); - this.Core = null; - VOID_EditorCore.Reset(); - return; - } - - if (this.Core == null) - { - this.Awake(); - } - - this.Core.Update (); - - if (this.Core.factoryReset) - { - KSP.IO.File.Delete("config.xml"); - this.Core = null; - VOID_EditorCore.Reset(); - } - } - - public void FixedUpdate() - { - if (this.Core == null || !HighLogic.LoadedSceneIsEditor) - { - return; - } - - this.Core.FixedUpdate (); - } - - public void OnGUI() - { - if (this.Core == null) - { - return; - } - - this.Core.OnGUI(); - } - - public void OnDestroy() - { - if (this.Core == null) - { - return; - } - - this.Core.OnDestroy(); - } - - public void OnApplicationQuit() - { - if (this.Core == null) - { - return; - } - - this.Core.OnApplicationQuit(); - } - } -} - --- a/VOIDFlightMaster.cs +++ /dev/null @@ -1,129 +1,1 @@ -// VOID -// -// VOIDFlightMaster.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// -// -// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors -// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some -// invaluable functions and making your nicely written code available to learn from. -// -/////////////////////////////////////////////////////////////////////////////// -// -// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux. -// Engineer Redux (c) 2013 cybutek -// Used by permission. -// -/////////////////////////////////////////////////////////////////////////////// -using System; -using UnityEngine; -using KerbalEngineer.VesselSimulator; -using ToadicusTools; - -namespace VOID -{ - [KSPAddon(KSPAddon.Startup.Flight, false)] - public class VOIDFlightMaster : MonoBehaviour - { - protected VOID_Core Core; - - public void Awake() - { - Tools.PostDebugMessage ("VOIDFlightMaster: Waking up."); - this.Core = (VOID_Core)VOID_Core.Instance; - this.Core.ResetGUI (); - Tools.PostDebugMessage ("VOIDFlightMaster: Awake."); - } - - public void Update() - { - if (!HighLogic.LoadedSceneIsFlight && this.Core != null) - { - this.Core.SaveConfig (); - this.Core = null; - VOID_Core.Reset(); - return; - } - - if (this.Core == null) - { - this.Awake(); - } - - this.Core.Update (); - - if (this.Core.factoryReset) - { - KSP.IO.File.Delete("config.xml"); - this.Core = null; - VOID_Core.Reset(); - } - } - - public void FixedUpdate() - { - if (this.Core == null || !HighLogic.LoadedSceneIsFlight) - { - return; - } - - this.Core.FixedUpdate (); - } - - public void OnGUI() - { - if (this.Core == null) - { - return; - } - - this.Core.OnGUI(); - } - - public void OnDestroy() - { - if (this.Core == null) - { - return; - } - - this.Core.OnDestroy(); - } - - public void OnApplicationQuit() - { - if (this.Core == null) - { - return; - } - - this.Core.OnApplicationQuit(); - } - } -} - --- /dev/null +++ b/VOIDMaster_Editor.cs @@ -1,1 +1,63 @@ +// VOID +// +// VOIDEditorMaster.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// +// +// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors +// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some +// invaluable functions and making your nicely written code available to learn from. +// +/////////////////////////////////////////////////////////////////////////////// +// +// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux. +// Engineer Redux (c) 2013 cybutek +// Used by permission. +// +/////////////////////////////////////////////////////////////////////////////// +using KerbalEngineer.VesselSimulator; +using KSP; +using System; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + [KSPAddon(KSPAddon.Startup.EditorAny, false)] + public class VOIDMaster_Editor : VOIDMaster + { + public override void Awake() + { + Tools.PostDebugMessage ("VOIDEditorMaster: Waking up."); + this.Core = VOIDCore_Editor.Instance; + this.Core.ResetGUI (); + Tools.PostDebugMessage ("VOIDEditorMaster: Awake."); + } + } +} + --- /dev/null +++ b/VOIDMaster_Flight.cs @@ -1,1 +1,62 @@ +// VOID +// +// VOIDFlightMaster.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// +// +// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors +// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some +// invaluable functions and making your nicely written code available to learn from. +// +/////////////////////////////////////////////////////////////////////////////// +// +// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux. +// Engineer Redux (c) 2013 cybutek +// Used by permission. +// +/////////////////////////////////////////////////////////////////////////////// +using System; +using UnityEngine; +using KerbalEngineer.VesselSimulator; +using ToadicusTools; + +namespace VOID +{ + [KSPAddon(KSPAddon.Startup.Flight, false)] + public class VOIDMaster_Flight : VOIDMaster + { + public override void Awake() + { + this.LogDebug("Waking up."); + this.Core = VOIDCore_Flight.Instance; + this.Core.ResetGUI (); + this.LogDebug("Awake."); + } + } +} + --- /dev/null +++ b/VOIDMaster_SpaceCentre.cs @@ -1,1 +1,62 @@ +// VOID +// +// VOIDFlightMaster.cs +// +// Copyright © 2014, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// +// +// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors +// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some +// invaluable functions and making your nicely written code available to learn from. +// +/////////////////////////////////////////////////////////////////////////////// +// +// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux. +// Engineer Redux (c) 2013 cybutek +// Used by permission. +// +/////////////////////////////////////////////////////////////////////////////// +using System; +using UnityEngine; +using KerbalEngineer.VesselSimulator; +using ToadicusTools; + +namespace VOID +{ + [KSPAddon(KSPAddon.Startup.SpaceCentre, false)] + public class VOIDMaster_SpaceCentre : VOIDMaster + { + public override void Awake() + { + this.LogDebug("Waking up."); + this.Core = VOIDCore_SpaceCentre.Instance; + this.Core.ResetGUI (); + this.LogDebug("Awake."); + } + } +} + --- a/VOID_CBInfoBrowser.cs +++ b/VOID_CBInfoBrowser.cs @@ -37,32 +37,39 @@ public class VOID_CBInfoBrowser : VOID_WindowModule { [AVOID_SaveValue("selectedBodyIdx1")] - protected VOID_SaveValue selectedBodyIdx1 = 1; + protected VOID_SaveValue selectedBodyIdx1; [AVOID_SaveValue("selectedBodyIdx2")] - protected VOID_SaveValue selectedBodyIdx2 = 2; + protected VOID_SaveValue selectedBodyIdx2; protected CelestialBody selectedBody1; protected CelestialBody selectedBody2; [AVOID_SaveValue("toggleOrbital")] - protected VOID_SaveValue toggleOrbital = false; + protected VOID_SaveValue toggleOrbital; [AVOID_SaveValue("togglePhysical")] - protected VOID_SaveValue togglePhysical = false; + protected VOID_SaveValue togglePhysical; [AVOID_SaveValue("toggleScience")] - protected VOID_SaveValue toggleScience = false; + protected VOID_SaveValue toggleScience; public VOID_CBInfoBrowser() { - this._Name = "Celestial Body Information Browser"; + this.Name = "Celestial Body Information Browser"; this.WindowPos.x = 10; this.WindowPos.y = 85; + + this.selectedBodyIdx1 = (VOID_SaveValue)1; + this.selectedBodyIdx2 = (VOID_SaveValue)2; + + this.toggleOrbital = (VOID_SaveValue)false; + this.togglePhysical = (VOID_SaveValue)false; + this.toggleScience = (VOID_SaveValue)false; } - public override void ModuleWindow(int _) + public override void ModuleWindow(int id) { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); @@ -75,20 +82,26 @@ GUILayout.BeginVertical(GUILayout.Width(150)); - selectedBody1 = this.core.allBodies[selectedBodyIdx1]; - selectedBody2 = this.core.allBodies[selectedBodyIdx2]; + selectedBody1 = this.core.AllBodies[selectedBodyIdx1]; + selectedBody2 = this.core.AllBodies[selectedBodyIdx2]; GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); if (GUILayout.Button("<", GUILayout.ExpandWidth(false))) { - selectedBodyIdx1--; - if (selectedBodyIdx1 < 0) selectedBodyIdx1 = this.core.allBodies.Count - 1; - } - GUILayout.Label(this.core.allBodies[selectedBodyIdx1].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); + selectedBodyIdx1.value--; + if (selectedBodyIdx1 < 0) + { + selectedBodyIdx1.value = this.core.AllBodies.Count - 1; + } + } + GUILayout.Label(this.core.AllBodies[selectedBodyIdx1].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); if (GUILayout.Button(">", GUILayout.ExpandWidth(false))) { - selectedBodyIdx1++; - if (selectedBodyIdx1 > this.core.allBodies.Count - 1) selectedBodyIdx1 = 0; + selectedBodyIdx1.value++; + if (selectedBodyIdx1 > this.core.AllBodies.Count - 1) + { + selectedBodyIdx1.value = 0; + } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); @@ -97,14 +110,20 @@ GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); if (GUILayout.Button("<", GUILayout.ExpandWidth(false))) { - selectedBodyIdx2--; - if (selectedBodyIdx2 < 0) selectedBodyIdx2 = this.core.allBodies.Count - 1; - } - GUILayout.Label(this.core.allBodies[selectedBodyIdx2].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); + selectedBodyIdx2.value--; + if (selectedBodyIdx2 < 0) + { + selectedBodyIdx2.value = this.core.AllBodies.Count - 1; + } + } + GUILayout.Label(this.core.AllBodies[selectedBodyIdx2].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); if (GUILayout.Button(">", GUILayout.ExpandWidth(false))) { - selectedBodyIdx2++; - if (selectedBodyIdx2 > this.core.allBodies.Count - 1) selectedBodyIdx2 = 0; + selectedBodyIdx2.value++; + if (selectedBodyIdx2 > this.core.AllBodies.Count - 1) + { + selectedBodyIdx2.value = 0; + } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); @@ -184,7 +203,7 @@ GUILayout.Label("Natural satellites:"); GUILayout.Label("Artificial satellites:"); GUILayout.Label("Surface gravity:"); - GUILayout.Label("Atmosphere altitude:"); + GUILayout.Label("Atmosphere Depth:"); GUILayout.Label("Atmospheric O\u2082:"); GUILayout.Label("Has ocean:"); @@ -277,7 +296,7 @@ GUILayout.EndHorizontal(); } - GUI.DragWindow(); + base.ModuleWindow(id); } private void body_OP_show_orbital_info(CelestialBody body) @@ -368,13 +387,13 @@ GUILayout.Label(num_art_sats.ToString(), VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); - double g_ASL = (VOID_Core.Constant_G * body.Mass) / (body.Radius * body.Radius); + double g_ASL = (VOIDCore.Constant_G * body.Mass) / (body.Radius * body.Radius); GUILayout.Label(Tools.MuMech_ToSI(g_ASL) + "m/s²", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); if (body.atmosphere) { - GUILayout.Label("≈ " + Tools.MuMech_ToSI(body.maxAtmosphereAltitude) + "m", + GUILayout.Label("≈ " + Tools.MuMech_ToSI(body.atmosphereDepth) + "m", VOID_Styles.labelRight, GUILayout.ExpandWidth(true)); --- a/VOID_CareerStatus.cs +++ b/VOID_CareerStatus.cs @@ -34,28 +34,29 @@ namespace VOID { - public class VOID_CareerStatus : VOID_WindowModule + [VOID_Scenes(GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER)] + [VOID_GameModes(Game.Modes.CAREER, Game.Modes.SCIENCE_SANDBOX)] + public class VOID_CareerStatus : VOID_SingletonWindow { - public static VOID_CareerStatus Instance - { - get; - private set; + public static string formatDelta(double delta, string numberFormat) + { + if (delta > 0) + { + return string.Format("{0}↑", delta.ToString(numberFormat, Tools.SIFormatter)); + } + else if (delta < 0) + { + return string.Format("{0}↓", delta.ToString(numberFormat, Tools.SIFormatter)); + } + else + { + return "0"; + } } public static string formatDelta(double delta) { - if (delta > 0) - { - return string.Format("{0:#,#.##}↑", delta); - } - else if (delta < 0) - { - return string.Format("{0:#,#.##}↓", delta); - } - else - { - return string.Intern("0"); - } + return formatDelta(delta, "#,##0.##"); } public static string formatDelta(float delta) @@ -67,76 +68,84 @@ private GUIContent repContent; private GUIContent scienceContent; + #pragma warning disable 0414 private Texture2D fundsIconGreen; private Texture2D fundsIconRed; private Texture2D reputationIconGreen; private Texture2D reputationIconRed; private Texture2D scienceIcon; - - public override bool toggleActive + #pragma warning restore 0414 + + public double lastFundsChange + { + get; + private set; + } + + public float lastRepChange + { + get; + private set; + } + + public float lastScienceChange + { + get; + private set; + } + + public double currentFunds + { + get; + private set; + } + + public float currentReputation + { + get; + private set; + } + + public float currentScience + { + get; + private set; + } + + private bool currenciesInitialized { get { - switch (HighLogic.CurrentGame.Mode) - { - case Game.Modes.CAREER: - case Game.Modes.SCIENCE_SANDBOX: - return base.toggleActive; - default: - return false; - } - } - set - { - switch (HighLogic.CurrentGame.Mode) - { - case Game.Modes.CAREER: - case Game.Modes.SCIENCE_SANDBOX: - base.toggleActive = value; - break; - default: - return; - } - } - } - - public double lastFundsChange - { - get; - private set; - } - - public float lastRepChange - { - get; - private set; - } - - public float lastScienceChange - { - get; - private set; - } - - public double currentFunds - { - get; - private set; - } - - public float currentReputation - { - get; - private set; - } - - public float currentScience - { - get; - private set; - } - - public override void ModuleWindow(int _) + Tools.PostDebugMessage( + this, + "Checking init state:" + + "\n\tcurrentFunds={0}" + + "\n\tcurrentScience={1}" + + "\n\tcurrentReputation={2}", + this.currentFunds, + this.currentScience, + this.currentReputation + ); + + return !( + double.IsNaN(this.currentFunds) || + float.IsNaN(this.currentScience) || + float.IsNaN(this.currentReputation) + ); + } + } + + public override void DrawGUI() + { + if (Event.current.type != EventType.Layout && !this.currenciesInitialized) + { + this.initCurrencies(); + } + + base.DrawGUI(); + } + + public override void ModuleWindow(int id) { GUILayout.BeginVertical(); @@ -144,26 +153,26 @@ GUILayout.Label(VOID_Data.fundingStatus.Label); GUILayout.FlexibleSpace(); this.fundsContent.text = VOID_Data.fundingStatus.Value; - GUILayout.Label(this.fundsContent, GUILayout.ExpandWidth(false)); + GUILayout.Label(this.fundsContent, GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label(VOID_Data.reputationStatus.Label); GUILayout.FlexibleSpace(); this.repContent.text = VOID_Data.reputationStatus.Value; - GUILayout.Label(this.repContent, GUILayout.ExpandWidth(false)); + GUILayout.Label(this.repContent, GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label(VOID_Data.scienceStatus.Label); GUILayout.FlexibleSpace(); this.scienceContent.text = VOID_Data.scienceStatus.Value; - GUILayout.Label(this.scienceContent, GUILayout.ExpandWidth(false)); + GUILayout.Label(this.scienceContent, GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); GUILayout.EndVertical(); - GUI.DragWindow(); + base.ModuleWindow(id); } // TODO: Update event handlers to do something useful with the new "reasons" parameter. @@ -183,6 +192,30 @@ { this.lastScienceChange = newValue - this.currentScience; this.currentScience = newValue; + } + + private void onGameStateLoad(ConfigNode node) + { + this.initCurrencies(); + } + + private void initCurrencies() + { + Tools.PostDebugMessage( + this, + "Initializing currencies." + + "\n\tFunding.Instance={0}" + + "ResearchAndDevelopment.Instance={1}" + + "Reputation.Instance={2}", + Funding.Instance == null ? "NULL" : Funding.Instance.ToString(), + ResearchAndDevelopment.Instance == null ? "NULL" : ResearchAndDevelopment.Instance.ToString(), + Reputation.Instance == null ? "NULL" : Reputation.Instance.ToString() + ); + + this.currentFunds = Funding.Instance != null ? Funding.Instance.Funds : double.NaN; + this.currentReputation = Reputation.Instance != null ? Reputation.Instance.reputation : float.NaN; + this.currentScience = ResearchAndDevelopment.Instance != null ? + ResearchAndDevelopment.Instance.Science : float.NaN; } /* @@ -194,13 +227,12 @@ * */ public VOID_CareerStatus() : base() { - VOID_CareerStatus.Instance = this; - - this._Name = "Career Status"; + this.Name = "Career Status"; GameEvents.OnFundsChanged.Add(this.onFundsChange); GameEvents.OnReputationChanged.Add(this.onRepChange); GameEvents.OnScienceChanged.Add(this.onScienceChange); + GameEvents.onGameStateLoad.Add(this.onGameStateLoad); bool texturesLoaded; @@ -221,19 +253,24 @@ this.scienceContent.image = this.scienceIcon; } - this.currentFunds = Funding.Instance != null ? Funding.Instance.Funds : double.NaN; - this.currentReputation = Reputation.Instance != null ? Reputation.Instance.reputation : float.NaN; - this.currentScience = ResearchAndDevelopment.Instance != null ? - ResearchAndDevelopment.Instance.Science : float.NaN; - } - - ~VOID_CareerStatus() + this.currentFunds = double.NaN; + this.currentScience = float.NaN; + this.currentReputation = float.NaN; + } + + public override void Dispose() { GameEvents.OnFundsChanged.Remove(this.onFundsChange); GameEvents.OnReputationChanged.Remove(this.onRepChange); GameEvents.OnScienceChanged.Remove(this.onScienceChange); - - VOID_CareerStatus.Instance = null; + GameEvents.onGameStateLoad.Remove(this.onGameStateLoad); + + base.Dispose(); + } + + ~VOID_CareerStatus() + { + this.Dispose(); } } } --- /dev/null +++ b/VOID_ConfigWindow.cs @@ -1,1 +1,76 @@ +// VOID +// +// VOID_ConfigModule.cs +// +// Copyright © 2015, toadicus +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used +// to endorse or promote products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +using KSP; +using System; +using ToadicusTools; +using UnityEngine; + +namespace VOID +{ + public class VOID_ConfigWindow : VOID_SingletonWindow + { + public override bool InValidScene + { + get + { + return true; + } + } + + public override bool InValidGame + { + get + { + return true; + } + } + + public VOID_ConfigWindow() : base() + { + this.Name = "VOID Configuration"; + } + + public override void ModuleWindow(int id) + { + GUILayout.BeginVertical(); + + this.core.DrawConfigurables(); + + GUILayout.EndVertical(); + + base.ModuleWindow(id); + } + + ~VOID_ConfigWindow() + { + this.Dispose(); + } + } +} + --- a/VOID_Core.cs +++ /dev/null @@ -1,1173 +1,1 @@ -// VOID -// -// VOID_Core.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using KerbalEngineer.VesselSimulator; -using KSP; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using ToadicusTools; -using UnityEngine; - -namespace VOID -{ - public class VOID_Core : VOID_Module, IVOID_Module - { - #region Singleton Members - /* - * Static Members - * */ - protected static bool _initialized = false; - - public static bool Initialized - { - get - { - return _initialized; - } - } - - protected static VOID_Core _instance; - - public static VOID_Core Instance - { - get - { - if (_instance == null) - { - _instance = new VOID_Core(); - _initialized = true; - } - return _instance; - } - } - - public static void Reset() - { - _instance.StopGUI(); - _instance.Dispose(); - _instance = null; - _initialized = false; - } - #endregion - - public static readonly double Constant_G = 6.674e-11; - - /* - * Fields - * */ - protected string VoidName = "VOID"; - protected string VoidVersion; - - protected bool _factoryReset = false; - - [AVOID_SaveValue("configValue")] - protected VOID_SaveValue configVersion = 1; - - protected List _modules = new List(); - protected bool _modulesLoaded = false; - - [AVOID_SaveValue("mainWindowPos")] - protected VOID_SaveValue mainWindowPos = new Rect(475, 575, 10f, 10f); - [AVOID_SaveValue("mainGuiMinimized")] - protected VOID_SaveValue mainGuiMinimized = false; - - [AVOID_SaveValue("configWindowPos")] - protected VOID_SaveValue configWindowPos = new Rect(825, 625, 10f, 10f); - [AVOID_SaveValue("configWindowMinimized")] - - protected VOID_SaveValue configWindowMinimized = true; - [AVOID_SaveValue("VOIDIconPos")] - protected VOID_SaveValue VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 32, 32f, 32f); - - protected Texture2D VOIDIconTexture; - protected string VOIDIconOnActivePath; - protected string VOIDIconOnInactivePath; - protected string VOIDIconOffActivePath; - protected string VOIDIconOffInactivePath; - - protected bool VOIDIconLocked = true; - - protected GUIStyle iconStyle; - - protected int windowBaseID = -96518722; - protected int _windowID = 0; - - protected bool GUIStylesLoaded = false; - - protected CelestialBody _homeBody; - - [AVOID_SaveValue("togglePower")] - public VOID_SaveValue togglePower = true; - public bool powerAvailable = true; - - [AVOID_SaveValue("consumeResource")] - protected VOID_SaveValue consumeResource = false; - - [AVOID_SaveValue("resourceName")] - protected VOID_SaveValue resourceName = "ElectricCharge"; - - [AVOID_SaveValue("resourceRate")] - protected VOID_SaveValue resourceRate = 0.2f; - - [AVOID_SaveValue("updatePeriod")] - protected VOID_SaveValue _updatePeriod = 1001f / 15000f; - protected float _updateTimer = 0f; - protected string stringFrequency; - - [AVOID_SaveValue("vesselSimActive")] - protected VOID_SaveValue vesselSimActive; - - // Vessel Type Housekeeping - protected List _allVesselTypes = new List(); - protected bool vesselTypesLoaded = false; - public float saveTimer = 0; - - protected string defaultSkin = "KSP window 2"; - - [AVOID_SaveValue("defaultSkin")] - protected VOID_SaveValue _skinName; - protected int _skinIdx; - - protected Dictionary validSkins; - protected string[] skinNames; - protected string[] forbiddenSkins = - { - "PlaqueDialogSkin", - "FlagBrowserSkin", - "SSUITextAreaDefault", - "ExperimentsDialogSkin", - "ExpRecoveryDialogSkin", - "KSP window 5", - "KSP window 6", - "PartTooltipSkin", - "KSCContextMenuSkin" - }; - protected bool skinsLoaded = false; - - public bool configDirty; - - [AVOID_SaveValue("UseBlizzyToolbar")] - protected VOID_SaveValue _UseToolbarManager; - internal IButton ToolbarButton; - - internal ApplicationLauncherButton AppLauncherButton; - - /* - * Events - * */ - public delegate void VOIDEventHandler(object sender); - public event VOIDEventHandler onApplicationQuit; - - /* - * Properties - * */ - public bool factoryReset - { - get - { - return this._factoryReset; - } - } - - public List Modules - { - get - { - return this._modules; - } - } - - public GUISkin Skin - { - get - { - if (this.skinsLoaded) - { - try - { - return this.validSkins[this._skinName]; - } - catch - { - } - } - - return AssetBase.GetGUISkin(this.defaultSkin); - } - } - - public int windowID - { - get - { - if (this._windowID == 0) - { - this._windowID = this.windowBaseID; - } - return this._windowID++; - } - } - - public List allBodies - { - get - { - return FlightGlobals.Bodies; - } - } - - public List sortedBodyList - { - get; - private set; - } - - public CelestialBody HomeBody - { - get - { - if (this._homeBody == null) - { - if (Planetarium.fetch != null) - { - this._homeBody = Planetarium.fetch.Home; - } - } - - return this._homeBody; - } - } - - public List allVesselTypes - { - get - { - return this._allVesselTypes; - } - } - - public float updateTimer - { - get - { - return this._updateTimer; - } - } - - public double updatePeriod - { - get - { - return this._updatePeriod; - } - } - - public Stage[] Stages - { - get; - protected set; - } - - public Stage LastStage - { - get; - protected set; - } - - protected IconState powerState - { - get - { - if (this.togglePower && this.powerAvailable) - { - return IconState.PowerOn; - } - else - { - return IconState.PowerOff; - } - - } - } - - protected IconState activeState - { - get - { - if (this.mainGuiMinimized) - { - return IconState.Inactive; - } - else - { - return IconState.Active; - } - - } - } - - protected bool UseToolbarManager - { - get - { - return _UseToolbarManager & ToolbarManager.ToolbarAvailable; - } - set - { - if (this._UseToolbarManager == value) - { - return; - } - - if (value == false && this.ToolbarButton != null) - { - this.ToolbarButton.Destroy(); - this.ToolbarButton = null; - } - if (value == true) - { - if (this.AppLauncherButton != null) - { - ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton); - this.AppLauncherButton = null; - } - - this.InitializeToolbarButton(); - } - - _UseToolbarManager.value = value; - } - } - - protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes - { - get - { - return ApplicationLauncher.AppScenes.FLIGHT; - } - } - - /* - * Methods - * */ - public override void DrawGUI() - { - this._windowID = this.windowBaseID; - - if (!this._modulesLoaded) - { - this.LoadModulesOfType(); - } - - if (!this.skinsLoaded) - { - this.LoadSkins(); - } - - GUI.skin = this.Skin; - - if (!this.GUIStylesLoaded) - { - this.LoadGUIStyles(); - - Tools.PostDebugMessage( - this, - "ToolbarAvailable: {0}, UseToobarManager: {1}", - ToolbarManager.ToolbarAvailable, - this.UseToolbarManager); - } - - if (!this.UseToolbarManager) - { - if (this.AppLauncherButton == null) - { - Tools.PostDebugMessage(this, - "UseToolbarManager = false (ToolbarAvailable = {0}) and " + - "AppLauncherButton is null, making AppLauncher button.", - ToolbarManager.ToolbarAvailable - ); - this.InitializeAppLauncherButton(); - } - } - else if (this.ToolbarButton == null) - { - Tools.PostDebugMessage(this, - "UseToolbarManager = true (ToolbarAvailable = {0}) and " + - "ToolbarButton is null, making Toolbar button.", - ToolbarManager.ToolbarAvailable - ); - this.InitializeToolbarButton(); - } - - if (!this.mainGuiMinimized) - { - - Rect _mainWindowPos = this.mainWindowPos; - - _mainWindowPos = GUILayout.Window( - this.windowID, - _mainWindowPos, - VOID_Tools.GetWindowHandler(this.VOIDMainWindow), - string.Join(" ", new string[] { this.VoidName, this.VoidVersion }), - GUILayout.Width(250), - GUILayout.Height(50) - ); - - if (HighLogic.LoadedSceneIsEditor) - { - _mainWindowPos = Tools.ClampRectToEditorPad(_mainWindowPos); - } - else - { - _mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos); - } - - if (_mainWindowPos != this.mainWindowPos) - { - this.mainWindowPos = _mainWindowPos; - } - } - - if (!this.configWindowMinimized && !this.mainGuiMinimized) - { - Rect _configWindowPos = this.configWindowPos; - - _configWindowPos = GUILayout.Window( - this.windowID, - _configWindowPos, - VOID_Tools.GetWindowHandler(this.VOIDConfigWindow), - string.Join(" ", new string[] { this.VoidName, "Configuration" }), - GUILayout.Width(250), - GUILayout.Height(50) - ); - - if (HighLogic.LoadedSceneIsEditor) - { - _configWindowPos = Tools.ClampRectToEditorPad(_configWindowPos); - } - else - { - _configWindowPos = Tools.ClampRectToScreen(_configWindowPos); - } - - if (_configWindowPos != this.configWindowPos) - { - this.configWindowPos = _configWindowPos; - } - } - } - - public virtual void OnGUI() - { - if (Event.current.type == EventType.Repaint) - { - return; - } - - /* - Tools.PostDebugMessage(string.Format( - "Event.current.type: {0}" + - "\nthis.VOIDIconLocked: {1}" + - "\nEvent.current.mousePosition: {2}" + - "\nVOIDIconPos: ({3}, {4}),({5}, {6})", - Event.current.type, - this.VOIDIconLocked, - Event.current.mousePosition, - this.VOIDIconPos.value.xMin, - this.VOIDIconPos.value.yMin, - this.VOIDIconPos.value.xMax, - this.VOIDIconPos.value.yMax - )); - */ - - if (!this.VOIDIconLocked && - VOIDIconPos.value.Contains(Event.current.mousePosition) - && Event.current.type == EventType.mouseDrag) - { - Tools.PostDebugMessage(string.Format( - "Event.current.type: {0}" + - "\ndelta.x: {1}; delta.y: {2}", - Event.current.type, - Event.current.delta.x, - Event.current.delta.y - )); - - Rect tmp = new Rect(VOIDIconPos); - - tmp.x = Event.current.mousePosition.x - tmp.width / 2; - tmp.y = Event.current.mousePosition.y - tmp.height / 2; - - if (tmp.x > Screen.width - tmp.width) - { - tmp.x = Screen.width - tmp.width; - } - - if (tmp.y > Screen.height - tmp.height) - { - tmp.y = Screen.height - tmp.height; - } - - VOIDIconPos = tmp; - } - } - - public virtual void Update() - { - this.LoadBeforeUpdate(); - - if (this.vessel != null && this.vesselSimActive) - { - Tools.PostDebugMessage(this, "Updating SimManager."); - this.UpdateSimManager(); - } - - if (!this.guiRunning) - { - this.StartGUI(); - } - - if (!HighLogic.LoadedSceneIsFlight && this.guiRunning) - { - this.StopGUI(); - } - - foreach (IVOID_Module module in this.Modules) - { - if (!module.guiRunning && module.toggleActive) - { - module.StartGUI(); - } - if (module.guiRunning && !module.toggleActive || - !this.togglePower || - !HighLogic.LoadedSceneIsFlight || - this.factoryReset) - { - module.StopGUI(); - } - - if (module is IVOID_BehaviorModule) - { - ((IVOID_BehaviorModule)module).Update(); - } - } - - this.CheckAndSave(); - this._updateTimer += Time.deltaTime; - } - - public virtual void FixedUpdate() - { - bool newPowerState = this.powerAvailable; - - if (this.togglePower && this.consumeResource && - this.vessel.vesselType != VesselType.EVA && - TimeWarp.deltaTime != 0) - { - float powerReceived = this.vessel.rootPart.RequestResource( - this.resourceName, - this.resourceRate * TimeWarp.fixedDeltaTime - ); - - if (powerReceived > 0) - { - newPowerState = true; - } - else - { - newPowerState = false; - } - - if (this.powerAvailable != newPowerState) - { - this.powerAvailable = newPowerState; - this.SetIconTexture(this.powerState | this.activeState); - } - } - - foreach (IVOID_Module module in this.Modules) - { - if (module is IVOID_BehaviorModule) - { - ((IVOID_BehaviorModule)module).FixedUpdate(); - } - } - } - - public void OnDestroy() - { - foreach (IVOID_Module module in this.Modules) - { - if (module is IVOID_BehaviorModule) - { - ((IVOID_BehaviorModule)module).OnDestroy(); - } - } - } - - public void OnApplicationQuit() - { - this.onApplicationQuit(this); - } - - public void ResetGUI() - { - this.StopGUI(); - - foreach (IVOID_Module module in this.Modules) - { - module.StopGUI(); - module.StartGUI(); - } - - this.StartGUI(); - } - - public void VOIDMainWindow(int _) - { - GUILayout.BeginVertical(); - - if (this.powerAvailable || HighLogic.LoadedSceneIsEditor) - { - if (!HighLogic.LoadedSceneIsEditor) - { - string str = string.Intern("ON"); - if (togglePower) - str = string.Intern("OFF"); - if (GUILayout.Button("Power " + str)) - { - togglePower.value = !togglePower; - this.SetIconTexture(this.powerState | this.activeState); - } - } - - if (togglePower || HighLogic.LoadedSceneIsEditor) - { - foreach (IVOID_Module module in this.Modules) - { - module.toggleActive = GUILayout.Toggle(module.toggleActive, module.Name); - } - } - } - else - { - GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed); - } - - this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration"); - - GUILayout.EndVertical(); - GUI.DragWindow(); - } - - public void VOIDConfigWindow(int _) - { - GUILayout.BeginVertical(); - - this.DrawConfigurables(); - - GUILayout.EndVertical(); - GUI.DragWindow(); - } - - public override void DrawConfigurables() - { - GUIContent _content; - - if (HighLogic.LoadedSceneIsFlight) - { - this.consumeResource.value = GUILayout.Toggle(this.consumeResource, "Consume Resources"); - - this.VOIDIconLocked = GUILayout.Toggle(this.VOIDIconLocked, "Lock Icon Position"); - } - - this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available"); - - this.vesselSimActive.value = GUILayout.Toggle(this.vesselSimActive.value, - "Enable Engineering Calculations"); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - - GUILayout.Label("Skin:", GUILayout.ExpandWidth(false)); - - _content = new GUIContent(); - - _content.text = "◄"; - _content.tooltip = "Select previous skin"; - if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) - { - this._skinIdx--; - Tools.PostDebugMessage(string.Format( - "{0}: new this._skinIdx = {1} :: skin_list.Count = {2}", - this.GetType().Name, - this._skinName, - this.validSkins.Count - )); - } - - _content.text = this.Skin.name; - _content.tooltip = "Current skin"; - GUILayout.Label(_content, VOID_Styles.labelCenter, GUILayout.ExpandWidth(true)); - - _content.text = "►"; - _content.tooltip = "Select next skin"; - if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) - { - this._skinIdx++; - Tools.PostDebugMessage(string.Format( - "{0}: new this._skinIdx = {1} :: skin_list.Count = {2}", - this.GetType().Name, - this._skinName, - this.validSkins.Count - )); - } - - this._skinIdx %= this.skinNames.Length; - if (this._skinIdx < 0) - { - this._skinIdx += this.skinNames.Length; - } - - if (this._skinName != skinNames[this._skinIdx]) - { - this._skinName.value = skinNames[this._skinIdx]; - this.GUIStylesLoaded = false; - } - - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - GUILayout.Label("Update Rate (Hz):"); - if (this.stringFrequency == null) - { - this.stringFrequency = (1f / this.updatePeriod).ToString(); - } - this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true)); - - if (GUILayout.Button("Apply")) - { - double updateFreq = 1f / this.updatePeriod; - double.TryParse(stringFrequency, out updateFreq); - this._updatePeriod = 1 / updateFreq; - } - GUILayout.EndHorizontal(); - - foreach (IVOID_Module mod in this.Modules) - { - mod.DrawConfigurables(); - } - - this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset"); - } - - protected void UpdateSimManager() - { - if (SimManager.ResultsReady()) - { - Tools.PostDebugMessage(this, "VesselSimulator results ready, setting Stages."); - - this.Stages = SimManager.Stages; - - if (this.Stages != null) - { - this.LastStage = this.Stages.Last(); - } - - if (HighLogic.LoadedSceneIsEditor) - { - SimManager.Gravity = VOID_Data.KerbinGee; - } - else - { - double radius = this.vessel.Radius(); - SimManager.Gravity = this.vessel.mainBody.gravParameter / (radius * radius); - } - - SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)(this.updatePeriod * 1000d)); - - SimManager.TryStartSimulation(); - } - #if DEBUG - else - { - Tools.PostDebugMessage(this, "VesselSimulator results not ready."); - } - #endif - } - - protected void LoadModulesOfType() - { - StringBuilder sb = new StringBuilder("Loading modules..."); - sb.AppendLine(); - - foreach (AssemblyLoader.LoadedAssembly assy in AssemblyLoader.loadedAssemblies) - { - foreach (Type loadedType in assy.assembly.GetExportedTypes()) - { - if ( - loadedType.IsInterface || - loadedType.IsAbstract || - !typeof(T).IsAssignableFrom(loadedType) || - this.GetType().IsAssignableFrom(loadedType) - ) - { - continue; - } - - // HACK: This stops editor modules from loading in flight. It is a dirty hack and should be fixed. - if (!HighLogic.LoadedSceneIsEditor && typeof(IVOID_EditorModule).IsAssignableFrom(loadedType)) - { - continue; - } - - sb.AppendFormat("Loading IVOID_Module type {0}...", loadedType.Name); - - try - { - this.LoadModule(loadedType); - sb.AppendLine("Success."); - } - catch (Exception ex) - { - sb.AppendFormat("Failed, caught {0}", ex.GetType().Name); - sb.AppendLine(); - - #if DEBUG - Debug.LogException(ex); - #endif - } - } - } - - this._modulesLoaded = true; - - sb.AppendFormat("Loaded {0} modules.", this.Modules.Count); - sb.AppendLine(); - } - - protected void LoadModule(Type T) - { - var existingModules = this._modules.Where(mod => mod.GetType().Name == T.Name); - if (existingModules.Any()) - { - Tools.PostDebugMessage(string.Format( - "{0}: refusing to load {1}: already loaded", - this.GetType().Name, - T.Name - )); - return; - } - IVOID_Module module = Activator.CreateInstance(T) as IVOID_Module; - module.LoadConfig(); - this._modules.Add(module); - - Tools.PostDebugMessage(string.Format( - "{0}: loaded module {1}.", - this.GetType().Name, - T.Name - )); - } - - protected void LoadSkins() - { - Tools.PostDebugMessage("AssetBase has skins: \n" + - string.Join("\n\t", - Resources.FindObjectsOfTypeAll(typeof(GUISkin)) - .Select(s => s.ToString()) - .ToArray() - ) - ); - - this.validSkins = Resources.FindObjectsOfTypeAll(typeof(GUISkin)) - .Where(s => !this.forbiddenSkins.Contains(s.name)) - .Select(s => s as GUISkin) - .GroupBy(s => s.name) - .Select(g => g.First()) - .ToDictionary(s => s.name); - - Tools.PostDebugMessage(string.Format( - "{0}: loaded {1} GUISkins.", - this.GetType().Name, - this.validSkins.Count - )); - - this.skinNames = this.validSkins.Keys.ToArray(); - Array.Sort(this.skinNames); - - int defaultIdx = int.MinValue; - - for (int i = 0; i < this.skinNames.Length; i++) - { - if (this.skinNames[i] == this._skinName) - { - this._skinIdx = i; - } - if (this.skinNames[i] == this.defaultSkin) - { - defaultIdx = i; - } - if (this._skinIdx != int.MinValue && defaultIdx != int.MinValue) - { - break; - } - } - - if (this._skinIdx == int.MinValue) - { - this._skinIdx = defaultIdx; - } - - Tools.PostDebugMessage(string.Format( - "{0}: _skinIdx = {1}.", - this.GetType().Name, - this._skinName.ToString() - )); - - this.skinsLoaded = true; - } - - protected void LoadGUIStyles() - { - VOID_Styles.OnSkinChanged(); - - this.GUIStylesLoaded = true; - } - - protected void LoadVesselTypes() - { - this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType().ToList(); - this.vesselTypesLoaded = true; - } - - protected void LoadBeforeUpdate() - { - if (!this.vesselTypesLoaded) - { - this.LoadVesselTypes(); - } - - if (this.sortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0) - { - this.sortedBodyList = new List(FlightGlobals.Bodies); - this.sortedBodyList.Sort(new CBListComparer()); - this.sortedBodyList.Reverse(); - - Debug.Log(string.Format("sortedBodyList: {0}", string.Join("\n\t", this.sortedBodyList.Select(b => b.bodyName).ToArray()))); - } - - } - - protected void InitializeToolbarButton() - { - // Do nothing if (the Toolbar is not available. - if (!ToolbarManager.ToolbarAvailable) - { - Tools.PostDebugMessage(this, "Refusing to make a ToolbarButton: ToolbarAvailable = false"); - return; - } - - this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle"); - this.ToolbarButton.Text = this.VoidName; - this.SetIconTexture(this.powerState | this.activeState); - - this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.EDITOR, GameScenes.FLIGHT); - - this.ToolbarButton.OnClick += - (e) => - { - this.ToggleMainWindow(); - }; - - Tools.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name)); - } - - protected void InitializeAppLauncherButton() - { - if (ApplicationLauncher.Ready) - { - this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication( - this.ToggleMainWindow, this.ToggleMainWindow, - this.appIconVisibleScenes, - this.VOIDIconTexture - ); - - Tools.PostDebugMessage( - this, - "AppLauncherButton initialized in {0}", - Enum.GetName( - typeof(GameScenes), - HighLogic.LoadedScene - ) - ); - } - } - - protected void ToggleMainWindow() - { - this.mainGuiMinimized = !this.mainGuiMinimized; - this.SetIconTexture(this.powerState | this.activeState); - } - - protected void SetIconTexture(IconState state) - { - switch (state) - { - case (IconState.PowerOff | IconState.Inactive): - this.SetIconTexture(this.VOIDIconOffInactivePath); - break; - case (IconState.PowerOff | IconState.Active): - this.SetIconTexture(this.VOIDIconOffActivePath); - break; - case (IconState.PowerOn | IconState.Inactive): - this.SetIconTexture(this.VOIDIconOnInactivePath); - break; - case (IconState.PowerOn | IconState.Active): - this.SetIconTexture(this.VOIDIconOnActivePath); - break; - default: - throw new NotImplementedException(); - } - } - - protected void SetIconTexture(string texturePath) - { - if (this.ToolbarButton != null) - { - this.ToolbarButton.TexturePath = texturePath; - } - - this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false); - - if (this.AppLauncherButton != null) - { - this.AppLauncherButton.SetTexture(VOIDIconTexture); - } - } - - protected void CheckAndSave() - { - this.saveTimer += Time.deltaTime; - - if (this.saveTimer > 2f) - { - if (!this.configDirty) - { - return; - } - - Tools.PostDebugMessage(string.Format( - "{0}: Time to save, checking if configDirty: {1}", - this.GetType().Name, - this.configDirty - )); - - this.SaveConfig(); - this.saveTimer = 0; - } - } - - public override void LoadConfig() - { - base.LoadConfig(); - - foreach (IVOID_Module module in this.Modules) - { - module.LoadConfig(); - } - } - - public void SaveConfig() - { - var config = KSP.IO.PluginConfiguration.CreateForType(); - config.load(); - - this._SaveToConfig(config); - - foreach (IVOID_Module module in this.Modules) - { - module._SaveToConfig(config); - } - - config.save(); - - this.configDirty = false; - } - - protected VOID_Core() - { - this._Name = "VOID Core"; - - System.Version version = this.GetType().Assembly.GetName().Version; - - this.VoidVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.MajorRevision); - - this.toggleActive = true; - - this._skinName = this.defaultSkin; - this._skinIdx = int.MinValue; - - this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_light_glow"; - this.VOIDIconOnActivePath = "VOID/Textures/void_icon_dark_glow"; - this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_light"; - this.VOIDIconOffActivePath = "VOID/Textures/void_icon_dark"; - - this.vesselSimActive = true; - - this.UseToolbarManager = ToolbarManager.ToolbarAvailable; - - this.LoadConfig(); - - this.SetIconTexture(this.powerState | this.activeState); - } - - public virtual void Dispose() - { - if (this.AppLauncherButton != null) - { - ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton); - this.AppLauncherButton = null; - } - if (this.ToolbarButton != null) - { - this.ToolbarButton.Destroy(); - this.ToolbarButton = null; - } - } - - protected enum IconState - { - PowerOff = 1, - PowerOn = 2, - Inactive = 4, - Active = 8 - } - } -} - - --- a/VOID_Data.cs +++ b/VOID_Data.cs @@ -38,6 +38,7 @@ public static class VOID_Data { private static Dictionary dataValues = new Dictionary(); + public static Dictionary DataValues { get @@ -56,7 +57,7 @@ { if (kerbinGee == default(double)) { - kerbinGee = core.HomeBody.gravParameter / (core.HomeBody.Radius * core.HomeBody.Radius); + kerbinGee = Core.HomeBody.gravParameter / (Core.HomeBody.Radius * Core.HomeBody.Radius); } return kerbinGee; @@ -67,21 +68,47 @@ #region Core Data - public static VOID_Core core + public static VOIDCore Core { get { - if (HighLogic.LoadedSceneIsEditor) - { - return VOID_EditorCore.Instance; - } - else - { - return VOID_Core.Instance; + if (!CoreInitialized) + { + return null; + } + + switch (HighLogic.LoadedScene) + { + case GameScenes.EDITOR: + return (VOIDCore)VOIDCore_Editor.Instance; + case GameScenes.FLIGHT: + return (VOIDCore)VOIDCore_Flight.Instance; + case GameScenes.SPACECENTER: + return (VOIDCore)VOIDCore_SpaceCentre.Instance; + default: + return null; } } } + public static bool CoreInitialized + { + get + { + switch (HighLogic.LoadedScene) + { + case GameScenes.EDITOR: + return VOIDCore_Editor.Initialized; + case GameScenes.FLIGHT: + return VOIDCore_Flight.Initialized; + case GameScenes.SPACECENTER: + return VOIDCore_SpaceCentre.Initialized; + default: + return false; + } + } + } + #endregion #region Atmosphere @@ -89,29 +116,29 @@ public static readonly VOID_DoubleValue atmDensity = new VOID_DoubleValue( "Atmosphere Density", - new Func(() => core.vessel.atmDensity * 1000f), + new Func(() => Core.Vessel.atmDensity * 1000d), "g/m³" ); - public static readonly VOID_FloatValue atmLimit = - new VOID_FloatValue( - "Atmosphere Limit", - new Func(() => core.vessel.mainBody.maxAtmosphereAltitude), + public static readonly VOID_DoubleValue atmLimit = + new VOID_DoubleValue( + "Atmosphere Depth", + new Func(() => Core.Vessel.mainBody.atmosphereDepth), "m" ); public static readonly VOID_DoubleValue atmPressure = new VOID_DoubleValue( - "Pressure", - new Func(() => core.vessel.staticPressure), - "atm" - ); - - public static readonly VOID_FloatValue temperature = - new VOID_FloatValue( + "Static Pressure", + new Func(() => Core.Vessel.staticPressurekPa * 1000d), + "Pa" + ); + + public static readonly VOID_DoubleValue temperature = + new VOID_DoubleValue( "Temperature", - new Func(() => core.vessel.flightIntegrator.getExternalTemperature()), - "°C" + new Func(() => Core.Vessel.atmosphericTemperature), + "K" ); #endregion @@ -123,7 +150,7 @@ "Heading", delegate() { - double heading = core.vessel.getSurfaceHeading(); + double heading = Core.Vessel.getSurfaceHeading(); string cardinal = VOID_Tools.get_heading_text(heading); return string.Format( @@ -137,7 +164,7 @@ public static readonly VOID_DoubleValue vesselPitch = new VOID_DoubleValue( "Pitch", - () => core.vessel.getSurfacePitch(), + () => Core.Vessel.getSurfacePitch(), "°" ); @@ -203,7 +230,7 @@ public static readonly VOID_FloatValue mainThrottle = new VOID_FloatValue( "Throttle", - new Func(() => core.vessel.ctrlState.mainThrottle * 100f), + new Func(() => Core.Vessel.ctrlState.mainThrottle * 100f), "%" ); @@ -214,7 +241,7 @@ public static readonly VOID_IntValue partCount = new VOID_IntValue( "Parts", - new Func(() => core.vessel.Parts.Count), + new Func(() => Core.Vessel.Parts.Count), "" ); @@ -237,12 +264,12 @@ "Resource Mass", delegate() { - if (core.Stages == null || core.LastStage == null) - { - return double.NaN; - } - - return core.LastStage.resourceMass; + if (Core.Stages == null || Core.LastStage == null) + { + return double.NaN; + } + + return Core.LastStage.totalResourceMass; }, "tons" ); @@ -252,12 +279,12 @@ "Resource Mass (Stage)", delegate() { - if (core.LastStage == null) - { - return double.NaN; - } - - return core.LastStage.resourceMass; + if (Core.LastStage == null) + { + return double.NaN; + } + + return Core.LastStage.resourceMass; }, "tons" ); @@ -267,12 +294,12 @@ "Total Mass", delegate() { - if (core.Stages == null || core.LastStage == null) - { - return double.NaN; - } - - return core.LastStage.totalMass; + if (Core.Stages == null || Core.LastStage == null) + { + return double.NaN; + } + + return Core.LastStage.totalMass; }, "tons" ); @@ -286,9 +313,9 @@ "DeltaV (Current Stage)", delegate() { - if (core.Stages == null || core.LastStage == null) - return double.NaN; - return core.LastStage.deltaV; + if (Core.Stages == null || Core.LastStage == null) + return double.NaN; + return Core.LastStage.deltaV; }, "m/s" ); @@ -298,9 +325,9 @@ "DeltaV (Total)", delegate() { - if (core.Stages == null || core.LastStage == null) - return double.NaN; - return core.LastStage.totalDeltaV; + if (Core.Stages == null || Core.LastStage == null) + return double.NaN; + return Core.LastStage.totalDeltaV; }, "m/s" ); @@ -314,7 +341,7 @@ "T:W (curr/max)", delegate() { - if (core.Stages == null || core.LastStage == null) + if (Core.Stages == null || Core.LastStage == null) return "N/A"; return string.Format( @@ -330,11 +357,11 @@ "Thrust (curr/max)", delegate() { - if (core.Stages == null || core.LastStage == null) + if (Core.Stages == null || Core.LastStage == null) return "N/A"; - double currThrust = core.LastStage.actualThrust; - double maxThrust = core.LastStage.thrust; + double currThrust = Core.LastStage.actualThrust; + double maxThrust = Core.LastStage.thrust; return string.Format( "{0} / {1}", @@ -349,24 +376,12 @@ "Stage Mass Flow", delegate() { - if (core.LastStage == null) - { - return double.NaN; - } - - double stageIsp = core.LastStage.isp; - double stageThrust = stageNominalThrust; - - Tools.PostDebugMessage(typeof(VOID_Data), "calculating stageMassFlow from:\n" + - "\tstageIsp: {0}\n" + - "\tstageThrust: {1}\n" + - "\tKerbinGee: {2}\n", - stageIsp, - stageThrust, - KerbinGee - ); - - return stageThrust / (stageIsp * KerbinGee); + if (Core.LastStage == null) + { + return double.NaN; + } + + return Core.LastStage.MassFlow(); }, "Mg/s" ); @@ -376,19 +391,12 @@ "Nominal Stage Thrust", delegate() { - if (core.LastStage == null) - { - return double.NaN; - } - - if (core.LastStage.actualThrust == 0d) - { - return core.LastStage.thrust; - } - else - { - return core.LastStage.actualThrust; - } + if (Core.LastStage == null) + { + return double.NaN; + } + + return Core.LastStage.NominalThrust(); }, "kN" ); @@ -402,12 +410,12 @@ "T:W Ratio", delegate() { - if (core.LastStage == null) - { - return double.NaN; - } - - return core.LastStage.actualThrustToWeight; + if (Core.LastStage == null) + { + return double.NaN; + } + + return Core.LastStage.actualThrustToWeight; }, "" ); @@ -419,12 +427,12 @@ "T:W Ratio", delegate() { - if (core.LastStage == null) - { - return double.NaN; - } - - return core.LastStage.thrustToWeight; + if (Core.LastStage == null) + { + return double.NaN; + } + + return Core.LastStage.thrustToWeight; }, "" ); @@ -449,13 +457,13 @@ "Max T:W @ surface", delegate() { - if (core.Stages == null || core.LastStage == null) - return double.NaN; - - double maxThrust = core.LastStage.thrust; - double mass = core.LastStage.totalMass; - double gravity = (VOID_Core.Constant_G * core.vessel.mainBody.Mass) / - (core.vessel.mainBody.Radius * core.vessel.mainBody.Radius); + if (Core.Stages == null || Core.LastStage == null) + return double.NaN; + + double maxThrust = Core.LastStage.thrust; + double mass = Core.LastStage.totalMass; + double gravity = (VOIDCore.Constant_G * Core.Vessel.mainBody.Mass) / + (Core.Vessel.mainBody.Radius * Core.Vessel.mainBody.Radius); double weight = mass * gravity; return maxThrust / weight; @@ -468,12 +476,12 @@ "Thrust Offset", delegate() { - if (core.vessel == null) + if (Core.Vessel == null) { return Vector3d.zero; } - List engineModules = core.vessel.getModulesOfType(); + List engineModules = Core.Vessel.getModulesOfType(); Vector3d thrustPos = Vector3d.zero; Vector3d thrustDir = Vector3d.zero; @@ -532,23 +540,23 @@ thrustDir /= thrust; } - Transform vesselTransform = core.vessel.transform; + Transform vesselTransform = Core.Vessel.transform; thrustPos = vesselTransform.InverseTransformPoint(thrustPos); thrustDir = vesselTransform.InverseTransformDirection(thrustDir); Vector3d thrustOffset = VectorTools.PointDistanceToLine( - thrustPos, thrustDir.normalized, core.vessel.findLocalCenterOfMass()); + thrustPos, thrustDir.normalized, Core.Vessel.findLocalCenterOfMass()); Tools.PostDebugMessage(typeof(VOID_Data), "vesselThrustOffset:\n" + - "\tthrustPos: {0}\n" + - "\tthrustDir: {1}\n" + - "\tthrustOffset: {2}\n" + - "\tvessel.CoM: {3}", + "\tthrustPos: {0}\n" + + "\tthrustDir: {1}\n" + + "\tthrustOffset: {2}\n" + + "\tvessel.CoM: {3}", thrustPos, thrustDir.normalized, thrustOffset, - core.vessel.findWorldCenterOfMass() + Core.Vessel.findWorldCenterOfMass() ); return thrustOffset; @@ -571,7 +579,7 @@ currentAmount = 0d; currentRequirement = 0d; - foreach (Part part in core.vessel.Parts) + foreach (Part part in Core.Vessel.Parts) { if (part.enabled) { @@ -584,9 +592,9 @@ propellantList = engineModule.propellants; } else if (part.tryGetFirstModuleOfType(out enginesFXModule)) - { - propellantList = enginesFXModule.propellants; - } + { + propellantList = enginesFXModule.propellants; + } if (propellantList != null) { @@ -630,9 +638,9 @@ "Crew Onboard", delegate() { - if (core.vessel != null) - { - return core.vessel.GetCrewCount(); + if (Core.Vessel != null) + { + return Core.Vessel.GetCrewCount(); } else { @@ -647,9 +655,9 @@ "Crew Capacity", delegate() { - if (core.vessel != null) - { - return core.vessel.GetCrewCapacity(); + if (Core.Vessel != null) + { + return Core.Vessel.GetCrewCapacity(); } else { @@ -665,41 +673,44 @@ #region Location + public const double kscLongitude = 285.442323427289 * Math.PI / 180d; + public const double kscLatitude = -0.0972112860655246 * Math.PI / 180d; + public static readonly VOID_DoubleValue downrangeDistance = new VOID_DoubleValue( "Downrange Distance", delegate() { - if (core.vessel == null || - Planetarium.fetch == null || - core.vessel.mainBody != Planetarium.fetch.Home) - { - return double.NaN; - } - - double vesselLongitude = core.vessel.longitude * Math.PI / 180d; - double vesselLatitude = core.vessel.latitude * Math.PI / 180d; - - const double kscLongitude = 285.442323427289 * Math.PI / 180d; - const double kscLatitude = -0.0972112860655246 * Math.PI / 180d; - - double diffLon = vesselLongitude - kscLongitude; - double diffLat = vesselLatitude - kscLatitude; - - double sinHalfDiffLat = Math.Sin(diffLat / 2d); - double sinHalfDiffLon = Math.Sin(diffLon / 2d); - - double cosVesselLon = Math.Cos(vesselLongitude); - double cosKSCLon = Math.Cos(kscLongitude); - - double haversine = - sinHalfDiffLat * sinHalfDiffLat + - cosVesselLon * cosKSCLon * sinHalfDiffLon * sinHalfDiffLon; - - double arc = 2d * Math.Atan2(Math.Sqrt(haversine), Math.Sqrt(1d - haversine)); - - return core.vessel.mainBody.Radius * arc; + if (Core.Vessel == null || + Planetarium.fetch == null || + Core.Vessel.mainBody != Planetarium.fetch.Home) + { + return double.NaN; + } + + double vesselLongitude = Core.Vessel.longitude * Math.PI / 180d; + double vesselLatitude = Core.Vessel.latitude * Math.PI / 180d; + + double diffLon = Math.Abs(vesselLongitude - kscLongitude); + + double cosVesselLatitude = Math.Cos(vesselLatitude); + double sinDiffLon = Math.Sin(diffLon); + + double term1 = cosVesselLatitude * sinDiffLon; + + double cosKSCLatitude = Math.Cos(kscLatitude); + double sinVesselLatitude = Math.Sin(vesselLatitude); + double sinKSCLatitude = Math.Sin(kscLatitude); + double cosDiffLon = Math.Cos(diffLon); + + double term2 = cosKSCLatitude * sinVesselLatitude - sinKSCLatitude * cosVesselLatitude * cosDiffLon; + + double term3 = sinKSCLatitude * sinVesselLatitude + cosKSCLatitude * cosVesselLatitude * cosDiffLon; + + double arc = Math.Atan2(Math.Sqrt(term1 * term1 + term2 * term2), term3); + + return arc * Core.Vessel.mainBody.Radius; }, "m" ); @@ -707,13 +718,13 @@ public static readonly VOID_StrValue surfLatitude = new VOID_StrValue( "Latitude", - new Func(() => VOID_Tools.GetLatitudeString(core.vessel)) + new Func(() => VOID_Tools.GetLatitudeString(Core.Vessel)) ); public static readonly VOID_StrValue surfLongitude = new VOID_StrValue( "Longitude", - new Func(() => VOID_Tools.GetLongitudeString(core.vessel)) + new Func(() => VOID_Tools.GetLongitudeString(Core.Vessel)) ); public static readonly VOID_DoubleValue trueAltitude = @@ -721,11 +732,11 @@ "Altitude (true)", delegate() { - double alt_true = core.vessel.orbit.altitude - core.vessel.terrainAltitude; + double alt_true = Core.Vessel.orbit.altitude - Core.Vessel.terrainAltitude; // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m, // and water covers the whole surface at 0 m. - if (core.vessel.terrainAltitude < 0 && core.vessel.mainBody.ocean) - alt_true = core.vessel.orbit.altitude; + if (Core.Vessel.terrainAltitude < 0 && Core.Vessel.mainBody.ocean) + alt_true = Core.Vessel.orbit.altitude; return alt_true; }, "m" @@ -738,28 +749,28 @@ public static readonly VOID_DoubleValue geeForce = new VOID_DoubleValue( "G-force", - new Func(() => core.vessel.geeForce), + new Func(() => Core.Vessel.geeForce), "gees" ); public static readonly VOID_DoubleValue horzVelocity = new VOID_DoubleValue( "Horizontal speed", - new Func(() => core.vessel.horizontalSrfSpeed), + new Func(() => Core.Vessel.horizontalSrfSpeed), "m/s" ); public static readonly VOID_DoubleValue surfVelocity = new VOID_DoubleValue( "Surface velocity", - new Func(() => core.vessel.srf_velocity.magnitude), + new Func(() => Core.Vessel.srf_velocity.magnitude), "m/s" ); public static readonly VOID_DoubleValue vertVelocity = new VOID_DoubleValue( "Vertical speed", - new Func(() => core.vessel.verticalSpeed), + new Func(() => Core.Vessel.verticalSpeed), "m/s" ); @@ -775,9 +786,9 @@ "Angular Velocity", delegate() { - if (core.vessel != null) - { - return core.vessel.angularVelocity.magnitude; + if (Core.Vessel != null) + { + return Core.Vessel.angularVelocity.magnitude; } else { @@ -795,14 +806,14 @@ { get { - if (core.vessel == null || - core.vessel.patchedConicSolver == null || - core.vessel.patchedConicSolver.maneuverNodes == null) + if (Core.Vessel == null || + Core.Vessel.patchedConicSolver == null || + Core.Vessel.patchedConicSolver.maneuverNodes == null) { return 0; } - return core.vessel.patchedConicSolver.maneuverNodes.Count; + return Core.Vessel.patchedConicSolver.maneuverNodes.Count; } } @@ -811,12 +822,12 @@ "Full burn time to be half done at node", delegate() { - if (core.LastStage == null && upcomingManeuverNodes < 1) + if (Core.LastStage == null && upcomingManeuverNodes < 1) { return "N/A"; } - ManeuverNode node = core.vessel.patchedConicSolver.maneuverNodes[0]; + ManeuverNode node = Core.Vessel.patchedConicSolver.maneuverNodes[0]; if ((node.UT - Planetarium.GetUniversalTime()) < 0) { @@ -853,12 +864,12 @@ "Full burn time to be half done at node", delegate() { - if (core.LastStage == null && upcomingManeuverNodes < 1) + if (Core.LastStage == null && upcomingManeuverNodes < 1) { return "N/A"; } - ManeuverNode node = core.vessel.patchedConicSolver.maneuverNodes[0]; + ManeuverNode node = Core.Vessel.patchedConicSolver.maneuverNodes[0]; if ((node.UT - Planetarium.GetUniversalTime()) < 0) { @@ -897,7 +908,7 @@ { if (upcomingManeuverNodes > 0) { - return core.vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude; + return Core.Vessel.patchedConicSolver.maneuverNodes[0].DeltaV.magnitude; } else { @@ -914,7 +925,7 @@ { if (upcomingManeuverNodes > 0) { - return core.vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(core.vessel.orbit).magnitude; + return Core.Vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(Core.Vessel.orbit).magnitude; } else { @@ -929,14 +940,12 @@ "Total Burn Time", delegate() { - if (core.LastStage == null || currManeuverDeltaV.Value == double.NaN) - { - return double.NaN; - } - - double stageThrust = stageNominalThrust; - - return burnTime(currManeuverDeltaV.Value, totalMass, stageMassFlow, stageThrust); + if (currManeuverDeltaV.Value == double.NaN) + { + return double.NaN; + } + + return realVesselBurnTime(currManeuverDeltaV.Value); }, "s" ); @@ -946,14 +955,12 @@ "Burn Time Remaining", delegate() { - if (core.LastStage == null || currManeuverDVRemaining == double.NaN) - { - return double.NaN; - } - - double stageThrust = stageNominalThrust; - - return burnTime(currManeuverDVRemaining, totalMass, stageMassFlow, stageThrust); + if (currManeuverDVRemaining.Value == double.NaN) + { + return double.NaN; + } + + return realVesselBurnTime(currManeuverDVRemaining.Value); }, "s" ); @@ -963,14 +970,12 @@ "Half Burn Time", delegate() { - if (core.LastStage == null || currManeuverDeltaV.Value == double.NaN) - { - return double.NaN; - } - - double stageThrust = stageNominalThrust; - - return burnTime(currManeuverDeltaV.Value / 2d, totalMass, stageMassFlow, stageThrust); + if (currManeuverDeltaV.Value == double.NaN) + { + return double.NaN; + } + + return realVesselBurnTime(currManeuverDeltaV.Value / 2d); }, "s" ); @@ -982,7 +987,7 @@ { if (upcomingManeuverNodes > 1) { - return core.vessel.patchedConicSolver.maneuverNodes[1].DeltaV.magnitude; + return Core.Vessel.patchedConicSolver.maneuverNodes[1].DeltaV.magnitude; } else { @@ -1001,58 +1006,58 @@ VOID_Localization.void_primary, delegate() { - if (core.vessel == null) + if (Core.Vessel == null) { return string.Empty; } - return core.vessel.mainBody.name; + return Core.Vessel.mainBody.name; } ); public static readonly VOID_DoubleValue orbitAltitude = new VOID_DoubleValue( "Altitude (ASL)", - new Func(() => core.vessel.orbit.altitude), + new Func(() => Core.Vessel.orbit.altitude), "m" ); public static readonly VOID_DoubleValue orbitVelocity = new VOID_DoubleValue( VOID_Localization.void_velocity, - new Func(() => core.vessel.orbit.vel.magnitude), + new Func(() => Core.Vessel.orbit.vel.magnitude), "m/s" ); public static readonly VOID_DoubleValue orbitApoAlt = new VOID_DoubleValue( VOID_Localization.void_apoapsis, - new Func(() => core.vessel.orbit.ApA), + new Func(() => Core.Vessel.orbit.ApA), "m" ); public static readonly VOID_DoubleValue oribtPeriAlt = new VOID_DoubleValue( VOID_Localization.void_periapsis, - new Func(() => core.vessel.orbit.PeA), + new Func(() => Core.Vessel.orbit.PeA), "m" ); public static readonly VOID_StrValue timeToApo = new VOID_StrValue( "Time to Apoapsis", - new Func(() => VOID_Tools.FormatInterval(core.vessel.orbit.timeToAp)) + new Func(() => VOID_Tools.FormatInterval(Core.Vessel.orbit.timeToAp)) ); public static readonly VOID_StrValue timeToPeri = new VOID_StrValue( "Time to Periapsis", - new Func(() => VOID_Tools.FormatInterval(core.vessel.orbit.timeToPe)) + new Func(() => VOID_Tools.FormatInterval(Core.Vessel.orbit.timeToPe)) ); public static readonly VOID_DoubleValue orbitInclination = new VOID_DoubleValue( "Inclination", - new Func(() => core.vessel.orbit.inclination), + new Func(() => Core.Vessel.orbit.inclination), "°" ); @@ -1061,9 +1066,9 @@ "Gravity", delegate() { - double orbitRadius = core.vessel.mainBody.Radius + - core.vessel.mainBody.GetAltitude(core.vessel.findWorldCenterOfMass()); - return (VOID_Core.Constant_G * core.vessel.mainBody.Mass) / + double orbitRadius = Core.Vessel.mainBody.Radius + + Core.Vessel.mainBody.GetAltitude(Core.Vessel.findWorldCenterOfMass()); + return (VOIDCore.Constant_G * Core.Vessel.mainBody.Mass) / (orbitRadius * orbitRadius); }, "m/s²" @@ -1072,63 +1077,107 @@ public static readonly VOID_StrValue orbitPeriod = new VOID_StrValue( "Period", - new Func(() => VOID_Tools.FormatInterval(core.vessel.orbit.period)) + new Func(() => VOID_Tools.FormatInterval(Core.Vessel.orbit.period)) ); public static readonly VOID_DoubleValue semiMajorAxis = new VOID_DoubleValue( "Semi-Major Axis", - new Func(() => core.vessel.orbit.semiMajorAxis), + new Func(() => Core.Vessel.orbit.semiMajorAxis), "m" ); public static readonly VOID_DoubleValue eccentricity = new VOID_DoubleValue( "Eccentricity", - new Func(() => core.vessel.orbit.eccentricity), + new Func(() => Core.Vessel.orbit.eccentricity), "" ); public static readonly VOID_DoubleValue meanAnomaly = new VOID_DoubleValue( "Mean Anomaly", - new Func(() => core.vessel.orbit.meanAnomaly * 180d / Math.PI), + new Func(() => Core.Vessel.orbit.meanAnomaly * 180d / Math.PI), "°" ); public static readonly VOID_DoubleValue trueAnomaly = new VOID_DoubleValue( "True Anomaly", - new Func(() => core.vessel.orbit.trueAnomaly), + new Func(() => Core.Vessel.orbit.trueAnomaly), "°" ); public static readonly VOID_DoubleValue eccAnomaly = new VOID_DoubleValue( "Eccentric Anomaly", - new Func(() => core.vessel.orbit.eccentricAnomaly * 180d / Math.PI), + new Func(() => Core.Vessel.orbit.eccentricAnomaly * 180d / Math.PI), "°" ); public static readonly VOID_DoubleValue longitudeAscNode = new VOID_DoubleValue( "Long. Ascending Node", - new Func(() => core.vessel.orbit.LAN), + new Func(() => Core.Vessel.orbit.LAN), "°" ); public static readonly VOID_DoubleValue argumentPeriapsis = new VOID_DoubleValue( "Argument of Periapsis", - new Func(() => core.vessel.orbit.argumentOfPeriapsis), + new Func(() => Core.Vessel.orbit.argumentOfPeriapsis), "°" + ); + + public static readonly VOID_StrValue timeToAscendingNode = + new VOID_StrValue( + "Time to Ascending Node", + delegate() + { + double trueAnomalyAscNode = 360d - argumentPeriapsis; + double dTAscNode = Core.Vessel.orbit.GetDTforTrueAnomaly( + trueAnomalyAscNode * Mathf.Deg2Rad, + Core.Vessel.orbit.period + ); + + dTAscNode %= Core.Vessel.orbit.period; + + if (dTAscNode < 0d) + { + dTAscNode += Core.Vessel.orbit.period; + } + + return VOID_Tools.FormatInterval(dTAscNode); + } + ); + + public static readonly VOID_StrValue timeToDescendingNode = + new VOID_StrValue( + "Time to Descending Node", + delegate() + { + double trueAnomalyAscNode = 180d - argumentPeriapsis; + double dTDescNode = Core.Vessel.orbit.GetDTforTrueAnomaly( + trueAnomalyAscNode * Mathf.Deg2Rad, + Core.Vessel.orbit.period + ); + + dTDescNode %= Core.Vessel.orbit.period; + + if (dTDescNode < 0d) + { + dTDescNode += Core.Vessel.orbit.period; + } + + return VOID_Tools.FormatInterval(dTDescNode); + } ); public static readonly VOID_DoubleValue localSiderealLongitude = new VOID_DoubleValue( "Local Sidereal Longitude", new Func(() => VOID_Tools.FixDegreeDomain( - core.vessel.longitude + core.vessel.orbit.referenceBody.rotationAngle)), + Core.Vessel.longitude + Core.Vessel.orbit.referenceBody.rotationAngle)), "°" ); @@ -1139,13 +1188,23 @@ public static readonly VOID_StrValue expSituation = new VOID_StrValue( "Situation", - new Func(() => core.vessel.GetExperimentSituation().HumanString()) + new Func(() => Core.Vessel.GetExperimentSituation().HumanString()) ); public static readonly VOID_StrValue currBiome = new VOID_StrValue( "Biome", - new Func(() => VOID_Tools.GetBiome(core.vessel).name) + delegate() + { + if (Core.Vessel.landedAt == string.Empty) + { + return VOID_Tools.GetBiome(Core.Vessel).name; + } + else + { + return Core.Vessel.landedAt; + } + } ); #endregion @@ -1155,7 +1214,7 @@ public static readonly VOID_DoubleValue terrainElevation = new VOID_DoubleValue( "Terrain elevation", - new Func(() => core.vessel.terrainAltitude), + new Func(() => Core.Vessel.terrainAltitude), "m" ); @@ -1164,10 +1223,10 @@ private static double burnTime(double deltaV, double initialMass, double massFlow, double thrust) { Tools.PostDebugMessage(typeof(VOID_Data), "calculating burnTime from:\n" + - "\tdeltaV: {0}\n" + - "\tinitialMass: {1}\n" + - "\tmassFlow: {2}\n" + - "\tthrust: {3}\n", + "\tdeltaV: {0}\n" + + "\tinitialMass: {1}\n" + + "\tmassFlow: {2}\n" + + "\tthrust: {3}\n", deltaV, initialMass, massFlow, @@ -1175,7 +1234,46 @@ ); return initialMass / massFlow * (1d - Math.Exp(-deltaV * massFlow / thrust)); } + + private static double dVfromBurnTime(double time, double initialMass, double massFlow, double thrust) + { + return -thrust / massFlow * Math.Log(1d - time * massFlow / initialMass); + } + + private static double realVesselBurnTime(double deltaV) + { + if (Core.Stages == null || Core.Stages.Length < 1) + { + return double.NaN; + } + + double burntime = 0d; + double dVRemaining = deltaV; + + int stageIdx = Core.Stages.Length - 1; + + while (dVRemaining > double.Epsilon) + { + if (stageIdx < 0) + { + return double.PositiveInfinity; + } + + Stage stage = Core.Stages[stageIdx]; + + if (stage.deltaV > 0) + { + double stageDVUsed = Math.Min(stage.deltaV, dVRemaining); + + burntime += burnTime(stageDVUsed, stage.totalMass, stage.MassFlow(), stage.NominalThrust()); + dVRemaining -= stageDVUsed; + } + + stageIdx--; + } + + return burntime; + } } } - --- a/VOID_DataLogger.cs +++ b/VOID_DataLogger.cs @@ -45,6 +45,9 @@ protected bool _loggingActive; protected bool firstWrite; + + [AVOID_SaveValue("waitForLaunch")] + protected VOID_SaveValue waitForLaunch; [AVOID_SaveValue("logInterval")] protected VOID_SaveValue logInterval; @@ -101,10 +104,10 @@ if (this._fileName == null || this._fileName == string.Empty) { this._fileName = KSP.IO.IOUtils.GetFilePathFor( - typeof(VOID_Core), + typeof(VOIDCore), string.Format( "{0}_{1}", - this.vessel.vesselName, + this.Vessel.vesselName, "data.csv" ), null @@ -194,7 +197,7 @@ // CSV Logging // from ISA MapSat - if (loggingActive) + if (loggingActive && (!waitForLaunch || this.Vessel.situation != Vessel.Situations.PRELAUNCH)) { //data logging is on //increment timers @@ -234,7 +237,7 @@ this.logIntervalStr = this.logInterval.value.ToString("#.0##"); } - public override void ModuleWindow(int _) + public override void ModuleWindow(int id) { GUILayout.BeginVertical(); @@ -255,12 +258,17 @@ activeLabelStyle = VOID_Styles.labelGreen; } - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - - this.loggingActive = GUILayout.Toggle(loggingActive, "Data logging: ", GUILayout.ExpandWidth(false)); - GUILayout.Label(activeLabelText, activeLabelStyle, GUILayout.ExpandWidth(true)); - - GUILayout.EndHorizontal(); + this.loggingActive = GUITools.Toggle( + loggingActive, + string.Format("Data logging: {0}", activeLabelText), + null, + activeLabelStyle + ); + + this.waitForLaunch.value = GUITools.Toggle( + this.waitForLaunch, + "Wait for launch" + ); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); @@ -280,7 +288,7 @@ GUILayout.EndVertical(); - GUI.DragWindow(); + base.ModuleWindow(id); } #endregion @@ -309,6 +317,8 @@ "\"Altitude above terrain (m)\"," + "\"Surface Latitude (°)\"," + "\"Surface Longitude (°)\"," + + "\"Apoapsis Altitude (m)\"," + + "\"Periapsis Altitude (m)\"," + "\"Orbital Velocity (m/s)\"," + "\"Surface Velocity (m/s)\"," + "\"Vertical Speed (m/s)\"," + @@ -327,7 +337,7 @@ line.Append(','); //Mission time - line.Append(vessel.missionTime.ToString("F3")); + line.Append(Vessel.missionTime.ToString("F3")); line.Append(','); //Altitude ASL @@ -350,6 +360,14 @@ line.Append('"'); line.Append(','); + // Apoapsis Altitude + line.Append(VOID_Data.orbitApoAlt.Value.ToString("G3")); + line.Append(','); + + // Periapsis Altitude + line.Append(VOID_Data.oribtPeriAlt.Value.ToString("G3")); + line.Append(','); + //Orbital velocity line.Append(VOID_Data.orbitVelocity.Value.ToString("F3")); line.Append(','); @@ -454,13 +472,15 @@ public VOID_DataLogger() { - this._Name = "CSV Data Logger"; + this.Name = "CSV Data Logger"; this.loggingActive = false; this.firstWrite = true; - this.logInterval = 0.5f; - this.csvCollectTimer = 0f; + this.waitForLaunch = (VOID_SaveValue)true; + + this.logInterval = (VOID_SaveValue)0.5f; + this.csvCollectTimer = (VOID_SaveValue)0f; this.outstandingWrites = 0; --- a/VOID_DataValue.cs +++ /dev/null @@ -1,379 +1,1 @@ -// VOID -// -// VOID_DataValue.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using System; -using ToadicusTools; -using UnityEngine; - -namespace VOID -{ - public interface IVOID_DataValue - { - string Label { get; } - string Units { get; } - object Value { get; } - - void Refresh(); - string ValueUnitString(); - void DoGUIHorizontal(); - } - - public class VOID_DataValue : IVOID_DataValue - { - /* - * Static Members - * */ - public static implicit operator T(VOID_DataValue v) - { - return (T)v.Value; - } - - /* - * Instance Members - * */ - /* - * Fields - * */ - protected T cache; - protected Func ValueFunc; - protected float lastUpdate; - - /* - * Properties - * */ - public string Label { get; protected set; } - public string Units { get; protected set; } - - object IVOID_DataValue.Value - { - get - { - return (object)this.Value; - } - } - - public T Value - { - get - { - if ( - HighLogic.LoadedSceneIsEditor || - (VOID_Core.Instance.updateTimer - this.lastUpdate > VOID_Core.Instance.updatePeriod) || - (this.lastUpdate > VOID_Core.Instance.updateTimer) - ) - { - this.Refresh(); - } - return (T)this.cache; - } - } - - /* - * Methods - * */ - public VOID_DataValue(string Label, Func ValueFunc, string Units = "") - { - this.Label = Label; - this.Units = Units; - this.ValueFunc = ValueFunc; - this.lastUpdate = 0; - - VOID_Data.DataValues[this.GetHashCode()] = this; - } - - public void Refresh() - { - this.cache = this.ValueFunc.Invoke (); - this.lastUpdate = VOID_Core.Instance.updateTimer; - } - - public T GetFreshValue() - { - this.Refresh (); - return (T)this.cache; - } - - public virtual string ValueUnitString() { - return this.Value.ToString() + this.Units; - } - - public virtual void DoGUIHorizontal() - { - GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true)); - GUILayout.Label (this.Label + ":"); - GUILayout.FlexibleSpace (); - GUILayout.Label (this.ValueUnitString(), GUILayout.ExpandWidth (false)); - GUILayout.EndHorizontal (); - } - - public override int GetHashCode() - { - int hash; - unchecked - { - hash = 79999; - - hash = hash * 104399 + this.Label.GetHashCode(); - hash = hash * 104399 + this.ValueFunc.GetHashCode(); - hash = hash * 104399 + this.Units.GetHashCode(); - } - - return hash; - } - - public override string ToString() - { - return string.Format ( - "{0}: {1}{2}", - this.Label, - this.Value.ToString (), - this.Units - ); - } - } - - public abstract class VOID_NumValue : VOID_DataValue - where T : IFormattable, IConvertible, IComparable - { - public static implicit operator Double(VOID_NumValue v) - { - return v.ToDouble(); - } - - public static implicit operator Int32(VOID_NumValue v) - { - return v.ToInt32(); - } - - - public static implicit operator Single(VOID_NumValue v) - { - return v.ToSingle(); - } - - protected IFormatProvider formatProvider; - - public VOID_NumValue(string Label, Func ValueFunc, string Units = "") : base(Label, ValueFunc, Units) - { - this.formatProvider = System.Globalization.CultureInfo.CurrentUICulture; - } - - public virtual double ToDouble(IFormatProvider provider) - { - return this.Value.ToDouble(provider); - } - - public virtual double ToDouble() - { - return this.ToDouble(this.formatProvider); - } - - public virtual int ToInt32(IFormatProvider provider) - { - return this.Value.ToInt32(provider); - } - - public virtual int ToInt32() - { - return this.ToInt32(this.formatProvider); - } - - public virtual float ToSingle(IFormatProvider provider) - { - return this.Value.ToSingle(provider); - } - - public virtual float ToSingle() - { - return this.ToSingle(this.formatProvider); - } - - public virtual string ToString(string Format) - { - return string.Format ( - "{0}: {1}{2}", - this.Label, - this.Value.ToString(Format, this.formatProvider), - this.Units - ); - } - - public virtual string ToSIString(int digits = 3, int MinMagnitude = 0, int MaxMagnitude = int.MaxValue) - { - return string.Format ( - "{0}{1}", - Tools.MuMech_ToSI (this, digits, MinMagnitude, MaxMagnitude), - this.Units - ); - } - - public virtual string ValueUnitString(string format) - { - return this.Value.ToString(format, this.formatProvider) + this.Units; - } - - public virtual string ValueUnitString(int digits) { - return Tools.MuMech_ToSI(this, digits) + this.Units; - } - - public virtual string ValueUnitString(int digits, int MinMagnitude, int MaxMagnitude) - { - return Tools.MuMech_ToSI(this, digits, MinMagnitude, MaxMagnitude) + this.Units; - } - - public virtual void DoGUIHorizontal(string format) - { - GUILayout.BeginHorizontal (GUILayout.ExpandWidth (true)); - GUILayout.Label (this.Label + ":"); - GUILayout.FlexibleSpace (); - GUILayout.Label (this.ValueUnitString(format), GUILayout.ExpandWidth (false)); - GUILayout.EndHorizontal (); - } - - public virtual int DoGUIHorizontal(int digits, bool precisionButton = true) - { - if (precisionButton) - { - return this.DoGUIHorizontalPrec(digits); - } - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label(this.Label + ":", GUILayout.ExpandWidth(true)); - GUILayout.FlexibleSpace(); - GUILayout.Label(this.ValueUnitString(digits), GUILayout.ExpandWidth(false)); - GUILayout.EndHorizontal(); - - return digits; - } - - public virtual int DoGUIHorizontalPrec(int digits) - { - double magnitude; - double magLimit; - - magnitude = Math.Log10(Math.Abs((double)this)); - - magLimit = Math.Max(Math.Abs(magnitude), 3d) + 3d; - magLimit = Math.Round(Math.Ceiling(magLimit / 3f)) * 3d; - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label(this.Label + "ⁱ:", GUILayout.ExpandWidth(true)); - GUILayout.FlexibleSpace(); - - if (magnitude >= 0) - { - GUILayout.Label(this.ValueUnitString(3, int.MinValue, (int)magnitude - digits), GUILayout.ExpandWidth(false)); - } - else - { - GUILayout.Label(this.ValueUnitString(3, (int)magnitude + digits, int.MaxValue), GUILayout.ExpandWidth(false)); - } - GUILayout.EndHorizontal(); - - if (Event.current.type == EventType.mouseUp) - { - Rect lastRect = GUILayoutUtility.GetLastRect(); - if (lastRect.Contains(Event.current.mousePosition)) - { - Tools.PostDebugMessage(string.Format("{0}: Changing digits from {1} within magLimit {2}.", - this.GetType().Name, - digits, - magLimit)); - - if (Event.current.button == 0) - { - digits = (digits + 3) % (int)magLimit; - } - else if (Event.current.button == 1) - { - digits = (digits - 3) % (int)magLimit; - } - - if (digits < 0) - { - digits += (int)magLimit; - } - - Tools.PostDebugMessage(string.Format("{0}: Changed digits to {1}." + - "\n\tNew minMagnitude: {2}, maxMagnitude: {3}" + - "\n\tMagnitude: {4}", - this.GetType().Name, - digits, - magnitude >= 0 ? int.MinValue : (int)magnitude - 4 + digits, - magnitude >= 0 ? (int)magnitude - digits : int.MaxValue, - magnitude - )); - } - } - - return digits; - } - } - - public class VOID_DoubleValue : VOID_NumValue - { - public VOID_DoubleValue(string Label, Func ValueFunc, string Units) : base(Label, ValueFunc, Units) {} - } - - public class VOID_FloatValue : VOID_NumValue - { - public VOID_FloatValue(string Label, Func ValueFunc, string Units) : base(Label, ValueFunc, Units) {} - } - - public class VOID_IntValue : VOID_NumValue - { - public VOID_IntValue(string Label, Func ValueFunc, string Units) : base(Label, ValueFunc, Units) {} - } - - public class VOID_StrValue : VOID_DataValue - { - public VOID_StrValue(string Label, Func ValueFunc) : base(Label, ValueFunc, "") {} - } - - public class VOID_Vector3dValue : VOID_DataValue - { - public VOID_Vector3dValue(string Label, Func ValueFunc, string Units) - : base(Label, ValueFunc, Units) - {} - - public string ToString(string format) - { - return string.Format("{0}: {1}{2}", - this.Label, - this.Value.ToString(format), - this.Units - ); - } - - public string ValueUnitString(string format) { - return this.Value.ToString(format) + this.Units; - } - } -} - - --- a/VOID_EditorCore.cs +++ /dev/null @@ -1,156 +1,1 @@ -// VOID -// -// VOID_EditorCore.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using KerbalEngineer.VesselSimulator; -using KSP; -using System; -using System.Collections.Generic; -using System.Linq; -using ToadicusTools; -using UnityEngine; - -namespace VOID -{ - public class VOID_EditorCore : VOID_Core - { - /* - * Static Members - * */ - protected new static bool _initialized = false; - public new static bool Initialized - { - get - { - return _initialized; - } - } - - protected new static VOID_EditorCore _instance; - public new static VOID_EditorCore Instance - { - get - { - if (_instance == null) - { - _instance = new VOID_EditorCore(); - _initialized = true; - } - return _instance; - } - } - - public new static void Reset() - { - if (_initialized) - { - _instance.StopGUI(); - _instance.Dispose(); - _instance = null; - _initialized = false; - } - } - - protected override ApplicationLauncher.AppScenes appIconVisibleScenes - { - get - { - return ApplicationLauncher.AppScenes.VAB | ApplicationLauncher.AppScenes.SPH; - } - } - - public VOID_EditorCore() : base() - { - this._Name = "VOID Editor Core"; - } - - public override void OnGUI() {} - - public override void DrawGUI() - { - if (!this._modulesLoaded) - { - this.LoadModulesOfType(); - } - - Rect _iconPos = Tools.DockToWindow (this.VOIDIconPos, this.mainWindowPos); - - _iconPos = Tools.ClampRectToEditorPad (_iconPos); - - if (_iconPos != this.VOIDIconPos) - { - this.VOIDIconPos = _iconPos; - } - - base.DrawGUI(); - } - - public override void Update() - { - this.LoadBeforeUpdate(); - - foreach (IVOID_EditorModule module in this.Modules) - { - if (EditorLogic.RootPart == null) - { - module.StopGUI(); - continue; - } - if (HighLogic.LoadedSceneIsEditor && module.toggleActive && EditorLogic.SortedShipList.Any()) - { - module.StartGUI(); - } - if (!HighLogic.LoadedSceneIsEditor || !module.toggleActive || !EditorLogic.SortedShipList.Any()) - { - module.StopGUI(); - } - } - - if (EditorLogic.RootPart == null || !HighLogic.LoadedSceneIsEditor) - { - this.StopGUI(); - return; - } - else if (!this.guiRunning && HighLogic.LoadedSceneIsEditor) - { - this.StartGUI(); - } - - if (EditorLogic.SortedShipList.Count > 0 && this.vesselSimActive) - { - Tools.PostDebugMessage(this, "Updating SimManager."); - this.UpdateSimManager(); - } - - this.CheckAndSave (); - } - - public override void FixedUpdate() {} - } -} - - --- a/VOID_EditorHUD.cs +++ b/VOID_EditorHUD.cs @@ -37,7 +37,8 @@ namespace VOID { - public class VOID_EditorHUD : VOID_HUDModule, IVOID_EditorModule + [VOID_Scenes(GameScenes.EDITOR)] + public class VOID_EditorHUD : VOID_HUDModule { /* * Fields @@ -97,9 +98,9 @@ * */ public VOID_EditorHUD() : base() { - this._Name = "Heads-Up Display"; - - this.toggleActive = true; + this.Name = "Heads-Up Display"; + + this.Active = true; this.snapToLeft.value = true; @@ -239,7 +240,7 @@ this.ehudWindow.WindowPos = hudPos; - this.snapToLeft = Mathf.Abs(this.ehudWindow.WindowPos.xMin - hudLeft) < 15f; + this.snapToLeft.value = Mathf.Abs(this.ehudWindow.WindowPos.xMin - hudLeft) < 15f; } } } --- a/VOID_HUD.cs +++ b/VOID_HUD.cs @@ -53,9 +53,9 @@ * */ public VOID_HUD() : base() { - this._Name = "Heads-Up Display"; + this.Name = "Heads-Up Display"; - this.toggleActive = true; + this.Active = true; this.leftHUD = new HUDWindow("leftHUD", this.leftHUDWindow, new Rect(Screen.width * .375f - 300f, 0f, 300f, 90f)); this.Windows.Add(this.leftHUD); @@ -150,12 +150,12 @@ ); if ( - this.core.vessel.mainBody == this.core.HomeBody && + this.core.Vessel.mainBody == this.core.HomeBody && ( - this.core.vessel.situation == Vessel.Situations.FLYING || - this.core.vessel.situation == Vessel.Situations.SUB_ORBITAL || - this.core.vessel.situation == Vessel.Situations.LANDED || - this.core.vessel.situation == Vessel.Situations.SPLASHED + this.core.Vessel.situation == Vessel.Situations.FLYING || + this.core.Vessel.situation == Vessel.Situations.SUB_ORBITAL || + this.core.Vessel.situation == Vessel.Situations.LANDED || + this.core.Vessel.situation == Vessel.Situations.SPLASHED ) ) { --- a/VOID_HUDAdvanced.cs +++ b/VOID_HUDAdvanced.cs @@ -72,9 +72,9 @@ * */ public VOID_HUDAdvanced() : base() { - this._Name = "Advanced Heads-Up Display"; - - this.toggleActive = true; + this.Name = "Advanced Heads-Up Display"; + + this.Active = true; this.leftHUD = new HUDWindow("leftHUD", this.leftHUDWindow, @@ -95,7 +95,7 @@ ); this.Windows.Add(this.rightHUD); - this.positionsLocked = true; + this.positionsLocked.value = true; Tools.PostDebugMessage (this, "Constructed."); } @@ -255,6 +255,8 @@ public override void DrawConfigurables() { + base.DrawConfigurables(); + if (GUILayout.Button(string.Intern("Reset Advanced HUD Positions"), GUILayout.ExpandWidth(false))) { foreach (HUDWindow window in this.Windows) @@ -263,9 +265,7 @@ } } - this.positionsLocked = GUILayout.Toggle(this.positionsLocked, - string.Intern("Lock Advanced HUD Positions"), - GUILayout.ExpandWidth(false)); + this.positionsLocked.value = GUITools.Toggle(this.positionsLocked, string.Intern("Lock Advanced HUD Positions")); } } } --- a/VOID_HUDModule.cs +++ /dev/null @@ -1,217 +1,1 @@ -// VOID -// -// VOID_HUDModule.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using KerbalEngineer.VesselSimulator; -using KSP; -using System; -using System.Collections.Generic; -using System.Text; -using ToadicusTools; -using UnityEngine; - -namespace VOID -{ - public abstract class VOID_HUDModule : VOID_Module - { - [AVOID_SaveValue("colorIndex")] - protected VOID_SaveValue _colorIndex; - - protected List textColors; - - [AVOID_SaveValue("positionsLocked")] - protected VOID_SaveValue positionsLocked; - - public virtual int ColorIndex - { - get - { - return this._colorIndex; - } - set - { - if (this._colorIndex >= this.textColors.Count - 1) - { - this._colorIndex = 0; - return; - } - - this._colorIndex = value; - } - } - - public virtual List Windows - { - get; - protected set; - } - - public VOID_HUDModule() : base() - { - this._colorIndex = 0; - - this.textColors = new List(); - - this.textColors.Add(Color.green); - this.textColors.Add(Color.black); - this.textColors.Add(Color.white); - this.textColors.Add(Color.red); - this.textColors.Add(Color.blue); - this.textColors.Add(Color.yellow); - this.textColors.Add(Color.gray); - this.textColors.Add(Color.cyan); - this.textColors.Add(Color.magenta); - - this.positionsLocked = true; - - this.Windows = new List(); - } - - public override void DrawGUI() - { - VOID_Styles.labelHud.normal.textColor = textColors [ColorIndex]; - - GUI.skin = this.core.Skin; - - if (HighLogic.LoadedSceneIsEditor || - (TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate) - ) - { - SimManager.RequestSimulation(); - } - - foreach (HUDWindow window in this.Windows) - { - window.WindowPos = GUILayout.Window( - this.core.windowID, - window.WindowPos, - VOID_Tools.GetWindowHandler(window.WindowFunction), - GUIContent.none, - GUIStyle.none - ); - } - } - - public override void DrawConfigurables() - { - if (GUILayout.Button (string.Intern("Change HUD color"), GUILayout.ExpandWidth (false))) - { - ++this.ColorIndex; - } - - if (GUILayout.Button(string.Intern("Reset HUD Positions"), GUILayout.ExpandWidth(false))) - { - foreach (HUDWindow window in this.Windows) - { - window.WindowPos = new Rect(window.defaultWindowPos); - } - } - - this.positionsLocked = GUILayout.Toggle(this.positionsLocked, - string.Intern("Lock HUD Positions"), - GUILayout.ExpandWidth(false)); - } - - public override void LoadConfig() - { - base.LoadConfig(); - - var config = KSP.IO.PluginConfiguration.CreateForType(); - config.load(); - - foreach (HUDWindow window in this.Windows) - { - string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName); - Rect loadedPos = config.GetValue(saveName, window.defaultWindowPos); - - window.WindowPos = loadedPos; - } - } - - public override void _SaveToConfig(KSP.IO.PluginConfiguration config) - { - base._SaveToConfig(config); - - foreach (HUDWindow window in this.Windows) - { - string saveName = string.Format("{0}_{1}", this.GetType().Name, window.WindowName); - config.SetValue(saveName, window.WindowPos); - } - } - } - - public class HUDWindow - { - public readonly Rect defaultWindowPos; - - private Rect _windowPos; - - public Action WindowFunction - { - get; - private set; - } - - public Rect WindowPos - { - get - { - return this._windowPos; - } - set - { - if (value != this._windowPos) - { - this._windowPos = value; - - if (VOID_Data.core != null) - { - VOID_Data.core.configDirty = true; - } - } - } - } - - public string WindowName - { - get; - private set; - } - - private HUDWindow() {} - - public HUDWindow(string name, Action windowFunc, Rect defaultPos) - { - this.WindowName = name; - this.WindowFunction = windowFunc; - this.defaultWindowPos = defaultPos; - this.WindowPos = new Rect(this.defaultWindowPos); - } - } -} - - --- a/VOID_Localization.cs +++ /dev/null @@ -1,36 +1,1 @@ -// VOID -// -// VOID_Localization.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -public static class VOID_Localization -{ - public static string void_primary = "Primary"; - public static string void_altitude_asl = "Altitude (ASL)"; - public static string void_velocity = "Velocity"; - public static string void_apoapsis = "Apoapsis"; - public static string void_periapsis = "Periapsis"; -} --- a/VOID_Module.cs +++ /dev/null @@ -1,310 +1,1 @@ -// VOID -// -// VOID_Module.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using ToadicusTools; -using UnityEngine; - -namespace VOID -{ - public abstract class VOID_Module : IVOID_Module - { - /* - * Fields - * */ - [AVOID_SaveValue("Active")] - protected VOID_SaveValue _Active = false; - protected bool _Running = false; - - protected string _Name; - - protected float lastUpdate = 0; - - /* - * Properties - * */ - protected virtual VOID_Core core - { - get - { - if (HighLogic.LoadedSceneIsEditor) - { - return VOID_EditorCore.Instance as VOID_Core; - } - - return VOID_Core.Instance; - } - } - - public virtual bool toggleActive - { - get - { - return this._Active; - } - set - { - this._Active.value = value; - } - } - - public virtual bool guiRunning - { - get - { - return this._Running; - } - } - - public virtual string Name - { - get - { - return this._Name; - } - } - - public virtual Vessel vessel - { - get - { - return FlightGlobals.ActiveVessel; - } - } - - /* - * Methods - * */ - public void StartGUI() - { - if (!this.toggleActive || this.guiRunning) - { - return; - } - - Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name)); - RenderingManager.AddToPostDrawQueue (3, this.DrawGUI); - this._Running = true; - } - - public void StopGUI() - { - if (!this.guiRunning) - { - return; - } - Tools.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name)); - RenderingManager.RemoveFromPostDrawQueue (3, this.DrawGUI); - this._Running = false; - } - - public abstract void DrawGUI(); - - public virtual void DrawConfigurables() {} - - public virtual void LoadConfig() - { - var config = KSP.IO.PluginConfiguration.CreateForType (); - config.load (); - - foreach (var field in this.GetType().GetFields( - BindingFlags.NonPublic | - BindingFlags.Public | - BindingFlags.Instance | - BindingFlags.FlattenHierarchy - )) - { - object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false); - - if (attrs.Length == 0) { - continue; - } - - AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue; - - string fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name); - - Tools.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName)); - - object fieldValue = field.GetValue(this); - - bool convertBack = false; - if (fieldValue is IVOID_SaveValue) - { - fieldValue = (fieldValue as IVOID_SaveValue).AsType; - convertBack = true; - } - - fieldValue = config.GetValue(fieldName, fieldValue); - - if (convertBack) - { - Type type = typeof(VOID_SaveValue<>).MakeGenericType (fieldValue.GetType ()); - IVOID_SaveValue convertValue = Activator.CreateInstance (type) as IVOID_SaveValue; - convertValue.SetValue (fieldValue); - fieldValue = convertValue; - } - - field.SetValue (this, fieldValue); - - Tools.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName)); - } - } - - public virtual void _SaveToConfig(KSP.IO.PluginConfiguration config) - { - foreach (var field in this.GetType().GetFields( - BindingFlags.Instance | - BindingFlags.NonPublic | - BindingFlags.Public | - BindingFlags.FlattenHierarchy - )) - { - object[] attrs = field.GetCustomAttributes(typeof(AVOID_SaveValue), false); - - if (attrs.Length == 0) { - continue; - } - - AVOID_SaveValue attr = attrs.FirstOrDefault () as AVOID_SaveValue; - - string fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name); - - object fieldValue = field.GetValue(this); - - if (fieldValue is IVOID_SaveValue) - { - fieldValue = (fieldValue as IVOID_SaveValue).AsType; - } - - config.SetValue(fieldName, fieldValue); - - Tools.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName)); - } - } - } - - public abstract class VOID_WindowModule : VOID_Module - { - [AVOID_SaveValue("WindowPos")] - protected Rect WindowPos; - protected float defWidth; - protected float defHeight; - - protected string inputLockName; - - public VOID_WindowModule() : base() - { - this.defWidth = 250f; - this.defHeight = 50f; - - this.inputLockName = string.Concat(this.Name, "_edlock"); - - this.WindowPos = new Rect(Screen.width / 2, Screen.height / 2, this.defWidth, this.defHeight); - } - - public abstract void ModuleWindow(int _); - - public override void DrawGUI() - { - GUI.skin = this.core.Skin; - - Rect _Pos = this.WindowPos; - - _Pos = GUILayout.Window( - this.core.windowID, - _Pos, - VOID_Tools.GetWindowHandler(this.ModuleWindow), - this.Name, - GUILayout.Width(this.defWidth), - GUILayout.Height(this.defHeight) - ); - - bool cursorInWindow = _Pos.Contains(Mouse.screenPos); - - switch (HighLogic.LoadedScene) - { - case GameScenes.EDITOR: - if (cursorInWindow) - { - InputLockManager.SetControlLock( - ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK | - ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY, - this.inputLockName - ); - EditorLogic.fetch.Lock(false, false, false, this.inputLockName); - } - else - { - EditorLogic.fetch.Unlock(this.inputLockName); - } - break; - case GameScenes.FLIGHT: - if (cursorInWindow) - { - InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName); - } - else if (InputLockManager.GetControlLock(this.inputLockName) != ControlTypes.None) - { - InputLockManager.RemoveControlLock(this.inputLockName); - } - break; - case GameScenes.SPACECENTER: - if (cursorInWindow) - { - InputLockManager.SetControlLock(ControlTypes.KSC_FACILITIES, this.inputLockName); - } - else if (InputLockManager.GetControlLock(this.inputLockName) != ControlTypes.None) - { - InputLockManager.RemoveControlLock(this.inputLockName); - } - break; - } - - if (HighLogic.LoadedSceneIsEditor) - { - _Pos = Tools.ClampRectToEditorPad(_Pos); - } - else - { - _Pos = Tools.ClampRectToScreen(_Pos); - } - - if (_Pos != this.WindowPos) - { - this.WindowPos = _Pos; - this.core.configDirty = true; - } - } - } -} - - --- a/VOID_Orbital.cs +++ b/VOID_Orbital.cs @@ -36,21 +36,25 @@ public class VOID_Orbital : VOID_WindowModule { [AVOID_SaveValue("toggleExtended")] - protected VOID_SaveValue toggleExtended = false; + protected VOID_SaveValue toggleExtended; [AVOID_SaveValue("precisionValues")] - protected long _precisionValues = 230584300921369395; + protected VOID_SaveValue _precisionValues; protected IntCollection precisionValues; public VOID_Orbital() { - this._Name = "Orbital Information"; + this.Name = "Orbital Information"; this.WindowPos.x = Screen.width - 520f; this.WindowPos.y = 250f; + + this.toggleExtended = (VOID_SaveValue)false; + + this._precisionValues = (VOID_SaveValue)384307168202282325; } - public override void ModuleWindow(int _) + public override void ModuleWindow(int id) { int idx = 0; @@ -79,7 +83,7 @@ this.precisionValues [idx]= (ushort)VOID_Data.gravityAccel.DoGUIHorizontal (this.precisionValues [idx]); idx++; - this.toggleExtended.value = GUILayout.Toggle(this.toggleExtended, "Extended info"); + this.toggleExtended.value = GUITools.Toggle(this.toggleExtended, "Extended info"); if (this.toggleExtended) { @@ -98,13 +102,18 @@ VOID_Data.longitudeAscNode.DoGUIHorizontal("F3"); + VOID_Data.timeToAscendingNode.DoGUIHorizontal(); + + VOID_Data.timeToDescendingNode.DoGUIHorizontal(); + VOID_Data.argumentPeriapsis.DoGUIHorizontal("F3"); VOID_Data.localSiderealLongitude.DoGUIHorizontal("F3"); } GUILayout.EndVertical(); - GUI.DragWindow(); + + base.ModuleWindow(id); } public override void LoadConfig () @@ -114,11 +123,11 @@ this.precisionValues = new IntCollection (4, this._precisionValues); } - public override void _SaveToConfig (KSP.IO.PluginConfiguration config) + public override void Save (KSP.IO.PluginConfiguration config) { - this._precisionValues = this.precisionValues.collection; + this._precisionValues.value = this.precisionValues.collection; - base._SaveToConfig (config); + base.Save (config); } } } --- a/VOID_Rendezvous.cs +++ b/VOID_Rendezvous.cs @@ -38,22 +38,25 @@ public class VOID_Rendezvous : VOID_WindowModule { [AVOID_SaveValue("untoggleRegisterInfo")] - protected VOID_SaveValue untoggleRegisterInfo = false; + protected VOID_SaveValue untoggleRegisterInfo; [AVOID_SaveValue("toggleExtendedOrbital")] - protected VOID_SaveValue toggleExtendedOrbital = false; + protected VOID_SaveValue toggleExtendedOrbital; protected VOID_VesselRegister RegisterModule; public VOID_Rendezvous() { - this._Name = "Rendezvous Information"; + this.Name = "Rendezvous Information"; this.WindowPos.x = 845; this.WindowPos.y = 85; + + this.untoggleRegisterInfo = (VOID_SaveValue)false; + this.toggleExtendedOrbital = (VOID_SaveValue)false; } - public override void ModuleWindow(int _) + public override void ModuleWindow(int id) { Vessel rendezvessel = new Vessel(); CelestialBody rendezbody = new CelestialBody(); @@ -74,7 +77,7 @@ if (FlightGlobals.fetch.vesselTargetMode == VesselTargetModes.Direction) { //a Body is selected - rendezbody = vessel.patchedConicSolver.targetBody; + rendezbody = Vessel.patchedConicSolver.targetBody; display_rendezvous_info(null, rendezbody); } else if (FlightGlobals.fetch.vesselTargetMode == VesselTargetModes.DirectionAndVelocity) @@ -126,15 +129,16 @@ } } - untoggleRegisterInfo.value = GUILayout.Toggle(untoggleRegisterInfo, "Hide Vessel Register Info"); + untoggleRegisterInfo.value = GUITools.Toggle(untoggleRegisterInfo, "Hide Vessel Register Info"); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label(" ", GUILayout.ExpandWidth(true)); - if (GUILayout.Button("Close", GUILayout.ExpandWidth(false))) this.toggleActive = false; + if (GUILayout.Button("Close", GUILayout.ExpandWidth(false))) this.Active = false; GUILayout.EndHorizontal(); GUILayout.EndVertical(); - GUI.DragWindow(); + + base.ModuleWindow(id); } private void display_rendezvous_info(Vessel v, CelestialBody cb) @@ -169,11 +173,11 @@ GUILayout.Label(v.orbit.inclination.ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); - if (vessel.mainBody == v.mainBody) + if (Vessel.mainBody == v.mainBody) { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Relative inclination:"); - GUILayout.Label(Vector3d.Angle(vessel.orbit.GetOrbitNormal(), v.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false)); + GUILayout.Label(Vector3d.Angle(Vessel.orbit.GetOrbitNormal(), v.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); } //if (debugging) Debug.Log("[CHATR] v -> v relative incl OK"); @@ -185,12 +189,12 @@ GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Relative velocity:"); - GUILayout.Label(Tools.MuMech_ToSI(v.orbit.vel.magnitude - vessel.orbit.vel.magnitude) + "m/s", GUILayout.ExpandWidth(false)); + GUILayout.Label(Tools.MuMech_ToSI(v.orbit.vel.magnitude - Vessel.orbit.vel.magnitude) + "m/s", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Distance:"); - GUILayout.Label(Tools.MuMech_ToSI((vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false)); + GUILayout.Label(Tools.MuMech_ToSI((Vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); // Toadicus edit: added local sidereal longitude. @@ -199,7 +203,7 @@ GUILayout.Label(LSL.ToString("F3") + "°", VOID_Styles.labelRight); GUILayout.EndHorizontal(); - toggleExtendedOrbital.value = GUILayout.Toggle(toggleExtendedOrbital, "Extended info"); + toggleExtendedOrbital.value = GUITools.Toggle(toggleExtendedOrbital, "Extended info"); if (toggleExtendedOrbital) { @@ -250,17 +254,17 @@ { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Latitude:"); - GUILayout.Label(VOID_Tools.GetLatitudeString(vessel), GUILayout.ExpandWidth(false)); + GUILayout.Label(VOID_Tools.GetLatitudeString(Vessel), GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Longitude:"); - GUILayout.Label(VOID_Tools.GetLongitudeString(vessel), GUILayout.ExpandWidth(false)); + GUILayout.Label(VOID_Tools.GetLongitudeString(Vessel), GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Distance:"); - GUILayout.Label(Tools.MuMech_ToSI((vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false)); + GUILayout.Label(Tools.MuMech_ToSI((Vessel.findWorldCenterOfMass() - v.findWorldCenterOfMass()).magnitude) + "m", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); } } @@ -281,47 +285,47 @@ GUILayout.EndHorizontal(); //if (debugging) Debug.Log("[VOID] Inclination OK"); - if (cb.referenceBody == vessel.mainBody) + if (cb.referenceBody == Vessel.mainBody) { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Relative inclination:"); - GUILayout.Label(Vector3d.Angle(vessel.orbit.GetOrbitNormal(), cb.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false)); + GUILayout.Label(Vector3d.Angle(Vessel.orbit.GetOrbitNormal(), cb.orbit.GetOrbitNormal()).ToString("F3") + "°", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); //if (debugging) Debug.Log("[VOID] cb Relative inclination OK"); } GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.Label("Distance:"); - GUILayout.Label(Tools.MuMech_ToSI((vessel.mainBody.position - cb.position).magnitude) + "m", GUILayout.ExpandWidth(false)); + GUILayout.Label(Tools.MuMech_ToSI((Vessel.mainBody.position - cb.position).magnitude) + "m", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); //if (debugging) Debug.Log("[VOID] Distance OK"); //SUN2PLANET: - if (vessel.mainBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody) - { - VOID_Tools.display_transfer_angles_SUN2PLANET(cb, vessel); + if (Vessel.mainBody.bodyName == "Sun" && cb.referenceBody == Vessel.mainBody) + { + VOID_Tools.display_transfer_angles_SUN2PLANET(cb, Vessel); //if (debugging) Debug.Log("[VOID] SUN2PLANET OK"); } //PLANET2PLANET - else if (vessel.mainBody.referenceBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody.referenceBody) - { - VOID_Tools.display_transfer_angles_PLANET2PLANET(cb, vessel); + else if (Vessel.mainBody.referenceBody.bodyName == "Sun" && cb.referenceBody == Vessel.mainBody.referenceBody) + { + VOID_Tools.display_transfer_angles_PLANET2PLANET(cb, Vessel); //if (debugging) Debug.Log("[VOID] PLANET2PLANET OK"); } //PLANET2MOON - else if (vessel.mainBody.referenceBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody) - { - VOID_Tools.display_transfer_angles_PLANET2MOON(cb, vessel); + else if (Vessel.mainBody.referenceBody.bodyName == "Sun" && cb.referenceBody == Vessel.mainBody) + { + VOID_Tools.display_transfer_angles_PLANET2MOON(cb, Vessel); //if (debugging) Debug.Log("[VOID] PLANET2MOON OK"); } //MOON2MOON - else if (vessel.mainBody.referenceBody.referenceBody.bodyName == "Sun" && cb.referenceBody == vessel.mainBody.referenceBody) - { - VOID_Tools.display_transfer_angles_MOON2MOON(cb, vessel); + else if (Vessel.mainBody.referenceBody.referenceBody.bodyName == "Sun" && cb.referenceBody == Vessel.mainBody.referenceBody) + { + VOID_Tools.display_transfer_angles_MOON2MOON(cb, Vessel); //if (debugging) Debug.Log("[VOID] MOON2MOON OK"); } --- a/VOID_SaveValue.cs +++ /dev/null @@ -1,166 +1,1 @@ -// VOID -// -// VOID_SaveValue.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using KSP; -using System; -using System.Collections.Generic; -using ToadicusTools; -using UnityEngine; - -namespace VOID -{ - public struct VOID_SaveValue : IVOID_SaveValue - { - private T _value; - private Type _type; - - private VOID_Core Core - { - get - { - if (HighLogic.LoadedSceneIsEditor) - { - if (VOID_EditorCore.Initialized) - { - return VOID_EditorCore.Instance; - } - } - else if (HighLogic.LoadedSceneIsFlight) - { - if (VOID_Core.Initialized) - { - return VOID_Core.Instance; - } - } - return null; - } - } - - public T value - { - get - { - return this._value; - } - set - { - if (this.Core != null && !System.Object.Equals(this._value, value)) - { - Tools.PostDebugMessage (string.Format ( - "VOID: Dirtying config for type {0} in method {1}." + - "\n\t Old Value: {2}, New Value: {3}" + - "\n\t Object.Equals(New, Old): {4}", - this._type, - new System.Diagnostics.StackTrace().GetFrame(1).GetMethod(), - this._value, - value, - System.Object.Equals(this._value, value) - )); - this.Core.configDirty = true; - } - this._value = value; - } - } - - public Type type - { - get - { - if (this._type == null && this._value != null) - { - this._type = this._value.GetType (); - } - return this._type; - } - set - { - this._type = value; - } - } - - public object AsType - { - get - { - return (T)this._value; - } - } - - public void SetValue(object v) - { - this.value = (T)v; - } - - public static implicit operator T(VOID_SaveValue v) - { - return (T)v.value; - } - - public static implicit operator VOID_SaveValue(T v) - { - VOID_SaveValue r = new VOID_SaveValue(); - r.type = v.GetType(); - r.value = v; - - return r; - } - - public override string ToString() - { - return this.value.ToString(); - } - } - - public interface IVOID_SaveValue - { - Type type { get; } - object AsType { get; } - void SetValue(object v); - } - - [AttributeUsage(AttributeTargets.Field)] - public class AVOID_SaveValue : Attribute - { - protected string _name; - - public string Name - { - get - { - return this._name; - } - } - - public AVOID_SaveValue(string fieldName) - { - this._name = fieldName; - } - } -} - - --- a/VOID_StageInfo.cs +++ b/VOID_StageInfo.cs @@ -13,6 +13,7 @@ namespace VOID { + [VOID_Scenes(GameScenes.EDITOR, GameScenes.FLIGHT)] public class VOID_StageInfo : VOID_WindowModule { private Table stageTable; @@ -25,60 +26,95 @@ private Table.Column stageTotalMassCol; private Table.Column stageThrustCol; private Table.Column stageTWRCol; + private Table.Column stageTimeCol; private bool stylesApplied; + private bool showBodyList; - private Rect bodyListPos; - private CelestialBody selectedBody; + private bool showColumnSelection; + + private CelestialBody _selectedBody; [AVOID_SaveValue("bodyIdx")] private VOID_SaveValue bodyIdx; private int lastIdx; + private bool showAdvanced; + + [AVOID_SaveValue("UseSealLevel")] + private VOID_SaveValue useSeaLevel; + private GUIContent seaLevelToggle; + + private CelestialBody selectedBody + { + get + { + return this._selectedBody; + } + set + { + this._selectedBody = value; + KerbalEngineer.Helpers.CelestialBodies.SelectedBody = value; + } + } + public VOID_StageInfo() : base() { - this._Name = "Stage Information"; - this.defWidth = 200f; - this.bodyIdx = 4; + this.Name = "Stage Information"; + this.defWidth = 20f; + this.bodyIdx = (VOID_SaveValue)4; this.stylesApplied = false; this.showBodyList = false; + this.showColumnSelection = false; this.bodyListPos = new Rect(); this.stageTable = new Table(); - this.stageNumberCol = new Table.Column("Stage", 40f); + this.stageNumberCol = new Table.Column("Stage", 20f); this.stageTable.Add(this.stageNumberCol); - this.stageDeltaVCol = new Table.Column("DeltaV [m/s]", 60f); + this.stageDeltaVCol = new Table.Column("DeltaV [m/s]", 20f); this.stageDeltaVCol.Format = "S2"; this.stageTable.Add(this.stageDeltaVCol); - this.stageTotalDVCol = new Table.Column("Total ΔV [m/s]", 60f); + this.stageTotalDVCol = new Table.Column("Total ΔV [m/s]", 20f); this.stageTotalDVCol.Format = "S2"; this.stageTable.Add(this.stageTotalDVCol); - this.stageInvertDVCol = new Table.Column("Invert ΔV [m/s]", 60f); + this.stageInvertDVCol = new Table.Column("Invert ΔV [m/s]", 20f); this.stageInvertDVCol.Format = "S2"; this.stageTable.Add(this.stageInvertDVCol); - this.stageMassCol = new Table.Column("Mass [Mg]", 60f); + this.stageMassCol = new Table.Column("Mass [Mg]", 20f); this.stageMassCol.Format = "#.#"; this.stageTable.Add(this.stageMassCol); - this.stageTotalMassCol = new Table.Column("Total [Mg]", 60f); + this.stageTotalMassCol = new Table.Column("Total [Mg]", 20f); this.stageTotalMassCol.Format = "#.#"; this.stageTable.Add(this.stageTotalMassCol); - this.stageThrustCol = new Table.Column("Thrust [N]", 60f); + this.stageThrustCol = new Table.Column("Thrust [N]", 20f); this.stageThrustCol.Format = "S2"; this.stageTable.Add(this.stageThrustCol); - this.stageTWRCol = new Table.Column("T/W Ratio", 60f); + this.stageTWRCol = new Table.Column("T/W Ratio", 20f); this.stageTWRCol.Format = "#.#"; this.stageTable.Add(this.stageTWRCol); + + this.stageTimeCol = new Table.Column("Burn Time", 20f); + this.stageTable.Add(this.stageTimeCol); + + this.showAdvanced = false; + + this.useSeaLevel = (VOID_SaveValue)false; + + seaLevelToggle = new GUIContent( + "Use Sea Level", + "Use 'sea' level atmospheric conditions on bodies with atmospheres." + ); } public override void DrawGUI() @@ -87,14 +123,19 @@ if (this.showBodyList) { - GUILayout.Window(core.windowID, this.bodyListPos, this.BodyPickerWindow, string.Empty); - } - } - - public override void ModuleWindow(int _) - { + GUILayout.Window(core.WindowID, this.bodyListPos, this.BodyPickerWindow, string.Empty); + } + } + + public override void ModuleWindow(int id) + { + if (this.selectedBody == null) + { + this.selectedBody = core.HomeBody; + } + if ( - HighLogic.LoadedSceneIsEditor || + !HighLogic.LoadedSceneIsFlight || (TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate) ) @@ -121,6 +162,15 @@ return; } + if (HighLogic.LoadedSceneIsEditor && this.selectedBody.atmosphere && this.useSeaLevel) + { + SimManager.Atmosphere = this.selectedBody.GetPressure(0) * PhysicsGlobals.KpaToAtmospheres; + } + else + { + SimManager.Atmosphere = 0d; + } + foreach (Stage stage in core.Stages) { if (stage.deltaV == 0 && stage.mass == 0) @@ -139,20 +189,27 @@ this.stageThrustCol.Add(stage.thrust * 1000f); this.stageTWRCol.Add(stage.thrustToWeight / (this.selectedBody ?? core.HomeBody).GeeASL); + + this.stageTimeCol.Add(VOID_Tools.FormatInterval(stage.time)); } this.stageTable.Render(); - if (core.sortedBodyList != null) + if (core.SortedBodyList != null) { GUILayout.BeginHorizontal(); if (GUILayout.Button("◄")) { - this.bodyIdx--; - } - - this.showBodyList = GUILayout.Toggle(this.showBodyList, (this.selectedBody ?? core.HomeBody).bodyName, GUI.skin.button); + this.bodyIdx.value--; + } + + this.showBodyList = GUILayout.Toggle( + this.showBodyList, + (this.selectedBody ?? core.HomeBody).bodyName, + GUI.skin.button + ); + Rect bodyButtonPos = GUILayoutUtility.GetLastRect(); if (Event.current.type == EventType.Repaint) @@ -164,21 +221,43 @@ if (GUILayout.Button("►")) { - this.bodyIdx++; - } - - this.bodyIdx %= core.sortedBodyList.Count; + this.bodyIdx.value++; + } + + this.bodyIdx.value %= core.SortedBodyList.Count; if (this.bodyIdx < 0) { - this.bodyIdx += core.sortedBodyList.Count; + this.bodyIdx.value += core.SortedBodyList.Count; } if (this.lastIdx != this.bodyIdx) { this.lastIdx = this.bodyIdx; - this.selectedBody = core.sortedBodyList[this.bodyIdx]; - } + this.selectedBody = core.SortedBodyList[this.bodyIdx]; + } + + if (HighLogic.LoadedSceneIsEditor) + { + if ( + GUILayout.Button( + this.showAdvanced ? "▲" : "▼", + GUILayout.ExpandWidth(false) + ) + ) + { + this.showAdvanced = !this.showAdvanced; + } + } + + GUILayout.EndHorizontal(); + } + + if (this.showAdvanced && HighLogic.LoadedSceneIsEditor) + { + GUILayout.BeginHorizontal(); + + this.useSeaLevel.value = GUITools.Toggle(this.useSeaLevel, this.seaLevelToggle, false); GUILayout.EndHorizontal(); } @@ -195,24 +274,31 @@ GUILayout.EndHorizontal(); - GUI.DragWindow(); + base.ModuleWindow(id); + } + + public override void DrawConfigurables() + { + this.showColumnSelection = GUILayout.Toggle( + this.showColumnSelection, + "Select StageInfo Columns", + GUI.skin.button + ); } private void BodyPickerWindow(int _) { - foreach (CelestialBody body in core.sortedBodyList) + foreach (CelestialBody body in core.SortedBodyList) { if (GUILayout.Button(body.bodyName, VOID_Styles.labelDefault)) { Debug.Log("Picked new body focus: " + body.bodyName); - this.bodyIdx = core.sortedBodyList.IndexOf(body); + this.bodyIdx.value = core.SortedBodyList.IndexOf(body); this.showBodyList = false; } } } } - - public class VOID_StageInfoEditor : VOID_StageInfo, IVOID_EditorModule {} } --- a/VOID_Styles.cs +++ b/VOID_Styles.cs @@ -121,6 +121,8 @@ static VOID_Styles() { + OnSkinChanged(); + Ready = false; } } --- a/VOID_SurfAtmo.cs +++ b/VOID_SurfAtmo.cs @@ -36,76 +36,80 @@ public class VOID_SurfAtmo : VOID_WindowModule { [AVOID_SaveValue("precisionValues")] - protected long _precisionValues = 230584300921369395; + protected VOID_SaveValue _precisionValues; protected IntCollection precisionValues; public VOID_SurfAtmo() { - this._Name = "Surface & Atmospheric Information"; + this.Name = "Surface & Atmospheric Info"; this.WindowPos.x = Screen.width - 260f; this.WindowPos.y = 85; + + this._precisionValues = (VOID_SaveValue)384307168202282325; } - public override void ModuleWindow(int _) + public override void ModuleWindow(int id) { int idx = 0; GUILayout.BeginVertical(); - this.precisionValues [idx]= (ushort)VOID_Data.trueAltitude.DoGUIHorizontal (this.precisionValues [idx]); + this.precisionValues[idx] = (ushort)VOID_Data.trueAltitude.DoGUIHorizontal(this.precisionValues[idx]); idx++; - VOID_Data.surfLatitude.DoGUIHorizontal (); + VOID_Data.surfLatitude.DoGUIHorizontal(); - VOID_Data.surfLongitude.DoGUIHorizontal (); + VOID_Data.surfLongitude.DoGUIHorizontal(); - VOID_Data.vesselHeading.DoGUIHorizontal (); + VOID_Data.vesselHeading.DoGUIHorizontal(); - this.precisionValues [idx]= (ushort)VOID_Data.terrainElevation.DoGUIHorizontal (this.precisionValues [idx]); + this.precisionValues[idx] = (ushort)VOID_Data.terrainElevation.DoGUIHorizontal(this.precisionValues[idx]); idx++; this.precisionValues[idx] = (ushort)VOID_Data.downrangeDistance.DoGUIHorizontal(this.precisionValues[idx]); idx++; - this.precisionValues [idx]= (ushort)VOID_Data.surfVelocity.DoGUIHorizontal (this.precisionValues [idx]); + this.precisionValues[idx] = (ushort)VOID_Data.surfVelocity.DoGUIHorizontal(this.precisionValues[idx]); idx++; - this.precisionValues [idx]= (ushort)VOID_Data.vertVelocity.DoGUIHorizontal (this.precisionValues [idx]); + this.precisionValues[idx] = (ushort)VOID_Data.vertVelocity.DoGUIHorizontal(this.precisionValues[idx]); idx++; - this.precisionValues [idx]= (ushort)VOID_Data.horzVelocity.DoGUIHorizontal (this.precisionValues [idx]); + this.precisionValues[idx] = (ushort)VOID_Data.horzVelocity.DoGUIHorizontal(this.precisionValues[idx]); idx++; - VOID_Data.temperature.DoGUIHorizontal ("F2"); + VOID_Data.temperature.DoGUIHorizontal("F2"); - this.precisionValues [idx]= (ushort)VOID_Data.atmDensity.DoGUIHorizontal (this.precisionValues [idx]); + this.precisionValues[idx] = (ushort)VOID_Data.atmDensity.DoGUIHorizontal(this.precisionValues[idx]); idx++; - VOID_Data.atmPressure.DoGUIHorizontal ("F2"); + this.precisionValues[idx] = (ushort)VOID_Data.atmPressure.DoGUIHorizontal(this.precisionValues[idx]); + idx++; - this.precisionValues [idx]= (ushort)VOID_Data.atmLimit.DoGUIHorizontal (this.precisionValues [idx]); + this.precisionValues[idx] = (ushort)VOID_Data.atmLimit.DoGUIHorizontal(this.precisionValues[idx]); idx++; // Toadicus edit: added Biome - VOID_Data.currBiome.DoGUIHorizontal (); + VOID_Data.currBiome.DoGUIHorizontal(); GUILayout.EndVertical(); - GUI.DragWindow(); + + base.ModuleWindow(id); } - public override void LoadConfig () + public override void LoadConfig() { - base.LoadConfig (); + base.LoadConfig(); - this.precisionValues = new IntCollection (4, this._precisionValues); + this.precisionValues = new IntCollection(4, this._precisionValues); } - public override void _SaveToConfig (KSP.IO.PluginConfiguration config) + public override void Save(KSP.IO.PluginConfiguration config) { - this._precisionValues = this.precisionValues.collection; + this._precisionValues.value = this.precisionValues.collection; - base._SaveToConfig (config); + base.Save(config); } } } --- a/VOID_TWR.cs +++ b/VOID_TWR.cs @@ -3,36 +3,35 @@ // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a // copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ +using KerbalEngineer.VesselSimulator; using KSP; using System; -using System.Collections.Generic; -using System.Linq; -using ToadicusTools; using UnityEngine; namespace VOID { + [VOID_Scenes(GameScenes.EDITOR, GameScenes.FLIGHT)] public class VOID_TWR : VOID_WindowModule { public VOID_TWR() : base() { - this._Name = "IP Thrust-to-Weight Ratios"; + this.Name = "IP Thrust-to-Weight Ratios"; } - public override void ModuleWindow(int _) + public override void ModuleWindow(int id) { if ( - HighLogic.LoadedSceneIsEditor || + !HighLogic.LoadedSceneIsFlight || (TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate) ) { - KerbalEngineer.VesselSimulator.SimManager.RequestSimulation(); + SimManager.RequestSimulation(); } GUILayout.BeginVertical(); - if (core.sortedBodyList == null) + if (core.SortedBodyList == null) { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); @@ -42,7 +41,7 @@ } else { - foreach (CelestialBody body in core.sortedBodyList) + foreach (CelestialBody body in core.SortedBodyList) { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); @@ -59,11 +58,9 @@ GUILayout.EndVertical(); - GUI.DragWindow(); + base.ModuleWindow(id); } } - - public class VOID_EditorTWR : VOID_TWR, IVOID_EditorModule {} } --- a/VOID_Tools.cs +++ /dev/null @@ -1,1055 +1,1 @@ -// VOID -// -// VOID_Tools.cs -// -// Copyright © 2014, toadicus -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used -// to endorse or promote products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -using KSP; -using System; -using System.Collections.Generic; -using ToadicusTools; -using UnityEngine; - -namespace VOID -{ - public static partial class VOID_Tools - { - #region CelestialBody Utilities - public static bool hasAncestor(this CelestialBody bodyA, CelestialBody bodyB) - { - if (bodyA == null || bodyB == null) - { - return false; - } - - while (bodyA.orbitDriver != null) - { - if (bodyA.orbit.referenceBody == bodyB) - { - return true; - } - - bodyA = bodyA.orbit.referenceBody; - } - - return false; - } - - public static bool NearestRelatedParents(ref CelestialBody bodyA, ref CelestialBody bodyB) - { - if (bodyA == null || bodyB == null || bodyA.orbitDriver == null || bodyB.orbitDriver == null) - { - throw new ArgumentException(string.Concat( - "CelestialBody::FindRelatedParents: ", - "Neither body may be null, and both bodies must have orbits." - )); - } - - CelestialBody a, b; - - a = bodyA; - - while (bodyA.orbitDriver != null) - { - b = bodyB; - - while (b.orbitDriver != null) - { - if (a.orbit.referenceBody == b.orbit.referenceBody) - { - bodyA = a; - bodyB = b; - return true; - } - - b = b.orbit.referenceBody; - } - - a = a.orbit.referenceBody; - } - - return false; - } - #endregion - - #region VESSEL_EXTENSIONS_SCIENCE - public static CBAttributeMapSO.MapAttribute GetBiome(this Vessel vessel) - { - CBAttributeMapSO.MapAttribute mapAttribute; - - try - { - CBAttributeMapSO BiomeMap = vessel.mainBody.BiomeMap; - - double lat = vessel.latitude * Math.PI / 180d; - double lon = vessel.longitude * Math.PI / 180d; - - mapAttribute = BiomeMap.GetAtt(lat, lon); - - /* - lon -= Math.PI / 2d; - - if (lon < 0d) - { - lon += 2d * Math.PI; - } - - float v = (float)(lat / Math.PI) + 0.5f; - float u = (float)(lon / (2d * Math.PI)); - - Color pixelBilinear = BiomeMap.Map.GetPixelBilinear(u, v); - mapAttribute = BiomeMap.defaultAttribute; - - if (BiomeMap.Map != null) - { - if (BiomeMap.exactSearch) - { - for (int i = 0; i < BiomeMap.Attributes.Length; ++i) - { - if (pixelBilinear == BiomeMap.Attributes[i].mapColor) - { - mapAttribute = BiomeMap.Attributes[i]; - } - } - } - else - { - float zero = 0; - float num = 1 / zero; - for (int j = 0; j < BiomeMap.Attributes.Length; ++j) - { - Color mapColor = BiomeMap.Attributes[j].mapColor; - float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude; - if (sqrMagnitude < num) - { - bool testCase = true; - if (BiomeMap.nonExactThreshold != -1) - { - testCase = (sqrMagnitude < BiomeMap.nonExactThreshold); - } - if (testCase) - { - mapAttribute = BiomeMap.Attributes[j]; - num = sqrMagnitude; - } - } - } - } - } - */ - } - catch (NullReferenceException) - { - mapAttribute = new CBAttributeMapSO.MapAttribute(); - mapAttribute.name = "N/A"; - } - - return mapAttribute; - } - - public static ExperimentSituations GetExperimentSituation(this Vessel vessel) - { - if (vessel == null) - { - return ExperimentSituations.SrfSplashed; - } - - Vessel.Situations situation = vessel.situation; - - switch (situation) - { - case Vessel.Situations.PRELAUNCH: - case Vessel.Situations.LANDED: - return ExperimentSituations.SrfLanded; - case Vessel.Situations.SPLASHED: - return ExperimentSituations.SrfSplashed; - case Vessel.Situations.FLYING: - if (vessel.altitude < (double)vessel.mainBody.scienceValues.flyingAltitudeThreshold) - { - return ExperimentSituations.FlyingLow; - } - else - { - return ExperimentSituations.FlyingHigh; - } - } - - if (vessel.altitude < (double)vessel.mainBody.scienceValues.spaceAltitudeThreshold) - { - return ExperimentSituations.InSpaceLow; - } - else - { - return ExperimentSituations.InSpaceHigh; - } - } - - public static string HumanString(this ExperimentSituations situation) - { - switch (situation) - { - case ExperimentSituations.FlyingHigh: - return "Upper Atmosphere"; - case ExperimentSituations.FlyingLow: - return "Flying"; - case ExperimentSituations.SrfLanded: - return "Surface"; - case ExperimentSituations.InSpaceLow: - return "Near in Space"; - case ExperimentSituations.InSpaceHigh: - return "High in Space"; - case ExperimentSituations.SrfSplashed: - return "Splashed Down"; - default: - return "Unknown"; - } - } - #endregion - - #region VESSEL_EXTENSIONS_LAT_LONG - public static string GetLongitudeString(this Vessel vessel, string format = "F4") - { - string dir_long = "W"; - double v_long = vessel.longitude; - - v_long = FixDegreeDomain(v_long); - - if (v_long < -180d) - { - v_long += 360d; - } - if (v_long >= 180) - { - v_long -= 360d; - } - - if (v_long > 0) - dir_long = "E"; - - return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long); - } - - public static string GetLatitudeString(this Vessel vessel, string format = "F4") - { - string dir_lat = "S"; - double v_lat = vessel.latitude; - if (v_lat > 0) - dir_lat = "N"; - - return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat); - } - #endregion - - #region VESSEL_EXTENSIONS_GENERAL - public static double TrueAltitude(Vessel vessel) - { - double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude; - - // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m, - // and water covers the whole surface at 0 m. - if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean) - { - trueAltitude = vessel.orbit.altitude; - } - - return trueAltitude; - } - - public static double Radius(this Vessel vessel) - { - double radius; - - radius = vessel.altitude; - - if (vessel.mainBody != null) - { - radius += vessel.mainBody.Radius; - } - - return radius; - } - #endregion - - #region GEOMETRY_UTILS - public static double FixAngleDomain(double Angle, bool Degrees = false) - { - double Extent = 2d * Math.PI; - if (Degrees) - { - Extent = 360d; - } - - Angle = Angle % (Extent); - if (Angle < 0d) - { - Angle += Extent; - } - - return Angle; - } - - public static double FixDegreeDomain(double Angle) - { - return FixAngleDomain(Angle, true); - } - #endregion - - private static Dictionary functionCache; - public static UnityEngine.GUI.WindowFunction GetWindowHandler(Action func) - { - if (functionCache == null) - { - functionCache = new Dictionary(); - } - - int hashCode = func.GetHashCode(); - - if (!functionCache.ContainsKey(hashCode)) - { - functionCache[hashCode] = delegate (int id) - { - try - { - func(id); - } - #if DEBUG - catch (ArgumentException) - #else - catch (ArgumentException) - #endif - { - Debug.LogWarning( - string.Format("[{0}]: ArgumentException caught during window call. This is not a bug.", - func.Target.GetType().Name - )); - - /*#if DEBUG - Debug.LogException(ex); - #endif*/ - } - catch (Exception ex) - { - Debug.LogError( - string.Format("[{0}]: {1} caught during window call.\nMessage:\n{2}\nStackTrace:\n{3}", - func.Target.GetType().Name, - ex.GetType().Name, - ex.Message, - ex.StackTrace - )); - } - }; - } - - return functionCache[hashCode]; - } - - /// - /// Formats the interval given in seconds as a human-friendly - /// time period in [[[[years, ]days, ]hours, ]minutes, and ]seconds. - /// - /// Uses sidereal days, since "6 hours per day" is the Kerbal standard. - /// - /// Human readable interval - /// - public static string FormatInterval(double seconds) - { - return UnpackedTime.FromSeconds(seconds).FormatAsSpan(); - } - - /// - /// Formats the date given in seconds since epoch as a human-friendly - /// date in the format YY, DD, HH:MM:SS - /// - /// The date. - /// Seconds. - public static string FormatDate(double seconds) - { - return UnpackedTime.FromSeconds(seconds).FormatAsDate(); - } - - public class UnpackedTime - { - public const double SecondsPerMinute = 60d; - public const double SecondsPerHour = 3600d; - - public static double SecondsPerDay - { - get - { - if (GameSettings.KERBIN_TIME) - { - return 21600d; - } - else - { - return 86164.1d; - } - } - } - - public static double SecondsPerYear - { - get - { - if (GameSettings.KERBIN_TIME) - { - return 9203545d; - } - else - { - return 31558149d; - } - } - } - - public static UnpackedTime FromSeconds(double seconds) - { - UnpackedTime time = new UnpackedTime(); - - time.years = (int)(seconds / SecondsPerYear); - - seconds %= SecondsPerYear; - - time.days = (int)(seconds / SecondsPerDay); - - seconds %= SecondsPerDay; - - time.hours = (int)(seconds / SecondsPerHour); - - seconds %= SecondsPerHour; - - time.minutes = (int)(seconds / SecondsPerMinute); - - seconds %= SecondsPerMinute; - - time.seconds = seconds; - - return time; - } - - public static explicit operator UnpackedTime(double seconds) - { - return FromSeconds(seconds); - } - - public static implicit operator double(UnpackedTime time) - { - return time.ToSeconds(); - } - - public static UnpackedTime operator+ (UnpackedTime lhs, UnpackedTime rhs) - { - return FromSeconds(lhs.ToSeconds() + rhs.ToSeconds()); - } - - public static UnpackedTime operator- (UnpackedTime lhs, UnpackedTime rhs) - { - return FromSeconds(lhs.ToSeconds() - rhs.ToSeconds()); - } - - public int years; - public int days; - public int hours; - public int minutes; - public double seconds; - - public double ToSeconds() - { - return (double)years * SecondsPerYear + - (double)days * SecondsPerDay + - (double)hours * SecondsPerHour + - (double)minutes * SecondsPerMinute + - seconds; - } - - public string FormatAsSpan() - { - string format_1 = "{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:00.0}s"; - string format_2 = "{0:D1}d {1:D2}h {2:D2}m {3:00.0}s"; - string format_3 = "{0:D2}h {1:D2}m {2:00.0}s"; - string format_4 = "{0:D2}m {1:00.0}s"; - string format_5 = "{0:00.0}s"; - - if (this.years > 0) - { - return string.Format(format_1, this.years, this.days, this.hours, this.minutes, this.seconds); - } - else if (this.days > 0) - { - return string.Format(format_2, this.days, this.hours, this.minutes, this.seconds); - } - else if (this.hours > 0) - { - return string.Format(format_3, this.hours, this.minutes, this.seconds); - } - else if (this.minutes > 0) - { - return string.Format(format_4, this.minutes, this.seconds); - } - else - { - return string.Format(format_5, this.seconds); - } - } - - public string FormatAsDate() - { - string format = "Y{0:D1}, D{1:D1} {2:D2}:{3:D2}:{4:00.0}s"; - - return string.Format(format, years, days, hours, minutes, seconds); - } - - public UnpackedTime(int years, int days, int hours, int minutes, double seconds) - { - this.years = years; - this.days = days; - this.hours = hours; - this.minutes = minutes; - this.seconds = seconds; - } - - public UnpackedTime() : this(0, 0, 0, 0, 0d) {} - } - - public static string UppercaseFirst(string s) - { - if (string.IsNullOrEmpty(s)) - { - return string.Empty; - } - char[] a = s.ToCharArray(); - a[0] = char.ToUpper(a[0]); - return new string(a); - } - - //transfer angles - public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param) - { - r_target /= 1000; - r_current /= 1000; - grav_param /= 1000000000; - - double midpoint = (r_target + r_current) / 2; - - double T_target = (2 * Math.PI) * Math.Sqrt((r_target * r_target * r_target) / grav_param); - double T_transfer = (2 * Math.PI) * Math.Sqrt((midpoint * midpoint * midpoint) / grav_param); - return 360 * (0.5 - (T_transfer / (2 * T_target))); - } - - public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2) - { - /* - def deltaVToGetToOtherBody(mu, r1, r2): - # mu = gravity param of common orbiting body of r1 and r2 - # (e.g. for mun to minmus, mu is kerbin's gravity param - # r1 = initial body's orbit radius - # r2 = target body's orbit radius - - # return value is km/s - sur1 = math.sqrt(mu / r1) - sr1r2 = math.sqrt(float(2*r2)/float(r1+r2)) - mult = sr1r2 - 1 - return sur1 * mult - */ - double sur1, sr1r2, mult; - sur1 = Math.Sqrt(mu / r1); - sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2)); - mult = sr1r2 - 1; - return sur1 * mult; - } - - public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v) - { - /* - def deltaVToExitSOI(mu, r1, r2, v): - # mu = gravity param of current body - # r1 = current orbit radius - # r2 = SOI radius - # v = SOI exit velocity - foo = r2 * (v**2) - 2 * mu - bar = r1 * foo + (2 * r2 * mu) - r = r1*r2 - return math.sqrt(bar / r) - */ - double foo = r2 * (v * v) - 2 * mu; - double bar = r1 * foo + (2 * r2 * mu); - double r = r1 * r2; - return Math.Sqrt(bar / r); - } - - public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu) - { - /* - def transferBurnPoint(r, v, angle, mu): - # r = parking orbit radius - # v = ejection velocity - # angle = phase angle (from function phaseAngle()) - # mu = gravity param of current body. - epsilon = ((v**2)/2) - (mu / r) - h = r * v * math.sin(angle) - e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2))) - theta = math.acos(1.0 / e) - degrees = theta * (180.0 / math.pi) - return 180 - degrees - */ - double epsilon, h, ee, theta, degrees; - epsilon = ((v * v) / 2) - (mu / r); - h = r * v * Math.Sin(angle); - ee = Math.Sqrt(1 + ((2 * epsilon * (h * h)) / (mu * mu))); - theta = Math.Acos(1.0 / ee); - degrees = theta * (180.0 / Math.PI); - return 180 - degrees; - // returns the ejection angle - } - - public static double Adammada_CurrrentPhaseAngle( - double body_LAN, - double body_orbitPct, - double origin_LAN, - double origin_orbitPct - ) - { - double angle = (body_LAN / 360 + body_orbitPct) - (origin_LAN / 360 + origin_orbitPct); - if (angle > 1) - angle = angle - 1; - if (angle < 0) - angle = angle + 1; - if (angle > 0.5) - angle = angle - 1; - angle = angle * 360; - return angle; - } - - public static double Adammada_CurrentEjectionAngle( - double vessel_long, - double origin_rotAngle, - double origin_LAN, - double origin_orbitPct - ) - { - //double eangle = ((FlightGlobals.ActiveVOID.vessel.longitude + orbiting.rotationAngle) - (orbiting.orbit.LAN / 360 + orbiting.orbit.orbitPercent) * 360); - double eangle = ((vessel_long + origin_rotAngle) - (origin_LAN / 360 + origin_orbitPct) * 360); - - while (eangle < 0) - eangle = eangle + 360; - while (eangle > 360) - eangle = eangle - 360; - if (eangle < 270) - eangle = 90 - eangle; - else - eangle = 450 - eangle; - return eangle; - } - - public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body - { - Vector3d vecthis = new Vector3d(); - Vector3d vectarget = new Vector3d(); - vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); - - if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun")) - { - vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); - } - else - { - vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); - } - - vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis); - vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget); - - Vector3d prograde = new Vector3d(); - prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis; - - double phase = Vector3d.Angle(vecthis, vectarget); - - if (Vector3d.Angle(prograde, vectarget) > 90) - phase = 360 - phase; - - return (phase + 360) % 360; - } - - public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase) - { - if (transfer_angle < 0) - { - if (curr_phase > 0) - return (-1 * (360 - curr_phase)); - else if (curr_phase < 0) - return curr_phase; - } - else if (transfer_angle > 0) - { - if (curr_phase > 0) - return curr_phase; - else if (curr_phase < 0) - return (360 + curr_phase); - } - return curr_phase; - } - - public static double adjust_current_ejection_angle(double curr_ejection) - { - //curr_ejection WILL need to be adjusted once for all transfers as it returns values ranging -180 to 180 - // need 0-360 instead - // - // ie i have -17 in the screenshot - // need it to show 343 - // - // do this - // - // if < 0, add curr to 360 // 360 + (-17) = 343 - // else its good as it is - - if (curr_ejection < 0) - return 360 + curr_ejection; - else - return curr_ejection; - - } - - public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase) - { - // if transfer_phase_angle < 0 its a lower transfer - //180 + curr_ejection - // else if transfer_phase_angle > 0 its good as it is - - if (trans_phase < 0) - return 180 + trans_ejection; - else - return trans_ejection; - - } - - public static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel) - { - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Phase angle (curr/trans):"); - GUILayout.Label( - VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + VOID_Tools.Nivvy_CalcTransferPhaseAngle( - vessel.orbit.semiMajorAxis, - body.orbit.semiMajorAxis, - vessel.mainBody.gravParameter - ).ToString("F3") + "°", - GUILayout.ExpandWidth(false) - ); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Transfer velocity:"); - GUILayout.Label( - (VOID_Tools.Younata_DeltaVToGetToOtherBody( - (vessel.mainBody.gravParameter / 1000000000), - (vessel.orbit.semiMajorAxis / 1000), - (body.orbit.semiMajorAxis / 1000) - ) * 1000).ToString("F2") + "m/s", - GUILayout.ExpandWidth(false) - ); - GUILayout.EndHorizontal(); - } - - public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel) - { - double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( - (vessel.mainBody.referenceBody.gravParameter / 1000000000), - (vessel.mainBody.orbit.semiMajorAxis / 1000), - (body.orbit.semiMajorAxis / 1000) - ); - double dv2 = VOID_Tools.Younata_DeltaVToExitSOI( - (vessel.mainBody.gravParameter / 1000000000), - (vessel.orbit.semiMajorAxis / 1000), - (vessel.mainBody.sphereOfInfluence / 1000), - Math.Abs(dv1) - ); - - double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint( - (vessel.orbit.semiMajorAxis / 1000), - dv2, - (Math.PI / 2.0), - (vessel.mainBody.gravParameter / 1000000000) - ); - double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle( - FlightGlobals.ActiveVessel.longitude, - FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle, - FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, - FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent - ); - - double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( - vessel.mainBody.orbit.semiMajorAxis, - body.orbit.semiMajorAxis, - vessel.mainBody.referenceBody.gravParameter - ) % 360; - double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle( - body.orbit.LAN, - body.orbit.orbitPercent, - FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, - FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent - ); - - double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle); - double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle); - double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Phase angle (curr/trans):"); - GUILayout.Label( - adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", - GUILayout.ExpandWidth(false) - ); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Ejection angle (curr/trans):"); - GUILayout.Label( - adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°", - GUILayout.ExpandWidth(false) - ); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Transfer velocity:"); - GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); - GUILayout.EndHorizontal(); - } - - public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel) - { - double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( - (vessel.mainBody.gravParameter / 1000000000), - (vessel.orbit.semiMajorAxis / 1000), - (body.orbit.semiMajorAxis / 1000) - ); - - double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( - vessel.orbit.semiMajorAxis, - body.orbit.semiMajorAxis, - vessel.mainBody.gravParameter - ); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Phase angle (curr/trans):"); - GUILayout.Label( - VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", - GUILayout.ExpandWidth(false) - ); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Transfer velocity:"); - GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); - GUILayout.EndHorizontal(); - } - - public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel) - { - double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( - (vessel.mainBody.referenceBody.gravParameter / 1000000000), - (vessel.mainBody.orbit.semiMajorAxis / 1000), - (body.orbit.semiMajorAxis / 1000) - ); - double dv2 = VOID_Tools.Younata_DeltaVToExitSOI( - (vessel.mainBody.gravParameter / 1000000000), - (vessel.orbit.semiMajorAxis / 1000), - (vessel.mainBody.sphereOfInfluence / 1000), - Math.Abs(dv1) - ); - double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint( - (vessel.orbit.semiMajorAxis / 1000), - dv2, - (Math.PI / 2.0), - (vessel.mainBody.gravParameter / 1000000000) - ); - - double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle( - body.orbit.LAN, - body.orbit.orbitPercent, - FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, - FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent - ); - double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle( - FlightGlobals.ActiveVessel.longitude, - FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle, - FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, - FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent - ); - - double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( - vessel.mainBody.orbit.semiMajorAxis, - body.orbit.semiMajorAxis, - vessel.mainBody.referenceBody.gravParameter - ) % 360; - - double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle); - //double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle); - - //new stuff - // - double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle); - double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle); - // - // - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Phase angle (curr/trans):"); - GUILayout.Label( - adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", - GUILayout.ExpandWidth(false) - ); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Ejection angle (curr/trans):"); - GUILayout.Label( - adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°", - GUILayout.ExpandWidth(false) - ); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - GUILayout.Label("Transfer velocity:"); - GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); - GUILayout.EndHorizontal(); - } - - public static string get_heading_text(double heading) - { - if (heading > 348.75 || heading <= 11.25) - return "N"; - else if (heading > 11.25 && heading <= 33.75) - return "NNE"; - else if (heading > 33.75 && heading <= 56.25) - return "NE"; - else if (heading > 56.25 && heading <= 78.75) - return "ENE"; - else if (heading > 78.75 && heading <= 101.25) - return "E"; - else if (heading > 101.25 && heading <= 123.75) - return "ESE"; - else if (heading > 123.75 && heading <= 146.25) - return "SE"; - else if (heading > 146.25 && heading <= 168.75) - return "SSE"; - else if (heading > 168.75 && heading <= 191.25) - return "S"; - else if (heading > 191.25 && heading <= 213.75) - return "SSW"; - else if (heading > 213.75 && heading <= 236.25) - return "SW"; - else if (heading > 236.25 && heading <= 258.75) - return "WSW"; - else if (heading > 258.75 && heading <= 281.25) - return "W"; - else if (heading > 281.25 && heading <= 303.75) - return "WNW"; - else if (heading > 303.75 && heading <= 326.25) - return "NW"; - else if (heading > 326.25 && heading <= 348.75) - return "NNW"; - else - return ""; - } - } - - public class CBListComparer : IComparer - { - public int Compare(CelestialBody bodyA, CelestialBody bodyB) - { - Tools.PostDebugMessage(this, "got bodyA: {0} & bodyB: {1}", bodyA, bodyB); - - if (bodyA == null && bodyB == null) - { - Tools.PostDebugMessage(this, "both bodies are null, returning 0"); - return 0; - } - if (bodyA == null) - { - Tools.PostDebugMessage(this, "bodyA is null, returning -1"); - return -1; - } - if (bodyB == null) - { - Tools.PostDebugMessage(this, "bodyB is null, returning 1"); - return 1; - } - - Tools.PostDebugMessage(this, "bodies are not null, carrying on"); - - if (object.ReferenceEquals(bodyA, bodyB)) - { - Tools.PostDebugMessage(this, "bodies are equal, returning 0"); - return 0; - } - - Tools.PostDebugMessage(this, "bodies are not equal, carrying on"); - - if (bodyA.orbitDriver == null) - { - Tools.PostDebugMessage(this, "bodyA.orbit is null (bodyA is the sun, returning 1"); - return 1; - } - if (bodyB.orbitDriver == null) - { - Tools.PostDebugMessage(this, "bodyB.orbit is null (bodyB is the sun, returning -1"); - return -1; - } - - Tools.PostDebugMessage(this, "orbits are not null, carrying on"); - - if (bodyA.orbit.referenceBody == bodyB.orbit.referenceBody) - { - Tools.PostDebugMessage(this, "bodies share a parent, comparing SMAs"); - return -bodyA.orbit.semiMajorAxis.CompareTo(bodyB.orbit.semiMajorAxis); - } - - Tools.PostDebugMessage(this, "orbits do not share a parent, carrying on"); - - if (bodyA.hasAncestor(bodyB)) - { - Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning -1"); - return -1; - } - if (bodyB.hasAncestor(bodyA)) - { - Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning 1"); - return 1; - } - - Tools.PostDebugMessage(this, "bodies do not have an obvious relationship, searching for one"); - - if (VOID_Tools.NearestRelatedParents(ref bodyA, ref bodyB)) - { - Tools.PostDebugMessage(this, "good relation {0} and {1}, comparing", bodyA.bodyName, bodyB.bodyName); - return this.Compare(bodyA, bodyB); - } - - Tools.PostDebugMessage(this, "bad relation {0} and {1}, giving up", bodyA.bodyName, bodyB.bodyName); - - return 0; - } - } -} - --- a/VOID_Transfer.cs +++ b/VOID_Transfer.cs @@ -41,20 +41,20 @@ public VOID_Transfer() : base() { - this._Name = "Transfer Angle Information"; + this.Name = "Transfer Angle Information"; this.WindowPos.x = 475; this.WindowPos.y = 85; this.defWidth = 315; } - public override void ModuleWindow(int _) + public override void ModuleWindow(int id) { GUILayout.BeginVertical(); - if (vessel.mainBody.name == "Sun") //Vessel is orbiting the Sun + if (Vessel.mainBody.name == "Sun") //Vessel is orbiting the Sun { - foreach (CelestialBody body in vessel.mainBody.orbitingBodies) + foreach (CelestialBody body in Vessel.mainBody.orbitingBodies) { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); if (GUILayout.Button(body.bodyName)) @@ -68,16 +68,16 @@ if (selectedBodies.Contains(body)) { - VOID_Tools.display_transfer_angles_SUN2PLANET(body, vessel); //show phase angles for each selected body + VOID_Tools.display_transfer_angles_SUN2PLANET(body, Vessel); //show phase angles for each selected body tad_targeting(body); //display Set/Unset Target button for each selected body } } } - else if (vessel.mainBody.referenceBody.name == "Sun") //Vessel is orbiting a planet + else if (Vessel.mainBody.referenceBody.name == "Sun") //Vessel is orbiting a planet { - foreach (CelestialBody body in vessel.mainBody.referenceBody.orbitingBodies) + foreach (CelestialBody body in Vessel.mainBody.referenceBody.orbitingBodies) { - if (body.name != vessel.mainBody.name) // show other planets + if (body.name != Vessel.mainBody.name) // show other planets { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); if (GUILayout.Button(body.bodyName)) @@ -91,12 +91,12 @@ if (selectedBodies.Contains(body)) { - VOID_Tools.display_transfer_angles_PLANET2PLANET(body, vessel); + VOID_Tools.display_transfer_angles_PLANET2PLANET(body, Vessel); tad_targeting(body); //display Set/Unset Target button } } } - foreach (CelestialBody body in vessel.mainBody.orbitingBodies) // show moons + foreach (CelestialBody body in Vessel.mainBody.orbitingBodies) // show moons { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); if (GUILayout.Button(body.bodyName)) @@ -110,16 +110,16 @@ if (selectedBodies.Contains(body)) { - VOID_Tools.display_transfer_angles_PLANET2MOON(body, vessel); + VOID_Tools.display_transfer_angles_PLANET2MOON(body, Vessel); tad_targeting(body); //display Set/Unset Target button } } } - else if (vessel.mainBody.referenceBody.referenceBody.name == "Sun") // Vessel is orbiting a moon + else if (Vessel.mainBody.referenceBody.referenceBody.name == "Sun") // Vessel is orbiting a moon { - foreach (CelestialBody body in vessel.mainBody.referenceBody.orbitingBodies) + foreach (CelestialBody body in Vessel.mainBody.referenceBody.orbitingBodies) { - if (body.name != vessel.mainBody.name) // show other moons + if (body.name != Vessel.mainBody.name) // show other moons { GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); if (GUILayout.Button(body.bodyName)) @@ -133,14 +133,15 @@ if (selectedBodies.Contains(body)) { - VOID_Tools.display_transfer_angles_MOON2MOON(body, vessel); + VOID_Tools.display_transfer_angles_MOON2MOON(body, Vessel); tad_targeting(body); //display Set/Unset Target button } } } } GUILayout.EndVertical(); - GUI.DragWindow(); + + base.ModuleWindow(id); } private void tad_targeting(CelestialBody body) --- a/VOID_VesselInfo.cs +++ b/VOID_VesselInfo.cs @@ -40,13 +40,13 @@ { public VOID_VesselInfo() : base() { - this._Name = "Vessel Information"; + this.Name = "Vessel Information"; this.WindowPos.x = Screen.width - 260; this.WindowPos.y = 450; } - public override void ModuleWindow(int _) + public override void ModuleWindow(int id) { if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)) { @@ -56,7 +56,7 @@ GUILayout.BeginVertical(); GUILayout.Label( - vessel.vesselName, + Vessel.vesselName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); @@ -66,9 +66,9 @@ VOID_Data.totalMass.DoGUIHorizontal ("F3"); - VOID_Data.stageResourceMass.DoGUIHorizontal("F2"); + VOID_Data.stageResourceMass.DoGUIHorizontal("F3"); - VOID_Data.resourceMass.DoGUIHorizontal("F2"); + VOID_Data.resourceMass.DoGUIHorizontal("F3"); VOID_Data.stageDeltaV.DoGUIHorizontal (3, false); @@ -86,7 +86,7 @@ GUILayout.EndVertical(); - GUI.DragWindow(); + base.ModuleWindow(id); } } } --- a/VOID_VesselRegister.cs +++ b/VOID_VesselRegister.cs @@ -37,16 +37,16 @@ public class VOID_VesselRegister : VOID_WindowModule { [AVOID_SaveValue("selectedBodyIdx")] - protected VOID_SaveValue selectedBodyIdx = 0; + protected VOID_SaveValue selectedBodyIdx; protected CelestialBody seletedBody; [AVOID_SaveValue("selectedVesselTypeIdx")] - protected VOID_SaveValue selectedVesselTypeIdx = 0; + protected VOID_SaveValue selectedVesselTypeIdx; protected VesselType selectedVesselType; - protected string vesselSituation = "Orbiting"; + protected string vesselSituation; - protected Vector2 selectorScrollPos = new Vector2(); + protected Vector2 selectorScrollPos; protected Vessel _selectedVessel; @@ -60,16 +60,23 @@ public VOID_VesselRegister() : base() { - this._Name = "Vessel Register"; + this.Name = "Vessel Register"; this.WindowPos.x = 845; this.WindowPos.y = 275; this.defHeight = 375; + + this.selectedBodyIdx = (VOID_SaveValue)0; + this.selectedVesselTypeIdx = (VOID_SaveValue)0; + + this.vesselSituation = "Orbiting"; + + this.selectorScrollPos = new Vector2(); } - public override void ModuleWindow(int _) + public override void ModuleWindow(int id) { - if (!this.core.allVesselTypes.Any()) + if (!this.core.AllVesselTypes.Any()) { return; } @@ -79,34 +86,46 @@ GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); if (GUILayout.Button("<")) { - selectedBodyIdx--; - if (selectedBodyIdx < 0) selectedBodyIdx = this.core.allBodies.Count - 1; + selectedBodyIdx.value--; + if (selectedBodyIdx < 0) + { + selectedBodyIdx.value = this.core.AllBodies.Count - 1; + } } - GUILayout.Label(this.core.allBodies[selectedBodyIdx].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); + GUILayout.Label(this.core.AllBodies[selectedBodyIdx].bodyName, VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); if (GUILayout.Button(">")) { - selectedBodyIdx++; - if (selectedBodyIdx > this.core.allBodies.Count - 1) selectedBodyIdx = 0; + selectedBodyIdx.value++; + if (selectedBodyIdx > this.core.AllBodies.Count - 1) + { + selectedBodyIdx.value = 0; + } } GUILayout.EndHorizontal(); - seletedBody = this.core.allBodies[selectedBodyIdx]; + seletedBody = this.core.AllBodies[selectedBodyIdx]; GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); if (GUILayout.Button("<")) { - selectedVesselTypeIdx--; - if (selectedVesselTypeIdx < 0) selectedVesselTypeIdx = this.core.allVesselTypes.Count - 1; + selectedVesselTypeIdx.value--; + if (selectedVesselTypeIdx < 0) + { + selectedVesselTypeIdx.value = this.core.AllVesselTypes.Length - 1; + } } - GUILayout.Label(this.core.allVesselTypes[selectedVesselTypeIdx].ToString(), VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); + GUILayout.Label(this.core.AllVesselTypes[selectedVesselTypeIdx].ToString(), VOID_Styles.labelCenterBold, GUILayout.ExpandWidth(true)); if (GUILayout.Button(">")) { - selectedVesselTypeIdx++; - if (selectedVesselTypeIdx > this.core.allVesselTypes.Count - 1) selectedVesselTypeIdx = 0; + selectedVesselTypeIdx.value++; + if (selectedVesselTypeIdx > this.core.AllVesselTypes.Length - 1) + { + selectedVesselTypeIdx.value = 0; + } } GUILayout.EndHorizontal(); - selectedVesselType = this.core.allVesselTypes[selectedVesselTypeIdx]; + selectedVesselType = this.core.AllVesselTypes[selectedVesselTypeIdx]; GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); if (GUILayout.Button("Landed", GUILayout.ExpandWidth(true))) vesselSituation = "Landed"; @@ -124,7 +143,7 @@ foreach (Vessel v in FlightGlobals.Vessels) { - if (v != vessel && v.vesselType == selectedVesselType && v.mainBody == seletedBody) + if (v != Vessel && v.vesselType == selectedVesselType && v.mainBody == seletedBody) { if ((vesselSituation == "Landed" && (v.situation == Vessel.Situations.LANDED || @@ -142,7 +161,7 @@ if (_selectedVessel != v) { _selectedVessel = v; //set clicked vessel as selected_vessel - this.toggleActive = true; //turn bool on to open the window if closed + this.Active = true; //turn bool on to open the window if closed } else { @@ -157,7 +176,7 @@ GUILayout.EndVertical(); - GUI.DragWindow(); + base.ModuleWindow(id); } } }