VOID_Core: Added AppLauncher button stuff.
[VOID.git] / VOID_Core.cs
blob:a/VOID_Core.cs -> blob:b/VOID_Core.cs
--- a/VOID_Core.cs
+++ b/VOID_Core.cs
@@ -31,6 +31,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Text;
 using ToadicusTools;
 using UnityEngine;
 
@@ -70,6 +71,7 @@
 		public static void Reset()
 		{
 			_instance.StopGUI();
+			_instance.Dispose();
 			_instance = null;
 			_initialized = false;
 		}
@@ -118,9 +120,8 @@
 		protected int _windowID = 0;
 
 		protected bool GUIStylesLoaded = false;
-		protected Dictionary<string, GUIStyle> _LabelStyles = new Dictionary<string, GUIStyle>();
-
-		protected CelestialBody _Kerbin;
+
+		protected CelestialBody _homeBody;
 
 		[AVOID_SaveValue("togglePower")]
 		public VOID_SaveValue<bool> togglePower = true;
@@ -165,7 +166,8 @@
 				"ExpRecoveryDialogSkin",
 				"KSP window 5",
 				"KSP window 6",
-				"PartTooltipSkin"
+				"PartTooltipSkin",
+				"KSCContextMenuSkin"
 			};
 		protected bool skinsLoaded = false;
 
@@ -227,14 +229,6 @@
 			}
 		}
 
-		public Dictionary<string, GUIStyle> LabelStyles
-		{
-			get
-			{
-				return this._LabelStyles;
-			}
-		}
-
 		public List<CelestialBody> allBodies
 		{
 			get
@@ -243,19 +237,25 @@
 			}
 		}
 
-		public CelestialBody Kerbin
-		{
-			get
-			{
-				if (this._Kerbin == null)
-				{
-					if (FlightGlobals.Bodies != null)
+		public List<CelestialBody> sortedBodyList
+		{
+			get;
+			private set;
+		}
+
+		public CelestialBody HomeBody
+		{
+			get
+			{
+				if (this._homeBody == null)
+				{
+					if (Planetarium.fetch != null)
 					{
-						this._Kerbin = FlightGlobals.Bodies.First(b => b.name == "Kerbin");
+						this._homeBody = Planetarium.fetch.Home;
 					}
 				}
 
-				return this._Kerbin;
+				return this._homeBody;
 			}
 		}
 
@@ -281,6 +281,18 @@
 			{
 				return this._updatePeriod;
 			}
+		}
+
+		public Stage[] Stages
+		{
+			get;
+			protected set;
+		}
+
+		public Stage LastStage
+		{
+			get;
+			protected set;
 		}
 
 		protected IconState powerState
@@ -348,6 +360,14 @@
 			}
 		}
 
+		protected virtual ApplicationLauncher.AppScenes appIconVisibleScenes
+		{
+			get
+			{
+				return ApplicationLauncher.AppScenes.FLIGHT;
+			}
+		}
+
 		/*
 		 * Methods
 		 * */
@@ -370,17 +390,33 @@
 			if (!this.GUIStylesLoaded)
 			{
 				this.LoadGUIStyles();
+
+				Tools.PostDebugMessage(
+					this,
+					"ToolbarAvailable: {0}, UseToobarManager: {1}",
+					ToolbarManager.ToolbarAvailable,
+					this.UseToolbarManager);
 			}
 
 			if (!this.UseToolbarManager)
 			{
 				if (this.AppLauncherButton == null)
 				{
+					Tools.PostDebugMessage(this,
+						"UseToolbarManager = false (ToolbarAvailable = {0}) and " +
+						"AppLauncherButton is null, making AppLauncher button.",
+						ToolbarManager.ToolbarAvailable
+					);
 					this.InitializeAppLauncherButton();
 				}
 			}
 			else if (this.ToolbarButton == null)
 			{
+				Tools.PostDebugMessage(this,
+					"UseToolbarManager = true (ToolbarAvailable = {0}) and " +
+					"ToolbarButton is null, making Toolbar button.",
+					ToolbarManager.ToolbarAvailable
+				);
 				this.InitializeToolbarButton();
 			}
 
@@ -398,7 +434,14 @@
 					GUILayout.Height(50)
 				);
 
-				_mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos);
+				if (HighLogic.LoadedSceneIsEditor)
+				{
+					_mainWindowPos = Tools.ClampRectToEditorPad(_mainWindowPos);
+				}
+				else
+				{
+					_mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos);
+				}
 
 				if (_mainWindowPos != this.mainWindowPos)
 				{
@@ -419,7 +462,14 @@
 					GUILayout.Height(50)
 				);
 
