Tweaks to OnGUI and OnPostRender per sarbian's recommendation.
Tweaks to OnGUI and OnPostRender per sarbian's recommendation.

// VOID // VOID
// //
// IVOID_Core.cs // IVOID_Core.cs
// //
// Copyright © 2015, toadicus // Copyright © 2015, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using KerbalEngineer.VesselSimulator; using KerbalEngineer.VesselSimulator;
using KSP; using KSP;
using System; using System;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public abstract class VOIDCore : VOID_WindowModule, IVOID_Module public abstract class VOIDCore : VOID_WindowModule, IVOID_Module
{ {
public const double Constant_G = 6.674e-11; public const double Constant_G = 6.674e-11;
public const int CONFIG_VERSION = 2; public const int CONFIG_VERSION = 2;
   
public abstract int ConfigVersion { get; } public abstract int ConfigVersion { get; }
public virtual bool configNeedsUpdate { get; set; } public virtual bool configNeedsUpdate { get; set; }
   
public virtual string SaveGamePath { get; protected set; } public virtual string SaveGamePath { get; protected set; }
public virtual string VOIDSettingsPath { get; protected set; } public virtual string VOIDSettingsPath { get; protected set; }
   
public abstract string SceneKey { get; } public abstract string SceneKey { get; }
   
public abstract int WindowID { get; } public abstract int WindowID { get; }
public abstract bool configDirty { get; set; } public abstract bool configDirty { get; set; }
public abstract bool powerAvailable { get; protected set; } public abstract bool powerAvailable { get; protected set; }
   
public abstract IList<IVOID_Module> Modules { get; } public abstract IList<IVOID_Module> Modules { get; }
   
public abstract float UpdateTimer { get; protected set; } public abstract float UpdateTimer { get; protected set; }
public abstract double UpdatePeriod { get; } public abstract double UpdatePeriod { get; }
   
public virtual float saveTimer { get; protected set; } public virtual float saveTimer { get; protected set; }
   
public abstract GUISkin Skin { get; } public abstract GUISkin Skin { get; }
   
public abstract CelestialBody HomeBody { get; } public abstract CelestialBody HomeBody { get; }
public abstract List<CelestialBody> SortedBodyList { get; protected set; } public abstract List<CelestialBody> SortedBodyList { get; protected set; }
   
public abstract VesselType[] AllVesselTypes { get; protected set; } public abstract VesselType[] AllVesselTypes { get; protected set; }
public abstract Stage LastStage { get; protected set; } public abstract Stage LastStage { get; protected set; }
public abstract Stage[] Stages { get; protected set; } public abstract Stage[] Stages { get; protected set; }
   
public abstract VOID_TimeScale TimeScale { get; protected set; } public abstract VOID_TimeScale TimeScale { get; protected set; }
   
public abstract event VOIDEventHandler onApplicationQuit; public abstract event VOIDEventHandler onApplicationQuit;
public abstract event VOIDEventHandler onSkinChanged; public abstract event VOIDEventHandler onSkinChanged;
public abstract event VOIDEventHandler onUpdate; public abstract event VOIDEventHandler onUpdate;
public virtual event VOIDEventHandler onGui;  
public virtual event VOIDEventHandler onPostRender; public virtual event VOIDEventHandler onPostRender;
  public virtual event VOIDEventHandler onPreRender;
   
public virtual bool MethodInPostRenderQueue(VOIDEventHandler method) public virtual bool MethodInPostRenderQueue(VOIDEventHandler method)
{ {
if (this.onGui != null) if (this.onPostRender != null)
{ {
ToadicusTools.Logging.PostDebugMessage(this, "Looking for method {0} in onGui", method); ToadicusTools.Logging.PostDebugMessage(this, "Looking for method {0} in onGui", method);
   
foreach (var invoker in this.onGui.GetInvocationList()) foreach (var invoker in this.onPostRender.GetInvocationList())
{ {
ToadicusTools.Logging.PostDebugMessage(this, "Checking invoker {0}", invoker); ToadicusTools.Logging.PostDebugMessage(this, "Checking invoker {0}", invoker);
   
if (invoker == method) if (invoker == method)
{ {
return true; return true;
} }
} }
} }
   
return false; return false;
} }
   
public abstract void OnGUI(); public abstract void OnGUI();
public abstract void OnPostRender();  
   
public abstract void SaveConfig(); public abstract void SaveConfig();
   
public override void Save(KSP.IO.PluginConfiguration config, string sceneKey) public override void Save(KSP.IO.PluginConfiguration config, string sceneKey)
{ {
base.Save(config, sceneKey); base.Save(config, sceneKey);
} }
} }
   
public delegate void VOIDEventHandler(object sender); public delegate void VOIDEventHandler(object sender);
} }
   
   
// VOID // VOID
// //
// VOIDMaster.cs // VOIDMaster.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors // Much, much credit to Younata, Adammada, Nivvydaskrl and to all the authors
// behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some // behind MechJeb, RemoteTech Relay Network, ISA MapSat, and Protractor for some
// invaluable functions and making your nicely written code available to learn from. // invaluable functions and making your nicely written code available to learn from.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// This software uses VesselSimulator and Engineer.Extensions from Engineer Redux. // This software uses VesselSimulator and Engineer.Extensions from Engineer Redux.
// Engineer Redux (c) 2013 cybutek // Engineer Redux (c) 2013 cybutek
// Used by permission. // Used by permission.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
   
using System; using System;
using UnityEngine; using UnityEngine;
using KerbalEngineer.VesselSimulator; using KerbalEngineer.VesselSimulator;
using ToadicusTools.Extensions; using ToadicusTools.Extensions;
   
namespace VOID namespace VOID
{ {
public abstract class VOIDMaster<T> : MonoBehaviour public abstract class VOIDMaster<T> : MonoBehaviour
where T : VOIDCore_Generic<T>, new() where T : VOIDCore_Generic<T>, new()
{ {
protected T Core; protected T Core;
   
public abstract void Awake(); public abstract void Awake();
   
public virtual void Update() public virtual void Update()
{ {
if (this.Core != null && !this.InValidScene()) 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.LogDebug("We have a Core but the scene is not valid for this master. Saving and disposing.");
   
this.Core.SaveConfig (); this.Core.SaveConfig ();
this.Core.Dispose(); this.Core.Dispose();
this.Core = null; this.Core = null;
return; return;
} }
   
if (this.Core == null && this.InValidScene()) if (this.Core == null && this.InValidScene())
{ {
this.LogDebug("We have no Core and the scene is valid for this master; re-trying Awake."); this.LogDebug("We have no Core and the scene is valid for this master; re-trying Awake.");
this.Awake(); this.Awake();
return; return;
} }
   
this.Core.Update (); this.Core.Update ();
   
if (this.Core.FactoryReset) if (this.Core.FactoryReset)
{ {
this.LogDebug("Factory reset is true; deleting config and disposing!"); this.LogDebug("Factory reset is true; deleting config and disposing!");
   
KSP.IO.File.Delete<T>("config.xml"); KSP.IO.File.Delete<T>("config.xml");
System.IO.File.Delete(this.Core.VOIDSettingsPath); System.IO.File.Delete(this.Core.VOIDSettingsPath);
   
this.Core.Dispose(); this.Core.Dispose();
this.Core = null; this.Core = null;
} }
} }
   
public virtual void FixedUpdate() public virtual void FixedUpdate()
{ {
if (this.Core == null) if (this.Core == null)
{ {
return; return;
} }
   
this.Core.FixedUpdate (); this.Core.FixedUpdate ();
} }
   
public virtual void OnGUI() public virtual void OnGUI()
{ {
if (this.Core == null) if (this.Core == null)
{ {
return; return;
} }
   
this.Core.OnGUI(); this.Core.OnGUI();
} }
   
public virtual void OnPostRender()  
{  
if (this.Core == null)  
{  
return;  
}  
   
this.Core.OnPostRender();  
}  
   
public virtual void OnDestroy() public virtual void OnDestroy()
{ {
if (this.Core == null) if (this.Core == null)
{ {
return; return;
} }
   
this.Core.OnDestroy(); this.Core.OnDestroy();
} }
   
public virtual void OnApplicationQuit() public virtual void OnApplicationQuit()
{ {
if (this.Core == null) if (this.Core == null)
{ {
return; return;
} }
   
this.Core.OnApplicationQuit(); this.Core.OnApplicationQuit();
} }
   
protected virtual bool InValidScene() protected virtual bool InValidScene()
{ {
object[] attributes = this.GetType().GetCustomAttributes(true); object[] attributes = this.GetType().GetCustomAttributes(true);
object attr; object attr;
for (int idx = 0; idx < attributes.Length; idx++) for (int idx = 0; idx < attributes.Length; idx++)
{ {
attr = attributes[idx]; attr = attributes[idx];
if (attr is KSPAddon) if (attr is KSPAddon)
{ {
KSPAddon addonAttr = (KSPAddon)attr; KSPAddon addonAttr = (KSPAddon)attr;
   
switch (addonAttr.startup) switch (addonAttr.startup)
{ {
case KSPAddon.Startup.EveryScene: case KSPAddon.Startup.EveryScene:
return true; return true;
case KSPAddon.Startup.EditorAny: case KSPAddon.Startup.EditorAny:
return HighLogic.LoadedSceneIsEditor; return HighLogic.LoadedSceneIsEditor;
case KSPAddon.Startup.Flight: case KSPAddon.Startup.Flight:
return HighLogic.LoadedSceneIsFlight; return HighLogic.LoadedSceneIsFlight;
case KSPAddon.Startup.MainMenu: case KSPAddon.Startup.MainMenu:
return HighLogic.LoadedScene == GameScenes.MAINMENU; return HighLogic.LoadedScene == GameScenes.MAINMENU;
case KSPAddon.Startup.SpaceCentre: case KSPAddon.Startup.SpaceCentre:
return HighLogic.LoadedScene == GameScenes.SPACECENTER; return HighLogic.LoadedScene == GameScenes.SPACECENTER;
case KSPAddon.Startup.TrackingStation: case KSPAddon.Startup.TrackingStation:
return HighLogic.LoadedScene == GameScenes.TRACKSTATION; return HighLogic.LoadedScene == GameScenes.TRACKSTATION;
default: default:
return false; return false;
} }
} }
} }
   
return false; return false;
} }
} }
} }
   
