Merge remote-tracking branch 'origin/toolbarwrapper_static_factory'
Merge remote-tracking branch 'origin/toolbarwrapper_static_factory'

Conflicts:
ToolbarButtonWrapper.cs

// //
// ToolbarWrapper.cs // ToolbarWrapper.cs
// //
// Author: // Author:
// toadicus <> // toadicus <>
// //
// Copyright (c) 2013 toadicus // Copyright (c) 2013 toadicus
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
/// <summary> /// <summary>
/// Wraps a Toolbar clickable button, after fetching it from a foreign assembly. /// Wraps a Toolbar clickable button, after fetching it from a foreign assembly.
/// </summary> /// </summary>
internal class ToolbarButtonWrapper internal class ToolbarButtonWrapper
{ {
protected System.Type ToolbarManager; protected static System.Type ToolbarManager;
protected object TBManagerInstance; protected static object TBManagerInstance;
protected MethodInfo TBManagerAdd; 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 System.Type IButton;
protected object Button; protected object Button;
protected PropertyInfo ButtonText; protected PropertyInfo ButtonText;
protected PropertyInfo ButtonTextColor; protected PropertyInfo ButtonTextColor;
protected PropertyInfo ButtonTexturePath; protected PropertyInfo ButtonTexturePath;
protected PropertyInfo ButtonToolTip; protected PropertyInfo ButtonToolTip;
protected PropertyInfo ButtonVisible; protected PropertyInfo ButtonVisible;
protected PropertyInfo ButtonVisibility; protected PropertyInfo ButtonVisibility;
protected PropertyInfo ButtonEnalbed; protected PropertyInfo ButtonEnalbed;
protected PropertyInfo ButtonImportant; protected PropertyInfo ButtonImportant;
protected EventInfo ButtonOnClick; protected EventInfo ButtonOnClick;
protected System.Type ClickHandlerType; protected System.Type ClickHandlerType;
protected MethodInfo ButtonDestroy; protected MethodInfo ButtonDestroy;
protected System.Type GameScenesVisibilityType; protected System.Type GameScenesVisibilityType;
   
/// <summary> /// <summary>
/// The text displayed on the button. Set to null to hide text. /// The text displayed on the button. Set to null to hide text.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// The text can be changed at any time to modify the button's appearance. Note that since this will also /// 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. /// modify the button's size, this feature should be used sparingly, if at all.
/// </remarks> /// </remarks>
/// <seealso cref="TexturePath"/> /// <seealso cref="TexturePath"/>
public string Text public string Text
{ {
get get
{ {
return this.ButtonText.GetValue(this.Button, null) as String; return this.ButtonText.GetValue(this.Button, null) as String;
} }
set set
{ {
this.ButtonText.SetValue(this.Button, value, null); this.ButtonText.SetValue(this.Button, value, null);
} }
} }
   
/// <summary> /// <summary>
/// The color the button text is displayed with. Defaults to Color.white. /// The color the button text is displayed with. Defaults to Color.white.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// The text color can be changed at any time to modify the button's appearance. /// The text color can be changed at any time to modify the button's appearance.
/// </remarks> /// </remarks>
public Color TextColor public Color TextColor
{ {
get get
{ {
return (Color)this.ButtonTextColor.GetValue(this.Button, null); return (Color)this.ButtonTextColor.GetValue(this.Button, null);
} }
set set
{ {
this.ButtonTextColor.SetValue(this.Button, value, null); this.ButtonTextColor.SetValue(this.Button, value, null);
} }
} }
   
/// <summary> /// <summary>
/// The path of a texture file to display an icon on the button. Set to null to hide icon. /// The path of a texture file to display an icon on the button. Set to null to hide icon.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// A texture path on a button will have precedence over text. That is, if both text and texture path /// 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. /// have been set on a button, the button will show the texture, not the text.
/// </para> /// </para>
/// <para> /// <para>
/// The texture size must not exceed 24x24 pixels. /// The texture size must not exceed 24x24 pixels.
/// </para> /// </para>
/// <para> /// <para>
/// The texture path must be relative to the "GameData" directory, and must not specify a file name suffix. /// The texture path must be relative to the "GameData" directory, and must not specify a file name suffix.
/// Valid example: MyAddon/Textures/icon_mybutton /// Valid example: MyAddon/Textures/icon_mybutton
/// </para> /// </para>
/// <para> /// <para>
/// The texture path can be changed at any time to modify the button's appearance. /// The texture path can be changed at any time to modify the button's appearance.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <seealso cref="Text"/> /// <seealso cref="Text"/>
public string TexturePath public string TexturePath
{ {
get get
{ {
return this.ButtonTexturePath.GetValue(this.Button, null) as string; return this.ButtonTexturePath.GetValue(this.Button, null) as string;
} }
set set
{ {
this.ButtonTexturePath.SetValue(this.Button, value, null); this.ButtonTexturePath.SetValue(this.Button, value, null);
} }
} }
   
/// <summary> /// <summary>
/// The button's tool tip text. Set to null if no tool tip is desired. /// The button's tool tip text. Set to null if no tool tip is desired.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Tool Tip Text Should Always Use Headline Style Like This. /// Tool Tip Text Should Always Use Headline Style Like This.
/// </remarks> /// </remarks>
public string ToolTip public string ToolTip
{ {
get get
{ {
return this.ButtonToolTip.GetValue(this.Button, null) as string; return this.ButtonToolTip.GetValue(this.Button, null) as string;
} }
set set
{ {
this.ButtonToolTip.SetValue(this.Button, value, null); this.ButtonToolTip.SetValue(this.Button, value, null);
} }
} }
   
/// <summary> /// <summary>
/// Whether this button is currently visible or not. Can be used in addition to or as a replacement for <see cref="Visibility"/>. /// Whether this button is currently visible or not. Can be used in addition to or as a replacement for <see cref="Visibility"/>.
/// </summary> /// </summary>
public bool Visible public bool Visible
{ {
get get
{ {
return (bool)this.ButtonVisible.GetValue(this.Button, null); return (bool)this.ButtonVisible.GetValue(this.Button, null);
} }
set set
{ {
this.ButtonVisible.SetValue(this.Button, value, null); this.ButtonVisible.SetValue(this.Button, value, null);
} }
} }
   
/// <summary> /// <summary>
/// Whether this button is currently enabled (clickable) or not. This will not affect the player's ability to /// Whether this button is currently enabled (clickable) or not. This will not affect the player's ability to
/// position the button on their screen. /// position the button on their screen.
/// </summary> /// </summary>
public bool Enabled public bool Enabled
{ {
get get
{ {
return (bool)this.ButtonEnalbed.GetValue(this.Button, null); return (bool)this.ButtonEnalbed.GetValue(this.Button, null);
} }
set set
{ {
this.ButtonEnalbed.SetValue(this.Button, value, null); this.ButtonEnalbed.SetValue(this.Button, value, null);
} }
} }
   
/// <summary> /// <summary>
/// Whether this button is currently "important." Set to false to return to normal button behaviour. /// Whether this button is currently "important." Set to false to return to normal button behaviour.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// This can be used to temporarily force the button to be shown on the screen regardless of the toolbar being /// 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 /// 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. /// chat room could mark itself as "important" as long as the message has not been read.
/// </para> /// </para>
/// <para> /// <para>
/// Setting this property does not change the appearance of the button. use <see cref="TexturePath"/> to /// Setting this property does not change the appearance of the button. use <see cref="TexturePath"/> to
/// change the button's icon. /// change the button's icon.
/// </para> /// </para>
/// <para> /// <para>
/// This feature should be used only sparingly, if at all, since it forces the button to be displayed on screen /// 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. /// even when it normally wouldn't.
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <value><c>true</c> if important; otherwise, <c>false</c>.</value> /// <value><c>true</c> if important; otherwise, <c>false</c>.</value>
public bool Important public bool Important
{ {
get get
{ {
return (bool)this.ButtonImportant.GetValue(this.Button, null); return (bool)this.ButtonImportant.GetValue(this.Button, null);
} }
set set
{ {
this.ButtonImportant.SetValue(this.Button, value, null); this.ButtonImportant.SetValue(this.Button, value, null);
} }
} }
   
private ToolbarButtonWrapper() private ToolbarButtonWrapper()
{ {
} }
   
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="VOID.ToolbarButtonWrapper"/> class. /// Initializes a new instance of the <see cref="VOID.ToolbarButtonWrapper"/> class.
/// </summary> /// </summary>
/// <param name="ns">Namespace, usually the plugin name.</param> /// <param name="ns">Namespace, usually the plugin name.</param>
/// <param name="id">Identifier, unique per namespace.</param> /// <param name="id">Identifier, unique per namespace.</param>
public ToolbarButtonWrapper(string ns, string id) protected ToolbarButtonWrapper(object button)
{ {
Tools.PostDebugMessage(string.Format(  
"{0}: Loading ToolbarManager.",  
this.GetType().Name  
));  
   
this.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.",  
this.GetType().Name  
));  
   
this.TBManagerInstance = this.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.",  
this.GetType().Name,  
this.TBManagerInstance  
));  
   
