Removed old ToolbarButtonWrapper.
Removed old ToolbarButtonWrapper.
VOID_Core: Rejiggered toolbar functionality to mesh with the new API-compatible wrapper from blizzy78.
VOID_Core: A bunch of reordering to make method locations a little more sensible hopefully.

file:a/ToolbarButtonWrapper.cs (deleted)
--- a/ToolbarButtonWrapper.cs
+++ /dev/null
@@ -1,529 +1,1 @@
-//
-//  ToolbarWrapper.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;
-using System.Linq;
-using System.Reflection;
-using UnityEngine;
 
-namespace VOID
-{
-	/// <summary>
-	/// Wraps a Toolbar clickable button, after fetching it from a foreign assembly.
-	/// </summary>
-	internal class ToolbarButtonWrapper
-	{
-		protected static System.Type ToolbarManager;
-		protected static object TBManagerInstance;
-		protected static MethodInfo TBManagerAdd;
-
-		/// <summary>
-		/// Wraps the ToolbarManager class, if present.
-		/// </summary>
-		/// <returns><c>true</c>, if ToolbarManager is wrapped, <c>false</c> otherwise.</returns>
-		protected static bool TryWrapToolbarManager()
-		{
-			if (ToolbarManager == null)
-			{
-				Tools.PostDebugMessage(string.Format(
-					"{0}: Loading ToolbarManager.",
-					"ToolbarButtonWrapper"
-					));
-
-				ToolbarManager = AssemblyLoader.loadedAssemblies
-					.Select(a => a.assembly.GetExportedTypes())
-						.SelectMany(t => t)
-						.FirstOrDefault(t => t.FullName == "Toolbar.ToolbarManager");
-
-				Tools.PostDebugMessage(string.Format(
-					"{0}: Loaded ToolbarManager.  Getting Instance.",
-					"ToolbarButtonWrapper"
-					));
-
-				if (ToolbarManager == null)
-				{
-					return false;
-				}
-
-				TBManagerInstance = ToolbarManager.GetProperty(
-					"Instance",
-					System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static
-					)
-					.GetValue(null, null);
-
-				Tools.PostDebugMessage(string.Format(
-					"{0}: Got ToolbarManager Instance '{1}'.  Getting 'add' method.",
-					"ToolbarButtonWrapper",
-					TBManagerInstance
-					));
-
-				TBManagerAdd = ToolbarManager.GetMethod("add");
-
-				Tools.PostDebugMessage(string.Format(
-					"{0}: Got ToolbarManager Instance 'add' method.  Loading IButton.",
-					"ToolbarButtonWrapper"
-					));
-			}
-
-			return true;
-		}
-
-		/// <summary>
-		/// Gets a value indicating whether <see cref="Toolbar.ToolbarManager"/> is present.
-		/// </summary>
-		/// <value><c>true</c>, if ToolbarManager is wrapped, <c>false</c> otherwise.</value>
-		public static bool ToolbarManagerPresent
-		{
-			get
-			{
-				return TryWrapToolbarManager();
-			}
-		}
-
-		/// <summary>
-		/// If ToolbarManager is present, initializes a new instance of the <see cref="VOID.ToolbarButtonWrapper"/> class.
-		/// </summary>
-		/// <param name="ns">Namespace, usually the plugin name.</param>
-		/// <param name="id">Identifier, unique per namespace.</param>
-		/// <returns>If ToolbarManager is present, a new <see cref="Toolbar.IButton"/> object, <c>null</c> otherwise.</returns>
-		public static ToolbarButtonWrapper TryWrapToolbarButton(string ns, string id)
-		{
-			if (ToolbarManagerPresent)
-			{
-				object button = TBManagerAdd.Invoke(TBManagerInstance, new object[] { ns, id });
-
-				Tools.PostDebugMessage(string.Format(
-					"{0}: Added Button '{1}' with ToolbarManager.  Getting 'Text' property",
-					"ToolbarButtonWrapper",
-					button.ToString()
-				));
-
-				return new ToolbarButtonWrapper(button);
-			}
-			else
-			{
-				return null;
-			}
-		}
-
-		protected System.Type IButton;
-		protected object Button;
-		protected PropertyInfo ButtonText;
-		protected PropertyInfo ButtonTextColor;
-		protected PropertyInfo ButtonTexturePath;
-		protected PropertyInfo ButtonToolTip;
-		protected PropertyInfo ButtonVisible;
-		protected PropertyInfo ButtonVisibility;
-		protected PropertyInfo ButtonEffectivelyVisible;
-		protected PropertyInfo ButtonEnalbed;
-		protected PropertyInfo ButtonImportant;
-		protected EventInfo ButtonOnClick;
-		protected EventInfo ButtonOnMouseEnter;
-		protected EventInfo ButtonOnMouseLeave;
-		protected MethodInfo ButtonDestroy;
-		protected System.Type GameScenesVisibilityType;
-
-		/// <summary>
-		/// The text displayed on the button. Set to null to hide text.
-		/// </summary>
-		/// <remarks>
-		/// The text can be changed at any time to modify the button's appearance. Note that since this will also
-		/// modify the button's size, this feature should be used sparingly, if at all.
-		/// </remarks>
-		/// <seealso cref="TexturePath"/>
-		public string Text
-		{
-			get
-			{
-				return this.ButtonText.GetValue(this.Button, null) as String;
-			}
-			set
-			{
-				this.ButtonText.SetValue(this.Button, value, null);
-			}
-		}
-
-		/// <summary>
-		/// The color the button text is displayed with. Defaults to Color.white.
-		/// </summary>
-		/// <remarks>
-		/// The text color can be changed at any time to modify the button's appearance.
-		/// </remarks>
-		public Color TextColor
-		{
-			get
-			{
-				return (Color)this.ButtonTextColor.GetValue(this.Button, null);
-			}
-			set
-			{
-				this.ButtonTextColor.SetValue(this.Button, value, null);
-			}
-		}
-
-		/// <summary>
-		/// The path of a texture file to display an icon on the button. Set to null to hide icon.
-		/// </summary>
-		/// <remarks>
-		/// <para>
-		/// A texture path on a button will have precedence over text. That is, if both text and texture path
-		/// have been set on a button, the button will show the texture, not the text.
-		/// </para>
-		/// <para>
-		/// The texture size must not exceed 24x24 pixels.
-		/// </para>
-		/// <para>
-		/// The texture path must be relative to the "GameData" directory, and must not specify a file name suffix.
-		/// Valid example: MyAddon/Textures/icon_mybutton
-		/// </para>
-		/// <para>
-		/// The texture path can be changed at any time to modify the button's appearance.
-		/// </para>
-		/// </remarks>
-		/// <seealso cref="Text"/>
-		public string TexturePath
-		{
-			get
-			{
-				return this.ButtonTexturePath.GetValue(this.Button, null) as string;
-			}
-			set
-			{
-				this.ButtonTexturePath.SetValue(this.Button, value, null);
-			}
-		}
-
-		/// <summary>
-		/// The button's tool tip text. Set to null if no tool tip is desired.
-		/// </summary>
-		/// <remarks>
-		/// Tool Tip Text Should Always Use Headline Style Like This.
-		/// </remarks>
-		public string ToolTip
-		{
-			get
-			{
-				return this.ButtonToolTip.GetValue(this.Button, null) as string;
-			}
-			set
-			{
-				this.ButtonToolTip.SetValue(this.Button, value, null);
-			}
-		}
-
-		/// <summary>
-		/// Whether this button is currently visible or not. Can be used in addition to or as a replacement for <see cref="Visibility"/>.
-		/// </summary>
-		public bool Visible
-		{
-			get
-			{
-				return (bool)this.ButtonVisible.GetValue(this.Button, null);
-			}
-			set
-			{
-				this.ButtonVisible.SetValue(this.Button, value, null);
-			}
-		}
-
-		/// <summary>
-		/// Whether this button is currently effectively visible or not. This is a combination of
-		/// <see cref="Visible"/> and <see cref="Visibility"/>.
-		/// </summary>
-		/// <remarks>
-		/// Note that the toolbar is not visible in certain game scenes, for example the loading screens. This property
-		/// does not reflect button invisibility in those scenes.
-		/// </remarks>
-		public bool EffectivelyVisible
-		{
-			get
-			{
-				return (bool)this.ButtonEffectivelyVisible.GetValue(this.Button, null);
-			}
-		}
-
-		/// <summary>
-		/// Whether this button is currently enabled (clickable) or not. This will not affect the player's ability to
-		/// position the button on their screen.
-		/// </summary>
-		public bool Enabled
-		{
-			get
-			{
-				return (bool)this.ButtonEnalbed.GetValue(this.Button, null);
-			}
-			set
-			{
-				this.ButtonEnalbed.SetValue(this.Button, value, null);
-			}
-		}
-
-		/// <summary>
-		/// Whether this button is currently "important."  Set to false to return to normal button behaviour.
-		/// </summary>
-		/// <remarks>
-		/// <para>
-		/// This can be used to temporarily force the button to be shown on the screen regardless of the toolbar being
-		/// currently in auto-hidden mode.  For example, a button that signals the arrival of a private message in a
-		/// chat room could mark itself as "important" as long as the message has not been read.
-		/// </para>
-		/// <para>
-		/// Setting this property does not change the appearance of the button.  use <see cref="TexturePath"/>  to
-		/// change the button's icon.
-		/// </para>
-		/// <para>
-		/// This feature should be used only sparingly, if at all, since it forces the button to be displayed on screen
-		/// even when it normally wouldn't.
-		/// </para>
-		/// </remarks>
-		/// <value><c>true</c> if important; otherwise, <c>false</c>.</value>
-		public bool Important
-		{
-			get
-			{
-				return (bool)this.ButtonImportant.GetValue(this.Button, null);
-			}
-			set
-			{
-				this.ButtonImportant.SetValue(this.Button, value, null);
-			}
-		}
-
-		private ToolbarButtonWrapper()
-		{
-		}
-
-		/// <summary>
-		/// Initializes a new instance of the <see cref="VOID.ToolbarButtonWrapper"/> class.
-		/// </summary>
-		/// <param name="ns">Namespace, usually the plugin name.</param>
-		/// <param name="id">Identifier, unique per namespace.</param>
-		protected ToolbarButtonWrapper(object button)
-		{
-			this.Button = button;
-
-			this.IButton = AssemblyLoader.loadedAssemblies
-				.Select(a => a.assembly.GetExportedTypes())
-				.SelectMany(t => t)
-				.FirstOrDefault(t => t.FullName == "Toolbar.IButton");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Loaded IButton.  Adding Button with ToolbarManager.",
-				this.GetType().Name
-			));
-
-			this.ButtonText = this.IButton.GetProperty("Text");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'Text' property.  Getting 'TextColor' property.",
-				this.GetType().Name
-			));
-
-			this.ButtonTextColor = this.IButton.GetProperty("TextColor");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'TextColor' property.  Getting 'TexturePath' property.",
-				this.GetType().Name
-			));
-
-			this.ButtonTexturePath = this.IButton.GetProperty("TexturePath");
-			
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'TexturePath' property.  Getting 'ToolTip' property.",
-				this.GetType().Name
-			));
-
-			this.ButtonToolTip = this.IButton.GetProperty("ToolTip");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'ToolTip' property.  Getting 'Visible' property.",
-				this.GetType().Name
-			));
-
-			this.ButtonVisible = this.IButton.GetProperty("Visible");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'Visible' property.  Getting 'Visibility' property.",
-				this.GetType().Name
-			));
-
-			this.ButtonVisibility = this.IButton.GetProperty("Visibility");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'Visibility' property.  Getting 'EffectivelyVisible' property.",
-				this.GetType().Name
-			));
-
-			this.ButtonEffectivelyVisible = this.IButton.GetProperty("EffectivelyVisible");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'Visibility' property.  Getting 'Enabled' property.",
-				this.GetType().Name
-			));
-
-			this.ButtonEnalbed = this.IButton.GetProperty("Enabled");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'Enabled' property.  Getting 'OnClick' event.",
-				this.GetType().Name
-			));
-
-			this.ButtonImportant = this.IButton.GetProperty("Important");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'Enabled' property.  Getting 'OnClick' event.",
-				this.GetType().Name
-			));
-
-			this.ButtonOnClick = this.IButton.GetEvent("OnClick");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'OnClick' event '{1}'.  Getting 'OnMouseEnter' event.",
-				this.GetType().Name,
-				this.ButtonOnClick.ToString()
-			));
-
-			this.ButtonOnMouseEnter = this.IButton.GetEvent("OnMouseEnter");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'OnMouseEnter' event '{1}'.  Getting 'OnMouseLeave' event.",
-				this.GetType().Name,
-				this.ButtonOnClick.ToString()
-				));
-
-			this.ButtonOnMouseLeave = this.IButton.GetEvent("OnMouseLeave");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'OnMouseLeave' event '{1}'.  Getting 'Destroy' method.",
-				this.GetType().Name,
-				this.ButtonOnClick.ToString()
-				));
-
-			this.ButtonDestroy = this.IButton.GetMethod("Destroy");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'Destroy' property '{1}'.  Loading GameScenesVisibility class.",
-				this.GetType().Name,
-				this.ButtonDestroy.ToString()
-			));
-
-			this.GameScenesVisibilityType = AssemblyLoader.loadedAssemblies
-				.Select(a => a.assembly.GetExportedTypes())
-					.SelectMany(t => t)
-					.FirstOrDefault(t => t.FullName == "Toolbar.GameScenesVisibility");
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Got 'GameScenesVisibility' class '{1}'.",
-				this.GetType().Name,
-				this.GameScenesVisibilityType.ToString()
-			));
-
-			Tools.PostDebugMessage("ToolbarButtonWrapper built!");
-		}
-
-		/// <summary>
-		/// Adds event handler to receive "on click" events.
-		/// </summary>
-		/// <example>
-		/// <code>
-		/// ToolbarButtonWrapper button = ...
-		/// button.AddButtonClickHandler(
-		/// 	(e) =>
-		/// 	{
-		/// 		Debug.Log("button clicked, mouseButton: " + e.Mousebutton");
-		/// 	}
-		/// );
-		/// </code>
-		/// </example>
-		/// <param name="Handler">Delegate to handle "on click" events</param>
-		public void AddButtonClickHandler(Action<object> Handler)
-		{
-			this.AddButtonEventHandler(this.ButtonOnClick, Handler);
-		}
-
-		/// <summary>
-		/// Adds event handler that can be registered with to receive "on mouse enter" events.
-		/// </summary>
-		/// <example>
-		/// <code>
-		/// ToolbarWrapperButton button = ...
-		/// button.AddButtonOnMouseEnterHandler(
-		/// 	(e) =>
-		/// 	{
-		/// 		Debug.Log("mouse entered button");
-		/// 	}
-		/// );
-		/// </code>
-		/// </example>
-		/// <param name="Handler">Delegate to handle "OnMouseEnter" events.</param>
-		public void AddButtonOnMouseEnterHandler(Action<object> Handler)
-		{
-			this.AddButtonEventHandler(this.ButtonOnMouseEnter, Handler);
-		}
-
-		/// <summary>
-		/// Adds event handler that can be registered with to receive "on mouse leave" events.
-		/// </summary>
-		/// <example>
-		/// <code>
-		/// ToolbarWrapperButton button = ...
-		/// button.AddButtonOnMouseLeaveHandler(
-		/// 	(e) =>
-		/// 	{
-		/// 		Debug.Log("mouse left button");
-		/// 	}
-		/// );
-		/// </code>
-		/// </example>
-		/// <param name="Handler">Delegate to handle "OnMouseLeave" events.</param>
-		public void AddButtonOnMouseLeaveHandler(Action<object> Handler)
-		{
-			this.AddButtonEventHandler(this.ButtonOnMouseLeave, Handler);
-		}
-
-		/// <summary>
-		/// Sets this button's visibility. Can be used in addition to or as a replacement for <see cref="Visible"/>.
-		/// </summary>
-		/// <param name="gameScenes">Array of GameScene objects in which the button should be visible.</param>
-		public void SetButtonVisibility(params GameScenes[] gameScenes)
-		{
-			object GameScenesVisibilityObj = Activator.CreateInstance(this.GameScenesVisibilityType, gameScenes);
-			this.ButtonVisibility.SetValue(this.Button, GameScenesVisibilityObj, null);
-		}
-
-		/// <summary>
-		/// Permanently destroys this button so that it is no longer displayed.
-		/// Should be used when a plugin is stopped to remove leftover buttons.
-		/// </summary>
-		public void Destroy()
-		{
-			this.ButtonDestroy.Invoke(this.Button, null);
-		}
-
-		// Utility method for use with the AddButton<event>Handler API methods.
-		protected void AddButtonEventHandler(EventInfo Event, Action<object> Handler)
-		{
-			Delegate d = Delegate.CreateDelegate(Event.EventHandlerType, Handler.Target, Handler.Method);
-			MethodInfo addHandler = Event.GetAddMethod();
-			addHandler.Invoke(this.Button, new object[] { d });
-		}
-	}
-}
-