// VOID // VOID
// //
// VOID_Module.cs // VOID_Module.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
// TODO: Remove ToadicusTools. prefixes after refactor is done. // TODO: Remove ToadicusTools. prefixes after refactor is done.
   
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using ToadicusTools.Extensions; using ToadicusTools.Extensions;
using ToadicusTools.GUIUtils; using ToadicusTools.GUIUtils;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public abstract class VOID_Module : IVOID_Module public abstract class VOID_Module : IVOID_Module
{ {
/* /*
* Fields * Fields
* */ * */
[AVOID_SaveValue("Active")] [AVOID_SaveValue("Active")]
protected VOID_SaveValue<bool> active = (VOID_SaveValue<bool>)false; protected VOID_SaveValue<bool> active = (VOID_SaveValue<bool>)false;
   
protected float lastUpdate = 0; protected float lastUpdate = 0;
   
private GameScenes[] validScenes; private GameScenes[] validScenes;
private Game.Modes[] validModes; private Game.Modes[] validModes;
   
/* /*
* Properties * Properties
* */ * */
   
public virtual bool Active public virtual bool Active
{ {
get get
{ {
return this.active && this.InValidGame && this.InValidScene; return this.active && this.InValidGame && this.InValidScene;
} }
set set
{ {
this.active.value = value && this.InValidGame && this.InValidScene; this.active.value = value && this.InValidGame && this.InValidScene;
} }
} }
   
public virtual bool GUIRunning public virtual bool GUIRunning
{ {
get get
{ {
/*if ( /*if (
RenderingManager.fetch == null || RenderingManager.fetch == null ||
RenderingManager.fetch.postDrawQueue == null || RenderingManager.fetch.postDrawQueue == null ||
RenderingManager.fetch.postDrawQueue.Length < 4 RenderingManager.fetch.postDrawQueue.Length < 4
) )
{ {
return false; return false;
} }
else else
{ {
Delegate callback = RenderingManager.fetch.postDrawQueue[3]; Delegate callback = RenderingManager.fetch.postDrawQueue[3];
if (callback == null) if (callback == null)
{ {
return false; return false;
} }
   
return callback.GetInvocationList().Contains((Callback)this.DrawGUI); return callback.GetInvocationList().Contains((Callback)this.DrawGUI);
}*/ }*/
return this.core != null && this.core.MethodInPostRenderQueue(this.DrawGUI); return this.core != null && this.core.MethodInPostRenderQueue(this.DrawGUI);
} }
} }
   
public virtual bool InValidGame public virtual bool InValidGame
{ {
get get
{ {
return this.ValidModes.Contains(HighLogic.CurrentGame.Mode); return this.ValidModes.Contains(HighLogic.CurrentGame.Mode);
} }
} }
   
public virtual bool InValidScene public virtual bool InValidScene
{ {
get get
{ {
return this.ValidScenes.Contains(HighLogic.LoadedScene); return this.ValidScenes.Contains(HighLogic.LoadedScene);
} }
} }
   
public virtual string Name public virtual string Name
{ {
get; get;
protected set; protected set;
} }
   
public virtual Game.Modes[] ValidModes public virtual Game.Modes[] ValidModes
{ {
get get
{ {
if (this.validModes == null) if (this.validModes == null)
{ {
ToadicusTools.Logging.PostDebugMessage(this, "validModes is null when checking inValidGame; fetching attribute."); ToadicusTools.Logging.PostDebugMessage(this, "validModes is null when checking inValidGame; fetching attribute.");
   
object[] attributes = this.GetType().GetCustomAttributes(false); object[] attributes = this.GetType().GetCustomAttributes(false);
object attr; object attr;
for (int idx = 0; idx < attributes.Length; idx++) for (int idx = 0; idx < attributes.Length; idx++)
{ {
attr = attributes[idx]; attr = attributes[idx];
   
if (attr is VOID_GameModesAttribute) if (attr is VOID_GameModesAttribute)
{ {
VOID_GameModesAttribute addonAttr = (VOID_GameModesAttribute)attr; VOID_GameModesAttribute addonAttr = (VOID_GameModesAttribute)attr;
   
this.validModes = addonAttr.ValidModes; this.validModes = addonAttr.ValidModes;
   
ToadicusTools.Logging.PostDebugMessage("Found VOID_GameModesAttribute; validScenes set."); ToadicusTools.Logging.PostDebugMessage("Found VOID_GameModesAttribute; validScenes set.");
   
break; break;
} }
} }
   
if (this.validModes == null) if (this.validModes == null)
{ {
this.validModes = new Game.Modes[] this.validModes = new Game.Modes[]
{ {
Game.Modes.CAREER, Game.Modes.CAREER,
Game.Modes.SANDBOX, Game.Modes.SANDBOX,
Game.Modes.SCENARIO, Game.Modes.SCENARIO,
Game.Modes.SCENARIO_NON_RESUMABLE, Game.Modes.SCENARIO_NON_RESUMABLE,
Game.Modes.SCIENCE_SANDBOX Game.Modes.SCIENCE_SANDBOX
}; };
   
ToadicusTools.Logging.PostDebugMessage("No VOID_GameModesAttribute found; validScenes defaulted to flight."); ToadicusTools.Logging.PostDebugMessage("No VOID_GameModesAttribute found; validScenes defaulted to flight.");
} }
} }
   
return this.validModes; return this.validModes;
} }
} }
   
public virtual GameScenes[] ValidScenes public virtual GameScenes[] ValidScenes
{ {
get get
{ {
if (this.validScenes == null) if (this.validScenes == null)
{ {
ToadicusTools.Logging.PostDebugMessage(this, "validScenes is null when checking inValidScene; fetching attribute."); ToadicusTools.Logging.PostDebugMessage(this, "validScenes is null when checking inValidScene; fetching attribute.");
object[] attributes = this.GetType().GetCustomAttributes(false); object[] attributes = this.GetType().GetCustomAttributes(false);
object attr; object attr;
for (int idx = 0; idx < attributes.Length; idx++) for (int idx = 0; idx < attributes.Length; idx++)
{ {
attr = attributes[idx]; attr = attributes[idx];
   
if (attr is VOID_ScenesAttribute) if (attr is VOID_ScenesAttribute)
{ {
VOID_ScenesAttribute addonAttr = (VOID_ScenesAttribute)attr; VOID_ScenesAttribute addonAttr = (VOID_ScenesAttribute)attr;
   
this.validScenes = addonAttr.ValidScenes; this.validScenes = addonAttr.ValidScenes;
   
ToadicusTools.Logging.PostDebugMessage("Found VOID_ScenesAttribute; validScenes set."); ToadicusTools.Logging.PostDebugMessage("Found VOID_ScenesAttribute; validScenes set.");
   
break; break;
} }
} }
   
if (this.validScenes == null) if (this.validScenes == null)
{ {
this.validScenes = new GameScenes[] { GameScenes.FLIGHT }; this.validScenes = new GameScenes[] { GameScenes.FLIGHT };
ToadicusTools.Logging.PostDebugMessage("No VOID_ScenesAttribute found; validScenes defaulted to flight."); ToadicusTools.Logging.PostDebugMessage("No VOID_ScenesAttribute found; validScenes defaulted to flight.");
} }
} }
   
return this.validScenes; return this.validScenes;
} }
} }
   
public virtual Vessel Vessel public virtual Vessel Vessel
{ {
get get
{ {
return FlightGlobals.ActiveVessel; return FlightGlobals.ActiveVessel;
} }
} }
   
protected virtual VOIDCore core protected virtual VOIDCore core
{ {
get get
{ {
return VOID_Data.Core; return VOID_Data.Core;
} }
} }
   
protected virtual bool timeToUpdate protected virtual bool timeToUpdate
{ {
get get
{ {
return ( return (
(this.core.UpdateTimer - this.lastUpdate) > this.core.UpdatePeriod || (this.core.UpdateTimer - this.lastUpdate) > this.core.UpdatePeriod ||
this.lastUpdate > this.core.UpdateTimer this.lastUpdate > this.core.UpdateTimer
); );
} }
} }
   
/* /*
* Methods * Methods
* */ * */
public virtual void StartGUI() public virtual void StartGUI()
{ {
if (!this.Active || this.GUIRunning) if (!this.Active || this.GUIRunning)
{ {
return; return;
} }
   
ToadicusTools.Logging.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name)); ToadicusTools.Logging.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name));
// RenderingManager.AddToPostDrawQueue (3, this.DrawGUI); // RenderingManager.AddToPostDrawQueue (3, this.DrawGUI);
this.core.onGui += this.DrawGUI; this.core.onPostRender += this.DrawGUI;
} }
   
public virtual void StopGUI() public virtual void StopGUI()
{ {
if (!this.GUIRunning) if (!this.GUIRunning)
{ {
return; return;
} }
ToadicusTools.Logging.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name)); ToadicusTools.Logging.PostDebugMessage (string.Format("Removing {0} from the draw queue.", this.GetType().Name));
this.core.onGui -= this.DrawGUI; this.core.onPostRender -= this.DrawGUI;
} }
   
public abstract void DrawGUI(object sender); public abstract void DrawGUI(object sender);
   
public virtual void DrawConfigurables() {} public virtual void DrawConfigurables() {}
   