this.TBManagerAdd = this.ToolbarManager.GetMethod("add");  
   
Tools.PostDebugMessage(string.Format(  
"{0}: Got ToolbarManager Instance 'add' method. Loading IButton.",  
this.GetType().Name  
));  
   
this.IButton = AssemblyLoader.loadedAssemblies this.IButton = AssemblyLoader.loadedAssemblies
.Select(a => a.assembly.GetExportedTypes()) .Select(a => a.assembly.GetExportedTypes())
.SelectMany(t => t) .SelectMany(t => t)
.FirstOrDefault(t => t.FullName == "Toolbar.IButton"); .FirstOrDefault(t => t.FullName == "Toolbar.IButton");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Loaded IButton. Adding Button with ToolbarManager.", "{0}: Loaded IButton. Adding Button with ToolbarManager.",
this.GetType().Name this.GetType().Name
));  
   
this.Button = this.TBManagerAdd.Invoke(this.TBManagerInstance, new object[] { ns, id });  
   
Tools.PostDebugMessage(string.Format(  
"{0}: Added Button '{1}' with ToolbarManager. Getting 'Text' property",  
this.GetType().Name,  
this.Button.ToString()  
)); ));
   
this.ButtonText = this.IButton.GetProperty("Text"); this.ButtonText = this.IButton.GetProperty("Text");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'Text' property. Getting 'TextColor' property.", "{0}: Got 'Text' property. Getting 'TextColor' property.",
this.GetType().Name this.GetType().Name
)); ));
   
this.ButtonTextColor = this.IButton.GetProperty("TextColor"); this.ButtonTextColor = this.IButton.GetProperty("TextColor");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'TextColor' property. Getting 'TexturePath' property.", "{0}: Got 'TextColor' property. Getting 'TexturePath' property.",
this.GetType().Name this.GetType().Name
)); ));
   
this.ButtonTexturePath = this.IButton.GetProperty("TexturePath"); this.ButtonTexturePath = this.IButton.GetProperty("TexturePath");
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'TexturePath' property. Getting 'ToolTip' property.", "{0}: Got 'TexturePath' property. Getting 'ToolTip' property.",
this.GetType().Name this.GetType().Name
)); ));
   
this.ButtonToolTip = this.IButton.GetProperty("ToolTip"); this.ButtonToolTip = this.IButton.GetProperty("ToolTip");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'ToolTip' property. Getting 'Visible' property.", "{0}: Got 'ToolTip' property. Getting 'Visible' property.",
this.GetType().Name this.GetType().Name
)); ));
   
this.ButtonVisible = this.IButton.GetProperty("Visible"); this.ButtonVisible = this.IButton.GetProperty("Visible");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'Visible' property. Getting 'Visibility' property.", "{0}: Got 'Visible' property. Getting 'Visibility' property.",
this.GetType().Name this.GetType().Name
)); ));
   
this.ButtonVisibility = this.IButton.GetProperty("Visibility"); this.ButtonVisibility = this.IButton.GetProperty("Visibility");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'Visibility' property. Getting 'Enabled' property.", "{0}: Got 'Visibility' property. Getting 'Enabled' property.",
this.GetType().Name this.GetType().Name
)); ));
   
this.ButtonEnalbed = this.IButton.GetProperty("Enabled"); this.ButtonEnalbed = this.IButton.GetProperty("Enabled");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'Enabled' property. Getting 'OnClick' event.", "{0}: Got 'Enabled' property. Getting 'OnClick' event.",
this.GetType().Name this.GetType().Name
)); ));
   
this.ButtonImportant = this.IButton.GetProperty("Important"); this.ButtonImportant = this.IButton.GetProperty("Important");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'Enabled' property. Getting 'OnClick' event.", "{0}: Got 'Enabled' property. Getting 'OnClick' event.",
this.GetType().Name this.GetType().Name
)); ));
   
this.ButtonOnClick = this.IButton.GetEvent("OnClick"); this.ButtonOnClick = this.IButton.GetEvent("OnClick");
this.ClickHandlerType = this.ButtonOnClick.EventHandlerType; this.ClickHandlerType = this.ButtonOnClick.EventHandlerType;
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'OnClick' event '{1}'. Getting 'Destroy' method.", "{0}: Got 'OnClick' event '{1}'. Getting 'Destroy' method.",
this.GetType().Name, this.GetType().Name,
this.ButtonOnClick.ToString() this.ButtonOnClick.ToString()
)); ));
   
