Fixed up the configurable save values; changed the way window positions are assigned after a draw.
Fixed up the configurable save values; changed the way window positions are assigned after a draw.

--- /dev/null
+++ b/AVOID_ConfigValue.cs
@@ -1,1 +1,28 @@
+//
+//  AVOID_ConfigValue.cs
+//
+//  Author:
+//       toadicus <>
+//
+//  Copyright (c) 2013 toadicus
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+using System;
 
+namespace VOID
+{
+
+}
+
+

--- a/VOIDFlightMaster.cs
+++ b/VOIDFlightMaster.cs
@@ -48,22 +48,7 @@
 		{

 			Tools.PostDebugMessage ("VOIDLightMaster: Waking up.");

 			this.Core = (VOID_Core)VOID_Core.Instance;

-			foreach (Type T in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())

-			{

-				Tools.PostDebugMessage (string.Format ("VOIDFlightMaster: Testing type {0}", T.Name));

-				if (typeof(IVOID_Module).IsAssignableFrom(T) &&

-				    !T.IsAbstract  &&

-				    !typeof(VOID_Core).IsAssignableFrom(T))

-				{

-					this.Core.LoadModule (T);

-					Tools.PostDebugMessage(string.Format("VOIDFlightMaster: Found module {0}.", T.Name));

-				}

-			}

-

-			Tools.PostDebugMessage (string.Format ("VOIDFlightMaster: Loaded {0} modules.", this.Core.Modules.Count));

-

-			this.Core.LoadConfig ();

-

+			this.Core.StartGUI ();

 			Tools.PostDebugMessage ("VOIDFlightMaster: Awake.");

 		}

 


--- a/VOID_ConfigValue.cs
+++ b/VOID_ConfigValue.cs
@@ -25,11 +25,12 @@
 

 namespace VOID

 {

-	public class VOID_ConfigValue<T>

+	public struct VOID_ConfigValue<T> : IVOID_ConfigValue

 	{

-		protected T _value;

+		private T _value;

+		private Type _type;

 

-		public T this

+		public T value

 		{

 			get

 			{

@@ -37,8 +38,76 @@
 			}

 			set

 			{

-				return this._value;

+				this._value = value;

 			}

+		}

+

+		public Type type

+		{

+			get

+			{

+				return this._type;

+			}

+			set

+			{

+				this._type = value;

+			}

+		}

+

+		public object AsType

+		{

+			get

+			{

+				return (T)this._value;

+			}

+		}

+

+		public void SetValue(object v)

+		{

+			this._value = (T)v;

+		}

+

+		public static implicit operator T(VOID_ConfigValue<T> v)

+		{

+			return v.value;

+		}

+

+		public static implicit operator VOID_ConfigValue<T>(T v)

+		{

+			VOID_ConfigValue<T> r = new VOID_ConfigValue<T>();

+			r.value = v;

+			r.type = v.GetType();

+			if (VOID_Core.Initialized)

+			{

+				VOID_Core.Instance.configDirty = true;

+			}

+			return r;

+		}

+	}

+

+	public interface IVOID_ConfigValue

+	{

+		Type type { get; }

+		object AsType { get; }

+		void SetValue(object v);

+	}

+

+	[AttributeUsage(AttributeTargets.Field)]

+	public class AVOID_ConfigValue : Attribute

+	{

+		protected string _name;

+

+		public string Name

+		{

+			get

+			{

+				return this._name;

+			}

+		}

+

+		public AVOID_ConfigValue(string fieldName)

+		{

+			this._name = fieldName;

 		}

 	}

 }


--- a/VOID_Core.cs
+++ b/VOID_Core.cs
@@ -31,6 +31,15 @@
 		/*

 		 * Static Members

 		 * */

+		protected static bool _initialized = false;

+		public static bool Initialized

+		{

+			get 

+			{

+			return _initialized;

+			}

+		}

+

 		protected static VOID_Core _instance;

 		public static VOID_Core Instance

 		{

@@ -39,6 +48,7 @@
 				if (_instance == null)

 				{

 					_instance = new VOID_Core();

+					_initialized = true;

 				}

 				return _instance;

 			}

@@ -49,17 +59,26 @@
 		 * */

 		protected string VoidName = "VOID";

 		protected string VoidVersion = "0.9.9";

-		protected int configVersion = 1;

+

+		[AVOID_ConfigValue("configValue")]

+		protected VOID_ConfigValue<int> configVersion = 1;

 

 		protected List<VOID_Module> _modules = new List<VOID_Module>();

 

-		protected Rect _mainWindowPos = new Rect(Screen.width / 2, Screen.height / 2, 10f, 10f);