public virtual void LoadConfig(KSP.IO.PluginConfiguration config) public virtual void LoadConfig(KSP.IO.PluginConfiguration config)
{ {
config.load (); config.load ();
   
if (this is VOIDCore) if (this is VOIDCore)
{ {
int configVersion = config.GetValue("VOID_Core_configValue", 2); int configVersion = config.GetValue("VOID_Core_configValue", 2);
   
if (configVersion < VOIDCore.CONFIG_VERSION) if (configVersion < VOIDCore.CONFIG_VERSION)
{ {
((VOIDCore)this).configNeedsUpdate = true; ((VOIDCore)this).configNeedsUpdate = true;
} }
} }
   
MemberInfo[] members = this.GetType().GetMembers( MemberInfo[] members = this.GetType().GetMembers(
BindingFlags.NonPublic | BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Public |
BindingFlags.Instance | BindingFlags.Instance |
BindingFlags.FlattenHierarchy BindingFlags.FlattenHierarchy
); );
MemberInfo member; MemberInfo member;
   
for (int fIdx = 0; fIdx < members.Length; fIdx++) for (int fIdx = 0; fIdx < members.Length; fIdx++)
{ {
member = members[fIdx]; member = members[fIdx];
   
if (!(member is FieldInfo || member is PropertyInfo)) if (!(member is FieldInfo || member is PropertyInfo))
{ {
continue; continue;
} }
   
if (member is PropertyInfo && (member as PropertyInfo).GetIndexParameters().Length > 0) if (member is PropertyInfo && (member as PropertyInfo).GetIndexParameters().Length > 0)
{ {
continue; continue;
} }
   
object[] attrs = member.GetCustomAttributes(typeof(AVOID_SaveValue), false); object[] attrs = member.GetCustomAttributes(typeof(AVOID_SaveValue), false);
   
AVOID_SaveValue attr; AVOID_SaveValue attr;
   
if (attrs.Length > 0) if (attrs.Length > 0)
{ {
attr = (AVOID_SaveValue)attrs[0]; attr = (AVOID_SaveValue)attrs[0];
} }
else else
{ {
continue; continue;
} }
   
string fieldName = string.Empty; string fieldName = string.Empty;
   
if (this is VOIDCore || this.core.configNeedsUpdate) if (this is VOIDCore || this.core.configNeedsUpdate)
{ {
string typeName = this.GetType().Name;; string typeName = this.GetType().Name;;
   
if (this is VOIDCore && ((VOIDCore)this).configNeedsUpdate) if (this is VOIDCore && ((VOIDCore)this).configNeedsUpdate)
{ {
if (this is VOIDCore_Flight) if (this is VOIDCore_Flight)
{ {
typeName = "VOID_Core"; typeName = "VOID_Core";
} }
else if (this is VOIDCore_Editor) else if (this is VOIDCore_Editor)
{ {
typeName = "VOID_EditorCore"; typeName = "VOID_EditorCore";
} }
} }
   
fieldName = string.Format("{0}_{1}", typeName, attr.Name); fieldName = string.Format("{0}_{1}", typeName, attr.Name);
} }
else else
{ {
fieldName = string.Format( fieldName = string.Format(
"{0}_{1}_{2}", "{0}_{1}_{2}",
this.GetType().Name, this.GetType().Name,
Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene), Enum.GetName(typeof(GameScenes), HighLogic.LoadedScene),
attr.Name attr.Name
); );
} }
   
ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName)); ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Loading field {1}.", this.GetType().Name, fieldName));
   
object fieldValue; object fieldValue;
   
if (member is FieldInfo) if (member is FieldInfo)
{ {
fieldValue = (member as FieldInfo).GetValue(this); fieldValue = (member as FieldInfo).GetValue(this);
} }
else else
{ {
fieldValue = (member as PropertyInfo).GetValue(this, null); fieldValue = (member as PropertyInfo).GetValue(this, null);
} }
   
bool convertBack = false; bool convertBack = false;
if (fieldValue is IVOID_SaveValue) if (fieldValue is IVOID_SaveValue)
{ {
fieldValue = (fieldValue as IVOID_SaveValue).value; fieldValue = (fieldValue as IVOID_SaveValue).value;
convertBack = true; convertBack = true;
} }
   
fieldValue = config.GetValue(fieldName, fieldValue); fieldValue = config.GetValue(fieldName, fieldValue);
   
if (convertBack) if (convertBack)
{ {
Type type = typeof(VOID_SaveValue<>).MakeGenericType (fieldValue.GetType ()); Type type = typeof(VOID_SaveValue<>).MakeGenericType (fieldValue.GetType ());
IVOID_SaveValue convertValue = Activator.CreateInstance (type) as IVOID_SaveValue; IVOID_SaveValue convertValue = Activator.CreateInstance (type) as IVOID_SaveValue;
convertValue.SetValue (fieldValue); convertValue.SetValue (fieldValue);
fieldValue = convertValue; fieldValue = convertValue;
} }
   
if (member is FieldInfo) if (member is FieldInfo)
{ {
(member as FieldInfo).SetValue(this, fieldValue); (member as FieldInfo).SetValue(this, fieldValue);
} }
else else
{ {
(member as PropertyInfo).SetValue(this, fieldValue, null); (member as PropertyInfo).SetValue(this, fieldValue, null);
} }
   
ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName)); ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName));
} }
} }
   
public virtual void Save(KSP.IO.PluginConfiguration config, string sceneKey) public virtual void Save(KSP.IO.PluginConfiguration config, string sceneKey)
{ {
if (config == null) if (config == null)
{ {
ToadicusTools.Logging.PostErrorMessage( ToadicusTools.Logging.PostErrorMessage(
"{0}: config argument was null, bailing out.", "{0}: config argument was null, bailing out.",
this.GetType().Name this.GetType().Name
); );
} }
   
if (sceneKey == null) if (sceneKey == null)
{ {
ToadicusTools.Logging.PostErrorMessage( ToadicusTools.Logging.PostErrorMessage(
"{0}: sceneKey argument was null, bailing out.", "{0}: sceneKey argument was null, bailing out.",
this.GetType().Name this.GetType().Name
); );
} }
   
MemberInfo[] members = this.GetType().GetMembers( MemberInfo[] members = this.GetType().GetMembers(
BindingFlags.NonPublic | BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Public |
BindingFlags.Instance | BindingFlags.Instance |
BindingFlags.FlattenHierarchy BindingFlags.FlattenHierarchy
); );
MemberInfo member; MemberInfo member;
   
for (int fIdx = 0; fIdx < members.Length; fIdx++) for (int fIdx = 0; fIdx < members.Length; fIdx++)
{ {
member = members[fIdx]; member = members[fIdx];
   
object[] attrs = member.GetCustomAttributes(typeof(AVOID_SaveValue), false); object[] attrs = member.GetCustomAttributes(typeof(AVOID_SaveValue), false);
   
AVOID_SaveValue attr; AVOID_SaveValue attr;
   
if (attrs.Length > 0) if (attrs.Length > 0)
{ {
attr = (AVOID_SaveValue)attrs[0]; attr = (AVOID_SaveValue)attrs[0];
} }
else else
{ {
continue; continue;
} }
   
string fieldName; string fieldName;
   
if (this is VOIDCore) if (this is VOIDCore)
{ {
fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name); fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name);
} }
else else
{ {
fieldName = string.Format( fieldName = string.Format(
"{0}_{1}_{2}", "{0}_{1}_{2}",
this.GetType().Name, this.GetType().Name,
sceneKey, sceneKey,
attr.Name attr.Name
); );
} }
   
object fieldValue; object fieldValue;
   
if (member is FieldInfo) if (member is FieldInfo)
{ {
fieldValue = (member as FieldInfo).GetValue(this); fieldValue = (member as FieldInfo).GetValue(this);
} }
else else
{ {
fieldValue = (member as PropertyInfo).GetValue(this, null); fieldValue = (member as PropertyInfo).GetValue(this, null);
} }
   
if (fieldValue is IVOID_SaveValue) if (fieldValue is IVOID_SaveValue)
{ {
fieldValue = (fieldValue as IVOID_SaveValue).value; fieldValue = (fieldValue as IVOID_SaveValue).value;
} }
   
config.SetValue(fieldName, fieldValue); config.SetValue(fieldName, fieldValue);
   
ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName)); ToadicusTools.Logging.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName));
} }
} }
} }
   
