VOIDCore_Generic: Basic cleanup removing underscores, fixing some naming conventions, etc.
[VOID.git] / VOIDCore_Generic.cs
blob:a/VOIDCore_Generic.cs -> blob:b/VOIDCore_Generic.cs
--- a/VOIDCore_Generic.cs
+++ b/VOIDCore_Generic.cs
@@ -26,6 +26,8 @@
 // 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;
@@ -37,7 +39,7 @@
 
 namespace VOID
 {
-	public abstract class VOIDCore_Generic<T> : VOID_SingletonModule<T>, IVOID_Module, IDisposable
+	public abstract class VOIDCore_Generic<T> : VOID_SingletonCore<T>, IVOID_Module, IDisposable
 		where T : VOID_Module, new()
 	{
 		/*
@@ -58,7 +60,8 @@
 		protected string VOIDIconOffActivePath;
 		protected string VOIDIconOffInactivePath;
 
-		private bool _useToolbarManager;
+		[AVOID_SaveValue("useToolbarManager")]
+		protected VOID_SaveValue<bool> useToolbarManager;
 
 		protected GUIStyle iconStyle;
 
@@ -90,8 +93,12 @@
 		[AVOID_SaveValue("vesselSimActive")]
 		protected VOID_SaveValue<bool> vesselSimActive;
 
-		// Vessel Type Housekeeping
+		[AVOID_SaveValue("timeScaleFlags")]
+		protected VOID_SaveValue<UInt32> timeScaleFlags;
+
+		// Load-up housekeeping
 		protected bool vesselTypesLoaded = false;
+		protected bool simManagerLoaded = false;
 
 		protected string defaultSkin = "KSP window 2";
 
@@ -119,14 +126,29 @@
 
 		public override bool configDirty { get; set; }
 
-		internal IButton ToolbarButton;
-
-		internal ApplicationLauncherButton AppLauncherButton;
+		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<CelestialBody> AllBodies
 		{
 			get
@@ -242,11 +264,23 @@
 			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.toggleActive)
+				if (this.Active)
 				{
 					return IconState.Inactive;
 				}
@@ -279,47 +313,16 @@
 			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 
 		public override event VOIDEventHandler onApplicationQuit;
 		public override event VOIDEventHandler onSkinChanged;
+		public override event VOIDEventHandler onUpdate;
 
 		/*
 		 * Methods
@@ -351,29 +354,17 @@
 					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.toggleActive)
+			if (
+				this.iconState != (this.powerState | this.activeState) ||
+				(this.VOIDIconTexture == null && this.AppLauncherButton != null)
+			)
+			{
+				this.iconState = this.powerState | this.activeState;
+
+				this.SetIconTexture(this.iconState);
+			}
+
+			if (this.Active)
 			{
 				base.DrawGUI();
 			}
@@ -386,7 +377,7 @@
 			if (
 				this.vesselSimActive &&
 				(
-					this.vessel != null ||
+					this.Vessel != null ||
 					(
 						HighLogic.LoadedSceneIsEditor &&
 						EditorLogic.RootPart != null &&
@@ -399,17 +390,20 @@
 				this.UpdateSimManager();
 			}
 
-			if (!this.guiRunning)
+			if (!this.GUIRunning)
 			{
 				this.StartGUI();
 			}
 
-			foreach (IVOID_Module module in this.modules)
-			{
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
 				if (
-					!module.guiRunning &&
-					module.toggleActive &&
-					module.inValidScene &&
+					!module.GUIRunning &&
+					module.Active &&
+					module.InValidScene &&
 					(
 						!HighLogic.LoadedSceneIsEditor ||
 						(EditorLogic.RootPart != null && EditorLogic.SortedShipList.Count > 0)
@@ -419,11 +413,11 @@
 					module.StartGUI();
 				}
 				if (
-					module.guiRunning &&
+					module.GUIRunning &&
 					(
-						!module.toggleActive ||
+						!module.Active ||
 					    !this.togglePower ||
-						!module.inValidScene ||
+						!module.InValidScene ||
 					    this.FactoryReset ||
 						(
 							HighLogic.LoadedSceneIsEditor &&
@@ -441,8 +435,58 @@
 				}
 			}
 
-			this.CheckAndSave();
+			if (this.useToolbarManager)
+			{
+				if (this.AppLauncherButton != null)
+				{
+					ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
+					this.AppLauncherButton = null;
+				}
+
+				if (this.ToolbarButton == null)
+				{
+					this.InitializeToolbarButton();
+				}
+			}
+			else
+			{
+				if (this.ToolbarButton != null)
+				{
+					this.ToolbarButton.Destroy();
+					this.ToolbarButton = null;
+				}
+
+				if (this.AppLauncherButton == null)
+				{
+					this.InitializeAppLauncherButton();
+				}
+
+			}
+
+			this.saveTimer += Time.deltaTime;
+
+			if (this.saveTimer > 2f)
+			{
+				if (this.configDirty)
+				{
+
+					Tools.PostDebugMessage(string.Format(
+							"{0}: Time to save, checking if configDirty: {1}",
+							this.GetType().Name,
+							this.configDirty
+						));
+
+					this.SaveConfig();
+					this.saveTimer = 0;
+				}
+			}
+
 			this.UpdateTimer += Time.deltaTime;
+
+			if (this.onUpdate != null)
+			{
+				this.onUpdate(this);
+			}
 		}
 
 		public virtual void FixedUpdate()
@@ -450,10 +494,10 @@
 			bool newPowerState = this.powerAvailable;
 
 			if (this.togglePower && this.consumeResource &&
-			    this.vessel.vesselType != VesselType.EVA &&
+			    this.Vessel.vesselType != VesselType.EVA &&
 			    TimeWarp.deltaTime != 0)
 			{
-				float powerReceived = this.vessel.rootPart.RequestResource(
+				float powerReceived = this.Vessel.rootPart.RequestResource(
 					this.resourceName,
 					this.resourceRate * TimeWarp.fixedDeltaTime
 				);
@@ -470,12 +514,14 @@
 				if (this.powerAvailable != newPowerState)
 				{
 					this.powerAvailable = newPowerState;
-					this.SetIconTexture(this.powerState | this.activeState);
-				}
-			}
-
-			foreach (IVOID_Module module in this.modules)
-			{
+				}
+			}
+
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
 				if (module is IVOID_BehaviorModule)
 				{
 					((IVOID_BehaviorModule)module).FixedUpdate();
@@ -485,8 +531,11 @@
 
 		public void OnDestroy()
 		{
-			foreach (IVOID_Module module in this.modules)
-			{
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
 				if (module is IVOID_BehaviorModule)
 				{
 					((IVOID_BehaviorModule)module).OnDestroy();
@@ -508,7 +557,7 @@
 
 		public override void StartGUI()
 		{
-			if (!this.guiRunning)
+			if (!this.GUIRunning)
 			{
 				RenderingManager.AddToPostDrawQueue(3, this.DrawGUI);
 			}
@@ -518,8 +567,11 @@
 		{
 			this.StopGUI();
 
-			foreach (IVOID_Module module in this.modules)
-			{
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
 				module.StopGUI();
 				module.StartGUI();
 			}
@@ -541,20 +593,22 @@
 					if (GUILayout.Button("Power " + str))
 					{
 						togglePower.value = !togglePower;
-						this.SetIconTexture(this.powerState | this.activeState);
 					}
 				}
 
 				if (togglePower || !HighLogic.LoadedSceneIsFlight)
 				{
-					foreach (IVOID_Module module in this.modules)
+					IVOID_Module module;
+					for (int idx = 0; idx < this.modules.Count; idx++)
 					{
+						module = this.modules[idx];
+
 						if (module is VOID_ConfigWindow)
 						{
 							continue;
 						}
 
-						module.toggleActive = GUITools.Toggle(module.toggleActive, module.Name);
+						module.Active = GUITools.Toggle(module.Active, module.Name);
 					}
 				}
 			}
@@ -563,8 +617,8 @@
 				GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed);
 			}
 
-			VOID_ConfigWindow.Instance.toggleActive = GUITools.Toggle(
-				VOID_ConfigWindow.Instance.toggleActive,
+			VOID_ConfigWindow.Instance.Active = GUITools.Toggle(
+				VOID_ConfigWindow.Instance.Active,
 				"Configuration"
 			);
 
@@ -577,10 +631,61 @@
 		{
 			GUIContent _content;
 
-			this.useToolbarManager = GUITools.Toggle(this.useToolbarManager, "Use Blizzy's Toolbar If Available");
+			this.useToolbarManager.value = 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));
 
@@ -648,9 +753,12 @@
 			}
 			GUILayout.EndHorizontal();
 
-			foreach (IVOID_Module mod in this.modules)
-			{
-				mod.DrawConfigurables();
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
+				module.DrawConfigurables();
 			}
 
 			this.FactoryReset = GUITools.Toggle(this.FactoryReset, "Factory Reset");
@@ -658,28 +766,26 @@
 
 		protected void UpdateSimManager()
 		{
-			if (SimManager.ResultsReady())
-			{
-				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 (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
-			else
-			{
-				Tools.PostDebugMessage(this, "VesselSimulator results not ready.");
-			}
+			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()
@@ -699,10 +805,17 @@
 			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())
-				{
+			AssemblyLoader.LoadedAssembly assy;
+			for (int aIdx = 0; aIdx < AssemblyLoader.loadedAssemblies.Count; aIdx++)
+			{
+				assy = AssemblyLoader.loadedAssemblies[aIdx];
+
+				Type[] loadedTypes = assy.assembly.GetExportedTypes();
+				Type loadedType;
+				for (int tIdx = 0; tIdx < loadedTypes.Length; tIdx++)
+				{
+					loadedType = loadedTypes[tIdx];
+
 					if (
 						loadedType.IsInterface ||
 						loadedType.IsAbstract ||
@@ -753,7 +866,9 @@
 
 			var InstanceProperty = T.GetProperty(
 				"Instance",
-				System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public
+				System.Reflection.BindingFlags.Static |
+				System.Reflection.BindingFlags.Public |
+				System.Reflection.BindingFlags.FlattenHierarchy
 			);
 
 			object modInstance = null;
@@ -773,7 +888,7 @@
 				module = Activator.CreateInstance(T) as IVOID_Module;
 			}
 
-			if (module.inValidGame && module.inValidScene)
+			if (module.InValidGame && module.InValidScene)
 			{
 				module.LoadConfig();
 				this.modules.Add(module);
@@ -783,6 +898,13 @@
 						this.GetType().Name,
 						T.Name
 					));
+			}
+			else
+			{
+				if (module is IDisposable)
+				{
+					(module as IDisposable).Dispose();
+				}
 			}
 		}
 
@@ -856,17 +978,12 @@
 			this.GUIStylesLoaded = true;
 		}
 
-		protected void LoadVesselTypes()
-		{
-			this.AllVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToArray();
-			this.vesselTypesLoaded = true;
-		}
-
 		protected void LoadBeforeUpdate()
 		{
 			if (!this.vesselTypesLoaded)
 			{
-				this.LoadVesselTypes();
+				this.AllVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToArray();
+				this.vesselTypesLoaded = true;
 			}
 
 			if (this.SortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0)
@@ -878,6 +995,18 @@
 				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()
@@ -927,8 +1056,7 @@
 
 		protected void ToggleMainWindow()
 		{
-			this.toggleActive = !this.toggleActive;
-			this.SetIconTexture(this.powerState | this.activeState);
+			this.Active = !this.Active;
 		}
 
 		protected void SetIconTexture(IconState state)
@@ -954,49 +1082,37 @@
 
 		protected void SetIconTexture(string texturePath)
 		{
+			if (texturePath == null)
+			{
+				return;
+			}
+
 			if (this.ToolbarButton != null)
 			{
 				this.ToolbarButton.TexturePath = texturePath;
 			}
 
-			this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false);
-
 			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)
-			{
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
 				module.LoadConfig();
 			}
+
+			this.TimeScale |= GameSettings.KERBIN_TIME ? VOID_TimeScale.KERBIN_TIME : 0u;
 		}
 
 		public override void SaveConfig()
@@ -1012,8 +1128,11 @@
 
 			this.Save(config);
 
-			foreach (IVOID_Module module in this.modules)
-			{
+			IVOID_Module module;
+			for (int idx = 0; idx < this.modules.Count; idx++)
+			{
+				module = this.modules[idx];
+
 				module.Save(config);
 			}
 
@@ -1032,7 +1151,7 @@
 
 			this.powerAvailable = true;
 
-			this.toggleActive = true;
+			this.Active = true;
 
 			this.skinName = (VOID_SaveValue<string>)this.defaultSkin;
 			this.skinIdx = int.MinValue;
@@ -1046,21 +1165,17 @@
 			this.UpdateTimer = 0f;
 
 			this.vesselSimActive = (VOID_SaveValue<bool>)true;
-			SimManager.Atmosphere = 0d;
-			SimManager.OnReady += this.GetSimManagerResults;
-
-			this.useToolbarManager = ToolbarManager.ToolbarAvailable;
+
+			this.useToolbarManager = (VOID_SaveValue<bool>)ToolbarManager.ToolbarAvailable;
 
 			this.LoadConfig();
 
 			this.configVersion = (VOID_SaveValue<int>)VOIDCore.CONFIG_VERSION;
-			
-			this.SetIconTexture(this.powerState | this.activeState);
 
 			this.FactoryReset = false;
 		}
 
-		public virtual void Dispose()
+		public override void Dispose()
 		{
 			this.StopGUI();
 
@@ -1080,14 +1195,6 @@
 			_instance = null;
 			_initialized = false;
 		}
-
-		protected enum IconState
-		{
-			PowerOff = 1,
-			PowerOn = 2,
-			Inactive = 4,
-			Active = 8
-		}
 	}
 }