this.ButtonDestroy = this.IButton.GetMethod("Destroy"); this.ButtonDestroy = this.IButton.GetMethod("Destroy");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'Destroy' property '{1}'. Loading GameScenesVisibility class.", "{0}: Got 'Destroy' property '{1}'. Loading GameScenesVisibility class.",
this.GetType().Name, this.GetType().Name,
this.ButtonDestroy.ToString() this.ButtonDestroy.ToString()
)); ));
   
this.GameScenesVisibilityType = AssemblyLoader.loadedAssemblies this.GameScenesVisibilityType = AssemblyLoader.loadedAssemblies
.Select(a => a.assembly.GetExportedTypes()) .Select(a => a.assembly.GetExportedTypes())
.SelectMany(t => t) .SelectMany(t => t)
.FirstOrDefault(t => t.FullName == "Toolbar.GameScenesVisibility"); .FirstOrDefault(t => t.FullName == "Toolbar.GameScenesVisibility");
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Got 'GameScenesVisibility' class '{1}'.", "{0}: Got 'GameScenesVisibility' class '{1}'.",
this.GetType().Name, this.GetType().Name,
this.GameScenesVisibilityType.ToString() this.GameScenesVisibilityType.ToString()
)); ));
   
Tools.PostDebugMessage("ToolbarButtonWrapper built!"); Tools.PostDebugMessage("ToolbarButtonWrapper built!");
} }
   
/// <summary> /// <summary>
/// Adds event handler to receive "on click" events. /// Adds event handler to receive "on click" events.
/// </summary> /// </summary>
/// <example> /// <example>
/// <code> /// <code>
/// ToolbarButtonWrapper button = ... /// ToolbarButtonWrapper button = ...
/// button.AddButtonClickHandler( /// button.AddButtonClickHandler(
/// (e) => /// (e) =>
/// { /// {
/// Debug.Log("button clicked, mouseButton: " + e.Mousebutton"); /// Debug.Log("button clicked, mouseButton: " + e.Mousebutton");
/// } /// }
/// ); /// );
/// </code> /// </code>
/// </example> /// </example>
/// <param name="Handler">Delegate to handle "on click" events</param> /// <param name="Handler">Delegate to handle "on click" events</param>
public void AddButtonClickHandler(Action<object> Handler) public void AddButtonClickHandler(Action<object> Handler)
{ {
Delegate d = Delegate.CreateDelegate(this.ClickHandlerType, Handler.Target, Handler.Method); Delegate d = Delegate.CreateDelegate(this.ClickHandlerType, Handler.Target, Handler.Method);
MethodInfo addHandler = this.ButtonOnClick.GetAddMethod(); MethodInfo addHandler = this.ButtonOnClick.GetAddMethod();
addHandler.Invoke(this.Button, new object[] { d }); addHandler.Invoke(this.Button, new object[] { d });
} }
   
/// <summary> /// <summary>
/// Sets this button's visibility. Can be used in addition to or as a replacement for <see cref="Visible"/>. /// Sets this button's visibility. Can be used in addition to or as a replacement for <see cref="Visible"/>.
/// </summary> /// </summary>
/// <param name="gameScenes">Array of GameScene objects in which the button should be visible.</param> /// <param name="gameScenes">Array of GameScene objects in which the button should be visible.</param>
public void SetButtonVisibility(params GameScenes[] gameScenes) public void SetButtonVisibility(params GameScenes[] gameScenes)
{ {
object GameScenesVisibilityObj = Activator.CreateInstance(this.GameScenesVisibilityType, gameScenes); object GameScenesVisibilityObj = Activator.CreateInstance(this.GameScenesVisibilityType, gameScenes);
this.ButtonVisibility.SetValue(this.Button, GameScenesVisibilityObj, null); this.ButtonVisibility.SetValue(this.Button, GameScenesVisibilityObj, null);
} }
   
/// <summary> /// <summary>
/// Permanently destroys this button so that it is no longer displayed. /// Permanently destroys this button so that it is no longer displayed.
/// Should be used when a plugin is stopped to remove leftover buttons. /// Should be used when a plugin is stopped to remove leftover buttons.
/// </summary> /// </summary>
public void Destroy() public void Destroy()
{ {
this.ButtonDestroy.Invoke(this.Button, null); this.ButtonDestroy.Invoke(this.Button, null);
} }
} }
} }
   
// //
// VOID_Core.cs // VOID_Core.cs
// //
// Author: // Author:
// toadicus <> // toadicus <>
// //
// Copyright (c) 2013 toadicus // Copyright (c) 2013 toadicus
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using KSP; using KSP;
using UnityEngine; using UnityEngine;
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
   