-				_configWindowPos = Tools.ClampRectToScreen(_configWindowPos);
+				if (HighLogic.LoadedSceneIsEditor)
+				{
+					_configWindowPos = Tools.ClampRectToEditorPad(_configWindowPos);
+				}
+				else
+				{
+					_configWindowPos = Tools.ClampRectToScreen(_configWindowPos);
+				}
 
 				if (_configWindowPos != this.configWindowPos)
 				{
@@ -428,7 +478,7 @@
 			}
 		}
 
-		public void OnGUI()
+		public virtual void OnGUI()
 		{
 			if (Event.current.type == EventType.Repaint)
 			{
@@ -482,20 +532,14 @@
 			}
 		}
 
-		public void Update()
+		public virtual void Update()
 		{
 			this.LoadBeforeUpdate();
 
 			if (this.vessel != null && this.vesselSimActive)
 			{
-				double radius = this.vessel.Radius();
-				SimManager.Gravity = this.vessel.mainBody.gravParameter /
-					(radius * radius);
-				SimManager.TryStartSimulation();
-			}
-			else if (!this.vesselSimActive)
-			{
-				SimManager.ClearResults();
+				Tools.PostDebugMessage(this, "Updating SimManager.");
+				this.UpdateSimManager();
 			}
 
 			if (!this.guiRunning)
@@ -532,7 +576,7 @@
 			this._updateTimer += Time.deltaTime;
 		}
 
-		public void FixedUpdate()
+		public virtual void FixedUpdate()
 		{
 			bool newPowerState = this.powerAvailable;
 
@@ -561,10 +605,23 @@
 				}
 			}
 
-			foreach (IVOID_BehaviorModule module in
-			         this._modules.OfType<IVOID_BehaviorModule>().Where(m => !m.GetType().IsAbstract))
-			{
-				module.FixedUpdate();
+			foreach (IVOID_Module module in this.Modules)
+			{
+				if (module is IVOID_BehaviorModule)
+				{
+					((IVOID_BehaviorModule)module).FixedUpdate();
+				}
+			}
+		}
+
+		public void OnDestroy()
+		{
+			foreach (IVOID_Module module in this.Modules)
+			{
+				if (module is IVOID_BehaviorModule)
+				{
+					((IVOID_BehaviorModule)module).OnDestroy();
+				}
 			}
 		}
 
@@ -609,7 +666,7 @@
 			}
 			else
 			{
-				GUILayout.Label("-- POWER LOST --", this.LabelStyles["red"]);
+				GUILayout.Label("-- POWER LOST --", VOID_Styles.labelRed);
 			}
 
 			this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration");