public abstract class VOID_WindowModule : VOID_Module public abstract class VOID_WindowModule : VOID_Module
{ {
[AVOID_SaveValue("WindowPos")] [AVOID_SaveValue("WindowPos")]
protected Rect WindowPos; protected Rect WindowPos;
protected float defWidth; protected float defWidth;
protected float defHeight; protected float defHeight;
   
protected bool decorateWindow; protected bool decorateWindow;
   
protected string inputLockName; protected string inputLockName;
   
public VOID_WindowModule() : base() public VOID_WindowModule() : base()
{ {
this.defWidth = 250f; this.defWidth = 250f;
this.defHeight = 50f; this.defHeight = 50f;
   
this.decorateWindow = true; this.decorateWindow = true;
   
this.inputLockName = string.Concat(this.Name, "_edlock"); this.inputLockName = string.Concat(this.Name, "_edlock");
   
this.WindowPos = new Rect(Screen.width / 2, Screen.height / 2, this.defWidth, this.defHeight); this.WindowPos = new Rect(Screen.width / 2, Screen.height / 2, this.defWidth, this.defHeight);
} }
   
public virtual void ModuleWindow(int id) public virtual void ModuleWindow(int id)
{ {
GUIStyle buttonStyle = this.core.Skin.button; GUIStyle buttonStyle = this.core.Skin.button;
RectOffset padding = buttonStyle.padding; RectOffset padding = buttonStyle.padding;
RectOffset border = buttonStyle.border; RectOffset border = buttonStyle.border;
   
Rect closeRect = new Rect( Rect closeRect = new Rect(
0f, 0f,
0f, 0f,
border.left + border.right, border.left + border.right,
border.top + border.bottom border.top + border.bottom
); );
   
closeRect.width = Mathf.Max(closeRect.width, 16f); closeRect.width = Mathf.Max(closeRect.width, 16f);
closeRect.height = Mathf.Max(closeRect.height, 16f); closeRect.height = Mathf.Max(closeRect.height, 16f);
   
closeRect.x = this.WindowPos.width - closeRect.width - 2f; closeRect.x = this.WindowPos.width - closeRect.width - 2f;
closeRect.y = 2f; closeRect.y = 2f;
   
GUI.Button(closeRect, GUIContent.none, buttonStyle); GUI.Button(closeRect, GUIContent.none, buttonStyle);
   
if (Event.current.type == EventType.repaint && Input.GetMouseButtonUp(0)) if (Event.current.type == EventType.repaint && Input.GetMouseButtonUp(0))
{ {
if (closeRect.Contains(Event.current.mousePosition)) if (closeRect.Contains(Event.current.mousePosition))
{ {
this.Active = false; this.Active = false;
this.removeUILock(); this.removeUILock();
} }
} }
   
GUI.DragWindow(); GUI.DragWindow();
} }
   
public override void DrawGUI(object sender) public override void DrawGUI(object sender)
{ {
GUI.skin = this.core.Skin; GUI.skin = this.core.Skin;
   
Rect _Pos = this.WindowPos; Rect _Pos = this.WindowPos;
   
_Pos = GUILayout.Window( _Pos = GUILayout.Window(
this.core.WindowID, this.core.WindowID,
_Pos, _Pos,
VOID_Tools.GetWindowHandler(this.ModuleWindow), VOID_Tools.GetWindowHandler(this.ModuleWindow),
this.Name, this.Name,
GUILayout.Width(this.defWidth), GUILayout.Width(this.defWidth),
GUILayout.Height(this.defHeight) GUILayout.Height(this.defHeight)
); );
   
bool cursorInWindow = _Pos.Contains(Mouse.screenPos); bool cursorInWindow = _Pos.Contains(Mouse.screenPos);
   
if (cursorInWindow) if (cursorInWindow)
{ {
this.setUILock(); this.setUILock();
} }
else else
{ {
this.removeUILock(); this.removeUILock();
} }
   
if (HighLogic.LoadedSceneIsEditor) if (HighLogic.LoadedSceneIsEditor)
{ {
_Pos = WindowTools.ClampRectToEditorPad(_Pos); _Pos = WindowTools.ClampRectToEditorPad(_Pos);
} }
else else
{ {
_Pos = WindowTools.ClampRectToScreen(_Pos); _Pos = WindowTools.ClampRectToScreen(_Pos);
} }
   
if (_Pos != this.WindowPos) if (_Pos != this.WindowPos)
{ {
this.WindowPos = _Pos; this.WindowPos = _Pos;
this.core.configDirty = true; this.core.configDirty = true;
} }
} }
   
protected void setUILock() protected void setUILock()
{ {
switch (HighLogic.LoadedScene) switch (HighLogic.LoadedScene)
{ {
case GameScenes.EDITOR: case GameScenes.EDITOR:
InputLockManager.SetControlLock( InputLockManager.SetControlLock(
ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK | ControlTypes.EDITOR_ICON_HOVER | ControlTypes.EDITOR_ICON_PICK |
ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY, ControlTypes.EDITOR_PAD_PICK_COPY | ControlTypes.EDITOR_PAD_PICK_COPY,
this.inputLockName this.inputLockName
); );
EditorLogic.fetch.Lock(false, false, false, this.inputLockName); EditorLogic.fetch.Lock(false, false, false, this.inputLockName);
break; break;
case GameScenes.FLIGHT: case GameScenes.FLIGHT:
InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName); InputLockManager.SetControlLock(ControlTypes.CAMERACONTROLS, this.inputLockName);
break; break;
case GameScenes.SPACECENTER: case GameScenes.SPACECENTER:
InputLockManager.SetControlLock( InputLockManager.SetControlLock(
ControlTypes.KSC_FACILITIES | ControlTypes.CAMERACONTROLS, ControlTypes.KSC_FACILITIES | ControlTypes.CAMERACONTROLS,
this.inputLockName this.inputLockName
); );
break; break;
} }
} }
   
protected void removeUILock() protected void removeUILock()
{ {
switch (HighLogic.LoadedScene) switch (HighLogic.LoadedScene)
{ {
case GameScenes.EDITOR: case GameScenes.EDITOR:
EditorLogic.fetch.Unlock(this.inputLockName); EditorLogic.fetch.Unlock(this.inputLockName);
break; break;
case GameScenes.FLIGHT: case GameScenes.FLIGHT:
InputLockManager.RemoveControlLock(this.inputLockName); InputLockManager.RemoveControlLock(this.inputLockName);
break; break;
case GameScenes.SPACECENTER: case GameScenes.SPACECENTER:
InputLockManager.RemoveControlLock(this.inputLockName); InputLockManager.RemoveControlLock(this.inputLockName);
break; break;
} }
} }
} }
} }
   
   
// VOID // VOID
// //
// VOIDCore_Generic.cs // VOIDCore_Generic.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 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 // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 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. // 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, // 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 // 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, // 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 // 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, // 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 // 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. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using KerbalEngineer.Editor; using KerbalEngineer.Editor;
using KerbalEngineer.Helpers; using KerbalEngineer.Helpers;
using KerbalEngineer.VesselSimulator; using KerbalEngineer.VesselSimulator;
using KSP; using KSP;
using KSP.UI.Screens; using KSP.UI.Screens;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using ToadicusTools; using ToadicusTools;
using ToadicusTools.DebugTools; using ToadicusTools.DebugTools;
using ToadicusTools.Extensions; using ToadicusTools.Extensions;
using ToadicusTools.GUIUtils; using ToadicusTools.GUIUtils;
using ToadicusTools.Wrappers; using ToadicusTools.Wrappers;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public abstract class VOIDCore_Generic<T> : VOID_SingletonCore<T>, IVOID_Module, IDisposable public abstract class VOIDCore_Generic<T> : VOID_SingletonCore<T>, IVOID_Module, IDisposable
where T : VOID_Module, new() where T : VOID_Module, new()
{ {
/* /*
* Fields * Fields
* */ * */
protected string VoidName = "VOID"; protected string VoidName = "VOID";
protected string VoidVersion; protected string VoidVersion;
   
[AVOID_SaveValue("configValue")] [AVOID_SaveValue("configValue")]
protected VOID_SaveValue<int> configVersion = (VOID_SaveValue<int>)VOIDCore.CONFIG_VERSION; protected VOID_SaveValue<int> configVersion = (VOID_SaveValue<int>)VOIDCore.CONFIG_VERSION;
   
protected List<IVOID_Module> modules = new List<IVOID_Module>(); protected List<IVOID_Module> modules = new List<IVOID_Module>();
protected bool modulesLoaded = false; protected bool modulesLoaded = false;
   
protected Texture2D VOIDIconTexture; protected Texture2D VOIDIconTexture;
protected string VOIDIconOnActivePath; protected string VOIDIconOnActivePath;
protected string VOIDIconOnInactivePath; protected string VOIDIconOnInactivePath;
protected string VOIDIconOffActivePath; protected string VOIDIconOffActivePath;
protected string VOIDIconOffInactivePath; protected string VOIDIconOffInactivePath;
   
[AVOID_SaveValue("useToolbarManager")] [AVOID_SaveValue("useToolbarManager")]
protected VOID_SaveValue<bool> useToolbarManager; protected VOID_SaveValue<bool> useToolbarManager;
   
protected GUIStyle iconStyle; protected GUIStyle iconStyle;
   
protected int windowBaseID = -96518722; protected int windowBaseID = -96518722;
protected int windowID = 0; protected int windowID = 0;
   
protected bool GUIStylesLoaded = false; protected bool GUIStylesLoaded = false;
   
protected CelestialBody homeBody; protected CelestialBody homeBody;
   
[AVOID_SaveValue("togglePower")] [AVOID_SaveValue("togglePower")]
public VOID_SaveValue<bool> togglePower = (VOID_SaveValue<bool>)true; public VOID_SaveValue<bool> togglePower = (VOID_SaveValue<bool>)true;
   
public override bool powerAvailable { get; protected set; } public override bool powerAvailable { get; protected set; }
   
[AVOID_SaveValue("consumeResource")] [AVOID_SaveValue("consumeResource")]
protected VOID_SaveValue<bool> consumeResource = (VOID_SaveValue<bool>)false; protected VOID_SaveValue<bool> consumeResource = (VOID_SaveValue<bool>)false;
   
[AVOID_SaveValue("resourceName")] [AVOID_SaveValue("resourceName")]
protected VOID_SaveValue<string> resourceName = (VOID_SaveValue<string>)"ElectricCharge"; protected VOID_SaveValue<string> resourceName = (VOID_SaveValue<string>)"ElectricCharge";
   
[AVOID_SaveValue("resourceRate")] [AVOID_SaveValue("resourceRate")]
protected VOID_SaveValue<float> resourceRate = (VOID_SaveValue<float>)0.2f; protected VOID_SaveValue<float> resourceRate = (VOID_SaveValue<float>)0.2f;
   
[AVOID_SaveValue("updatePeriod")] [AVOID_SaveValue("updatePeriod")]
protected VOID_SaveValue<double> updatePeriod = (VOID_SaveValue<double>)(1001f / 15000f); protected VOID_SaveValue<double> updatePeriod = (VOID_SaveValue<double>)(1001f / 15000f);
protected string stringFrequency; protected string stringFrequency;
   
[AVOID_SaveValue("vesselSimActive")] [AVOID_SaveValue("vesselSimActive")]
protected VOID_SaveValue<bool> vesselSimActive; protected VOID_SaveValue<bool> vesselSimActive;
   
[AVOID_SaveValue("timeScaleFlags")] [AVOID_SaveValue("timeScaleFlags")]
protected VOID_SaveValue<UInt32> timeScaleFlags; protected VOID_SaveValue<UInt32> timeScaleFlags;
   
// Load-up housekeeping // Load-up housekeeping
protected bool vesselTypesLoaded = false; protected bool vesselTypesLoaded = false;
protected bool simManagerLoaded = false; protected bool simManagerLoaded = false;
   
protected string defaultSkin = "KSP window 2"; protected string defaultSkin = "KSP window 2";
   
[AVOID_SaveValue("defaultSkin")] [AVOID_SaveValue("defaultSkin")]
protected VOID_SaveValue<string> skinName; protected VOID_SaveValue<string> skinName;
protected int skinIdx; protected int skinIdx;
   
protected Dictionary<string, GUISkin> validSkins; protected Dictionary<string, GUISkin> validSkins;
protected List<string> skinNames; protected List<string> skinNames;
protected string[] forbiddenSkins = protected string[] forbiddenSkins =
{ {
"PlaqueDialogSkin", "PlaqueDialogSkin",
"FlagBrowserSkin", "FlagBrowserSkin",
"SSUITextAreaDefault", "SSUITextAreaDefault",
"ExperimentsDialogSkin", "ExperimentsDialogSkin",
"ExpRecoveryDialogSkin", "ExpRecoveryDialogSkin",
"KSP window 1", "KSP window 1",
"KSP window 3", "KSP window 3",
"KSP window 5", "KSP window 5",
"KSP window 6", "KSP window 6",
"PartTooltipSkin", "PartTooltipSkin",
"KSCContextMenuSkin" "KSCContextMenuSkin"
}; };
protected bool skinsLoaded = false; protected bool skinsLoaded = false;
   
public override bool configDirty { get; set; } public override bool configDirty { get; set; }
   
protected IButton ToolbarButton; protected IButton ToolbarButton;
protected ApplicationLauncherButton AppLauncherButton; protected ApplicationLauncherButton AppLauncherButton;
protected IconState iconState; protected IconState iconState;
   
/* /*
* Properties * Properties
* */ * */
public override bool Active public override bool Active
{ {
get get
{ {
return base.Active; return base.Active;
} }
set set
{ {
if (value != base.Active) if (value != base.Active)
{ {
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
} }
   
base.Active = value; base.Active = value;
} }
} }
   
public override VesselType[] AllVesselTypes public override VesselType[] AllVesselTypes
{ {
get; get;
protected set; protected set;
} }
   
public override int ConfigVersion public override int ConfigVersion
{ {
get get
{ {
return this.configVersion; return this.configVersion;
} }
} }
   
public bool FactoryReset public bool FactoryReset
{ {
get; get;
protected set; protected set;
} }
   
public override CelestialBody HomeBody public override CelestialBody HomeBody
{ {
get get
{ {
if (this.homeBody == null) if (this.homeBody == null)
{ {
if (Planetarium.fetch != null) if (Planetarium.fetch != null)
{ {
this.homeBody = Planetarium.fetch.Home; this.homeBody = Planetarium.fetch.Home;
} }
} }
   
return this.homeBody; return this.homeBody;
} }
} }
   
public override IList<IVOID_Module> Modules public override IList<IVOID_Module> Modules
{ {
get get
{ {
return this.modules.AsReadOnly(); return this.modules.AsReadOnly();
} }
} }
   
public override GUISkin Skin public override GUISkin Skin
{ {
get get
{ {
if (this.skinsLoaded) if (this.skinsLoaded)
{ {
try try
{ {
return this.validSkins[this.skinName]; return this.validSkins[this.skinName];
} }
catch catch
{ {
} }
} }
   
return AssetBase.GetGUISkin(this.defaultSkin); return AssetBase.GetGUISkin(this.defaultSkin);
} }
} }
   
public override List<CelestialBody> SortedBodyList public override List<CelestialBody> SortedBodyList
{ {
get; get;
protected set; protected set;
} }
   
public override double UpdatePeriod public override double UpdatePeriod
{ {
get get
{ {
return this.updatePeriod; return this.updatePeriod;
} }
} }
   
public override float UpdateTimer public override float UpdateTimer
{ {
get; get;
protected set; protected set;
} }
   
public override int WindowID public override int WindowID
{ {
get get
{ {
if (this.windowID == 0) if (this.windowID == 0)
{ {
this.windowID = this.windowBaseID; this.windowID = this.windowBaseID;
} }
return this.windowID++; return this.windowID++;
} }
} }
   
public override Stage[] Stages public override Stage[] Stages
{ {
get; get;
protected set; protected set;
} }
   
public override Stage LastStage public override Stage LastStage
{ {
get; get;
protected set; protected set;
} }
   
public override VOID_TimeScale TimeScale public override VOID_TimeScale TimeScale
{ {
get get
{ {
return (VOID_TimeScale)this.timeScaleFlags.value; return (VOID_TimeScale)this.timeScaleFlags.value;
} }
protected set protected set
{ {
this.timeScaleFlags.value = (UInt32)value; this.timeScaleFlags.value = (UInt32)value;
} }
} }
   
protected IconState activeState protected IconState activeState
{ {
get get
{ {
if (this.Active) if (this.Active)
{ {
return IconState.Inactive; return IconState.Inactive;
} }
else else
{ {
return IconState.Active; return IconState.Active;
} }
   
} }
} }
   
protected IconState powerState protected IconState powerState
{ {
get get
{ {
if (this.togglePower && this.powerAvailable) if (this.togglePower && this.powerAvailable)
{ {
return IconState.PowerOn; return IconState.PowerOn;
} }
else else
{ {
return IconState.PowerOff; return IconState.PowerOff;
} }
   
} }
} }
   
protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes
{ {
get get
{ {
return HighLogic.LoadedScene.ToAppScenes(); return HighLogic.LoadedScene.ToAppScenes();
} }
} }
   
/* /*
* Events * Events
* */ * */
// public // public
public override event VOIDEventHandler onApplicationQuit; public override event VOIDEventHandler onApplicationQuit;
public override event VOIDEventHandler onSkinChanged; public override event VOIDEventHandler onSkinChanged;
public override event VOIDEventHandler onUpdate; public override event VOIDEventHandler onUpdate;
public override event VOIDEventHandler onGui;  
public override event VOIDEventHandler onPostRender; public override event VOIDEventHandler onPostRender;
  public override event VOIDEventHandler onPreRender;
   
/* /*
* Methods * Methods
* */ * */
public override void DrawGUI(object sender) public override void DrawGUI(object sender)
{ {
this.windowID = this.windowBaseID; this.windowID = this.windowBaseID;
   
if (!this.modulesLoaded) if (!this.modulesLoaded)
{ {
this.LoadModulesOfType<IVOID_Module>(); this.LoadModulesOfType<IVOID_Module>();
} }
   
if (!this.skinsLoaded) if (!this.skinsLoaded)
{ {
this.LoadSkins(); this.LoadSkins();
} }
   
GUI.skin = this.Skin; GUI.skin = this.Skin;
   
if (!this.GUIStylesLoaded) if (!this.GUIStylesLoaded)
{ {
this.LoadGUIStyles(); this.LoadGUIStyles();
   
Logging.PostDebugMessage( Logging.PostDebugMessage(
this, this,
"ToolbarAvailable: {0}, UseToobarManager: {1}", "ToolbarAvailable: {0}, UseToobarManager: {1}",
ToolbarManager.ToolbarAvailable, ToolbarManager.ToolbarAvailable,
this.useToolbarManager); this.useToolbarManager);
} }
   
if ( if (
this.iconState != (this.powerState | this.activeState) || this.iconState != (this.powerState | this.activeState) ||
(this.VOIDIconTexture == null && this.AppLauncherButton != null) (this.VOIDIconTexture == null && this.AppLauncherButton != null)
) )
{ {
this.iconState = this.powerState | this.activeState; this.iconState = this.powerState | this.activeState;
   
this.SetIconTexture(this.iconState); this.SetIconTexture(this.iconState);
} }
   
if (this.Active) if (this.Active)
{ {
base.DrawGUI(sender); base.DrawGUI(sender);
} }
} }
   
public virtual void Update() public virtual void Update()
{ {
this.LoadBeforeUpdate(); this.LoadBeforeUpdate();
   
if ( if (
this.vesselSimActive && this.vesselSimActive &&
( (
this.Vessel != null || this.Vessel != null ||
( (
HighLogic.LoadedSceneIsEditor && HighLogic.LoadedSceneIsEditor &&
EditorLogic.RootPart != null && EditorLogic.RootPart != null &&
EditorLogic.SortedShipList.Count > 0 EditorLogic.SortedShipList.Count > 0
) )
) )
) )
{ {
Logging.PostDebugMessage(this, "Updating SimManager."); Logging.PostDebugMessage(this, "Updating SimManager.");
this.UpdateSimManager(); this.UpdateSimManager();
} }
   
if (!this.GUIRunning) if (!this.GUIRunning)
{ {
this.StartGUI(); this.StartGUI();
} }
   
IVOID_Module module; IVOID_Module module;
for (int idx = 0; idx < this.modules.Count; idx++) for (int idx = 0; idx < this.modules.Count; idx++)
{ {
module = this.modules[idx]; module = this.modules[idx];
   
if ( if (
!module.GUIRunning && !module.GUIRunning &&
module.Active && module.Active &&
module.InValidScene && module.InValidScene &&
( (
!HighLogic.LoadedSceneIsEditor || !HighLogic.LoadedSceneIsEditor ||
(EditorLogic.RootPart != null && EditorLogic.SortedShipList.Count > 0) (EditorLogic.RootPart != null && EditorLogic.SortedShipList.Count > 0)
) )
) )
{ {
module.StartGUI(); module.StartGUI();
} }
if ( if (
module.GUIRunning && module.GUIRunning &&
( (
!module.Active || !module.Active ||
!this.togglePower || !this.togglePower ||
!module.InValidScene || !module.InValidScene ||
this.FactoryReset || this.FactoryReset ||
( (
HighLogic.LoadedSceneIsEditor && HighLogic.LoadedSceneIsEditor &&
(EditorLogic.RootPart == null || EditorLogic.SortedShipList.Count == 0) (EditorLogic.RootPart == null || EditorLogic.SortedShipList.Count == 0)
) )
) )
) )
{ {
module.StopGUI(); module.StopGUI();
} }
   
if (module is IVOID_BehaviorModule) if (module is IVOID_BehaviorModule)
{ {
((IVOID_BehaviorModule)module).Update(); ((IVOID_BehaviorModule)module).Update();
} }
} }
   
if (this.useToolbarManager) if (this.useToolbarManager)
{ {
if (this.AppLauncherButton != null) if (this.AppLauncherButton != null)
{ {
ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton); ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
this.AppLauncherButton = null; this.AppLauncherButton = null;
} }
   
if (this.ToolbarButton == null) if (this.ToolbarButton == null)
{ {
this.InitializeToolbarButton(); this.InitializeToolbarButton();
} }
} }
else else
{ {
if (this.ToolbarButton != null) if (this.ToolbarButton != null)
{ {
this.ToolbarButton.Destroy(); this.ToolbarButton.Destroy();
this.ToolbarButton = null; this.ToolbarButton = null;
} }
   
if (this.AppLauncherButton == null) if (this.AppLauncherButton == null)
{ {
this.InitializeAppLauncherButton(); this.InitializeAppLauncherButton();
} }
   
} }
   
this.saveTimer += Time.deltaTime; this.saveTimer += Time.deltaTime;
   
if (this.modulesLoaded && this.saveTimer > 2f) if (this.modulesLoaded && this.saveTimer > 2f)
{ {
if (this.configDirty) if (this.configDirty)
{ {
   
Logging.PostDebugMessage(string.Format( Logging.PostDebugMessage(string.Format(
"{0}: Time to save, checking if configDirty: {1}", "{0}: Time to save, checking if configDirty: {1}",
this.GetType().Name, this.GetType().Name,
this.configDirty this.configDirty
)); ));
   
this.SaveConfig(); this.SaveConfig();
this.saveTimer = 0; this.saveTimer = 0;
} }
} }
   
this.UpdateTimer += Time.deltaTime; this.UpdateTimer += Time.deltaTime;
   
if (this.onUpdate != null) if (this.onUpdate != null)
{ {
this.onUpdate(this); this.onUpdate(this);
} }
} }
   
public virtual void FixedUpdate() public virtual void FixedUpdate()
{ {
bool newPowerState = this.powerAvailable; bool newPowerState = this.powerAvailable;
   
if (this.togglePower && this.consumeResource && if (this.togglePower && this.consumeResource &&
this.Vessel.vesselType != VesselType.EVA && this.Vessel.vesselType != VesselType.EVA &&
TimeWarp.deltaTime != 0) TimeWarp.deltaTime != 0)
{ {
float powerReceived = this.Vessel.rootPart.RequestResource( float powerReceived = this.Vessel.rootPart.RequestResource(
this.resourceName, this.resourceName,
this.resourceRate * TimeWarp.fixedDeltaTime this.resourceRate * TimeWarp.fixedDeltaTime
); );
   
if (powerReceived > 0) if (powerReceived > 0)
{ {
newPowerState = true; newPowerState = true;
} }
else else
{ {
newPowerState = false; newPowerState = false;
} }
   
if (this.powerAvailable != newPowerState) if (this.powerAvailable != newPowerState)
{ {
this.powerAvailable = newPowerState; this.powerAvailable = newPowerState;
} }
} }
   
IVOID_Module module; IVOID_Module module;
for (int idx = 0; idx < this.modules.Count; idx++) for (int idx = 0; idx < this.modules.Count; idx++)
{ {
module = this.modules[idx]; module = this.modules[idx];
   
if (module is IVOID_BehaviorModule) if (module is IVOID_BehaviorModule)
{ {
((IVOID_BehaviorModule)module).FixedUpdate(); ((IVOID_BehaviorModule)module).FixedUpdate();
} }
} }
} }
   
public override void OnGUI() public override void OnGUI()
{ {
Logging.PostDebugMessage(this, "In OnGUI"); if (Event.current.type == EventType.Repaint || Event.current.isMouse)
if (this.onGui != null) {
{ if (this.onPreRender != null)
this.onGui(this); {
} Logging.PostDebugMessage(this, "In OnGUI; doing 'pre draw' stuff");
} this.onPreRender(this);
  }
public override void OnPostRender() }
{  
Logging.PostDebugMessage(this, "In OnPostRender");  
if (this.onPostRender != null) if (this.onPostRender != null)
{ {
  Logging.PostDebugMessage(this, "In OnGUI; doing 'post draw' stuff");
this.onPostRender(this); this.onPostRender(this);
} }
} }
   
public void OnDestroy() public void OnDestroy()
{ {
IVOID_Module module; IVOID_Module module;
for (int idx = 0; idx < this.modules.Count; idx++) for (int idx = 0; idx < this.modules.Count; idx++)
{ {
module = this.modules[idx]; module = this.modules[idx];
   
if (module is IVOID_BehaviorModule) if (module is IVOID_BehaviorModule)
{ {
((IVOID_BehaviorModule)module).OnDestroy(); ((IVOID_BehaviorModule)module).OnDestroy();
} }
} }
   
this.Dispose(); this.Dispose();
} }
   
public virtual void OnApplicationQuit() public virtual void OnApplicationQuit()
{ {
if (this.onApplicationQuit != null) if (this.onApplicationQuit != null)
{ {
this.onApplicationQuit(this); this.onApplicationQuit(this);
} }
   
this.OnDestroy(); this.OnDestroy();
} }
   
public override void StartGUI() public override void StartGUI()
{ {
if (!this.GUIRunning) if (!this.GUIRunning)
{ {
// RenderingManager.AddToPostDrawQueue(3, this.DrawGUI); // RenderingManager.AddToPostDrawQueue(3, this.DrawGUI);
Logging.PostDebugMessage(this, "Adding DrawGUI to onGui"); Logging.PostDebugMessage(this, "Adding DrawGUI to onGui");
this.onGui += this.DrawGUI; this.onPostRender += this.DrawGUI;
} }
} }
   
public void ResetGUI() public void ResetGUI()
{ {
this.StopGUI(); this.StopGUI();
   
IVOID_Module module; IVOID_Module module;
for (int idx = 0; idx < this.modules.Count; idx++) for (int idx = 0; idx < this.modules.Count; idx++)
{ {
module = this.modules[idx]; module = this.modules[idx];
   
module.StopGUI(); module.StopGUI();
module.StartGUI(); module.StartGUI();
} }
   
this.StartGUI(); this.StartGUI();
} }
   
public override void ModuleWindow(int id) public override void ModuleWindow(int id)
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
if (this.powerAvailable || !HighLogic.LoadedSceneIsFlight) if (this.powerAvailable || !HighLogic.LoadedSceneIsFlight)
{ {
if (!HighLogic.LoadedSceneIsEditor) if (!HighLogic.LoadedSceneIsEditor)
{ {
string str = string.Intern("ON"); string str = string.Intern("ON");
if (togglePower) if (togglePower)
str = string.Intern("OFF"); str = string.Intern("OFF");
if (GUILayout.Button("Power " + str)) if (GUILayout.Button("Power " + str))
{ {
togglePower.value = !togglePower; togglePower.value = !togglePower;
} }
} }
   
if (togglePower || !HighLogic.LoadedSceneIsFlight) if (togglePower || !HighLogic.LoadedSceneIsFlight)
{ {
IVOID_Module module; IVOID_Module module;
for (int idx = 0; idx < this.modules.Count; idx++) for (int idx = 0; idx < this.modules.Count; idx++)
{ {
module = this.modules[idx]; module = this.modules[idx];
   
if (module is VOID_ConfigWindow) if (module is VOID_ConfigWindow)
{ {
continue; continue;
} }
   
module.Active = Layout.Toggle(module.Active, module.Name); module.Active = Layout.Toggle(module.Active, module.Name);
} }
} }
} }
else else
{ {
GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed); GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed);
} }
   