namespace VOID namespace VOID
{ {
public class VOID_Core : VOID_Module, IVOID_Module public class VOID_Core : VOID_Module, IVOID_Module
{ {
/* /*
* Static Members * Static Members
* */ * */
protected static bool _initialized = false; protected static bool _initialized = false;
   
public static bool Initialized public static bool Initialized
{ {
get get
{ {
return _initialized; return _initialized;
} }
} }
   
protected static VOID_Core _instance; protected static VOID_Core _instance;
   
public static VOID_Core Instance public static VOID_Core Instance
{ {
get get
{ {
if (_instance == null) if (_instance == null)
{ {
_instance = new VOID_Core(); _instance = new VOID_Core();
_initialized = true; _initialized = true;
} }
return _instance; return _instance;
} }
} }
   
public static void Reset() public static void Reset()
{ {
_instance.StopGUI(); _instance.StopGUI();
_instance = null; _instance = null;
_initialized = false; _initialized = false;
} }
   
public static double Constant_G = 6.674e-11; public static double Constant_G = 6.674e-11;
/* /*
* Fields * Fields
* */ * */
protected string VoidName = "VOID"; protected string VoidName = "VOID";
protected string VoidVersion = "0.9.18"; protected string VoidVersion = "0.9.18";
protected bool _factoryReset = false; protected bool _factoryReset = false;
[AVOID_SaveValue("configValue")] [AVOID_SaveValue("configValue")]
protected VOID_SaveValue<int> configVersion = 1; protected VOID_SaveValue<int> configVersion = 1;
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;
[AVOID_SaveValue("mainWindowPos")] [AVOID_SaveValue("mainWindowPos")]
protected VOID_SaveValue<Rect> mainWindowPos = new Rect(475, 575, 10f, 10f); protected VOID_SaveValue<Rect> mainWindowPos = new Rect(475, 575, 10f, 10f);
[AVOID_SaveValue("mainGuiMinimized")] [AVOID_SaveValue("mainGuiMinimized")]
protected VOID_SaveValue<bool> mainGuiMinimized = false; protected VOID_SaveValue<bool> mainGuiMinimized = false;
[AVOID_SaveValue("configWindowPos")] [AVOID_SaveValue("configWindowPos")]
protected VOID_SaveValue<Rect> configWindowPos = new Rect(825, 625, 10f, 10f); protected VOID_SaveValue<Rect> configWindowPos = new Rect(825, 625, 10f, 10f);
[AVOID_SaveValue("configWindowMinimized")] [AVOID_SaveValue("configWindowMinimized")]
protected VOID_SaveValue<bool> configWindowMinimized = true; protected VOID_SaveValue<bool> configWindowMinimized = true;
[AVOID_SaveValue("VOIDIconPos")] [AVOID_SaveValue("VOIDIconPos")]
protected VOID_SaveValue<Rect> VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 32, 32f, 32f); protected VOID_SaveValue<Rect> VOIDIconPos = new Rect(Screen.width / 2 - 200, Screen.height - 32, 32f, 32f);
protected Texture2D VOIDIconOff; protected Texture2D VOIDIconOff;
protected Texture2D VOIDIconOn; protected Texture2D VOIDIconOn;
protected Texture2D VOIDIconTexture; protected Texture2D VOIDIconTexture;
protected string VOIDIconOnPath = "VOID/Textures/void_icon_on"; protected string VOIDIconOnPath = "VOID/Textures/void_icon_on";
protected string VOIDIconOffPath = "VOID/Textures/void_icon_off"; protected string VOIDIconOffPath = "VOID/Textures/void_icon_off";
protected bool VOIDIconLocked = true; protected bool VOIDIconLocked = true;
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 Dictionary<string, GUIStyle> _LabelStyles = new Dictionary<string, GUIStyle>(); protected Dictionary<string, GUIStyle> _LabelStyles = new Dictionary<string, GUIStyle>();
[AVOID_SaveValue("togglePower")] [AVOID_SaveValue("togglePower")]
public VOID_SaveValue<bool> togglePower = true; public VOID_SaveValue<bool> togglePower = true;
public bool powerAvailable = true; public bool powerAvailable = true;
[AVOID_SaveValue("consumeResource")] [AVOID_SaveValue("consumeResource")]
protected VOID_SaveValue<bool> consumeResource = false; protected VOID_SaveValue<bool> consumeResource = false;
[AVOID_SaveValue("resourceName")] [AVOID_SaveValue("resourceName")]
protected VOID_SaveValue<string> resourceName = "ElectricCharge"; protected VOID_SaveValue<string> resourceName = "ElectricCharge";
[AVOID_SaveValue("resourceRate")] [AVOID_SaveValue("resourceRate")]
protected VOID_SaveValue<float> resourceRate = 0.2f; protected VOID_SaveValue<float> resourceRate = 0.2f;
[AVOID_SaveValue("updatePeriod")] [AVOID_SaveValue("updatePeriod")]
protected VOID_SaveValue<double> _updatePeriod = 1001f / 15000f; protected VOID_SaveValue<double> _updatePeriod = 1001f / 15000f;
protected float _updateTimer = 0f; protected float _updateTimer = 0f;
protected string stringFrequency; protected string stringFrequency;
// Celestial Body Housekeeping // Celestial Body Housekeeping
protected List<CelestialBody> _allBodies = new List<CelestialBody>(); protected List<CelestialBody> _allBodies = new List<CelestialBody>();
protected bool bodiesLoaded = false; protected bool bodiesLoaded = false;
// Vessel Type Housekeeping // Vessel Type Housekeeping
protected List<VesselType> _allVesselTypes = new List<VesselType>(); protected List<VesselType> _allVesselTypes = new List<VesselType>();
protected bool vesselTypesLoaded = false; protected bool vesselTypesLoaded = false;
public float saveTimer = 0; public float saveTimer = 0;
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 Dictionary<string, GUISkin> skin_list; protected Dictionary<string, GUISkin> skin_list;
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 5", "KSP window 5",
"KSP window 6", "KSP window 6",
"PartTooltipSkin" "PartTooltipSkin"
}; };
protected bool skinsLoaded = false; protected bool skinsLoaded = false;
public bool configDirty; public bool configDirty;
[AVOID_SaveValue("UseBlizzyToolbar")] [AVOID_SaveValue("UseBlizzyToolbar")]
protected VOID_SaveValue<bool> _UseToolbarManager; protected VOID_SaveValue<bool> _UseToolbarManager;
protected bool ToolbarManagerLoaded = false; protected bool ToolbarManagerLoaded;
internal ToolbarButtonWrapper ToolbarButton; internal ToolbarButtonWrapper ToolbarButton;
/* /*
* Properties * Properties
* */ * */
public bool factoryReset public bool factoryReset
{ {
get get
{ {
return this._factoryReset; return this._factoryReset;
} }
} }
   
public List<IVOID_Module> Modules public List<IVOID_Module> Modules
{ {
get get
{ {
return this._modules; return this._modules;
} }
} }
   
public GUISkin Skin public GUISkin Skin
{ {
get get
{ {
if (!this.skinsLoaded || this._skinName == null) if (!this.skinsLoaded || this._skinName == null)
{ {
return AssetBase.GetGUISkin(this.defaultSkin); return AssetBase.GetGUISkin(this.defaultSkin);
} }
return this.skin_list[this._skinName]; return this.skin_list[this._skinName];
} }
} }
   
public int windowID public 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 Dictionary<string, GUIStyle> LabelStyles public Dictionary<string, GUIStyle> LabelStyles
{ {
get get
{ {
return this._LabelStyles; return this._LabelStyles;
} }
} }
   
public List<CelestialBody> allBodies public List<CelestialBody> allBodies
{ {
get get
{ {
return this._allBodies; return this._allBodies;
} }
} }
   
public List<VesselType> allVesselTypes public List<VesselType> allVesselTypes
{ {
get get
{ {
return this._allVesselTypes; return this._allVesselTypes;
} }
} }
   
public float updateTimer public float updateTimer
{ {
get get
{ {
return this._updateTimer; return this._updateTimer;
} }
} }
   
public double updatePeriod public double updatePeriod
{ {
get get
{ {
return this._updatePeriod; return this._updatePeriod;
} }
} }
   
protected bool UseToolbarManager protected bool UseToolbarManager
{ {
get get
{ {
return _UseToolbarManager; return _UseToolbarManager;
} }
set set
{ {
if (value == false && this.ToolbarManagerLoaded && this.ToolbarButton != null) if (value == false && this.ToolbarManagerLoaded && this.ToolbarButton != null)
{ {
this.ToolbarButton.Destroy(); this.ToolbarButton.Destroy();
this.ToolbarButton = null; this.ToolbarButton = null;
} }
if (value == true && this.ToolbarManagerLoaded && this.ToolbarButton == null) if (value == true && this.ToolbarManagerLoaded && this.ToolbarButton == null)
{ {
this.InitializeToolbarButton(); this.InitializeToolbarButton();
} }
   
_UseToolbarManager.value = value; _UseToolbarManager.value = value;
} }
} }
/* /*
* Methods * Methods
* */ * */
protected VOID_Core() protected VOID_Core()
{ {
this._Name = "VOID Core"; this._Name = "VOID Core";
   
this._Active.value = true; this._Active.value = true;
   
this.VOIDIconOn = GameDatabase.Instance.GetTexture(this.VOIDIconOnPath, false); this.VOIDIconOn = GameDatabase.Instance.GetTexture(this.VOIDIconOnPath, false);
this.VOIDIconOff = GameDatabase.Instance.GetTexture(this.VOIDIconOffPath, false); this.VOIDIconOff = GameDatabase.Instance.GetTexture(this.VOIDIconOffPath, false);
   
this._skinName = this.defaultSkin; this._skinName = this.defaultSkin;
   
this.UseToolbarManager = false; this.UseToolbarManager = false;
  this.ToolbarManagerLoaded = false;
   
this.LoadConfig(); this.LoadConfig();
} }
   
protected void LoadModulesOfType<T>() protected void LoadModulesOfType<T>()
{ {
var types = AssemblyLoader.loadedAssemblies var types = AssemblyLoader.loadedAssemblies
.Select(a => a.assembly.GetExportedTypes()) .Select(a => a.assembly.GetExportedTypes())
.SelectMany(t => t) .SelectMany(t => t)
.Where(v => typeof(T).IsAssignableFrom(v) .Where(v => typeof(T).IsAssignableFrom(v)
&& !(v.IsInterface || v.IsAbstract) && && !(v.IsInterface || v.IsAbstract) &&
!typeof(VOID_Core).IsAssignableFrom(v) !typeof(VOID_Core).IsAssignableFrom(v)
); );
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Found {1} modules to check.", "{0}: Found {1} modules to check.",
this.GetType().Name, this.GetType().Name,
types.Count() types.Count()
)); ));
foreach (var voidType in types) foreach (var voidType in types)
{ {
if (!HighLogic.LoadedSceneIsEditor && if (!HighLogic.LoadedSceneIsEditor &&
typeof(IVOID_EditorModule).IsAssignableFrom(voidType)) typeof(IVOID_EditorModule).IsAssignableFrom(voidType))
{ {
continue; continue;
} }
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: found Type {1}", "{0}: found Type {1}",
this.GetType().Name, this.GetType().Name,
voidType.Name voidType.Name
)); ));
   