-		protected bool mainGuiMinimized = false;

-

-		protected Rect _configWindowPos = new Rect(Screen.width / 2, Screen.height  /2, 10f, 10f);

-		protected bool configWindowMinimized = true;

-

-		protected Rect VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 30, 30f, 30f);

+		[AVOID_ConfigValue("mainWindowPos")]

+		protected VOID_ConfigValue<Rect> mainWindowPos = new Rect(Screen.width / 2, Screen.height / 2, 10f, 10f);

+

+		[AVOID_ConfigValue("mainGuiMinimized")]

+		protected VOID_ConfigValue<bool> mainGuiMinimized = false;

+

+		[AVOID_ConfigValue("configWindowPos")]

+		protected VOID_ConfigValue<Rect> configWindowPos = new Rect(Screen.width / 2, Screen.height  /2, 10f, 10f);

+

+		[AVOID_ConfigValue("configWindowMinimized")]

+		protected VOID_ConfigValue<bool> configWindowMinimized = true;

+

+		[AVOID_ConfigValue("VOIDIconPos")]

+		protected VOID_ConfigValue<Rect> VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 30, 30f, 30f);

 		protected Texture2D VOIDIconOff = new Texture2D(30, 30, TextureFormat.ARGB32, false);

 		protected Texture2D VOIDIconOn = new Texture2D(30, 30, TextureFormat.ARGB32, false);

 		protected Texture2D VOIDIconTexture;

@@ -68,16 +87,26 @@
 

 		protected int windowBaseID = -96518722;

 

-		public bool togglePower = true;

+		[AVOID_ConfigValue("togglePower")]

+		public VOID_ConfigValue<bool> togglePower = true;

+

 		public bool powerAvailable = true;

-		protected bool consumeResource = false;

-		protected string resourceName = "ElectricCharge";

-		protected float resourceRate = 0.2f;

+

+		[AVOID_ConfigValue("consumeResource")]

+		protected VOID_ConfigValue<bool> consumeResource = false;

+

+		[AVOID_ConfigValue("resourceName")]

+		protected VOID_ConfigValue<string> resourceName = "ElectricCharge";

+

+		[AVOID_ConfigValue("resourceRate")]

+		protected VOID_ConfigValue<float> resourceRate = 0.2f;

 

 		public float saveTimer = 0;

 

 		protected string defaultSkin = "KSP window 2";

-		protected string _skin;

+		protected VOID_ConfigValue<string> _skin;

+

+		public bool configDirty;

 

 		/*

 		 * Properties

@@ -110,31 +139,6 @@
 			}

 		}

 

-		protected Rect mainWindowPos

-		{

-			get

-			{

-				return this._mainWindowPos;

-			}

-			set

-			{

-				this._mainWindowPos = value;

-				this.configDirty = true;

-			}

-		}

-

-		protected Rect configWindowPos

-		{

-			get

-			{

-				return this._configWindowPos;

-			}

-			set

-			{

-				this._configWindowPos = value;

-				this.configDirty = true;

-			}

-		}

 		/*

 		 * Methods

 		 * */

@@ -144,6 +148,23 @@
 

 			this.VOIDIconOn = GameDatabase.Instance.GetTexture (this.VOIDIconOnPath, false);

 			this.VOIDIconOff = GameDatabase.Instance.GetTexture (this.VOIDIconOffPath, false);

+

+			// HACK: This is modular but not extensible.  We need to look outside our assembly or move this to modules.

+			foreach (Type T in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())

+			{

+				Tools.PostDebugMessage (string.Format ("VOID_Core: Testing type {0}", T.Name));

+				if (typeof(IVOID_Module).IsAssignableFrom(T) &&

+				    !T.IsAbstract  &&

+				    !typeof(VOID_Core).IsAssignableFrom(T))

+				{

+					this.LoadModule (T);

+					Tools.PostDebugMessage(string.Format("VOID_Core: Found module {0}.", T.Name));

+				}

+			}

+

+			Tools.PostDebugMessage (string.Format ("VOID_Core: Loaded {0} modules.", this.Modules.Count));

+

+			this.LoadConfig ();

 		}

 

 		public void LoadModule(Type T)

@@ -160,13 +181,18 @@
 				this.StartGUI ();

 			}

 

+			if (!HighLogic.LoadedSceneIsFlight && this.guiRunning)

+			{

+				this.StopGUI ();

+			}