VOID_ConfigWindow.Instance.Active = Layout.Toggle( VOID_ConfigWindow.Instance.Active = Layout.Toggle(
VOID_ConfigWindow.Instance.Active, VOID_ConfigWindow.Instance.Active,
"Configuration" "Configuration"
); );
   
GUILayout.EndVertical(); GUILayout.EndVertical();
   
base.ModuleWindow(id); base.ModuleWindow(id);
} }
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
GUIContent _content; GUIContent _content;
   
this.useToolbarManager.value = Layout.Toggle(this.useToolbarManager, "Use Blizzy's Toolbar If Available"); this.useToolbarManager.value = Layout.Toggle(this.useToolbarManager, "Use Blizzy's Toolbar If Available");
   
this.vesselSimActive.value = Layout.Toggle(this.vesselSimActive.value, this.vesselSimActive.value = Layout.Toggle(this.vesselSimActive.value,
"Enable Engineering Calculations"); "Enable Engineering Calculations");
   
bool useEarthTime = (this.TimeScale & VOID_TimeScale.KERBIN_TIME) == 0u; bool useEarthTime = (this.TimeScale & VOID_TimeScale.KERBIN_TIME) == 0u;
bool useSiderealTime = (this.TimeScale & VOID_TimeScale.SOLAR_DAY) == 0u; bool useSiderealTime = (this.TimeScale & VOID_TimeScale.SOLAR_DAY) == 0u;
bool useRoundedScale = (this.TimeScale & VOID_TimeScale.ROUNDED_SCALE) != 0u; bool useRoundedScale = (this.TimeScale & VOID_TimeScale.ROUNDED_SCALE) != 0u;
   