this.LoadModule(voidType); this.LoadModule(voidType);
} }
   
this._modulesLoaded = true; this._modulesLoaded = true;
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: Loaded {1} modules.", "{0}: Loaded {1} modules.",
this.GetType().Name, this.GetType().Name,
this.Modules.Count this.Modules.Count
)); ));
} }
   
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())
{ {
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: refusing to load {1}: already loaded", "{0}: refusing to load {1}: already loaded",
this.GetType().Name, this.GetType().Name,
T.Name T.Name
)); ));
return; return;
} }
IVOID_Module module = Activator.CreateInstance(T) as IVOID_Module; IVOID_Module module = Activator.CreateInstance(T) as IVOID_Module;
module.LoadConfig(); module.LoadConfig();
this._modules.Add(module); this._modules.Add(module);
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: loaded module {1}.", "{0}: loaded module {1}.",
this.GetType().Name, this.GetType().Name,
T.Name T.Name
)); ));
} }
   
protected void LoadSkins() protected void LoadSkins()
{ {
Tools.PostDebugMessage("AssetBase has skins: \n" + Tools.PostDebugMessage("AssetBase has skins: \n" +
string.Join("\n\t", string.Join("\n\t",
Resources.FindObjectsOfTypeAll(typeof(GUISkin)) Resources.FindObjectsOfTypeAll(typeof(GUISkin))
.Select(s => s.ToString()) .Select(s => s.ToString())
.ToArray() .ToArray()
) )
); );
   
this.skin_list = Resources.FindObjectsOfTypeAll(typeof(GUISkin)) this.skin_list = Resources.FindObjectsOfTypeAll(typeof(GUISkin))
.Where(s => !this.forbiddenSkins.Contains(s.name)) .Where(s => !this.forbiddenSkins.Contains(s.name))
.Select(s => s as GUISkin) .Select(s => s as GUISkin)
.GroupBy(s => s.name) .GroupBy(s => s.name)
.Select(g => g.First()) .Select(g => g.First())
.ToDictionary(s => s.name); .ToDictionary(s => s.name);
   
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: loaded {1} GUISkins.", "{0}: loaded {1} GUISkins.",
this.GetType().Name, this.GetType().Name,
this.skin_list.Count this.skin_list.Count
)); ));
   
this.skinNames = this.skin_list.Keys.ToList(); this.skinNames = this.skin_list.Keys.ToList();
this.skinNames.Sort(); this.skinNames.Sort();
   
if (this._skinName == null || !this.skinNames.Contains(this._skinName)) if (this._skinName == null || !this.skinNames.Contains(this._skinName))
{ {
this._skinName = this.defaultSkin; this._skinName = this.defaultSkin;
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"{0}: resetting _skinIdx to default.", "{0}: resetting _skinIdx to default.",
this.GetType().Name this.GetType().Name
)); ));
} }
   