+

 			foreach (VOID_Module module in this.Modules)

 			{

 				if (!module.guiRunning && module.toggleActive)

 				{

 					module.StartGUI ();

 				}

-				if (module.guiRunning && !module.toggleActive || !this.togglePower)

+				if (module.guiRunning && !module.toggleActive || !this.togglePower || !HighLogic.LoadedSceneIsFlight)

 				{

 					module.StopGUI();

 				}

@@ -255,72 +281,46 @@
 

 			if (!this.mainGuiMinimized)

 			{

-				this.mainWindowPos = GUILayout.Window (

+				Rect _mainWindowPos = this.mainWindowPos;

+

+				_mainWindowPos = GUILayout.Window (

 					++windowID,

-					this.mainWindowPos,

+					_mainWindowPos,

 					this.VOIDMainWindow,

 					string.Join (" ", this.VoidName, this.VoidVersion),

 					GUILayout.Width (250),

 					GUILayout.Height (50)

 				);

+

+				if (_mainWindowPos != this.mainWindowPos.value)

+				{

+					this.mainWindowPos = _mainWindowPos;

+				}

 			}

 

 			if (!this.configWindowMinimized)

 			{

+				Rect _configWindowPos = this.configWindowPos;

+

 				this.configWindowPos = GUILayout.Window (

 					++windowID,

-					this.configWindowPos,

+					_configWindowPos,

 					this.VOIDConfigWindow,

 					string.Join (" ", this.VoidName, "Configuration"),

 					GUILayout.Width (250),

 					GUILayout.Height (50)

 				);

-			}

-		}

-

-		public new void StartGUI()

-		{

-			base.StartGUI ();

-			foreach (var module in this._modules)

-			{

-				if (module.toggleActive)

-				{

-					module.StartGUI ();

-				}

-			}

-

-			this._Running = true;

-		}

-

-		public new void StopGUI()

-		{

-			base.StopGUI ();

-			foreach (var module in this._modules)

-			{

-				if (module.guiRunning)

-				{

-					module.StopGUI ();

-				}

-			}

-

-			this._Running = false;

+

+				if (_configWindowPos != this.configWindowPos.value)

+				{

+					this.mainWindowPos = _configWindowPos;

+				}

+			}

 		}

 

 		public override void LoadConfig()

 		{

-			var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core>();

-			config.load();

-

-			if (this.configVersion > config.GetValue("configVersion", 0))

-			{

-				// TODO: Config update stuff.

-			}

-

-			this.mainWindowPos = config.GetValue("main_window_pos", this.mainWindowPos);

-			this.VOIDIconPos = config.GetValue("VOIDIconPos", this.VOIDIconPos);

-			this._skin = config.GetValue ("void_skin", this.defaultSkin);

-			this.togglePower = config.GetValue ("togglePower", this.togglePower);

-			this.consumeResource = config.GetValue ("consumePower", this.consumeResource);

+			base.LoadConfig ();

 

 			foreach (VOID_Module module in this.Modules)

 			{

@@ -330,17 +330,12 @@
 

 		public override void SaveConfig()

 		{

-			var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core> ();

-			config.load ();

-

-			config.SetValue ("main_window_pos", this.mainWindowPos);

-			config.SetValue ("VOIDIconPos", this.VOIDIconPos);

-			config.SetValue ("void_skin", this.Skin.name);

-			config.SetValue ("togglePower", this.togglePower);

-			config.SetValue ("configVersion", this.configVersion);

-			config.SetValue ("consumePower", this.consumeResource);

-

-			config.save ();

+			if (!this.configDirty)

+			{

+				return;

+			}

+

+			base.SaveConfig ();

 

 			foreach (VOID_Module module in this.Modules)

 			{


--- a/VOID_HUD.cs
+++ b/VOID_HUD.cs
@@ -36,7 +36,8 @@
 

 		protected GUIStyle labelStyle;

 

-		protected int _counterTextColor = 0;

+		[AVOID_ConfigValue("colorIndex")]

+		protected VOID_ConfigValue<int> _colorIndex = 0;

 

 		protected Vessel vessel = null;

 

@@ -47,17 +48,17 @@
 		{

 			get

 			{

-				return this._counterTextColor;

+				return this._colorIndex;

 			}

 			set

 			{

-				if (this._counterTextColor >= this.textColors.Count - 1)

+				if (this._colorIndex >= this.textColors.Count - 1)

 				{

-					this._counterTextColor = 0;

+					this._colorIndex = 0;

 					return;

 				}

 

-				this._counterTextColor = value;

+				this._colorIndex = value;

 			}

 		}

 

@@ -134,23 +135,6 @@
 				GUI.Label (new Rect ((Screen.width * .625f), 0, 300f, 70f), "-- POWER LOST --", labelStyle);

 			}

 		}

-

-		public override void SaveConfig()

-		{

-			Tools.PostDebugMessage ("VOID_HUD: Saving Config.");

-			var config = KSP.IO.PluginConfiguration.CreateForType<VOID_HUD> ();

-			config.load ();

-			config.SetValue ("ColorIndex", this.ColorIndex);

-			config.save ();

-		}

-

-		public override void LoadConfig()

-		{

-			Tools.PostDebugMessage ("VOID_HUD: Loading Config.");

-			var config = KSP.IO.PluginConfiguration.CreateForType<VOID_HUD> ();

-			config.load ();

-			this.ColorIndex = config.GetValue ("ColorIndex", 0);

-		}

 	}

 }

 