@@ -654,7 +711,6 @@
 			_content.tooltip = "Select previous skin";
 			if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
 			{
-				this.GUIStylesLoaded = false;
 				this._skinIdx--;
 				Tools.PostDebugMessage(string.Format(
 					"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
@@ -666,13 +722,12 @@
 
 			_content.text = this.Skin.name;
 			_content.tooltip = "Current skin";
-			GUILayout.Label(_content, this.LabelStyles["center"], GUILayout.ExpandWidth(true));
+			GUILayout.Label(_content, VOID_Styles.labelCenter, GUILayout.ExpandWidth(true));
 
 			_content.text = "►";
 			_content.tooltip = "Select next skin";
 			if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
 			{
-				this.GUIStylesLoaded = false;
 				this._skinIdx++;
 				Tools.PostDebugMessage(string.Format(
 					"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
@@ -691,6 +746,7 @@
 			if (this._skinName != skinNames[this._skinIdx])
 			{
 				this._skinName.value = skinNames[this._skinIdx];
+				this.GUIStylesLoaded = false;
 			}
 
 			GUILayout.EndHorizontal();
@@ -702,7 +758,7 @@
 				this.stringFrequency = (1f / this.updatePeriod).ToString();
 			}
 			this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true));
-			// GUILayout.FlexibleSpace();
+
 			if (GUILayout.Button("Apply"))
 			{
 				double updateFreq = 1f / this.updatePeriod;
@@ -719,45 +775,89 @@
 			this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset");
 		}
 
+		protected void UpdateSimManager()
+		{
+			if (SimManager.ResultsReady())
+			{
+				Tools.PostDebugMessage(this, "VesselSimulator results ready, setting Stages.");
+
+				this.Stages = SimManager.Stages;
+
+				if (this.Stages != null)
+				{
+					this.LastStage = this.Stages.Last();
+				}
+
+				if (HighLogic.LoadedSceneIsEditor)
+				{
+					SimManager.Gravity = VOID_Data.KerbinGee;
+				}
+				else
+				{
+					double radius = this.vessel.Radius();
+					SimManager.Gravity = this.vessel.mainBody.gravParameter / (radius * radius);
+				}
+
+				SimManager.minSimTime = (long)(this.updatePeriod * 1000);
+
+				SimManager.TryStartSimulation();
+			}
+			#if DEBUG
+			else
+			{
+				Tools.PostDebugMessage(this, "VesselSimulator results not ready.");
+			}
+			#endif
+		}
+
 		protected void LoadModulesOfType<T>()
 		{
-			var types = AssemblyLoader.loadedAssemblies
-				.Select(a => a.assembly.GetExportedTypes())
-				.SelectMany(t => t)
-				.Where(v => typeof(T).IsAssignableFrom(v)
-					&& !(v.IsInterface || v.IsAbstract) &&
-					!typeof(VOID_Core).IsAssignableFrom(v)
-				);
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Found {1} modules to check.",
-				this.GetType().Name,
-				types.Count()
-			));
-			foreach (var voidType in types)
-			{
-				if (!HighLogic.LoadedSceneIsEditor &&
-					typeof(IVOID_EditorModule).IsAssignableFrom(voidType))
-				{
-					continue;
-				}
-
-				Tools.PostDebugMessage(string.Format(
-					"{0}: found Type {1}",
-					this.GetType().Name,
-					voidType.Name
-				));
-
-				this.LoadModule(voidType);
+			StringBuilder sb = new StringBuilder("Loading modules...");
+			sb.AppendLine();
+
+			foreach (AssemblyLoader.LoadedAssembly assy in AssemblyLoader.loadedAssemblies)
+			{
+				foreach (Type loadedType in assy.assembly.GetExportedTypes())
+				{
+					if (
+						loadedType.IsInterface ||
+						loadedType.IsAbstract ||
+						!typeof(T).IsAssignableFrom(loadedType) ||
+						this.GetType().IsAssignableFrom(loadedType)
+					)
+					{
+						continue;
+					}
+
+					// HACK: This stops editor modules from loading in flight.  It is a dirty hack and should be fixed.
+					if (!HighLogic.LoadedSceneIsEditor && typeof(IVOID_EditorModule).IsAssignableFrom(loadedType))
+					{
+						continue;
+					}
+
+					sb.AppendFormat("Loading IVOID_Module type {0}...", loadedType.Name);
+
+					try
+					{
+						this.LoadModule(loadedType);
+						sb.AppendLine("Success.");
+					}
+					catch (Exception ex)
+					{
+						sb.AppendFormat("Failed, caught {0}", ex.GetType().Name);
+						sb.AppendLine();
+
+						#if DEBUG
+						Debug.LogException(ex);
+						#endif
+					}
+				}
 			}
 
 			this._modulesLoaded = true;
 
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Loaded {1} modules.",
-				this.GetType().Name,
-				this.Modules.Count
-			));
+			sb.AppendFormat("Loaded {0} modules.", this.Modules.Count);
+			sb.AppendLine();
 		}
 
 		protected void LoadModule(Type T)
@@ -843,32 +943,7 @@
 
 		protected void LoadGUIStyles()
 		{
-			this.LabelStyles["link"] = new GUIStyle(GUI.skin.label);
-			this.LabelStyles["link"].fontStyle = FontStyle.Bold;
-
-			this.LabelStyles["center"] = new GUIStyle(GUI.skin.label);
-			this.LabelStyles["center"].normal.textColor = Color.white;
-			this.LabelStyles["center"].alignment = TextAnchor.UpperCenter;
-
-			this.LabelStyles["center_bold"] = new GUIStyle(GUI.skin.label);
-			this.LabelStyles["center_bold"].normal.textColor = Color.white;
-			this.LabelStyles["center_bold"].alignment = TextAnchor.UpperCenter;
-			this.LabelStyles["center_bold"].fontStyle = FontStyle.Bold;
-
-			this.LabelStyles["right"] = new GUIStyle(GUI.skin.label);
-			this.LabelStyles["right"].normal.textColor = Color.white;
-			this.LabelStyles["right"].alignment = TextAnchor.UpperRight;
-
-			this.LabelStyles["red"] = new GUIStyle(GUI.skin.label);
-			this.LabelStyles["red"].normal.textColor = Color.red;
-			this.LabelStyles["red"].alignment = TextAnchor.MiddleCenter;
-
-			this.iconStyle = new GUIStyle(GUI.skin.button);
-			this.iconStyle.padding = new RectOffset(0, 0, 0, 0);
-			// this.iconStyle.margin = new RectOffset(0, 0, 0, 0);
-			// this.iconStyle.contentOffset = new Vector2(0, 0);
-			this.iconStyle.overflow = new RectOffset(0, 0, 0, 0);
-			// this.iconStyle.border = new RectOffset(0, 0, 0, 0);
+			VOID_Styles.OnSkinChanged();
 
 			this.GUIStylesLoaded = true;
 		}