Tools.PostDebugMessage(string.Format( Tools.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()
{ {
this.LabelStyles["link"] = new GUIStyle(GUI.skin.label); this.LabelStyles["link"] = new GUIStyle(GUI.skin.label);
this.LabelStyles["link"].fontStyle = FontStyle.Bold; this.LabelStyles["link"].fontStyle = FontStyle.Bold;
   
this.LabelStyles["center"] = new GUIStyle(GUI.skin.label); this.LabelStyles["center"] = new GUIStyle(GUI.skin.label);
this.LabelStyles["center"].normal.textColor = Color.white; this.LabelStyles["center"].normal.textColor = Color.white;
this.LabelStyles["center"].alignment = TextAnchor.UpperCenter; this.LabelStyles["center"].alignment = TextAnchor.UpperCenter;
   
this.LabelStyles["center_bold"] = new GUIStyle(GUI.skin.label); this.LabelStyles["center_bold"] = new GUIStyle(GUI.skin.label);
this.LabelStyles["center_bold"].normal.textColor = Color.white; this.LabelStyles["center_bold"].normal.textColor = Color.white;
this.LabelStyles["center_bold"].alignment = TextAnchor.UpperCenter; this.LabelStyles["center_bold"].alignment = TextAnchor.UpperCenter;
this.LabelStyles["center_bold"].fontStyle = FontStyle.Bold; this.LabelStyles["center_bold"].fontStyle = FontStyle.Bold;
   
this.LabelStyles["right"] = new GUIStyle(GUI.skin.label); this.LabelStyles["right"] = new GUIStyle(GUI.skin.label);
this.LabelStyles["right"].normal.textColor = Color.white; this.LabelStyles["right"].normal.textColor = Color.white;
this.LabelStyles["right"].alignment = TextAnchor.UpperRight; this.LabelStyles["right"].alignment = TextAnchor.UpperRight;
   
this.LabelStyles["red"] = new GUIStyle(GUI.skin.label); this.LabelStyles["red"] = new GUIStyle(GUI.skin.label);
this.LabelStyles["red"].normal.textColor = Color.red; this.LabelStyles["red"].normal.textColor = Color.red;
this.LabelStyles["red"].alignment = TextAnchor.MiddleCenter; this.LabelStyles["red"].alignment = TextAnchor.MiddleCenter;
   
this.iconStyle = new GUIStyle(GUI.skin.button); this.iconStyle = new GUIStyle(GUI.skin.button);
this.iconStyle.padding = new RectOffset(0, 0, 0, 0); this.iconStyle.padding = new RectOffset(0, 0, 0, 0);
// this.iconStyle.margin = new RectOffset(0, 0, 0, 0); // this.iconStyle.margin = new RectOffset(0, 0, 0, 0);
// this.iconStyle.contentOffset = new Vector2(0, 0); // this.iconStyle.contentOffset = new Vector2(0, 0);
this.iconStyle.overflow = new RectOffset(0, 0, 0, 0); this.iconStyle.overflow = new RectOffset(0, 0, 0, 0);
// this.iconStyle.border = new RectOffset(0, 0, 0, 0); // this.iconStyle.border = new RectOffset(0, 0, 0, 0);
   
this.GUIStylesLoaded = true; this.GUIStylesLoaded = true;
} }
   
protected void LoadAllBodies() protected void LoadAllBodies()
{ {
this._allBodies = FlightGlobals.Bodies; this._allBodies = FlightGlobals.Bodies;
this.bodiesLoaded = true; this.bodiesLoaded = true;
} }
   
protected void LoadVesselTypes() protected void LoadVesselTypes()
{ {
this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList(); this._allVesselTypes = Enum.GetValues(typeof(VesselType)).OfType<VesselType>().ToList();
this.vesselTypesLoaded = true; this.vesselTypesLoaded = true;
} }
   
protected void LoadBeforeUpdate() protected void LoadBeforeUpdate()
{ {
if (!this.bodiesLoaded) if (!this.bodiesLoaded)
{ {
this.LoadAllBodies(); this.LoadAllBodies();
} }
   
if (!this.vesselTypesLoaded) if (!this.vesselTypesLoaded)
{ {
this.LoadVesselTypes(); this.LoadVesselTypes();
} }
} }
   
protected void LoadToolbarManager() protected void LoadToolbarManager()
{ {
Type ToolbarManager = AssemblyLoader.loadedAssemblies this.ToolbarManagerLoaded = ToolbarButtonWrapper.ToolbarManagerPresent;
.Select(a => a.assembly.GetExportedTypes())  
.SelectMany(t => t) if (this.ToolbarManagerLoaded)
.FirstOrDefault(t => t.FullName == "Toolbar.ToolbarManager"); {
  this.InitializeToolbarButton();
if (ToolbarManager == null) }
{  
Tools.PostDebugMessage(string.Format(  
"{0}: Could not load ToolbarManager.",  
this.GetType().Name  
));  
   
return;  
}  
   
this.InitializeToolbarButton();  
   
this.ToolbarManagerLoaded = true;  
} }
   
protected void InitializeToolbarButton() protected void InitializeToolbarButton()
{ {
this.ToolbarButton = new ToolbarButtonWrapper(this.GetType().Name, "coreToggle"); this.ToolbarButton = ToolbarButtonWrapper.TryWrapToolbarButton(this.GetType().Name, "coreToggle");
this.ToolbarButton.Text = this.VoidName; this.ToolbarButton.Text = this.VoidName;
this.ToolbarButton.TexturePath = this.VOIDIconOffPath + "_24x24"; this.ToolbarButton.TexturePath = this.VOIDIconOffPath + "_24x24";
if (this is VOID_EditorCore) if (this is VOID_EditorCore)
{ {
this.ToolbarButton.SetButtonVisibility(new GameScenes[] { GameScenes.EDITOR }); this.ToolbarButton.SetButtonVisibility(new GameScenes[] { GameScenes.EDITOR });
} }
else else
{ {
this.ToolbarButton.SetButtonVisibility(new GameScenes[] { GameScenes.FLIGHT }); this.ToolbarButton.SetButtonVisibility(new GameScenes[] { GameScenes.FLIGHT });
} }
this.ToolbarButton.AddButtonClickHandler( this.ToolbarButton.AddButtonClickHandler(
(e) => this.mainGuiMinimized = !this.mainGuiMinimized (e) => this.mainGuiMinimized = !this.mainGuiMinimized
); );
} }
   
public void VOIDMainWindow(int _) public void VOIDMainWindow(int _)
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
if (this.powerAvailable || HighLogic.LoadedSceneIsEditor) if (this.powerAvailable || HighLogic.LoadedSceneIsEditor)
{ {
if (!HighLogic.LoadedSceneIsEditor) if (!HighLogic.LoadedSceneIsEditor)
{ {
string str = "ON"; string str = "ON";
if (togglePower) if (togglePower)
str = "OFF"; str = "OFF";
if (GUILayout.Button("Power " + str)) if (GUILayout.Button("Power " + str))
togglePower.value = !togglePower; togglePower.value = !togglePower;
} }
   
if (togglePower || HighLogic.LoadedSceneIsEditor) if (togglePower || HighLogic.LoadedSceneIsEditor)
{ {
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module.toggleActive = GUILayout.Toggle(module.toggleActive, module.Name); module.toggleActive = GUILayout.Toggle(module.toggleActive, module.Name);
} }
} }
} }
else else
{ {
GUILayout.Label("-- POWER LOST --", this.LabelStyles["red"]); GUILayout.Label("-- POWER LOST --", this.LabelStyles["red"]);
} }
   
this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration"); this.configWindowMinimized.value = !GUILayout.Toggle(!this.configWindowMinimized, "Configuration");
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
public void VOIDConfigWindow(int _) public void VOIDConfigWindow(int _)
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
this.DrawConfigurables(); this.DrawConfigurables();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
GUI.DragWindow(); GUI.DragWindow();
} }
   