--- a/VOID_Module.cs
+++ b/VOID_Module.cs
@@ -19,6 +19,9 @@
 //  You should have received a copy of the GNU General Public License

 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.

 using System;

+using System.Collections.Generic;

+using System.Linq;

+using System.Reflection;

 

 namespace VOID

 {

@@ -27,10 +30,10 @@
 		/*

 		 * Fields

 		 * */

-		protected bool _Active = true;

+		[AVOID_ConfigValue("Active")]

+		protected VOID_ConfigValue<bool> _Active = true;

 		protected bool _Running = false;

 		protected bool _hasGUICfg = false;

-		protected bool configDirty = false;

 

 		protected string _Name;

 

@@ -78,6 +81,11 @@
 		 * */

 		public void StartGUI()

 		{

+			if (!this.toggleActive)

+			{

+				return;

+			}

+

 			Tools.PostDebugMessage (string.Format("Adding {0} to the draw queue.", this.GetType().Name));

 			RenderingManager.AddToPostDrawQueue (3, this.DrawGUI);

 			this._Running = true;

@@ -92,13 +100,91 @@
 

 		public abstract void DrawGUI();

 

-		public abstract void LoadConfig();

+		public virtual void LoadConfig()

+		{

+			var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core> ();

+			config.load ();

 

-		public abstract void SaveConfig();

+			foreach (var field in this.GetType().GetFields(

+				BindingFlags.NonPublic |

+				BindingFlags.Public |

+				BindingFlags.Instance

+				))

+			{

+				object[] attrs = field.GetCustomAttributes(typeof(AVOID_ConfigValue), false);

 

-		~VOID_Module()

+				if (attrs.Length == 0) {

+					return;

+				}

+

+				AVOID_ConfigValue attr = attrs.FirstOrDefault () as AVOID_ConfigValue;

+

+				string fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name);

+

+				object fieldValue = field.GetValue(this);

+

+				bool convertBack = false;

+				if (fieldValue is IVOID_ConfigValue)

+				{

+					fieldValue = (fieldValue as IVOID_ConfigValue).AsType;

+					convertBack = true;

+				}

+

+				fieldValue = config.GetValue(fieldName, fieldValue);

+

+				if (convertBack)

+				{

+					Type type = typeof(VOID_ConfigValue<>).MakeGenericType (fieldValue.GetType ());

+					IVOID_ConfigValue convertValue = Activator.CreateInstance (type) as IVOID_ConfigValue;

+					convertValue.SetValue (fieldValue);

+					fieldValue = convertValue;

+				}

+

+				field.SetValue (this, fieldValue);

+

+				Tools.PostDebugMessage(string.Format("{0}: Loaded field {1}.", this.GetType().Name, fieldName));

+			}

+		}

+

+		public virtual void SaveConfig()

 		{

-			this.SaveConfig ();

+			if (!VOID_Core.Instance.configDirty)

+			{

+				return;

+			}

+

+			var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core> ();

+			config.load ();

+

+			foreach (var field in this.GetType().GetFields(

+				BindingFlags.NonPublic |

+				BindingFlags.Public |

+				BindingFlags.Instance

+				))

+			{

+				object[] attrs = field.GetCustomAttributes(typeof(AVOID_ConfigValue), false);

+

+				if (attrs.Length == 0) {

+					return;

+				}

+

+				AVOID_ConfigValue attr = attrs.FirstOrDefault () as AVOID_ConfigValue;

+

+				string fieldName = string.Format("{0}_{1}", this.GetType().Name, attr.Name);

+

+				object fieldValue = field.GetValue(this);

+

+				if (fieldValue is IVOID_ConfigValue)

+				{

+					fieldValue = (fieldValue as IVOID_ConfigValue).AsType;

+				}

+

+				config.SetValue(fieldName, fieldValue);

+

+				Tools.PostDebugMessage(string.Format("{0}: Saved field {1}.", this.GetType().Name, fieldName));

+			}

+

+			config.save ();

 		}

 	}

 }