--- a/VOID_Core.cs
+++ b/VOID_Core.cs
@@ -153,8 +153,7 @@
 
 		[AVOID_SaveValue("UseBlizzyToolbar")]
 		protected VOID_SaveValue<bool> _UseToolbarManager;
-		protected bool ToolbarManagerLoaded;
-		internal ToolbarButtonWrapper ToolbarButton;
+		internal IButton ToolbarButton;
 
 		/*
 		 * Properties
@@ -284,12 +283,12 @@
 					return;
 				}
 
-				if (value == false && this.ToolbarManagerLoaded && this.ToolbarButton != null)
+				if (value == false && this.ToolbarButton != null)
 				{
 					this.ToolbarButton.Destroy();
 					this.ToolbarButton = null;
 				}
-				if (value == true && this.ToolbarManagerLoaded && this.ToolbarButton == null)
+				if (value == true && this.ToolbarButton == null)
 				{
 					this.InitializeToolbarButton();
 				}
@@ -303,394 +302,37 @@
 		/*
 		 * Methods
 		 * */
-		protected VOID_Core()
-		{
-			this._Name = "VOID Core";
-
-			this._Active.value = true;
-
-			this._skinName = this.defaultSkin;
-
-			this.VOIDIconOnActivePath = "VOID/Textures/void_icon_light_glow";
-			this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_dark_glow";
-			this.VOIDIconOffActivePath = "VOID/Textures/void_icon_light";
-			this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_dark";
-
-			this.UseToolbarManager = false;
-			this.ToolbarManagerLoaded = false;
-
-			this.LoadConfig();
-
-			this.SetIconTexture(this.powerState | this.activeState);
-		}
-
-		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);
-			}
-
-			this._modulesLoaded = true;
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: Loaded {1} modules.",
-				this.GetType().Name,
-				this.Modules.Count
-			));
-		}
-
-		protected void LoadModule(Type T)
-		{
-			var existingModules = this._modules.Where(mod => mod.GetType().Name == T.Name);
-			if (existingModules.Any())
-			{
-				Tools.PostDebugMessage(string.Format(
-					"{0}: refusing to load {1}: already loaded",
-					this.GetType().Name,
-					T.Name
-				));
-				return;
-			}
-			IVOID_Module module = Activator.CreateInstance(T) as IVOID_Module;
-			module.LoadConfig();
-			this._modules.Add(module);
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: loaded module {1}.",
-				this.GetType().Name,
-				T.Name
-			));
-		}
-
-		protected void LoadSkins()
-		{
-			Tools.PostDebugMessage("AssetBase has skins: \n" +
-			string.Join("\n\t",
-				Resources.FindObjectsOfTypeAll(typeof(GUISkin))
-			            .Select(s => s.ToString())
-			            .ToArray()
-			)
-			);
-
-			this.skin_list = Resources.FindObjectsOfTypeAll(typeof(GUISkin))
-				.Where(s => !this.forbiddenSkins.Contains(s.name))
-					.Select(s => s as GUISkin)
-					.GroupBy(s => s.name)
-					.Select(g => g.First())
-					.ToDictionary(s => s.name);
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: loaded {1} GUISkins.",
-				this.GetType().Name,
-				this.skin_list.Count
-			));
-
-			this.skinNames = this.skin_list.Keys.ToList();
-			this.skinNames.Sort();
-
-			if (this._skinName == null || !this.skinNames.Contains(this._skinName))
-			{
-				this._skinName = this.defaultSkin;
-				Tools.PostDebugMessage(string.Format(
-					"{0}: resetting _skinIdx to default.",
-					this.GetType().Name
-				));
-			}
-
-			Tools.PostDebugMessage(string.Format(
-				"{0}: _skinIdx = {1}.",
-				this.GetType().Name,
-				this._skinName.ToString()
-			));
-
-			this.skinsLoaded = true;
-		}
-
-		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);
-
-			this.GUIStylesLoaded = true;
-		}
-
-		protected void LoadVesselTypes()
-		{
-			this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList();
-			this.vesselTypesLoaded = true;
-		}
-
-		protected void LoadBeforeUpdate()
-		{
-			if (!this.vesselTypesLoaded)
-			{
-				this.LoadVesselTypes();
-			}
-		}
-
-		protected void LoadToolbarManager()
-		{
-			this.ToolbarManagerLoaded = ToolbarButtonWrapper.ToolbarManagerPresent;
-
-			if (this.ToolbarManagerLoaded)
+		public override void DrawGUI()
+		{
+			this._windowID = this.windowBaseID;
+
+			if (!this._modulesLoaded)
+			{
+				this.LoadModulesOfType<IVOID_Module>();
+			}
+
+			if (!this.skinsLoaded)
+			{
+				this.LoadSkins();
+			}
+
+			GUI.skin = this.Skin;
+
+			if (!this.GUIStylesLoaded)
+			{
+				this.LoadGUIStyles();
+			}
+
+			if (!this.UseToolbarManager)
+			{
+				if (GUI.Button(VOIDIconPos, VOIDIconTexture, this.iconStyle) && this.VOIDIconLocked)
+				{
+					this.ToggleMainWindow();
+				}
+			}
+			else if (this.ToolbarButton == null)
 			{
 				this.InitializeToolbarButton();
-			}
-		}
-
-		protected void InitializeToolbarButton()
-		{
-			this.ToolbarButton = ToolbarButtonWrapper.TryWrapToolbarButton(this.GetType().Name, "coreToggle");
-			this.ToolbarButton.Text = this.VoidName;
-			this.ToolbarButton.TexturePath = this.VOIDIconOffActivePath;
-			if (this is VOID_EditorCore)
-			{
-				this.ToolbarButton.SetButtonVisibility(new GameScenes[] { GameScenes.EDITOR });
-			}
-			else
-			{
-				this.ToolbarButton.SetButtonVisibility(new GameScenes[] { GameScenes.FLIGHT });
-			}
-			this.ToolbarButton.AddButtonClickHandler(
-				(e) =>
-				{
-					this.mainGuiMinimized = !this.mainGuiMinimized;
-					this.SetIconTexture(this.powerState | this.activeState);
-				}
-			);
-		}
-
-		public void VOIDMainWindow(int _)
-		{
-			GUILayout.BeginVertical();
-			
-			if (this.powerAvailable || HighLogic.LoadedSceneIsEditor)
-			{
-				if (!HighLogic.LoadedSceneIsEditor)
-				{
-					string str = "ON";
-					if (togglePower)
-						str = "OFF";
-					if (GUILayout.Button("Power " + str))
-					{
-						togglePower.value = !togglePower;
-						this.SetIconTexture(this.powerState | this.activeState);
-					}
-				}
-
-				if (togglePower || HighLogic.LoadedSceneIsEditor)
-				{
-					foreach (IVOID_Module module in this.Modules)
-					{
-						module.toggleActive = GUILayout.Toggle(module.toggleActive, module.Name);
-					}
-				}
-			}
-			else
-			{
-				GUILayout.Label("-- POWER LOST --", this.LabelStyles["red"]);
-			}
-
-			this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration");
-
-			GUILayout.EndVertical();
-			GUI.DragWindow();
-		}
-
-		public void VOIDConfigWindow(int _)
-		{
-			GUILayout.BeginVertical();
-
-			this.DrawConfigurables();
-
-			GUILayout.EndVertical();
-			GUI.DragWindow();
-		}
-
-		public override void DrawConfigurables()
-		{
-			int skinIdx;
-
-			GUIContent _content;
-
-			if (HighLogic.LoadedSceneIsFlight)
-			{
-				this.consumeResource.value = GUILayout.Toggle(this.consumeResource, "Consume Resources");
-
-				this.VOIDIconLocked = GUILayout.Toggle(this.VOIDIconLocked, "Lock Icon Position");
-			}
-
-			this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available");
-
-			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
-
-			GUILayout.Label("Skin:", GUILayout.ExpandWidth(false));
-
-			_content = new GUIContent();
-
-			if (skinNames.Contains(this._skinName))
-			{
-				skinIdx = skinNames.IndexOf(this._skinName);
-			}
-			else if (skinNames.Contains(this.defaultSkin))
-			{
-				skinIdx = skinNames.IndexOf(this.defaultSkin);
-			}
-			else
-			{
-				skinIdx = 0;
-			}
-
-			_content.text = "◄";
-			_content.tooltip = "Select previous skin";
-			if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
-			{
-				this.GUIStylesLoaded = false;
-				skinIdx--;
-				if (skinIdx < 0)
-					skinIdx = skinNames.Count - 1;
-				Tools.PostDebugMessage(string.Format(
-					"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
-					this.GetType().Name,
-					this._skinName,
-					this.skin_list.Count
-				));
-			}
-
-			_content.text = this.Skin.name;
-			_content.tooltip = "Current skin";
-			GUILayout.Label(_content, this.LabelStyles["center"], GUILayout.ExpandWidth(true));
-
-			_content.text = "►";
-			_content.tooltip = "Select next skin";
-			if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
-			{
-				this.GUIStylesLoaded = false;
-				skinIdx++;
-				if (skinIdx >= skinNames.Count)
-					skinIdx = 0;
-				Tools.PostDebugMessage(string.Format(
-					"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
-					this.GetType().Name,
-					this._skinName,
-					this.skin_list.Count
-				));
-			}
-
-			if (this._skinName != skinNames[skinIdx])
-			{
-				this._skinName = skinNames[skinIdx];
-			}
-
-			GUILayout.EndHorizontal();
-
-			GUILayout.BeginHorizontal();
-			GUILayout.Label("Update Rate (Hz):");
-			if (this.stringFrequency == null)
-			{
-				this.stringFrequency = (1f / this.updatePeriod).ToString();
-			}
-			this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true));
-			// GUILayout.FlexibleSpace();
-			if (GUILayout.Button("Apply"))
-			{
-				double updateFreq = 1f / this.updatePeriod;
-				double.TryParse(stringFrequency, out updateFreq);
-				this._updatePeriod = 1 / updateFreq;
-			}
-			GUILayout.EndHorizontal();
-
-			foreach (IVOID_Module mod in this.Modules)
-			{
-				mod.DrawConfigurables();
-			}
-
-			this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset");
-		}
-
-		public override void DrawGUI()
-		{
-			this._windowID = this.windowBaseID;
-
-			if (!this._modulesLoaded)
-			{
-				this.LoadModulesOfType<IVOID_Module>();
-			}
-
-			if (this.UseToolbarManager && !this.ToolbarManagerLoaded)
-			{
-				this.LoadToolbarManager();
-			}
-
-			if (!this.skinsLoaded)
-			{
-				this.LoadSkins();
-			}
-
-			GUI.skin = this.Skin;
-
-			if (!this.GUIStylesLoaded)
-			{
-				this.LoadGUIStyles();
-			}
-
-			if (!(this.UseToolbarManager && this.ToolbarManagerLoaded))
-			{
-				if (GUI.Button(VOIDIconPos, VOIDIconTexture, this.iconStyle) && this.VOIDIconLocked)
-				{
-					this.mainGuiMinimized.value = !this.mainGuiMinimized;
-					this.SetIconTexture(this.powerState | this.activeState);
-				}
 			}
 
 			if (!this.mainGuiMinimized)
@@ -885,6 +527,336 @@
 			this.StartGUI();
 		}
 