public override void DrawConfigurables() public override void DrawConfigurables()
{ {
int skinIdx; int skinIdx;
   
GUIContent _content; GUIContent _content;
   
if (HighLogic.LoadedSceneIsFlight) if (HighLogic.LoadedSceneIsFlight)
{ {
this.consumeResource.value = GUILayout.Toggle(this.consumeResource, "Consume Resources"); this.consumeResource.value = GUILayout.Toggle(this.consumeResource, "Consume Resources");
   
this.VOIDIconLocked = GUILayout.Toggle(this.VOIDIconLocked, "Lock Icon Position"); this.VOIDIconLocked = GUILayout.Toggle(this.VOIDIconLocked, "Lock Icon Position");
} }
   
this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available"); this.UseToolbarManager = GUILayout.Toggle(this.UseToolbarManager, "Use Blizzy's Toolbar If Available");
   
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();
   
if (skinNames.Contains(this._skinName)) if (skinNames.Contains(this._skinName))
{ {
skinIdx = skinNames.IndexOf(this._skinName); skinIdx = skinNames.IndexOf(this._skinName);
} }
else if (skinNames.Contains(this.defaultSkin)) else if (skinNames.Contains(this.defaultSkin))
{ {
skinIdx = skinNames.IndexOf(this.defaultSkin); skinIdx = skinNames.IndexOf(this.defaultSkin);
} }
else else
{ {
skinIdx = 0; skinIdx = 0;
} }
   
_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.GUIStylesLoaded = false; this.GUIStylesLoaded = false;
skinIdx--; skinIdx--;
if (skinIdx < 0) if (skinIdx < 0)
skinIdx = skinNames.Count - 1; skinIdx = skinNames.Count - 1;
Tools.PostDebugMessage(string.Format( Tools.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.skin_list.Count this.skin_list.Count
)); ));
} }
   
_content.text = this.Skin.name; _content.text = this.Skin.name;
_content.tooltip = "Current skin"; _content.tooltip = "Current skin";
GUILayout.Label(_content, this.LabelStyles["center"], GUILayout.ExpandWidth(true)); GUILayout.Label(_content, this.LabelStyles["center"], 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.GUIStylesLoaded = false; this.GUIStylesLoaded = false;
skinIdx++; skinIdx++;
if (skinIdx >= skinNames.Count) if (skinIdx >= skinNames.Count)
skinIdx = 0; skinIdx = 0;
Tools.PostDebugMessage(string.Format( Tools.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.skin_list.Count this.skin_list.Count
)); ));
} }
   
if (this._skinName != skinNames[skinIdx]) if (this._skinName != skinNames[skinIdx])
{ {
this._skinName = skinNames[skinIdx]; this._skinName = skinNames[skinIdx];
} }
   
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));
// GUILayout.FlexibleSpace(); // GUILayout.FlexibleSpace();
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 = 1 / updateFreq; this._updatePeriod = 1 / updateFreq;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
foreach (IVOID_Module mod in this.Modules) foreach (IVOID_Module mod in this.Modules)
{ {
mod.DrawConfigurables(); mod.DrawConfigurables();
} }
   
this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset"); this._factoryReset = GUILayout.Toggle(this._factoryReset, "Factory Reset");
} }
   
public override void DrawGUI() public override void DrawGUI()
{ {
this._windowID = this.windowBaseID; this._windowID = this.windowBaseID;
   
if (!this._modulesLoaded) if (!this._modulesLoaded)
{ {
this.LoadModulesOfType<IVOID_Module>(); this.LoadModulesOfType<IVOID_Module>();
} }
   
if (this.UseToolbarManager && !this.ToolbarManagerLoaded) if (this.UseToolbarManager && !this.ToolbarManagerLoaded)
{ {
this.LoadToolbarManager(); this.LoadToolbarManager();
} }
   
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();
} }
   
if (this.UseToolbarManager && this.ToolbarManagerLoaded) if (this.UseToolbarManager && this.ToolbarManagerLoaded)
{ {
this.ToolbarButton.TexturePath = VOIDIconOffPath; this.ToolbarButton.TexturePath = VOIDIconOffPath;
if (this.togglePower) if (this.togglePower)
{ {
this.ToolbarButton.TexturePath = VOIDIconOnPath; this.ToolbarButton.TexturePath = VOIDIconOnPath;
} }
} }
else else
{ {
this.VOIDIconTexture = this.VOIDIconOff; //icon off default this.VOIDIconTexture = this.VOIDIconOff; //icon off default
if (this.togglePower) if (this.togglePower)
this.VOIDIconTexture = this.VOIDIconOn; //or on if power_toggle==true this.VOIDIconTexture = this.VOIDIconOn; //or on if power_toggle==true
   
if (GUI.Button(VOIDIconPos, VOIDIconTexture, this.iconStyle) && this.VOIDIconLocked) if (GUI.Button(VOIDIconPos, VOIDIconTexture, this.iconStyle) && this.VOIDIconLocked)
{ {
this.mainGuiMinimized.value = !this.mainGuiMinimized; this.mainGuiMinimized.value = !this.mainGuiMinimized;
} }
} }
   
if (!this.mainGuiMinimized) if (!this.mainGuiMinimized)
{ {
Rect _mainWindowPos = this.mainWindowPos; Rect _mainWindowPos = this.mainWindowPos;
   
_mainWindowPos = GUILayout.Window( _mainWindowPos = GUILayout.Window(
this.windowID, this.windowID,
_mainWindowPos, _mainWindowPos,
this.VOIDMainWindow, this.VOIDMainWindow,
string.Join(" ", new string[] { this.VoidName, this.VoidVersion }), string.Join(" ", new string[] { this.VoidName, this.VoidVersion }),
GUILayout.Width(250), GUILayout.Width(250),
GUILayout.Height(50) GUILayout.Height(50)
); );
   
_mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos); _mainWindowPos = Tools.ClampRectToScreen(_mainWindowPos);
   
if (_mainWindowPos != this.mainWindowPos) if (_mainWindowPos != this.mainWindowPos)
{ {
this.mainWindowPos = _mainWindowPos; this.mainWindowPos = _mainWindowPos;
} }
} }
   
if (!this.configWindowMinimized && !this.mainGuiMinimized) if (!this.configWindowMinimized && !this.mainGuiMinimized)
{ {
Rect _configWindowPos = this.configWindowPos; Rect _configWindowPos = this.configWindowPos;
   
_configWindowPos = GUILayout.Window( _configWindowPos = GUILayout.Window(
this.windowID, this.windowID,
_configWindowPos, _configWindowPos,
this.VOIDConfigWindow, this.VOIDConfigWindow,
string.Join(" ", new string[] { this.VoidName, "Configuration" }), string.Join(" ", new string[] { this.VoidName, "Configuration" }),
GUILayout.Width(250), GUILayout.Width(250),
GUILayout.Height(50) GUILayout.Height(50)
); );
   
_configWindowPos = Tools.ClampRectToScreen(_configWindowPos); _configWindowPos = Tools.ClampRectToScreen(_configWindowPos);
   
if (_configWindowPos != this.configWindowPos) if (_configWindowPos != this.configWindowPos)
{ {
this.configWindowPos = _configWindowPos; this.configWindowPos = _configWindowPos;
} }
} }
} }
   