useEarthTime = Layout.Toggle(useEarthTime, "Use Earth Time (changes KSP option)"); useEarthTime = Layout.Toggle(useEarthTime, "Use Earth Time (changes KSP option)");
   
GameSettings.KERBIN_TIME = !useEarthTime; GameSettings.KERBIN_TIME = !useEarthTime;
   
useSiderealTime = Layout.Toggle( useSiderealTime = Layout.Toggle(
useSiderealTime, useSiderealTime,
string.Format( string.Format(
"Time Scale: {0}", "Time Scale: {0}",
useSiderealTime ? "Sidereal" : "Solar" useSiderealTime ? "Sidereal" : "Solar"
) )
); );
   
useRoundedScale = Layout.Toggle( useRoundedScale = Layout.Toggle(
useRoundedScale, useRoundedScale,
string.Format( string.Format(
"Time Scale: {0}", "Time Scale: {0}",
useRoundedScale ? "Rounded" : "True" useRoundedScale ? "Rounded" : "True"
) )
); );
   
if (useEarthTime) if (useEarthTime)
{ {
this.TimeScale &= ~VOID_TimeScale.KERBIN_TIME; this.TimeScale &= ~VOID_TimeScale.KERBIN_TIME;
} }
else else
{ {
this.TimeScale |= VOID_TimeScale.KERBIN_TIME; this.TimeScale |= VOID_TimeScale.KERBIN_TIME;
} }
   
if (useSiderealTime) if (useSiderealTime)
{ {
this.TimeScale &= ~VOID_TimeScale.SOLAR_DAY; this.TimeScale &= ~VOID_TimeScale.SOLAR_DAY;
} }
else else
{ {
this.TimeScale |= VOID_TimeScale.SOLAR_DAY; this.TimeScale |= VOID_TimeScale.SOLAR_DAY;
} }
   
if (useRoundedScale) if (useRoundedScale)
{ {
this.TimeScale |= VOID_TimeScale.ROUNDED_SCALE; this.TimeScale |= VOID_TimeScale.ROUNDED_SCALE;
} }
else else
{ {
this.TimeScale &= ~VOID_TimeScale.ROUNDED_SCALE; this.TimeScale &= ~VOID_TimeScale.ROUNDED_SCALE;
} }
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
   
GUILayout.Label("Skin:", GUILayout.ExpandWidth(false)); GUILayout.Label("Skin:", GUILayout.ExpandWidth(false));
   
_content = new GUIContent(); _content = new GUIContent();
   
_content.text = "◄"; _content.text = "◄";
_content.tooltip = "Select previous skin"; _content.tooltip = "Select previous skin";
if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
{ {
this.skinIdx--; this.skinIdx--;
Logging.PostDebugMessage(string.Format( Logging.PostDebugMessage(string.Format(
"{0}: new this.skinIdx = {1} :: skin_list.Count = {2}", "{0}: new this.skinIdx = {1} :: skin_list.Count = {2}",
this.GetType().Name, this.GetType().Name,
this.skinName, this.skinName,
this.validSkins.Count this.validSkins.Count
)); ));
} }
   
_content.text = this.Skin.name; _content.text = this.Skin.name;
_content.tooltip = "Current skin"; _content.tooltip = "Current skin";
GUILayout.Label(_content, VOID_Styles.labelCenter, GUILayout.ExpandWidth(true)); GUILayout.Label(_content, VOID_Styles.labelCenter, GUILayout.ExpandWidth(true));
   
_content.text = "►"; _content.text = "►";
_content.tooltip = "Select next skin"; _content.tooltip = "Select next skin";
if (GUILayout.Button(_content, GUILayout.ExpandWidth(true))) if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
{ {
this.skinIdx++; this.skinIdx++;
Logging.PostDebugMessage(string.Format( Logging.PostDebugMessage(string.Format(
"{0}: new this.skinIdx = {1} :: skin_list.Count = {2}", "{0}: new this.skinIdx = {1} :: skin_list.Count = {2}",
this.GetType().Name, this.GetType().Name,
this.skinName, this.skinName,
this.validSkins.Count this.validSkins.Count
)); ));
} }
   
this.skinIdx %= this.skinNames.Count; this.skinIdx %= this.skinNames.Count;
if (this.skinIdx < 0) if (this.skinIdx < 0)
{ {
this.skinIdx += this.skinNames.Count; this.skinIdx += this.skinNames.Count;
} }
   
if (this.skinName != skinNames[this.skinIdx]) if (this.skinName != skinNames[this.skinIdx])
{ {
this.skinName.value = skinNames[this.skinIdx]; this.skinName.value = skinNames[this.skinIdx];
this.GUIStylesLoaded = false; this.GUIStylesLoaded = false;
} }
   
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.Label("Update Rate (Hz):"); GUILayout.Label("Update Rate (Hz):");
if (this.stringFrequency == null) if (this.stringFrequency == null)
{ {
this.stringFrequency = (1f / this.UpdatePeriod).ToString(); this.stringFrequency = (1f / this.UpdatePeriod).ToString();
} }
this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true)); this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true));
   
if (GUILayout.Button("Apply")) if (GUILayout.Button("Apply"))
{ {
double updateFreq = 1f / this.UpdatePeriod; double updateFreq = 1f / this.UpdatePeriod;
double.TryParse(stringFrequency, out updateFreq); double.TryParse(stringFrequency, out updateFreq);
this.updatePeriod.value = 1 / updateFreq; this.updatePeriod.value = 1 / updateFreq;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
IVOID_Module module; IVOID_Module module;
for (int idx = 0; idx < this.modules.Count; idx++) for (int idx = 0; idx < this.modules.Count; idx++)
{ {
module = this.modules[idx]; module = this.modules[idx];
   
module.DrawConfigurables(); module.DrawConfigurables();
} }
   
this.FactoryReset = Layout.Toggle(this.FactoryReset, "Factory Reset"); this.FactoryReset = Layout.Toggle(this.FactoryReset, "Factory Reset");
} }
   