+		public void VOIDMainWindow(int _)
+		{
+			GUILayout.BeginVertical();
+
+			if (this.powerAvailable || HighLogic.LoadedSceneIsEditor)
+			{
+				if (!HighLogic.LoadedSceneIsEditor)
+				{
+					string str = string.Intern("ON");
+					if (togglePower)
+						str = string.Intern("OFF");
+					if (GUILayout.Button("Power " + str))
+					{
+						togglePower.value = !togglePower;
+						this.SetIconTexture(this.powerState | this.activeState);
+					}
+				}
+
+				if (togglePower || HighLogic.LoadedSceneIsEditor)
+				{
+					foreach (IVOID_Module module in this.Modules)
+					{
+						module.toggleActive = GUILayout.Toggle(module.toggleActive, module.Name);
+					}
+				}
+			}
+			else
+			{
+				GUILayout.Label("-- POWER LOST --", this.LabelStyles["red"]);
+			}
+
+			this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration");
+
+			GUILayout.EndVertical();
+			GUI.DragWindow();
+		}
+
+		public void VOIDConfigWindow(int _)
+		{
+			GUILayout.BeginVertical();
+
+			this.DrawConfigurables();
+
+			GUILayout.EndVertical();
+			GUI.DragWindow();
+		}
+
+		public override void DrawConfigurables()
+		{
+			int skinIdx;
+
+			GUIContent _content;
+
+			if (HighLogic.LoadedSceneIsFlight)
+			{
+				this.consumeResource.value = GUILayout.Toggle(this.consumeResource, "Consume Resources");
+
+				this.VOIDIconLocked = GUILayout.Toggle(this.VOIDIconLocked, "Lock Icon Position");
+			}
+
+			this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available");
+
+			GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
+
+			GUILayout.Label("Skin:", GUILayout.ExpandWidth(false));
+
+			_content = new GUIContent();
+
+			if (skinNames.Contains(this._skinName))
+			{
+				skinIdx = skinNames.IndexOf(this._skinName);
+			}
+			else if (skinNames.Contains(this.defaultSkin))
+			{
+				skinIdx = skinNames.IndexOf(this.defaultSkin);
+			}
+			else
+			{
+				skinIdx = 0;
+			}
+
+			_content.text = "◄";
+			_content.tooltip = "Select previous skin";
+			if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
+			{
+				this.GUIStylesLoaded = false;
+				skinIdx--;
+				if (skinIdx < 0)
+					skinIdx = skinNames.Count - 1;
+				Tools.PostDebugMessage(string.Format(
+					"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
+					this.GetType().Name,
+					this._skinName,
+					this.skin_list.Count
+				));
+			}
+
+			_content.text = this.Skin.name;
+			_content.tooltip = "Current skin";
+			GUILayout.Label(_content, this.LabelStyles["center"], GUILayout.ExpandWidth(true));
+
+			_content.text = "►";
+			_content.tooltip = "Select next skin";
+			if (GUILayout.Button(_content, GUILayout.ExpandWidth(true)))
+			{
+				this.GUIStylesLoaded = false;
+				skinIdx++;
+				if (skinIdx >= skinNames.Count)
+					skinIdx = 0;
+				Tools.PostDebugMessage(string.Format(
+					"{0}: new this._skinIdx = {1} :: skin_list.Count = {2}",
+					this.GetType().Name,
+					this._skinName,
+					this.skin_list.Count
+				));
+			}
+
+			if (this._skinName != skinNames[skinIdx])
+			{
+				this._skinName = skinNames[skinIdx];
+			}
+
+			GUILayout.EndHorizontal();
+
+			GUILayout.BeginHorizontal();
+			GUILayout.Label("Update Rate (Hz):");
+			if (this.stringFrequency == null)
+			{
+				this.stringFrequency = (1f / this.updatePeriod).ToString();
+			}
+			this.stringFrequency = GUILayout.TextField(this.stringFrequency.ToString(), 5, GUILayout.ExpandWidth(true));
+			// GUILayout.FlexibleSpace();
+			if (GUILayout.Button("Apply"))
+			{
+				double updateFreq = 1f / this.updatePeriod;
+				double.TryParse(stringFrequency, out updateFreq);
+				this._updatePeriod = 1 / updateFreq;
+			}
+			GUILayout.EndHorizontal();
+
+			foreach (IVOID_Module mod in this.Modules)
+			{
+				mod.DrawConfigurables();
+			}
+
+			this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset");
+		}
+
+		protected void 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);
+			}
+
+			this._modulesLoaded = true;
+
+			Tools.PostDebugMessage(string.Format(
+				"{0}: Loaded {1} modules.",
+				this.GetType().Name,
+				this.Modules.Count
+			));
+		}
+
+		protected void LoadModule(Type T)
+		{
+			var existingModules = this._modules.Where(mod => mod.GetType().Name == T.Name);
+			if (existingModules.Any())
+			{
+				Tools.PostDebugMessage(string.Format(
+					"{0}: refusing to load {1}: already loaded",
+					this.GetType().Name,
+					T.Name
+				));
+				return;
+			}
+			IVOID_Module module = Activator.CreateInstance(T) as IVOID_Module;
+			module.LoadConfig();
+			this._modules.Add(module);
+
+			Tools.PostDebugMessage(string.Format(
+				"{0}: loaded module {1}.",
+				this.GetType().Name,
+				T.Name
+			));
+		}
+
+		protected void LoadSkins()
+		{
+			Tools.PostDebugMessage("AssetBase has skins: \n" +
+				string.Join("\n\t",
+					Resources.FindObjectsOfTypeAll(typeof(GUISkin))
+					.Select(s => s.ToString())
+					.ToArray()
+				)
+			);
+
+			this.skin_list = Resources.FindObjectsOfTypeAll(typeof(GUISkin))
+				.Where(s => !this.forbiddenSkins.Contains(s.name))
+				.Select(s => s as GUISkin)
+				.GroupBy(s => s.name)
+				.Select(g => g.First())
+				.ToDictionary(s => s.name);
+
+			Tools.PostDebugMessage(string.Format(
+				"{0}: loaded {1} GUISkins.",
+				this.GetType().Name,
+				this.skin_list.Count
+			));
+
+			this.skinNames = this.skin_list.Keys.ToList();
+			this.skinNames.Sort();
+
+			if (this._skinName == null || !this.skinNames.Contains(this._skinName))
+			{
+				this._skinName = this.defaultSkin;
+				Tools.PostDebugMessage(string.Format(
+					"{0}: resetting _skinIdx to default.",
+					this.GetType().Name
+				));
+			}
+
+			Tools.PostDebugMessage(string.Format(
+				"{0}: _skinIdx = {1}.",
+				this.GetType().Name,
+				this._skinName.ToString()
+			));
+
+			this.skinsLoaded = true;
+		}
+
+		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);
+
+			this.GUIStylesLoaded = true;
+		}
+
+		protected void LoadVesselTypes()
+		{
+			this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList();
+			this.vesselTypesLoaded = true;
+		}
+
+		protected void LoadBeforeUpdate()
+		{
+			if (!this.vesselTypesLoaded)
+			{
+				this.LoadVesselTypes();
+			}
+		}
+
+		protected void InitializeToolbarButton()
+		{
+			this.ToolbarButton = ToolbarManager.Instance.add(this.GetType().Name, "coreToggle");
+			this.ToolbarButton.Text = this.VoidName;
+			this.SetIconTexture(this.powerState | this.activeState);
+
+			if (this is VOID_EditorCore)
+			{
+				this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.EDITOR);
+			}
+			else
+			{
+				this.ToolbarButton.Visibility = new GameScenesVisibility(GameScenes.FLIGHT);
+			}
+
+			this.ToolbarButton.OnClick += 
+				(e) =>
+			{
+				this.ToggleMainWindow();
+			};
+		}
+
+		protected void ToggleMainWindow()
+		{
+			this.mainGuiMinimized = !this.mainGuiMinimized;
+			this.SetIconTexture(this.powerState | this.activeState);
+		}
+
 		protected void SetIconTexture(IconState state)
 		{
 			switch (state)
@@ -967,6 +939,26 @@
 			this.configDirty = false;
 		}
 
+		protected VOID_Core()
+		{
+			this._Name = "VOID Core";
+
+			this._Active.value = true;
+
+			this._skinName = this.defaultSkin;
+
+			this.VOIDIconOnActivePath = "VOID/Textures/void_icon_light_glow";
+			this.VOIDIconOnInactivePath = "VOID/Textures/void_icon_dark_glow";
+			this.VOIDIconOffActivePath = "VOID/Textures/void_icon_light";
+			this.VOIDIconOffInactivePath = "VOID/Textures/void_icon_dark";
+
+			this.UseToolbarManager = false;
+
+			this.LoadConfig();
+
+			this.SetIconTexture(this.powerState | this.activeState);
+		}
+
 		protected enum IconState
 		{
 			PowerOff = 1,