public void OnGUI() public void OnGUI()
{ {
if (Event.current.type == EventType.Repaint) if (Event.current.type == EventType.Repaint)
{ {
return; return;
} }
   
/* /*
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"Event.current.type: {0}" + "Event.current.type: {0}" +
"\nthis.VOIDIconLocked: {1}" + "\nthis.VOIDIconLocked: {1}" +
"\nEvent.current.mousePosition: {2}" + "\nEvent.current.mousePosition: {2}" +
"\nVOIDIconPos: ({3}, {4}),({5}, {6})", "\nVOIDIconPos: ({3}, {4}),({5}, {6})",
Event.current.type, Event.current.type,
this.VOIDIconLocked, this.VOIDIconLocked,
Event.current.mousePosition, Event.current.mousePosition,
this.VOIDIconPos.value.xMin, this.VOIDIconPos.value.xMin,
this.VOIDIconPos.value.yMin, this.VOIDIconPos.value.yMin,
this.VOIDIconPos.value.xMax, this.VOIDIconPos.value.xMax,
this.VOIDIconPos.value.yMax this.VOIDIconPos.value.yMax
)); ));
*/ */
   
if (!this.VOIDIconLocked && if (!this.VOIDIconLocked &&
VOIDIconPos.value.Contains(Event.current.mousePosition) VOIDIconPos.value.Contains(Event.current.mousePosition)
&& Event.current.type == EventType.mouseDrag) && Event.current.type == EventType.mouseDrag)
{ {
Tools.PostDebugMessage(string.Format( Tools.PostDebugMessage(string.Format(
"Event.current.type: {0}" + "Event.current.type: {0}" +
"\ndelta.x: {1}; delta.y: {2}", "\ndelta.x: {1}; delta.y: {2}",
Event.current.type, Event.current.type,
Event.current.delta.x, Event.current.delta.x,
Event.current.delta.y Event.current.delta.y
)); ));
   
Rect tmp = new Rect(VOIDIconPos); Rect tmp = new Rect(VOIDIconPos);
   
tmp.x = Event.current.mousePosition.x - tmp.width / 2; tmp.x = Event.current.mousePosition.x - tmp.width / 2;
tmp.y = Event.current.mousePosition.y - tmp.height / 2; tmp.y = Event.current.mousePosition.y - tmp.height / 2;
   
if (tmp.x > Screen.width - tmp.width) if (tmp.x > Screen.width - tmp.width)
{ {
tmp.x = Screen.width - tmp.width; tmp.x = Screen.width - tmp.width;
} }
   
if (tmp.y > Screen.height - tmp.height) if (tmp.y > Screen.height - tmp.height)
{ {
tmp.y = Screen.height - tmp.height; tmp.y = Screen.height - tmp.height;
} }
   
VOIDIconPos = tmp; VOIDIconPos = tmp;
} }
} }
   
public void Update() public void Update()
{ {
this.LoadBeforeUpdate(); this.LoadBeforeUpdate();
   
if (this.vessel != null) if (this.vessel != null)
{ {
SimManager.Instance.Gravity = VOID_Core.Instance.vessel.mainBody.gravParameter / SimManager.Instance.Gravity = VOID_Core.Instance.vessel.mainBody.gravParameter /
Math.Pow(VOID_Core.Instance.vessel.mainBody.Radius, 2); Math.Pow(VOID_Core.Instance.vessel.mainBody.Radius, 2);
SimManager.Instance.TryStartSimulation(); SimManager.Instance.TryStartSimulation();
} }
   
if (!this.guiRunning) if (!this.guiRunning)
{ {
this.StartGUI(); this.StartGUI();
} }
   
if (!HighLogic.LoadedSceneIsFlight && this.guiRunning) if (!HighLogic.LoadedSceneIsFlight && this.guiRunning)
{ {
this.StopGUI(); this.StopGUI();
} }
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
if (!module.guiRunning && module.toggleActive) if (!module.guiRunning && module.toggleActive)
{ {
module.StartGUI(); module.StartGUI();
} }
if (module.guiRunning && !module.toggleActive || if (module.guiRunning && !module.toggleActive ||
!this.togglePower || !this.togglePower ||
!HighLogic.LoadedSceneIsFlight || !HighLogic.LoadedSceneIsFlight ||
this.factoryReset) this.factoryReset)
{ {
module.StopGUI(); module.StopGUI();
} }
   
if (module is IVOID_BehaviorModule) if (module is IVOID_BehaviorModule)
{ {
((IVOID_BehaviorModule)module).Update(); ((IVOID_BehaviorModule)module).Update();
} }
} }
   
this.CheckAndSave(); this.CheckAndSave();
this._updateTimer += Time.deltaTime; this._updateTimer += Time.deltaTime;
} }
   
public void FixedUpdate() public void FixedUpdate()
{ {
if (this.consumeResource && if (this.consumeResource &&
this.vessel.vesselType != VesselType.EVA && this.vessel.vesselType != VesselType.EVA &&
TimeWarp.deltaTime != 0) TimeWarp.deltaTime != 0)
{ {
float powerReceived = this.vessel.rootPart.RequestResource(this.resourceName, float powerReceived = this.vessel.rootPart.RequestResource(this.resourceName,
this.resourceRate * TimeWarp.fixedDeltaTime); this.resourceRate * TimeWarp.fixedDeltaTime);
if (powerReceived > 0) if (powerReceived > 0)
{ {
this.powerAvailable = true; this.powerAvailable = true;
} }
else else
{ {
this.powerAvailable = false; this.powerAvailable = false;
} }
} }
   
foreach (IVOID_BehaviorModule module in foreach (IVOID_BehaviorModule module in
this._modules.OfType<IVOID_BehaviorModule>().Where(m => !m.GetType().IsAbstract)) this._modules.OfType<IVOID_BehaviorModule>().Where(m => !m.GetType().IsAbstract))
{ {
module.FixedUpdate(); module.FixedUpdate();
} }
} }
   
public void ResetGUI() public void ResetGUI()
{ {
this.StopGUI(); this.StopGUI();
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module.StopGUI(); module.StopGUI();
module.StartGUI(); module.StartGUI();
} }
   
this.StartGUI(); this.StartGUI();
} }
   
protected void CheckAndSave() protected void CheckAndSave()
{ {
this.saveTimer += Time.deltaTime; this.saveTimer += Time.deltaTime;
   
if (this.saveTimer > 2f) if (this.saveTimer > 2f)
{ {
if (!this.configDirty) if (!this.configDirty)
{ {
return; return;
} }
   
Tools.PostDebugMessage(string.Format( Tools.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;
} }
} }
   
public override void LoadConfig() public override void LoadConfig()
{ {
base.LoadConfig(); base.LoadConfig();
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module.LoadConfig(); module.LoadConfig();
} }
} }
   
public void SaveConfig() public void SaveConfig()
{ {
var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core>(); var config = KSP.IO.PluginConfiguration.CreateForType<VOID_Core>();
config.load(); config.load();
   
this._SaveToConfig(config); this._SaveToConfig(config);
   
foreach (IVOID_Module module in this.Modules) foreach (IVOID_Module module in this.Modules)
{ {
module._SaveToConfig(config); module._SaveToConfig(config);
} }
   
config.save(); config.save();
   
this.configDirty = false; this.configDirty = false;
} }
} }
} }