@@ -885,13 +960,24 @@
 			{
 				this.LoadVesselTypes();
 			}
+
+			if (this.sortedBodyList == null && FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0)
+			{
+				this.sortedBodyList = new List<CelestialBody>(FlightGlobals.Bodies);
+				this.sortedBodyList.Sort(new CBListComparer());
+				this.sortedBodyList.Reverse();
+
+				Debug.Log(string.Format("sortedBodyList: {0}", string.Join("\n\t", this.sortedBodyList.Select(b => b.bodyName).ToArray())));
+			}
+
 		}
 
 		protected void InitializeToolbarButton()
 		{
-			// Do nothing if the Toolbar is not available.
+			// Do nothing if (the Toolbar is not available.
 			if (!ToolbarManager.ToolbarAvailable)
 			{
+				Tools.PostDebugMessage(this, "Refusing to make a ToolbarButton: ToolbarAvailable = false");
 				return;
 			}
 
@@ -916,7 +1002,7 @@
 			{
 				this.AppLauncherButton = ApplicationLauncher.Instance.AddModApplication(
 					this.ToggleMainWindow, this.ToggleMainWindow,
-					HighLogic.LoadedScene.ToAppScenes(),
+					this.appIconVisibleScenes,
 					this.VOIDIconTexture
 				);
 
@@ -965,7 +1051,7 @@
 				this.ToolbarButton.TexturePath = texturePath;
 			}
 
-			this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath, false);
+			this.VOIDIconTexture = GameDatabase.Instance.GetTexture(texturePath.Replace("icon", "appIcon"), false);
 
 			if (this.AppLauncherButton != null)
 			{
@@ -1022,27 +1108,6 @@
 			this.configDirty = false;
 		}
 
-		public void onSceneChangeRequested(GameScenes scene)
-		{
-			if (this.AppLauncherButton != null)
-			{
-				if (this is VOID_EditorCore)
-				{
-					if (!HighLogic.LoadedSceneIsEditor)
-					{
-						ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
-					}
-				}
-				else
-				{
-					if (!HighLogic.LoadedSceneIsFlight)
-					{
-						ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
-					}
-				}
-			}
-		}
-
 		protected VOID_Core()
 		{
 			this._Name = "VOID Core";
@@ -1051,7 +1116,7 @@
 
 			this.VoidVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.MajorRevision);
 
-			this._Active.value = true;
+			this.toggleActive = true;
 
 			this._skinName = this.defaultSkin;
 			this._skinIdx = int.MinValue;
@@ -1070,6 +1135,20 @@
 			this.SetIconTexture(this.powerState | this.activeState);
 		}
 
+		public virtual void Dispose()
+		{
+			if (this.AppLauncherButton != null)
+			{
+				ApplicationLauncher.Instance.RemoveModApplication(this.AppLauncherButton);
+				this.AppLauncherButton = null;
+			}
+			if (this.ToolbarButton != null)
+			{
+				this.ToolbarButton.Destroy();
+				this.ToolbarButton = null;
+			}
+		}
+
 		protected enum IconState
 		{
 			PowerOff = 1,
@@ -1078,32 +1157,6 @@
 			Active = 8
 		}
 	}
-
-	public static partial class VOID_Data
-	{
-		public static VOID_Core core
-		{
-			get
-			{
-				if (HighLogic.LoadedSceneIsEditor)
-				{
-					return VOID_EditorCore.Instance;
-				}
-				else
-				{
-					return VOID_Core.Instance;
-				}
-			}
-		}
-
-		public static double KerbinGee
-		{
-			get
-			{
-				return core.Kerbin.gravParameter / (core.Kerbin.Radius * core.Kerbin.Radius);
-			}
-		}
-	}
 }