protected void UpdateSimManager() protected void UpdateSimManager()
{ {
if (HighLogic.LoadedSceneIsFlight) if (HighLogic.LoadedSceneIsFlight)
{ {
double radius = this.Vessel.Radius(); double radius = this.Vessel.Radius();
SimManager.Gravity = this.Vessel.mainBody.gravParameter / (radius * radius); SimManager.Gravity = this.Vessel.mainBody.gravParameter / (radius * radius);
SimManager.Atmosphere = this.Vessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres; SimManager.Atmosphere = this.Vessel.staticPressurekPa * PhysicsGlobals.KpaToAtmospheres;
SimManager.Mach = this.Vessel.mach; SimManager.Mach = this.Vessel.mach;
BuildAdvanced.Altitude = this.Vessel.altitude; BuildAdvanced.Altitude = this.Vessel.altitude;
CelestialBodies.SelectedBody = this.Vessel.mainBody; CelestialBodies.SelectedBody = this.Vessel.mainBody;
} }
   
#if DEBUG #if DEBUG
SimManager.logOutput = true; SimManager.logOutput = true;
#endif #endif
   
SimManager.TryStartSimulation(); SimManager.TryStartSimulation();
   
Logging.PostDebugMessage(this, "Started Engineer simulation with Atmosphere={0} atm and Gravity={1} m/s²", Logging.PostDebugMessage(this, "Started Engineer simulation with Atmosphere={0} atm and Gravity={1} m/s²",
SimManager.Atmosphere, SimManager.Atmosphere,
SimManager.Gravity SimManager.Gravity
); );
} }
   
protected void GetSimManagerResults() protected void GetSimManagerResults()
{ {
Logging.PostDebugMessage(this, "VesselSimulator results ready, setting Stages."); Logging.PostDebugMessage(this, "VesselSimulator results ready, setting Stages.");
   
this.Stages = SimManager.Stages; this.Stages = SimManager.Stages;
   
if (this.Stages != null && this.Stages.Length > 0) if (this.Stages != null && this.Stages.Length > 0)
{ {
this.LastStage = this.Stages[this.Stages.Length - 1]; this.LastStage = this.Stages[this.Stages.Length - 1];
} }
} }
   
protected void LoadModulesOfType<U>() protected void LoadModulesOfType<U>()
{ {
using (PooledDebugLogger sb = PooledDebugLogger.New(this)) using (PooledDebugLogger sb = PooledDebugLogger.New(this))
{ {
sb.AppendLine("Loading modules..."); sb.AppendLine("Loading modules...");
   
AssemblyLoader.LoadedAssembly assy; AssemblyLoader.LoadedAssembly assy;
for (int aIdx = 0; aIdx < AssemblyLoader.loadedAssemblies.Count; aIdx++) for (int aIdx = 0; aIdx < AssemblyLoader.loadedAssemblies.Count; aIdx++)
{ {
assy = AssemblyLoader.loadedAssemblies[aIdx]; assy = AssemblyLoader.loadedAssemblies[aIdx];
   
Type[] loadedTypes = assy.assembly.GetExportedTypes(); Type[] loadedTypes = assy.assembly.GetExportedTypes();
Type loadedType; Type loadedType;
for (int tIdx = 0; tIdx < loadedTypes.Length; tIdx++) for (int tIdx = 0; tIdx < loadedTypes.Length; tIdx++)
{ {
loadedType = loadedTypes[tIdx]; loadedType = loadedTypes[tIdx];
   
if ( if (
loadedType.IsInterface || loadedType.IsInterface ||
loadedType.IsAbstract || loadedType.IsAbstract ||
!typeof(U).IsAssignableFrom(loadedType) || !typeof(U).IsAssignableFrom(loadedType) ||
typeof(VOIDCore).IsAssignableFrom(loadedType)) typeof(VOIDCore).IsAssignableFrom(loadedType))
{ {
continue; continue;
} }
   
sb.AppendFormat("Checking IVOID_Module type {0}...", loadedType.Name); sb.AppendFormat("Checking IVOID_Module type {0}...", loadedType.Name);
   
try try
{ {
this.LoadModule(loadedType); this.LoadModule(loadedType);
sb.AppendLine("Success."); sb.AppendLine("Success.");
} }
catch (Exception ex) catch (Exception ex)
{ {
sb.AppendFormat("Failed, caught {0}\n", ex.GetType().Name); sb.AppendFormat("Failed, caught {0}\n", ex.GetType().Name);
   
#if DEBUG #if DEBUG
Debug.LogException(ex); Debug.LogException(ex);
#endif #endif
} }
} }
} }
   
this.LoadConfig(); this.LoadConfig();
   
this.modulesLoaded = true; this.modulesLoaded = true;
   
sb.AppendFormat("Loaded {0} modules.\n", this.Modules.Count); sb.AppendFormat("Loaded {0} modules.\n", this.Modules.Count);
   
sb.Print(); sb.Print();
} }
} }
   
protected void LoadModule(Type T) protected void LoadModule(Type T)
{ {
/*var existingModules = this.modules.Where(mod => mod.GetType().Name == T.Name); /*var existingModules = this.modules.Where(mod => mod.GetType().Name == T.Name);
if (existingModules.Any())*/ if (existingModules.Any())*/
for (int mIdx = 0; mIdx < this.modules.Count; mIdx++) for (int mIdx = 0; mIdx < this.modules.Count; mIdx++)
{ {
if (this.modules[mIdx].Name == T.Name) if (this.modules[mIdx].Name == T.Name)
{ {
Logging.PostErrorMessage("{0}: refusing to load {1}: already loaded", this.GetType().Name, T.Name); Logging.PostErrorMessage("{0}: refusing to load {1}: already loaded", this.GetType().Name, T.Name);
return; return;
} }
} }
   
var InstanceProperty = T.GetProperty( var InstanceProperty = T.GetProperty(
"Instance", "Instance",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Static |
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.FlattenHierarchy System.Reflection.BindingFlags.FlattenHierarchy
); );
   
object modInstance = null; object modInstance = null;
IVOID_Module module; IVOID_Module module;
   
if (InstanceProperty != null) if (InstanceProperty != null)
{ {
modInstance = InstanceProperty.GetValue(null, null); modInstance = InstanceProperty.GetValue(null, null);
} }
   
if (modInstance != null) if (modInstance != null)
{ {
module = modInstance as IVOID_Module; module = modInstance as IVOID_Module;
} }
else else
{ {
module = Activator.CreateInstance(T) as IVOID_Module; module = Activator.CreateInstance(T) as IVOID_Module;
} }
   
if (module.InValidGame && module.InValidScene) if (module.InValidGame && module.InValidScene)
{ {
this.modules.Add(module); this.modules.Add(module);
   
Logging.PostDebugMessage(string.Format( Logging.PostDebugMessage(string.Format(
"{0}: loaded module {1}.", "{0}: loaded module {1}.",
this.GetType().Name, this.GetType().Name,
T.Name T.Name
)); ));
} }
else else
{ {
if (module is IDisposable) if (module is IDisposable)
{ {
(module as IDisposable).Dispose(); (module as IDisposable).Dispose();
} }
} }
} }
   
protected void LoadSkins() protected void LoadSkins()
{ {
this.validSkins = new Dictionary<string, GUISkin>(); this.validSkins = new Dictionary<string, GUISkin>();
this.skinNames = new List<string>(); this.skinNames = new List<string>();
   
UnityEngine.Object[] skins = Resources.FindObjectsOfTypeAll(typeof(GUISkin)); UnityEngine.Object[] skins = Resources.FindObjectsOfTypeAll(typeof(GUISkin));
GUISkin skin; GUISkin skin;
for (int sIdx = 0; sIdx < skins.Length; sIdx++) for (int sIdx = 0; sIdx < skins.Length; sIdx++)
{ {
skin = (GUISkin)skins[sIdx]; skin = (GUISkin)skins[sIdx];
   
if (!this.forbiddenSkins.Contains(skin.name)) if (!this.forbiddenSkins.Contains(skin.name))
{ {
this.validSkins[skin.name] = skin; this.validSkins[skin.name] = skin;
this.skinNames.Add(skin.name); this.skinNames.Add(skin.name);
} }
} }
   
Logging.PostDebugMessage(string.Format( Logging.PostDebugMessage(string.Format(
"{0}: loaded {1} GUISkins.", "{0}: loaded {1} GUISkins.",
this.GetType().Name, this.GetType().Name,
this.validSkins.Count this.validSkins.Count
)); ));
   
this.skinNames.Sort(); this.skinNames.Sort();
   
int defaultIdx = int.MinValue; int defaultIdx = int.MinValue;
   
for (int i = 0; i < this.skinNames.Count; i++) for (int i = 0; i < this.skinNames.Count; i++)
{ {
if (this.skinNames[i] == this.skinName) if (this.skinNames[i] == this.skinName)
{ {
this.skinIdx = i; this.skinIdx = i;
} }
if (this.skinNames[i] == this.defaultSkin) if (this.skinNames[i] == this.defaultSkin)
{ {
defaultIdx = i; defaultIdx = i;
} }
if (this.skinIdx != int.MinValue && defaultIdx != int.MinValue) if (this.skinIdx != int.MinValue && defaultIdx != int.MinValue)
{ {
break; break;
} }
} }
   
if (this.skinIdx == int.MinValue) if (this.skinIdx == int.MinValue)
{ {
this.skinIdx = defaultIdx; this.skinIdx = defaultIdx;
} }
   
Logging.PostDebugMessage(string.Format( Logging.PostDebugMessage(string.Format(
"{0}: _skinIdx = {1}.", "{0}: _skinIdx = {1}.",
this.GetType().Name, this.GetType().Name,
this.skinName.ToString() this.skinName.ToString()
)); ));
   
this.skinsLoaded = true; this.skinsLoaded = true;
} }
   
protected void LoadGUIStyles() protected void LoadGUIStyles()
{ {
VOID_Styles.OnSkinChanged(); VOID_Styles.OnSkinChanged();
   
if (this.onSkinChanged != null) if (this.onSkinChanged != null)
{ {
this.onSkinChanged(this); this.onSkinChanged(this);
} }
   
this.GUIStylesLoaded = true; this.GUIStylesLoaded = true;
} }
   
protected void LoadBeforeUpdate() protected void LoadBeforeUpdate()
{ {
if (!this.vesselTypesLoaded) if (!this.vesselTypesLoaded)
{ {
Array typeObjs = Enum.GetValues(typeof(VesselType)); Array typeObjs = Enum.GetValues(typeof(VesselType));
this.AllVesselTypes = new VesselType[typeObjs.Length]; this.AllVesselTypes = new VesselType[typeObjs.Length];
   
for (int idx = 0; idx < typeObjs.Length; idx++) for (int idx = 0; idx < typeObjs.Length; idx++)
{ {
this.AllVesselTypes[idx] = (VesselType)typeObjs.GetValue(idx); this.AllVesselTypes[idx] = (VesselType)typeObjs.GetValue(idx);
} }
   
this.vesselTypesLoaded = true; this.vesselTypesLoaded = true;
} }
   
if (this.SortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0) if (this.SortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0)
{ {
this.SortedBodyList = new List<CelestialBody>(FlightGlobals.Bodies); this.SortedBodyList = new List<CelestialBody>(FlightGlobals.Bodies);
this.SortedBodyList.Sort(new CBListComparer()); this.SortedBodyList.Sort(new CBListComparer());
this.SortedBodyList.Reverse(); this.SortedBodyList.Reverse();
} }
   
// SimManager initialization that we don't necessarily want to repeat every Update. // SimManager initialization that we don't necessarily want to repeat every Update.
if (!this.simManagerLoaded && this.HomeBody != null) if (!this.simManagerLoaded && this.HomeBody != null)
{ {
SimManager.Gravity = VOID_Data.KerbinGee; SimManager.Gravity = VOID_Data.KerbinGee;
SimManager.Atmosphere = 0d; SimManager.Atmosphere = 0d;
SimManager.Mach = 1d; SimManager.Mach = 1d;
CelestialBodies.SelectedBody = this.HomeBody; CelestialBodies.SelectedBody = this.HomeBody;
BuildAdvanced.Altitude = 0d; BuildAdvanced.Altitude = 0d;
SimManager.OnReady += this.GetSimManagerResults; SimManager.OnReady += this.GetSimManagerResults;
   
this.simManagerLoaded = true; this.simManagerLoaded = true;
} }
} }
   
protected void InitializeToolbarButton() protected void InitializeToolbarButton()
{ {
// Do nothing if (the Toolbar is not available. // Do nothing if (the Toolbar is not available.
if (!ToolbarManager.ToolbarAvailable) if (!ToolbarManager.ToolbarAvailable)
{ {
Logging.PostDebugMessage(this, "Refusing to make a ToolbarButton: ToolbarAvailable = false"); Logging.PostDebugMessage(this, "Refusing to make a ToolbarButton: ToolbarAvailable = false");
return; return;
} }
   
this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle"); this.ToolbarButton = ToolbarManager.Instance.add(this.VoidName, "coreToggle");
this.ToolbarButton.Text = this.VoidName; this.ToolbarButton.Text = this.VoidName;
this.SetIconTexture(this.powerState | this.activeState); this.SetIconTexture(this.powerState | this.activeState);
   
this.ToolbarButton.Visible = true; this.ToolbarButton.Visible = true;
   
this.ToolbarButton.OnClick += this.ToolbarButton.OnClick +=
(e) => (e) =>
{ {
this.ToggleMainWindow(); this.ToggleMainWindow();
}; };
   
Logging.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name)); Logging.PostDebugMessage(string.Format("{0}: Toolbar Button initialized.", this.GetType().Name));
} }
   
protected void InitializeAppLauncherButton() protected void InitializeAppLauncherButton()
{ {
if (ApplicationLauncher.Ready) if (ApplicationLauncher.Ready)
{ {
this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication( this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication(
this.ToggleMainWindow, this.ToggleMainWindow, this.ToggleMainWindow, this.ToggleMainWindow,
this.appIconVisibleScenes, this.appIconVisibleScenes,
this.VOIDIconTexture this.VOIDIconTexture
); );
   
Logging.PostDebugMessage( Logging.PostDebugMessage(
this, this,
"AppLauncherButton initialized in {0}", "AppLauncherButton initialized in {0}",
Enum.GetName( Enum.GetName(
typeof(GameScenes), typeof(GameScenes),
HighLogic.LoadedScene HighLogic.LoadedScene
) )
); );
} }
} }
   
protected void ToggleMainWindow() protected void ToggleMainWindow()
{ {
this.Active = !this.Active; this.Active = !this.Active;
} }
   
protected void SetIconTexture(IconState state) protected void SetIconTexture(IconState state)
{ {
switch (state) switch (state)
{ {
case (IconState.PowerOff | IconState.Inactive): case (IconState.PowerOff | IconState.Inactive):
this.SetIconTexture(this.VOIDIconOffInactivePath); this.SetIconTexture(this.VOIDIconOffInactivePath);
break; break;
case (IconState.PowerOff | IconState.Active): case (IconState.PowerOff | IconState.Active):
this.SetIconTexture(this.VOIDIconOffActivePath); this.SetIconTexture(this.VOIDIconOffActivePath);
break; break;
case (IconState.PowerOn | IconState.Inactive): case (IconState.PowerOn | IconState.Inactive):
this.SetIconTexture(this.VOIDIconOnInactivePath); this.SetIconTexture(this.VOIDIconOnInactivePath);
break; break;
case (IconState.PowerOn | IconState.Active): case (IconState.PowerOn | IconState.Active):
this.SetIconTexture(this.VOIDIconOnActivePath); this.SetIconTexture(this.VOIDIconOnActivePath);
break; break;
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
   
protected void SetIconTexture(string texturePath) protected void SetIconTexture(string texturePath)
{ {
if (texturePath == null) if (texturePath == null)
{ {
return; return;
} }
   
if (this.ToolbarButton != null) if (this.ToolbarButton != null)
{ {
this.ToolbarButton.TexturePath = texturePath; this.ToolbarButton.TexturePath = texturePath;
} }
   
if (this.AppLauncherButton != null) if (this.AppLauncherButton != null)
{ {
this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false); this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false);
   
this.AppLauncherButton.SetTexture(VOIDIconTexture); this.AppLauncherButton.SetTexture(VOIDIconTexture);
} }
} }
   
public void LoadConfig() public void LoadConfig()
{ {
   
if (!System.IO.File.Exists(this.VOIDSettingsPath) && KSP.IO.File.Exists<VOID_Module>("config.xml")) if (!System.IO.File.Exists(this.VOIDSettingsPath) && KSP.IO.File.Exists<VOID_Module>("config.xml"))
{ {
Logging.PostLogMessage( Logging.PostLogMessage(
"VOID: No per-save config file but old file detected; copying from old file." "VOID: No per-save config file but old file detected; copying from old file."
); );
   
System.IO.File.Copy( System.IO.File.Copy(
KSP.IO.IOUtils.GetFilePathFor(typeof(VOID_Module), "config.xml"), KSP.IO.IOUtils.GetFilePathFor(typeof(VOID_Module), "config.xml"),
this.VOIDSettingsPath this.VOIDSettingsPath
); );
} }
   
this.LoadConfig(new PluginConfiguration(this.VOIDSettingsPath)); this.LoadConfig(new PluginConfiguration(this.VOIDSettingsPath));
} }
   
public override void LoadConfig(KSP.IO.PluginConfiguration config) public override void LoadConfig(KSP.IO.PluginConfiguration config)
{ {
base.LoadConfig(config); base.LoadConfig(config);
   
IVOID_Module module; IVOID_Module module;
for (int idx = 0; idx < this.modules.Count; idx++) for (int idx = 0; idx < this.modules.Count; idx++)
{ {
module = this.modules[idx]; module = this.modules[idx];
   
module.LoadConfig(config); module.LoadConfig(config);
} }
   
this.TimeScale |= GameSettings.KERBIN_TIME ? VOID_TimeScale.KERBIN_TIME : 0u; this.TimeScale |= GameSettings.KERBIN_TIME ? VOID_TimeScale.KERBIN_TIME : 0u;
} }
   
public override void SaveConfig() public override void SaveConfig()
{ {
if (this.configNeedsUpdate && this is VOIDCore_Flight) if (this.configNeedsUpdate && this is VOIDCore_Flight)
{ {
KSP.IO.File.Delete<T>("config.xml"); KSP.IO.File.Delete<T>("config.xml");
System.IO.File.Delete(this.VOIDSettingsPath); System.IO.File.Delete(this.VOIDSettingsPath);
} }
   
KSP.IO.PluginConfiguration config = new PluginConfiguration(this.VOIDSettingsPath); KSP.IO.PluginConfiguration config = new PluginConfiguration(this.VOIDSettingsPath);
   
config.load(); config.load();
   
this.Save(config, this.SceneKey); this.Save(config, this.SceneKey);
   
IVOID_Module module; IVOID_Module module;
for (int idx = 0; idx < this.modules.Count; idx++) for (int idx = 0; idx < this.modules.Count; idx++)
{ {
module = this.modules[idx]; module = this.modules[idx];
   
module.Save(config, this.SceneKey); module.Save(config, this.SceneKey);
} }
   
config.save(); config.save();
   
this.configDirty = false; this.configDirty = false;
} }
   
public VOIDCore_Generic() public VOIDCore_Generic()
{ {
System.Version version = this.GetType().Assembly.GetName().Version; System.Version version = this.GetType().Assembly.GetName().Version;
   
this.VoidVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.MajorRevision); this.VoidVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.MajorRevision);
   
this.Name = string.Format("VOID {0}", this.VoidVersion.ToString()); this.Name = string.Format("VOID {0}", this.VoidVersion.ToString());
   
this.powerAvailable = true; this.powerAvailable = true;
   
this.Active = true; this.Active = true;
   
this.skinName = (VOID_SaveValue<string>)this.defaultSkin; this.skinName = (VOID_SaveValue<string>)this.defaultSkin;
this.skinIdx = int.MinValue; this.skinIdx = int.MinValue;
   
this.VOIDIconOnActivePath = "VOID/Textures/void_icon_light_glow"; this.VOIDIconOnActivePath = "VOID/Textures/void_icon_light_glow";
this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_dark_glow"; this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_dark_glow";
this.VOIDIconOffActivePath = "VOID/Textures/void_icon_light"; this.VOIDIconOffActivePath = "VOID/Textures/void_icon_light";
this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_dark"; this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_dark";
   
this.saveTimer = 0f; this.saveTimer = 0f;
this.UpdateTimer = 0f; this.UpdateTimer = 0f;
   
this.vesselSimActive = (VOID_SaveValue<bool>)true; this.vesselSimActive = (VOID_SaveValue<bool>)true;
   
this.useToolbarManager = (VOID_SaveValue<bool>)ToolbarManager.ToolbarAvailable; this.useToolbarManager = (VOID_SaveValue<bool>)ToolbarManager.ToolbarAvailable;
   
this.SaveGamePath = string.Format("{0}saves/{1}", IOTools.KSPRootPath, HighLogic.SaveFolder); this.SaveGamePath = string.Format("{0}saves/{1}", IOTools.KSPRootPath, HighLogic.SaveFolder);
this.VOIDSettingsPath = string.Format("{0}/VOIDConfig.xml", this.SaveGamePath); this.VOIDSettingsPath = string.Format("{0}/VOIDConfig.xml", this.SaveGamePath);
   
this.FactoryReset = false; this.FactoryReset = false;
} }
   
public override void Dispose() public override void Dispose()
{ {
this.StopGUI(); this.StopGUI();
   
this.onSkinChanged(this); this.onSkinChanged(this);
   
if (this.AppLauncherButton != null) if (this.AppLauncherButton != null)
{ {
ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton); ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
this.AppLauncherButton = null; this.AppLauncherButton = null;
} }
if (this.ToolbarButton != null) if (this.ToolbarButton != null)
{ {
this.ToolbarButton.Destroy(); this.ToolbarButton.Destroy();
this.ToolbarButton = null; this.ToolbarButton = null;
} }
   
_instance = null; _instance = null;
_initialized = false; _initialized = false;
} }
} }
} }