Added calls to UpdateModSettings in relevant places
Added calls to UpdateModSettings in relevant places

1.0.14.0, 1.0.14.1, 28-12-2014
  Fixed: Missing texture on the ER-7500 model.
   
  1.0.14.0, 28-12-2014
  Added: Career mode that limits the Flight Engineer by:
  - Requiring an Engineer Kerbal of any level, or placement of an Engineer Chip or ER-7500 part.
  - Tracking station level 3 enables Flight Engineer everywhere.
   
  Added: New readouts to the orbital category:
  - Mean Anomaly at Epoc
   
  Added: New readouts to the miscellaneous category:
  - System Time
   
Added: Editor Overlay Tab's X position is now changable in the BuildOverlay.xml settings file. Added: Editor Overlay Tab's X position is now changable in the BuildOverlay.xml settings file.
  Changed: Editor Overlay Tabs start position moved over as to not overlap the parts menu.
  Fixed: Bug where STAGE_PRIORITY_FLOW resources would not be corrently disabled/enabled.
  Fixed: Issue with the formatting large Mass and Cost values.
  Fixed: Error when loading the Engineer7500 part model.
   
1.0.13.1, 16-12-2014 1.0.13.1, 16-12-2014
Fixed: Issue with manoeuvre node readouts and low tier tracking station. Fixed: Issue with manoeuvre node readouts and low tier tracking station.
   
1.0.13.0, 16-12-2014 1.0.13.0, 16-12-2014
Updated for KSP version 0.90 Updated for KSP version 0.90
   
Added: New readouts to the vessel category: Added: New readouts to the vessel category:
- Heading Rate - Heading Rate
- Pitch Rate - Pitch Rate
- Roll Rate - Roll Rate
   
Changed: Simulation to look for fuel lines that use CModuleFuelLine module. Changed: Simulation to look for fuel lines that use CModuleFuelLine module.
Fixed: Editor Overlay now loads the saved visibility value properly. Fixed: Editor Overlay now loads the saved visibility value properly.
Fixed: Altitude (Terrain) will no longer give a reading below sea level. Fixed: Altitude (Terrain) will no longer give a reading below sea level.
Fixed: Suicide burn now uses radar altitude that clamps to sea level. Fixed: Suicide burn now uses radar altitude that clamps to sea level.
   
1.0.12.0, 01-12-2014 1.0.12.0, 01-12-2014
Added: Setting in Build Engineer to enable/disable vectored thrust calculations. Added: Setting in Build Engineer to enable/disable vectored thrust calculations.
Added: Thrust torque field in Build Engineer (courtesy of mic_e). Added: Thrust torque field in Build Engineer (courtesy of mic_e).
Added: New readouts to the vessel category: Added: New readouts to the vessel category:
- Thrust Offset Angle (courtesy of mic_e) - Thrust Offset Angle (courtesy of mic_e)
- Thrust Torque (courtesy of mic_e) - Thrust Torque (courtesy of mic_e)
- Part Count: stage/total - Part Count: stage/total
- Heading - Heading
- Pitch - Pitch
- Roll - Roll
   
Added: New readouts to the surface category: Added: New readouts to the surface category:
- Situation - Situation
   
Added: New readouts to the miscellaneous category: Added: New readouts to the miscellaneous category:
- Vectored Thrust Toggle - Vectored Thrust Toggle
   
Fixed: The category selection within the section editors now do not always reset back to 'Orbital'. Fixed: The category selection within the section editors now do not always reset back to 'Orbital'.
Fixed: Issue where the vessel simulation can sometimes permanently freeze. Fixed: Issue where the vessel simulation can sometimes permanently freeze.
Fixed: Issue where the vessel simulation would not show updates when the delay was set lower than the frame rate. Fixed: Issue where the vessel simulation would not show updates when the delay was set lower than the frame rate.
   
1.0.11.3, 11-11-2014 1.0.11.3, 11-11-2014
Changed: Gravity measurements for Isp to 9.82. Changed: Gravity measurements for Isp to 9.82.
   
1.0.11.2, 10-11-2014 1.0.11.2, 10-11-2014
Changed: Gravity measurements for Isp calculations from 9.81 to 9.8066 for accuracy. Changed: Gravity measurements for Isp calculations from 9.81 to 9.8066 for accuracy.
Changed: Manoeuvre node burn times are now more accurate. Changed: Manoeuvre node burn times are now more accurate.
Fixed: Bug in the manoeuvre node burn time calculations where it was not averaging acceleration correctly. Fixed: Bug in the manoeuvre node burn time calculations where it was not averaging acceleration correctly.
   
1.0.11.1, 07-11-2014 1.0.11.1, 07-11-2014
Changed: Build Engineer now shows stage part count as well as total. Changed: Build Engineer now shows stage part count as well as total.
Changed: Build Overlay Vessel tab data: Changed: Build Overlay Vessel tab data:
DeltaV: stage / total DeltaV: stage / total
Mass: stage / total Mass: stage / total
TWR: start (max) <- shows for bottom stage only. TWR: start (max) <- shows for bottom stage only.
Parts: stage / total Parts: stage / total
   
Fixed: Issue with the vessel tab vanishing from the editor. Fixed: Issue with the vessel tab vanishing from the editor.
   
1.0.11.0, 06-11-2014 1.0.11.0, 06-11-2014
Added: New readouts to the orbital category: Added: New readouts to the orbital category:
- Current SOI - Current SOI
- Manoeuvre Node DeltaV (Prograde) - Manoeuvre Node DeltaV (Prograde)
- Manoeuvre Node DeltaV (Normal) - Manoeuvre Node DeltaV (Normal)
- Manoeuvre Node DeltaV (Radial) - Manoeuvre Node DeltaV (Radial)
- Manoeuvre Node DeltaV (Total) - Manoeuvre Node DeltaV (Total)
- Manoeuvre Node Burn Time - Manoeuvre Node Burn Time
- Manoeuvre Node Half Burn Time - Manoeuvre Node Half Burn Time
- Manoeuvre Node Angle to Prograde - Manoeuvre Node Angle to Prograde
- Manoeuvre Node Angle to Retrograde - Manoeuvre Node Angle to Retrograde
- Time to Manoeuvre Node - Time to Manoeuvre Node
- Time to Manoeuvre Burn - Time to Manoeuvre Burn
   
Added: Readout help strings by ClassyJakey. Added: Readout help strings by ClassyJakey.
   
Fixed: Issue with separators in HUDs. Fixed: Issue with separators in HUDs.
Fixed: Issue with HUDs with backgrounds that have no displayed lines. Fixed: Issue with HUDs with backgrounds that have no displayed lines.
   
Padishar's Fixes: Padishar's Fixes:
Fixed: Issue with multicouplers when attached to parent by bottom node. Fixed: Issue with multicouplers when attached to parent by bottom node.
Fixed: Issue with sepratrons on solid rocket boosters. Fixed: Issue with sepratrons on solid rocket boosters.
   
1.0.10.0, 19-10-2014 1.0.10.0, 19-10-2014
UPDATE NOTICE: If you are updating from a previous version of Kerbal Engineer 1.0, please UPDATE NOTICE: If you are updating from a previous version of Kerbal Engineer 1.0, please
delete the 'Settings/SectionLibrary.xml' file, or remove the old install first. This will delete the 'Settings/SectionLibrary.xml' file, or remove the old install first. This will
reset the Flight Engineer sections to their default values and enable the new HUD functionality. reset the Flight Engineer sections to their default values and enable the new HUD functionality.
   
Added: New reaouts to the vessel category: Added: New reaouts to the vessel category:
- Suicide Burn Altitude (height above terrain to start burn) - Suicide Burn Altitude (height above terrain to start burn)
- Suicide Burn Distance (distance to suicide burn altitude) - Suicide Burn Distance (distance to suicide burn altitude)
- Suicide Burn DeltaV (velocity change required to zero vertical speed) - Suicide Burn DeltaV (velocity change required to zero vertical speed)
*** F5 for safety and use at your own risk! *** *** F5 for safety and use at your own risk! ***
   
Added: HUD type sections to the Flight Engineer. Added: HUD type sections to the Flight Engineer.
Added: HUD sections can have a smoked background for easy visibility. Added: HUD sections can have a smoked background for easy visibility.
Added: 'Switch to Target' button on the Target Selector readout. Added: 'Switch to Target' button on the Target Selector readout.
Changed: The default installed readouts to reduce new user brain melt. Changed: The default installed readouts to reduce new user brain melt.
Fixed: Flight Engineer not saving its hidden state. Fixed: Flight Engineer not saving its hidden state.
Fixed: Bug in the phase angle calculations. Fixed: Bug in the phase angle calculations.
Fixed: Bug where the Build Engineer would stay locked after hiding with the shortcut key. Fixed: Bug where the Build Engineer would stay locked after hiding with the shortcut key.
   
1.0.9.3, 08-10-2014 1.0.9.3, 08-10-2014
Added: Title of the build engineer in compact mode now shows if you are using atmospheric data. Added: Title of the build engineer in compact mode now shows if you are using atmospheric data.
Added: New readout to the surface category: Added: New readout to the surface category:
- Vertical Acceleration - Vertical Acceleration
- Horizontal Acceleration - Horizontal Acceleration
Changed: Atmospheric efficiency readout now shows as a percentage. Changed: Atmospheric efficiency readout now shows as a percentage.
Changed: Atmospheric settings (pressure/velocity) in the editor condensed onto a single line. Changed: Atmospheric settings (pressure/velocity) in the editor condensed onto a single line.
Fixed: Bug where the overlays in the editor would stay open outside of parts screen. Fixed: Bug where the overlays in the editor would stay open outside of parts screen.
   
1.0.9.2, 07-10-2014 1.0.9.2, 07-10-2014
Updated for KSP v0.25.0 Updated for KSP v0.25.0
Changed: Prettyfied Latitude and Longitude readouts. Changed: Prettyfied Latitude and Longitude readouts.
Changed: ModuleLandingGear now uses the physical significance flag. Changed: ModuleLandingGear now uses the physical significance flag.
Changed: Updated MiniAVC to 1.0.2.4. Changed: Updated MiniAVC to 1.0.2.4.
   
1.0.9.1, 17-09-2014 1.0.9.1, 17-09-2014
Fixed: Part size bug caused by TweakScale's cost calculator. Fixed: Part size bug caused by TweakScale's cost calculator.
   
1.0.9.0, 15-09-2014 1.0.9.0, 15-09-2014
Added: Build Engineer now also implements the '\' backslash show/hide shortcut. Added: Build Engineer now also implements the '\' backslash show/hide shortcut.
Added: New readouts to the vessel category: Added: New readouts to the vessel category:
- Current Stage DeltaV - Current Stage DeltaV
- Surface Thrust to Weight Ratio - Surface Thrust to Weight Ratio
   
Added: New editor overlay system. Added: New editor overlay system.
- Sleeker design. - Sleeker design.
- Hover over part information options: - Hover over part information options:
- Name only - Name only
- Middle click to show - Middle click to show
- Always show - Always show
- Slide out overlay displays: - Slide out overlay displays:
- Vessel information - Vessel information
- Resources list - Resources list
   
Fixed: Cost calculation now works with mods implementing IPartCostModifier. Fixed: Cost calculation now works with mods implementing IPartCostModifier.
   
1.0.8.1, 06-09-2014 1.0.8.1, 06-09-2014
Fixed: Bug which caused rendezvous readouts to freeze the game or show all zeros. Fixed: Bug which caused rendezvous readouts to freeze the game or show all zeros.
   
1.0.8.0, 06-09-2014 1.0.8.0, 06-09-2014
Added: New readouts to the vessel category: Added: New readouts to the vessel category:
- Intake Air (Usage) - Intake Air (Usage)
   
Added: New readouts to the rendezvous category: Added: New readouts to the rendezvous category:
- Relative Velocity - Relative Velocity
- Relative Speed - Relative Speed
   
Fixed: An issue where deltaV would not be calculated whilst flying. Fixed: An issue where deltaV would not be calculated whilst flying.
Fixed: NullRef whilst loading the in flight Action Menu. Fixed: NullRef whilst loading the in flight Action Menu.
   
1.0.7.1, 02-09-2014 1.0.7.1, 02-09-2014
Changed: Reversed Intake Air readout from 'S/D' to 'D/S' for easier reading. Changed: Reversed Intake Air readout from 'S/D' to 'D/S' for easier reading.
Changed: Increased Intake Air readout precision to 4 decimal places. Changed: Increased Intake Air readout precision to 4 decimal places.
Fixed: Issue where Intake Air supply was not representative of total supply. Fixed: Issue where Intake Air supply was not representative of total supply.
Fixed: Bug where actual thrust does not reset to zero on deactivated engines. Fixed: Bug where actual thrust does not reset to zero on deactivated engines.
Fixed: Thrust now scales with velocity for atmospheric engines. (Padishar's fix) Fixed: Thrust now scales with velocity for atmospheric engines. (Padishar's fix)
   
1.0.7.0, 01-09-2014 1.0.7.0, 01-09-2014
Added: Part count information to the Build Engineer. Added: Part count information to the Build Engineer.
Added: Reset button to the G-Force readout. Added: Reset button to the G-Force readout.
Added: Preset system to the Flight Engineer. Added: Preset system to the Flight Engineer.
Added: New stock presets: Added: New stock presets:
- Orbital - Orbital
- Surface - Surface
- Vessel - Vessel
- Rendezvous - Rendezvous
   
Added: New readouts to the orbital category: Added: New readouts to the orbital category:
- True Anomaly - True Anomaly
- Eccentric Anomaly - Eccentric Anomaly
- Mean Anomaly - Mean Anomaly
- Argument of Periapsis - Argument of Periapsis
- Angle to Prograde - Angle to Prograde
- Angle to Retrograde - Angle to Retrograde
   
Added: New readouts to the vessel category: Added: New readouts to the vessel category:
- Intake Air (Demand) - Intake Air (Demand)
- Intake Air (Supply) - Intake Air (Supply)
- Intake Air (Supply/Demand) - Intake Air (Supply/Demand)
   
Added: New readouts to the rendezvous category. Added: New readouts to the rendezvous category.
- Semi-major Axis - Semi-major Axis
- Semi-minor Axis - Semi-minor Axis
   
Added: Time formatter which can show time as referenced by any celestial body. Added: Time formatter which can show time as referenced by any celestial body.
Added: New readouts to the miscellaneous category: Added: New readouts to the miscellaneous category:
- Time Reference Adjuster - Time Reference Adjuster
   
Changed: Moved Sim Delay readout into the Miscellaneous category. Changed: Moved Sim Delay readout into the Miscellaneous category.
Changed: Updated MiniAVC to v1.0.2.3. Changed: Updated MiniAVC to v1.0.2.3.
Fixed: Issues with large value wrap around in the Flight Engineer. Fixed: Issues with large value wrap around in the Flight Engineer.
Fixed: Bug in the phase angle calculation. Fixed: Bug in the phase angle calculation.
   
1.0.6.0, 23-08-2014 1.0.6.0, 23-08-2014
Added: Time and Angle to equatorial ascending/descending nodes in the orbital display. Added: Time and Angle to equatorial ascending/descending nodes in the orbital display.
Added: Time and Angle to relative ascending/descending nodes in the rendezvous display. Added: Time and Angle to relative ascending/descending nodes in the rendezvous display.
Added: Overlay tooltip information delay adjustment slider to the Build Engineer settings. Added: Overlay tooltip information delay adjustment slider to the Build Engineer settings.
Added: Ability to rename the stock displays in the Flight Engineer. Added: Ability to rename the stock displays in the Flight Engineer.
Changed: Build Engineer is now hidden when not in parts view. Changed: Build Engineer is now hidden when not in parts view.
Changed: Custom display panels will only show in the control bar if an abbreviation is set. Changed: Custom display panels will only show in the control bar if an abbreviation is set.
Changed: Licensing and readme structures are now more verbose to satisfy the new add-on rules. Changed: Licensing and readme structures are now more verbose to satisfy the new add-on rules.
Fixed: Updated MiniAVC to v1.0.2.1 (fixes remote check bug as well as other minor bugs). Fixed: Updated MiniAVC to v1.0.2.1 (fixes remote check bug as well as other minor bugs).
   
1.0.5.0, 13-08-2014 1.0.5.0, 13-08-2014
Added: Acceleration readout to the Vessel category (current / maximum). Added: Acceleration readout to the Vessel category (current / maximum).
Added: Category library system for the Flight Engineer readouts. Added: Category library system for the Flight Engineer readouts.
Added: Drop-down category selection to better support the new system. Added: Drop-down category selection to better support the new system.
Changed: Misc category now called Miscellaneous (this will cause previously added readouts from this category to vanish). Changed: Misc category now called Miscellaneous (this will cause previously added readouts from this category to vanish).
Fixed: Bug with the Build Engineer toolbar button. Fixed: Bug with the Build Engineer toolbar button.
Fixed: Some buggyness when trying to close the bodies drop-down in the Build Engineer via the button. Fixed: Some buggyness when trying to close the bodies drop-down in the Build Engineer via the button.
Fixed: Flight Engineer toolbar menu now hides when hiding the GUI with F2. Fixed: Flight Engineer toolbar menu now hides when hiding the GUI with F2.
Fixed: Flight Engineer toolbar button now disables when in module mode and no engineer is running. Fixed: Flight Engineer toolbar button now disables when in module mode and no engineer is running.
   
1.0.4.0, 12-08-2014 1.0.4.0, 12-08-2014
Added: Better stock toolbar support in the flight engineer. Added: Better stock toolbar support in the flight engineer.
Added: Dynamically generated celestial body library for supporting add-ons that modify the star system. Added: Dynamically generated celestial body library for supporting add-ons that modify the star system.
Changed: Reference bodies are now listed with a nestable menu system. Changed: Reference bodies are now listed with a nestable menu system.
Changed: Extended logging system has been improved. Changed: Extended logging system has been improved.
Changed: Swapped out integrated MiniAVC in place of the official bundle version. Changed: Swapped out integrated MiniAVC in place of the official bundle version.
Changed: Increased general distance precision to 1 decimal place. Changed: Increased general distance precision to 1 decimal place.
Changed: Increased Semi-major/minor axis precision to 3 decimal places. Changed: Increased Semi-major/minor axis precision to 3 decimal places.
Fixed: Impact altitude was mistakenly formatted as an angle, it is now formatted correctly as a distance. Fixed: Impact altitude was mistakenly formatted as an angle, it is now formatted correctly as a distance.
   
1.0.3.0, 30-07-2014 1.0.3.0, 30-07-2014
Added: Integrated KSP-AVC support with MiniAVC. Added: Integrated KSP-AVC support with MiniAVC.
Added: Setting to change the simulation delay in the Build Engineer. Added: Setting to change the simulation delay in the Build Engineer.
Added: Setting to enable and disable the build overlay system. Added: Setting to enable and disable the build overlay system.
Added: Burn time to Delta-V readouts. Added: Burn time to Delta-V readouts.
Added: Atmospheric readouts fully support FAR. Added: Atmospheric readouts fully support FAR.
Added: Atmospheric readouts are disabled with NEAR. Added: Atmospheric readouts are disabled with NEAR.
Changed: Force formatting inversely scales decimal precision with value. Changed: Force formatting inversely scales decimal precision with value.
Fixed: Flickering in VAB and Vessel display. Fixed: Flickering in VAB and Vessel display.
Fixed: Bug saving the GUI display size. Fixed: Bug saving the GUI display size.
   
1.0.2.0, 27-07-2014 1.0.2.0, 27-07-2014
Added: Separator readout module under Misc in the Flight Engineer. Added: Separator readout module under Misc in the Flight Engineer.
Added: Adjustable GUI display size. Added: Adjustable GUI display size.
Added: Display size can be adjusted in the Build Engineer settings. Added: Display size can be adjusted in the Build Engineer settings.
Added: Misc readout for adjusting display size in the Flight Engineer. Added: Misc readout for adjusting display size in the Flight Engineer.
Changed: The rendezvous readout for the target's Orbital Period has higher precision. Changed: The rendezvous readout for the target's Orbital Period has higher precision.
Fixed: White toolbar icon by manually importing the texture if it cannot be found in the game database. Fixed: White toolbar icon by manually importing the texture if it cannot be found in the game database.
Fixed: Engines that have a minimum thrust are now calculated properly. (Thanks to nosscire.) Fixed: Engines that have a minimum thrust are now calculated properly. (Thanks to nosscire.)
Fixed: Compact collapse mode is now saved in the Build Engineer. Fixed: Compact collapse mode is now saved in the Build Engineer.
   
1.0.1.0, 26-07-2014 1.0.1.0, 26-07-2014
Added: Part-less Flight Engineer. Added: Part-less Flight Engineer.
Added: Ability to collapse the Build Engineer into compact mode from left or right. Added: Ability to collapse the Build Engineer into compact mode from left or right.
Added: Settings in Build Engineer for compact collapse mode and partless/module Flight Engineer. Added: Settings in Build Engineer for compact collapse mode and partless/module Flight Engineer.
Added: Biome, Impact Biome and Slope readouts. Added: Biome, Impact Biome and Slope readouts.
Added: Extra logging and exception handling. Added: Extra logging and exception handling.
Added: The original Engineer Chip part. Added: The original Engineer Chip part.
Added: "Show Engineer" toggle on the Flight Engineer toolbar. Added: "Show Engineer" toggle on the Flight Engineer toolbar.
Changed: Extended logging system now also writes to the standard KSP logs. Changed: Extended logging system now also writes to the standard KSP logs.
Changed: Extended logging saves next to the .dll file. Changed: Extended logging saves next to the .dll file.
Changed: ER7500 part has no physical significance. Changed: ER7500 part has no physical significance.
Fixed: ActionMenu and DisplayStack destruction bug. Fixed: ActionMenu and DisplayStack destruction bug.
   
1.0.0.1, 24-07-2014 1.0.0.1, 24-07-2014
Added: Stock toolbar support in the Flight Engineer. Added: Stock toolbar support in the Flight Engineer.
Changed: Orbital Period has higher precision. Changed: Orbital Period has higher precision.
Fixed: Various NullRefs in editor window and overlay. Fixed: Various NullRefs in editor window and overlay.
1.0.0.0, 24-07-2014 1.0.0.0, 24-07-2014
Initial release for public testing. Initial release for public testing.
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
namespace KerbalEngineer.Editor namespace KerbalEngineer.Editor
{ {
#region Using Directives #region Using Directives
   
using System; using System;
using System.Linq; using System.Linq;
using Extensions; using Extensions;
using Flight; using Flight;
using Helpers; using Helpers;
using Settings; using Settings;
using UIControls; using UIControls;
using UnityEngine; using UnityEngine;
using VesselSimulator; using VesselSimulator;
   
#endregion #endregion
   
[KSPAddon(KSPAddon.Startup.EditorAny, false)] [KSPAddon(KSPAddon.Startup.EditorAny, false)]
public class BuildAdvanced : MonoBehaviour public class BuildAdvanced : MonoBehaviour
{ {
#region Fields #region Fields
   
private GUIStyle areaSettingStyle; private GUIStyle areaSettingStyle;
private GUIStyle areaStyle; private GUIStyle areaStyle;
private float atmosphericPercentage = 1.0f; private float atmosphericPercentage = 1.0f;
private float atmosphericVelocity; private float atmosphericVelocity;
private GUIStyle bodiesButtonActiveStyle; private GUIStyle bodiesButtonActiveStyle;
private GUIStyle bodiesButtonStyle; private GUIStyle bodiesButtonStyle;
private DropDown bodiesList; private DropDown bodiesList;
private Rect bodiesListPosition; private Rect bodiesListPosition;
private GUIStyle buttonStyle; private GUIStyle buttonStyle;
private int compactCheck; private int compactCheck;
private bool compactCollapseRight; private bool compactCollapseRight;
private bool compactMode; private bool compactMode;
private float compactRight; private float compactRight;
private bool hasChanged; private bool hasChanged;
private GUIStyle infoStyle; private GUIStyle infoStyle;
private bool isEditorLocked; private bool isEditorLocked;
private int numberOfStages; private int numberOfStages;
private Rect position = new Rect(265.0f, 45.0f, 0, 0); private Rect position = new Rect(265.0f, 45.0f, 0, 0);
private GUIStyle settingAtmoStyle; private GUIStyle settingAtmoStyle;
private GUIStyle settingStyle; private GUIStyle settingStyle;
private bool showAllStages; private bool showAllStages;
private bool showAtmosphericDetails; private bool showAtmosphericDetails;
private bool showSettings; private bool showSettings;
private Stage[] stages; private Stage[] stages;
private GUIStyle titleStyle; private GUIStyle titleStyle;
private bool visible = true; private bool visible = true;
private GUIStyle windowStyle; private GUIStyle windowStyle;
   
#endregion #endregion
   
#region Properties #region Properties
   
/// <summary> /// <summary>
/// Gets the current instance if started or returns null. /// Gets the current instance if started or returns null.
/// </summary> /// </summary>
public static BuildAdvanced Instance { get; private set; } public static BuildAdvanced Instance { get; private set; }
   
/// <summary> /// <summary>
/// Gets and sets whether to show in compact mode. /// Gets and sets whether to show in compact mode.
/// </summary> /// </summary>
public bool CompactMode public bool CompactMode
{ {
get { return this.compactMode; } get { return this.compactMode; }
set { this.compactMode = value; } set { this.compactMode = value; }
} }
   
/// <summary> /// <summary>
/// Gets and sets whether to show all stages. /// Gets and sets whether to show all stages.
/// </summary> /// </summary>
public bool ShowAllStages public bool ShowAllStages
{ {
get { return this.showAllStages; } get { return this.showAllStages; }
set { this.showAllStages = value; } set { this.showAllStages = value; }
} }
   
/// <summary> /// <summary>
/// Gets and sets whether to use atmospheric details. /// Gets and sets whether to use atmospheric details.
/// </summary> /// </summary>
public bool ShowAtmosphericDetails public bool ShowAtmosphericDetails
{ {
get { return this.showAtmosphericDetails; } get { return this.showAtmosphericDetails; }
set { this.showAtmosphericDetails = value; } set { this.showAtmosphericDetails = value; }
} }
   
/// <summary> /// <summary>
/// Gets and sets whether to show the settings display. /// Gets and sets whether to show the settings display.
/// </summary> /// </summary>
public bool ShowSettings public bool ShowSettings
{ {
get { return this.showSettings; } get { return this.showSettings; }
set { this.showSettings = value; } set { this.showSettings = value; }
} }
   
/// <summary> /// <summary>
/// Gets and sets whether the display is enabled. /// Gets and sets whether the display is enabled.
/// </summary> /// </summary>
public bool Visible public bool Visible
{ {
get { return this.visible; } get { return this.visible; }
set { this.visible = value; } set { this.visible = value; }
} }
   
#endregion #endregion
   
#region Methods #region Methods
   
protected void Awake() protected void Awake()
{ {
try try
{ {
Instance = this; Instance = this;
this.bodiesList = this.gameObject.AddComponent<DropDown>(); this.bodiesList = this.gameObject.AddComponent<DropDown>();
this.bodiesList.DrawCallback = this.DrawBodiesList; this.bodiesList.DrawCallback = this.DrawBodiesList;
this.Load(); this.Load();
   
  SimManager.UpdateModSettings();
SimManager.OnReady -= this.GetStageInfo; SimManager.OnReady -= this.GetStageInfo;
SimManager.OnReady += this.GetStageInfo; SimManager.OnReady += this.GetStageInfo;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Saves the settings when this object is destroyed. /// Saves the settings when this object is destroyed.
/// </summary> /// </summary>
protected void OnDestroy() protected void OnDestroy()
{ {
try try
{ {
var handler = new SettingHandler(); var handler = new SettingHandler();
handler.Set("visible", this.visible); handler.Set("visible", this.visible);
handler.Set("windowPositionX", this.position.x); handler.Set("windowPositionX", this.position.x);
handler.Set("windowPositionY", this.position.y); handler.Set("windowPositionY", this.position.y);
handler.Set("compactMode", this.compactMode); handler.Set("compactMode", this.compactMode);
handler.Set("compactCollapseRight", this.compactCollapseRight); handler.Set("compactCollapseRight", this.compactCollapseRight);
handler.Set("showAllStages", this.showAllStages); handler.Set("showAllStages", this.showAllStages);
handler.Set("showAtmosphericDetails", this.showAtmosphericDetails); handler.Set("showAtmosphericDetails", this.showAtmosphericDetails);
handler.Set("showSettings", this.showSettings); handler.Set("showSettings", this.showSettings);
handler.Set("selectedBodyName", CelestialBodies.SelectedBody.Name); handler.Set("selectedBodyName", CelestialBodies.SelectedBody.Name);
handler.Save("BuildAdvanced.xml"); handler.Save("BuildAdvanced.xml");
GuiDisplaySize.OnSizeChanged -= this.OnSizeChanged; GuiDisplaySize.OnSizeChanged -= this.OnSizeChanged;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
private void GetStageInfo()  
{  
this.stages = SimManager.Stages;  
}  
   
protected void OnGUI() protected void OnGUI()
{ {
try try
{ {
if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts) if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
{ {
return; return;
} }
   
if (this.stages == null) if (this.stages == null)
{ {
return; return;
} }
   
// Change the window title based on whether in compact mode or not. // Change the window title based on whether in compact mode or not.
var title = !this.compactMode ? "KERBAL ENGINEER REDUX " + EngineerGlobals.AssemblyVersion : "K.E.R. " + EngineerGlobals.AssemblyVersion + (this.showAtmosphericDetails ? " (ATMOS.)" : String.Empty); var title = !this.compactMode ? "KERBAL ENGINEER REDUX " + EngineerGlobals.AssemblyVersion : "K.E.R. " + EngineerGlobals.AssemblyVersion + (this.showAtmosphericDetails ? " (ATMOS.)" : String.Empty);
   
// Reset the window size when the staging or something else has changed. // Reset the window size when the staging or something else has changed.
var stageCount = this.stages.Count(stage => this.showAllStages || stage.deltaV > 0); var stageCount = this.stages.Count(stage => this.showAllStages || stage.deltaV > 0);
if (this.hasChanged || stageCount != this.numberOfStages) if (this.hasChanged || stageCount != this.numberOfStages)
{ {
this.hasChanged = false; this.hasChanged = false;
this.numberOfStages = stageCount; this.numberOfStages = stageCount;
   
this.position.width = 0; this.position.width = 0;
this.position.height = 0; this.position.height = 0;
} }
   
GUI.skin = null; GUI.skin = null;
this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, title, this.windowStyle).ClampToScreen(); this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, title, this.windowStyle).ClampToScreen();
   
if (this.compactCheck > 0 && this.compactCollapseRight) if (this.compactCheck > 0 && this.compactCollapseRight)
{ {
this.position.x = this.compactRight - this.position.width; this.position.x = this.compactRight - this.position.width;
this.compactCheck--; this.compactCheck--;
} }
else if (this.compactCheck > 0) else if (this.compactCheck > 0)
{ {
this.compactCheck = 0; this.compactCheck = 0;
} }
   
// Check editor lock to manage click-through. // Check editor lock to manage click-through.
this.CheckEditorLock(); this.CheckEditorLock();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
protected void Start() protected void Start()
{ {
try try
{ {
this.InitialiseStyles(); this.InitialiseStyles();
GuiDisplaySize.OnSizeChanged += this.OnSizeChanged; GuiDisplaySize.OnSizeChanged += this.OnSizeChanged;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
protected void Update() protected void Update()
{ {
try try
{ {
if (Input.GetKeyDown(KeyBinder.EditorShowHide)) if (Input.GetKeyDown(KeyBinder.EditorShowHide))
{ {
this.visible = !this.visible; this.visible = !this.visible;
if (!this.visible) if (!this.visible)
{ {
this.EditorLock(false); this.EditorLock(false);
} }
} }
   
if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0) if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0)
{ {
this.bodiesList.enabled = false; this.bodiesList.enabled = false;
return; return;
} }
   
// Configure the simulation parameters based on the selected reference body. // Configure the simulation parameters based on the selected reference body.
SimManager.Gravity = CelestialBodies.SelectedBody.Gravity; SimManager.Gravity = CelestialBodies.SelectedBody.Gravity;
   
if (this.showAtmosphericDetails) if (this.showAtmosphericDetails)
{ {
SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01d * this.atmosphericPercentage; SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01d * this.atmosphericPercentage;
} }
else else
{ {
SimManager.Atmosphere = 0; SimManager.Atmosphere = 0;
} }
   
SimManager.Velocity = this.atmosphericVelocity; SimManager.Velocity = this.atmosphericVelocity;
   
SimManager.RequestSimulation(); SimManager.RequestSimulation();
SimManager.TryStartSimulation(); SimManager.TryStartSimulation();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex, "BuildAdvanced->Update"); Logger.Exception(ex, "BuildAdvanced->Update");
} }
} }
   
/// <summary> /// <summary>
/// Checks whether the editor should be locked to stop click-through. /// Checks whether the editor should be locked to stop click-through.
/// </summary> /// </summary>
private void CheckEditorLock() private void CheckEditorLock()
{ {
if ((this.position.MouseIsOver() || this.bodiesList.Position.MouseIsOver()) && !this.isEditorLocked) if ((this.position.MouseIsOver() || this.bodiesList.Position.MouseIsOver()) && !this.isEditorLocked)
{ {
this.EditorLock(true); this.EditorLock(true);
} }
else if (!this.position.MouseIsOver() && !this.bodiesList.Position.MouseIsOver() && this.isEditorLocked) else if (!this.position.MouseIsOver() && !this.bodiesList.Position.MouseIsOver() && this.isEditorLocked)
{ {
this.EditorLock(false); this.EditorLock(false);
} }
} }
   
/// <summary> /// <summary>
/// Draws the atmospheric settings. /// Draws the atmospheric settings.
/// </summary> /// </summary>
private void DrawAtmosphericDetails() private void DrawAtmosphericDetails()
{ {
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.BeginVertical(); GUILayout.BeginVertical();
GUILayout.Label("Pressure: " + (this.atmosphericPercentage * 100.0f).ToString("F1") + "%", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset)); GUILayout.Label("Pressure: " + (this.atmosphericPercentage * 100.0f).ToString("F1") + "%", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
GUI.skin = HighLogic.Skin; GUI.skin = HighLogic.Skin;
this.atmosphericPercentage = GUILayout.HorizontalSlider(this.atmosphericPercentage, 0, 1.0f); this.atmosphericPercentage = GUILayout.HorizontalSlider(this.atmosphericPercentage, 0, 1.0f);
GUI.skin = null; GUI.skin = null;
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUILayout.Space(5.0f); GUILayout.Space(5.0f);
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
GUILayout.Label("Velocity: " + this.atmosphericVelocity.ToString("F1") + "m/s", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset)); GUILayout.Label("Velocity: " + this.atmosphericVelocity.ToString("F1") + "m/s", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset));
GUI.skin = HighLogic.Skin; GUI.skin = HighLogic.Skin;
this.atmosphericVelocity = GUILayout.HorizontalSlider(this.atmosphericVelocity, 0, 2500f); this.atmosphericVelocity = GUILayout.HorizontalSlider(this.atmosphericVelocity, 0, 2500f);
GUI.skin = null; GUI.skin = null;
GUILayout.EndVertical(); GUILayout.EndVertical();
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
private void DrawBodiesList() private void DrawBodiesList()
{ {
if (CelestialBodies.SystemBody == CelestialBodies.SelectedBody) if (CelestialBodies.SystemBody == CelestialBodies.SelectedBody)
{ {
this.DrawBody(CelestialBodies.SystemBody); this.DrawBody(CelestialBodies.SystemBody);
} }
else else
{ {
foreach (var body in CelestialBodies.SystemBody.Children) foreach (var body in CelestialBodies.SystemBody.Children)
{ {
this.DrawBody(body); this.DrawBody(body);
} }
} }
} }
   
private void DrawBody(CelestialBodies.BodyInfo bodyInfo, int depth = 0) private void DrawBody(CelestialBodies.BodyInfo bodyInfo, int depth = 0)
{ {
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.Space(20.0f * depth); GUILayout.Space(20.0f * depth);
if (GUILayout.Button(bodyInfo.Children.Count > 0 ? bodyInfo.Name + " [" + bodyInfo.Children.Count + "]" : bodyInfo.Name, bodyInfo.Selected && bodyInfo.SelectedDepth == 0 ? this.bodiesButtonActiveStyle : this.bodiesButtonStyle)) if (GUILayout.Button(bodyInfo.Children.Count > 0 ? bodyInfo.Name + " [" + bodyInfo.Children.Count + "]" : bodyInfo.Name, bodyInfo.Selected && bodyInfo.SelectedDepth == 0 ? this.bodiesButtonActiveStyle : this.bodiesButtonStyle))
{ {
CelestialBodies.SetSelectedBody(bodyInfo.Name); CelestialBodies.SetSelectedBody(bodyInfo.Name);
this.bodiesList.Resize = true; this.bodiesList.Resize = true;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
if (bodyInfo.Selected) if (bodyInfo.Selected)
{ {
foreach (var body in bodyInfo.Children) foreach (var body in bodyInfo.Children)
{ {
this.DrawBody(body, depth + 1); this.DrawBody(body, depth + 1);
} }
} }
} }
   
/// <summary> /// <summary>
/// Draws the burn time column. /// Draws the burn time column.
/// </summary> /// </summary>
private void DrawBurnTime() private void DrawBurnTime()
{ {
GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset)); GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
GUILayout.Label("BURN", this.titleStyle); GUILayout.Label("BURN", this.titleStyle);
foreach (var stage in this.stages) foreach (var stage in this.stages)
{ {
if (this.showAllStages || stage.deltaV > 0) if (this.showAllStages || stage.deltaV > 0)
{ {
GUILayout.Label(TimeFormatter.ConvertToString(stage.time), this.infoStyle); GUILayout.Label(TimeFormatter.ConvertToString(stage.time), this.infoStyle);
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
/// <summary> /// <summary>
/// Draws the cost column. /// Draws the cost column.
/// </summary> /// </summary>
private void DrawCost() private void DrawCost()
{ {
GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset)); GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset));
GUILayout.Label("COST", this.titleStyle); GUILayout.Label("COST", this.titleStyle);
foreach (var stage in this.stages) foreach (var stage in this.stages)
{ {
if (this.showAllStages || stage.deltaV > 0) if (this.showAllStages || stage.deltaV > 0)
{ {
GUILayout.Label(Units.Concat(stage.cost, stage.totalCost), this.infoStyle); GUILayout.Label(Units.Cost(stage.cost, stage.totalCost), this.infoStyle);
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
/// <summary> /// <summary>
/// Draws the deltaV column. /// Draws the deltaV column.
/// </summary> /// </summary>
private void DrawDeltaV() private void DrawDeltaV()
{ {
GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset)); GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset));
GUILayout.Label("DELTA-V", this.titleStyle); GUILayout.Label("DELTA-V", this.titleStyle);
foreach (var stage in this.stages) foreach (var stage in this.stages)
{ {
if (this.showAllStages || stage.deltaV > 0) if (this.showAllStages || stage.deltaV > 0)
{ {
GUILayout.Label(stage.deltaV.ToString("N0") + " / " + stage.inverseTotalDeltaV.ToString("N0") + "m/s", this.infoStyle); GUILayout.Label(stage.deltaV.ToString("N0") + " / " + stage.inverseTotalDeltaV.ToString("N0") + "m/s", this.infoStyle);
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
/// <summary> /// <summary>
/// Draws the specific impluse column. /// Draws the specific impluse column.
/// </summary> /// </summary>
private void DrawIsp() private void DrawIsp()
{ {
GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset)); GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
GUILayout.Label("ISP", this.titleStyle); GUILayout.Label("ISP", this.titleStyle);
foreach (var stage in this.stages) foreach (var stage in this.stages)
{ {
if (this.showAllStages || stage.deltaV > 0) if (this.showAllStages || stage.deltaV > 0)
{ {
GUILayout.Label(stage.isp.ToString("F1") + "s", this.infoStyle); GUILayout.Label(stage.isp.ToString("F1") + "s", this.infoStyle);
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
/// <summary> /// <summary>
/// Draws the mass column. /// Draws the mass column.
/// </summary> /// </summary>
private void DrawMass() private void DrawMass()
{ {
GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset)); GUILayout.BeginVertical(GUILayout.Width(110.0f * GuiDisplaySize.Offset));
GUILayout.Label("MASS", this.titleStyle); GUILayout.Label("MASS", this.titleStyle);
foreach (var stage in this.stages) foreach (var stage in this.stages)
{ {
if (this.showAllStages || stage.deltaV > 0) if (this.showAllStages || stage.deltaV > 0)
{ {
GUILayout.Label(Units.ToMass(stage.mass, stage.totalMass), this.infoStyle); GUILayout.Label(Units.ToMass(stage.mass, stage.totalMass), this.infoStyle);
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
/// <summary> /// <summary>
/// Draws the part count column. /// Draws the part count column.
/// </summary> /// </summary>
private void DrawPartCount() private void DrawPartCount()
{ {
GUILayout.BeginVertical(GUILayout.Width(50.0f * GuiDisplaySize.Offset)); GUILayout.BeginVertical(GUILayout.Width(50.0f * GuiDisplaySize.Offset));
GUILayout.Label("PARTS", this.titleStyle); GUILayout.Label("PARTS", this.titleStyle);
foreach (var stage in this.stages) foreach (var stage in this.stages)
{ {
if (this.showAllStages || stage.deltaV > 0) if (this.showAllStages || stage.deltaV > 0)
{ {
GUILayout.Label(stage.partCount + " / " + stage.totalPartCount, this.infoStyle); GUILayout.Label(stage.partCount + " / " + stage.totalPartCount, this.infoStyle);
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
/// <summary> /// <summary>
/// Draws the settings panel. /// Draws the settings panel.
/// </summary> /// </summary>
private void DrawSettings() private void DrawSettings()
{ {
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.Label("Compact mode collapses to the:", this.settingStyle); GUILayout.Label("Compact mode collapses to the:", this.settingStyle);
this.compactCollapseRight = !GUILayout.Toggle(!this.compactCollapseRight, "LEFT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); this.compactCollapseRight = !GUILayout.Toggle(!this.compactCollapseRight, "LEFT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
this.compactCollapseRight = GUILayout.Toggle(this.compactCollapseRight, "RIGHT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); this.compactCollapseRight = GUILayout.Toggle(this.compactCollapseRight, "RIGHT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.Label("Simulate using vectored thrust values:"); GUILayout.Label("Simulate using vectored thrust values:");
SimManager.vectoredThrust = GUILayout.Toggle(SimManager.vectoredThrust, "ENABLED", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); SimManager.vectoredThrust = GUILayout.Toggle(SimManager.vectoredThrust, "ENABLED", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.Label("Build Engineer Overlay:", this.settingStyle); GUILayout.Label("Build Engineer Overlay:", this.settingStyle);
BuildOverlay.Visible = GUILayout.Toggle(BuildOverlay.Visible, "VISIBLE", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); BuildOverlay.Visible = GUILayout.Toggle(BuildOverlay.Visible, "VISIBLE", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
BuildOverlayPartInfo.NamesOnly = GUILayout.Toggle(BuildOverlayPartInfo.NamesOnly, "NAMES ONLY", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); BuildOverlayPartInfo.NamesOnly = GUILayout.Toggle(BuildOverlayPartInfo.NamesOnly, "NAMES ONLY", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
BuildOverlayPartInfo.ClickToOpen = GUILayout.Toggle(BuildOverlayPartInfo.ClickToOpen, "CLICK TO OPEN", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); BuildOverlayPartInfo.ClickToOpen = GUILayout.Toggle(BuildOverlayPartInfo.ClickToOpen, "CLICK TO OPEN", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.Label("Flight Engineer activation mode:", this.settingStyle); GUILayout.Label("Flight Engineer activation mode:", this.settingStyle);
FlightEngineerPartless.IsPartless = GUILayout.Toggle(FlightEngineerPartless.IsPartless, "PARTLESS", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); FlightEngineerCore.IsCareerMode = GUILayout.Toggle(FlightEngineerCore.IsCareerMode, "CAREER", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
FlightEngineerPartless.IsPartless = !GUILayout.Toggle(!FlightEngineerPartless.IsPartless, "MODULE", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); FlightEngineerCore.IsCareerMode = !GUILayout.Toggle(!FlightEngineerCore.IsCareerMode, "PARTLESS", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
  GUILayout.EndHorizontal();
   
  GUILayout.BeginHorizontal();
  GUILayout.Label("Flight Engineer Career Limitations:", this.settingStyle);
  FlightEngineerCore.IsKerbalLimited = GUILayout.Toggle(FlightEngineerCore.IsKerbalLimited, "KERBAL", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
  FlightEngineerCore.IsTrackingStationLimited = GUILayout.Toggle(FlightEngineerCore.IsTrackingStationLimited, "TRACKING", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.Label("GUI Size: " + GuiDisplaySize.Increment, this.settingStyle); GUILayout.Label("GUI Size: " + GuiDisplaySize.Increment, this.settingStyle);
if (GUILayout.Button("<", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset))) if (GUILayout.Button("<", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
{ {
GuiDisplaySize.Increment--; GuiDisplaySize.Increment--;
} }
if (GUILayout.Button(">", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset))) if (GUILayout.Button(">", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)))
{ {
GuiDisplaySize.Increment++; GuiDisplaySize.Increment++;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.Label("Minimum delay between simulations: " + SimManager.minSimTime.Milliseconds + "ms", this.settingStyle); GUILayout.Label("Minimum delay between simulations: " + SimManager.minSimTime.Milliseconds + "ms", this.settingStyle);
GUI.skin = HighLogic.Skin; GUI.skin = HighLogic.Skin;
SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)GUILayout.HorizontalSlider(SimManager.minSimTime.Milliseconds, 0, 2000.0f)); SimManager.minSimTime = new TimeSpan(0, 0, 0, 0, (int)GUILayout.HorizontalSlider(SimManager.minSimTime.Milliseconds, 0, 2000.0f));
GUI.skin = null; GUI.skin = null;
} }
   
/// <summary> /// <summary>
/// Draws the stage number column. /// Draws the stage number column.
/// </summary> /// </summary>
private void DrawStageNumbers() private void DrawStageNumbers()
{ {
GUILayout.BeginVertical(GUILayout.Width(30.0f * GuiDisplaySize.Offset)); GUILayout.BeginVertical(GUILayout.Width(30.0f * GuiDisplaySize.Offset));
GUILayout.Label(string.Empty, this.titleStyle); GUILayout.Label(string.Empty, this.titleStyle);
foreach (var stage in this.stages) foreach (var stage in this.stages)
{ {
if (this.showAllStages || stage.deltaV > 0) if (this.showAllStages || stage.deltaV > 0)
{ {
GUILayout.Label("S" + stage.number, this.titleStyle); GUILayout.Label("S" + stage.number, this.titleStyle);
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
/// <summary> /// <summary>
/// Draws the thrust column. /// Draws the thrust column.
/// </summary> /// </summary>
private void DrawThrust() private void DrawThrust()
{ {
GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset)); GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
GUILayout.Label("THRUST", this.titleStyle); GUILayout.Label("THRUST", this.titleStyle);
foreach (var stage in this.stages) foreach (var stage in this.stages)
{ {
if (this.showAllStages || stage.deltaV > 0) if (this.showAllStages || stage.deltaV > 0)
{ {
GUILayout.Label(stage.thrust.ToForce(), this.infoStyle); GUILayout.Label(stage.thrust.ToForce(), this.infoStyle);
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
/// <summary> /// <summary>
/// Draws the torque column. /// Draws the torque column.
/// </summary> /// </summary>
private void DrawTorque() private void DrawTorque()
{ {
GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset)); GUILayout.BeginVertical(GUILayout.Width(75.0f * GuiDisplaySize.Offset));
GUILayout.Label("TORQUE", this.titleStyle); GUILayout.Label("TORQUE", this.titleStyle);
foreach (var stage in this.stages) foreach (var stage in this.stages)
{ {
if (this.showAllStages || stage.deltaV > 0) if (this.showAllStages || stage.deltaV > 0)
{ {
GUILayout.Label(stage.maxThrustTorque.ToTorque(), this.infoStyle); GUILayout.Label(stage.maxThrustTorque.ToTorque(), this.infoStyle);
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
/// <summary> /// <summary>
/// Drwas the thrust to weight ratio column. /// Drwas the thrust to weight ratio column.
/// </summary> /// </summary>
private void DrawTwr() private void DrawTwr()
{ {
GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset)); GUILayout.BeginVertical(GUILayout.Width(100.0f * GuiDisplaySize.Offset));
GUILayout.Label("TWR (MAX)", this.titleStyle); GUILayout.Label("TWR (MAX)", this.titleStyle);
foreach (var stage in this.stages) foreach (var stage in this.stages)
{ {
if (this.showAllStages || stage.deltaV > 0) if (this.showAllStages || stage.deltaV > 0)
{ {
GUILayout.Label(stage.thrustToWeight.ToString("F2") + " (" + stage.maxThrustToWeight.ToString("F2") + ")", this.infoStyle); GUILayout.Label(stage.thrustToWeight.ToString("F2") + " (" + stage.maxThrustToWeight.ToString("F2") + ")", this.infoStyle);
} }
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
private void EditorLock(bool state) private void EditorLock(bool state)
{ {
if (state) if (state)
{ {
EditorLogic.fetch.Lock(true, true, true, "KER_BuildAdvanced"); EditorLogic.fetch.Lock(true, true, true, "KER_BuildAdvanced");
BuildOverlayPartInfo.Hidden = true; BuildOverlayPartInfo.Hidden = true;
this.isEditorLocked = true; this.isEditorLocked = true;
} }
else else
{ {
EditorLogic.fetch.Unlock("KER_BuildAdvanced"); EditorLogic.fetch.Unlock("KER_BuildAdvanced");
BuildOverlayPartInfo.Hidden = false; BuildOverlayPartInfo.Hidden = false;
this.isEditorLocked = false; this.isEditorLocked = false;
} }
  }
   
  private void GetStageInfo()
  {
  this.stages = SimManager.Stages;
} }
   
/// <summary> /// <summary>
/// Initialises all the styles that are required. /// Initialises all the styles that are required.
/// </summary> /// </summary>
private void InitialiseStyles() private void InitialiseStyles()
{ {
this.windowStyle = new GUIStyle(HighLogic.Skin.window) this.windowStyle = new GUIStyle(HighLogic.Skin.window)
{ {
alignment = TextAnchor.UpperLeft alignment = TextAnchor.UpperLeft
}; };
   
this.areaStyle = new GUIStyle(HighLogic.Skin.box) this.areaStyle = new GUIStyle(HighLogic.Skin.box)
{ {
padding = new RectOffset(0, 0, 9, 0) padding = new RectOffset(0, 0, 9, 0)
}; };
   
this.areaSettingStyle = new GUIStyle(HighLogic.Skin.box) this.areaSettingStyle = new GUIStyle(HighLogic.Skin.box)
{ {
padding = new RectOffset(10, 10, 10, 10) padding = new RectOffset(10, 10, 10, 10)
}; };
   
this.buttonStyle = new GUIStyle(HighLogic.Skin.button) this.buttonStyle = new GUIStyle(HighLogic.Skin.button)
{ {
normal = normal =
{ {
textColor = Color.white textColor = Color.white
}, },
fontSize = (int)(11 * GuiDisplaySize.Offset), fontSize = (int)(11 * GuiDisplaySize.Offset),
fontStyle = FontStyle.Bold, fontStyle = FontStyle.Bold,
alignment = TextAnchor.MiddleCenter alignment = TextAnchor.MiddleCenter
}; };
   
this.titleStyle = new GUIStyle(HighLogic.Skin.label) this.titleStyle = new GUIStyle(HighLogic.Skin.label)
{ {
normal = normal =
{ {
textColor = Color.white textColor = Color.white
}, },
fontSize = (int)(11 * GuiDisplaySize.Offset), fontSize = (int)(11 * GuiDisplaySize.Offset),
fontStyle = FontStyle.Bold, fontStyle = FontStyle.Bold,
alignment = TextAnchor.MiddleCenter, alignment = TextAnchor.MiddleCenter,
stretchWidth = true, stretchWidth = true,
}; };
   
this.infoStyle = new GUIStyle(HighLogic.Skin.label) this.infoStyle = new GUIStyle(HighLogic.Skin.label)
{ {
fontSize = (int)(11 * GuiDisplaySize.Offset), fontSize = (int)(11 * GuiDisplaySize.Offset),
fontStyle = FontStyle.Bold, fontStyle = FontStyle.Bold,
alignment = TextAnchor.MiddleCenter, alignment = TextAnchor.MiddleCenter,
stretchWidth = true stretchWidth = true
}; };
   
this.settingStyle = new GUIStyle(this.titleStyle) this.settingStyle = new GUIStyle(this.titleStyle)
{ {
alignment = TextAnchor.MiddleLeft, alignment = TextAnchor.MiddleLeft,
stretchWidth = true, stretchWidth = true,
stretchHeight = true stretchHeight = true
}; };
   
this.settingAtmoStyle = new GUIStyle(this.titleStyle) this.settingAtmoStyle = new GUIStyle(this.titleStyle)
{ {
margin = new RectOffset(), margin = new RectOffset(),
padding = new RectOffset(), padding = new RectOffset(),
alignment = TextAnchor.UpperLeft alignment = TextAnchor.UpperLeft
}; };
   
this.bodiesButtonStyle = new GUIStyle(HighLogic.Skin.button) this.bodiesButtonStyle = new GUIStyle(HighLogic.Skin.button)
{ {
margin = new RectOffset(0, 0, 2, 0), margin = new RectOffset(0, 0, 2, 0),
padding = new RectOffset(5, 5, 5, 5), padding = new RectOffset(5, 5, 5, 5),
normal = normal =
{ {
textColor = Color.white textColor = Color.white
}, },
active = active =
{ {
textColor = Color.white textColor = Color.white
}, },
fontSize = (int)(11 * GuiDisplaySize.Offset), fontSize = (int)(11 * GuiDisplaySize.Offset),
fontStyle = FontStyle.Bold, fontStyle = FontStyle.Bold,
alignment = TextAnchor.MiddleCenter, alignment = TextAnchor.MiddleCenter,
fixedHeight = 20.0f fixedHeight = 20.0f
}; };
   
this.bodiesButtonActiveStyle = new GUIStyle(this.bodiesButtonStyle) this.bodiesButtonActiveStyle = new GUIStyle(this.bodiesButtonStyle)
{ {
normal = this.bodiesButtonStyle.onNormal, normal = this.bodiesButtonStyle.onNormal,
hover = this.bodiesButtonStyle.onHover hover = this.bodiesButtonStyle.onHover
}; };
} }
   
/// <summary> /// <summary>
/// Loads the settings when this object is created. /// Loads the settings when this object is created.
/// </summary> /// </summary>
private void Load() private void Load()
{ {
try try
{ {
var handler = SettingHandler.Load("BuildAdvanced.xml"); var handler = SettingHandler.Load("BuildAdvanced.xml");
handler.Get("visible", ref this.visible); handler.Get("visible", ref this.visible);
this.position.x = handler.Get("windowPositionX", this.position.x); this.position.x = handler.Get("windowPositionX", this.position.x);
this.position.y = handler.Get("windowPositionY", this.position.y); this.position.y = handler.Get("windowPositionY", this.position.y);
handler.Get("compactMode", ref this.compactMode); handler.Get("compactMode", ref this.compactMode);
handler.Get("compactCollapseRight", ref this.compactCollapseRight); handler.Get("compactCollapseRight", ref this.compactCollapseRight);
handler.Get("showAllStages", ref this.showAllStages); handler.Get("showAllStages", ref this.showAllStages);
handler.Get("showAtmosphericDetails", ref this.showAtmosphericDetails); handler.Get("showAtmosphericDetails", ref this.showAtmosphericDetails);
handler.Get("showSettings", ref this.showSettings); handler.Get("showSettings", ref this.showSettings);
CelestialBodies.SetSelectedBody(handler.Get("selectedBodyName", CelestialBodies.SelectedBody.Name)); CelestialBodies.SetSelectedBody(handler.Get("selectedBodyName", CelestialBodies.SelectedBody.Name));
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex, "BuildAdvanced->Load"); Logger.Exception(ex, "BuildAdvanced->Load");
} }
} }
   
private void OnSizeChanged() private void OnSizeChanged()
{ {
this.InitialiseStyles(); this.InitialiseStyles();
this.hasChanged = true; this.hasChanged = true;
} }
   
/// <summary> /// <summary>
/// Draws the OnGUI window. /// Draws the OnGUI window.
/// </summary> /// </summary>
private void Window(int windowId) private void Window(int windowId)
{ {
try try
{ {
// Draw the compact mode toggle. // Draw the compact mode toggle.
if (GUI.Toggle(new Rect(this.position.width - 70.0f * GuiDisplaySize.Offset, 5.0f, 65.0f * GuiDisplaySize.Offset, 20.0f), this.compactMode, "COMPACT", this.buttonStyle) != this.compactMode) if (GUI.Toggle(new Rect(this.position.width - 70.0f * GuiDisplaySize.Offset, 5.0f, 65.0f * GuiDisplaySize.Offset, 20.0f), this.compactMode, "COMPACT", this.buttonStyle) != this.compactMode)
{ {
this.hasChanged = true; this.hasChanged = true;
this.compactCheck = 2; this.compactCheck = 2;
this.compactRight = this.position.xMax; this.compactRight = this.position.xMax;
this.compactMode = !this.compactMode; this.compactMode = !this.compactMode;
} }
   
// When not in compact mode draw the 'All Stages' and 'Atmospheric' toggles. // When not in compact mode draw the 'All Stages' and 'Atmospheric' toggles.
if (!this.compactMode) if (!this.compactMode)
{ {
if (GUI.Toggle(new Rect(this.position.width - 143.0f * GuiDisplaySize.Offset, 5.0f, 70.0f * GuiDisplaySize.Offset, 20.0f), this.showSettings, "SETTINGS", this.buttonStyle) != this.showSettings) if (GUI.Toggle(new Rect(this.position.width - 143.0f * GuiDisplaySize.Offset, 5.0f, 70.0f * GuiDisplaySize.Offset, 20.0f), this.showSettings, "SETTINGS", this.buttonStyle) != this.showSettings)
{ {
this.hasChanged = true; this.hasChanged = true;
this.showSettings = !this.showSettings; this.showSettings = !this.showSettings;
} }
   
if (GUI.Toggle(new Rect(this.position.width - 226.0f * GuiDisplaySize.Offset, 5.0f, 80.0f * GuiDisplaySize.Offset, 20.0f), this.showAllStages, "ALL STAGES", this.buttonStyle) != this.showAllStages) if (GUI.Toggle(new Rect(this.position.width - 226.0f * GuiDisplaySize.Offset, 5.0f, 80.0f * GuiDisplaySize.Offset, 20.0f), this.showAllStages, "ALL STAGES", this.buttonStyle) != this.showAllStages)
{ {
this.hasChanged = true; this.hasChanged = true;
this.showAllStages = !this.showAllStages; this.showAllStages = !this.showAllStages;
} }
   
if (GUI.Toggle(new Rect(this.position.width - 324.0f * GuiDisplaySize.Offset, 5.0f, 95.0f * GuiDisplaySize.Offset, 20.0f), this.showAtmosphericDetails, "ATMOSPHERIC", this.buttonStyle) != this.showAtmosphericDetails) if (GUI.Toggle(new Rect(this.position.width - 324.0f * GuiDisplaySize.Offset, 5.0f, 95.0f * GuiDisplaySize.Offset, 20.0f), this.showAtmosphericDetails, "ATMOSPHERIC", this.buttonStyle) != this.showAtmosphericDetails)
{ {
this.hasChanged = true; this.hasChanged = true;
this.showAtmosphericDetails = !this.showAtmosphericDetails; this.showAtmosphericDetails = !this.showAtmosphericDetails;
} }
   
this.bodiesListPosition = new Rect(this.position.width - 452.0f * GuiDisplaySize.Offset, 5.0f, 125.0f * GuiDisplaySize.Offset, 20.0f); this.bodiesListPosition = new Rect(this.position.width - 452.0f * GuiDisplaySize.Offset, 5.0f, 125.0f * GuiDisplaySize.Offset, 20.0f);
this.bodiesList.enabled = GUI.Toggle(this.bodiesListPosition, this.bodiesList.enabled, "BODY: " + CelestialBodies.SelectedBody.Name.ToUpper(), this.buttonStyle); this.bodiesList.enabled = GUI.Toggle(this.bodiesListPosition, this.bodiesList.enabled, "BODY: " + CelestialBodies.SelectedBody.Name.ToUpper(), this.buttonStyle);
this.bodiesList.SetPosition(this.bodiesListPosition.Translate(this.position)); this.bodiesList.SetPosition(this.bodiesListPosition.Translate(this.position));
} }
   
// Draw the main informational display box. // Draw the main informational display box.
if (!this.compactMode) if (!this.compactMode)
{ {
GUILayout.BeginHorizontal(this.areaStyle); GUILayout.BeginHorizontal(this.areaStyle);
this.DrawStageNumbers(); this.DrawStageNumbers();
this.DrawPartCount(); this.DrawPartCount();
this.DrawCost(); this.DrawCost();
this.DrawMass(); this.DrawMass();
this.DrawIsp(); this.DrawIsp();
this.DrawThrust(); this.DrawThrust();
this.DrawTorque(); this.DrawTorque();
this.DrawTwr(); this.DrawTwr();
this.DrawDeltaV(); this.DrawDeltaV();
this.DrawBurnTime(); this.DrawBurnTime();
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
if (this.showAtmosphericDetails) if (this.showAtmosphericDetails)
{ {
GUILayout.BeginVertical(this.areaSettingStyle); GUILayout.BeginVertical(this.areaSettingStyle);
this.DrawAtmosphericDetails(); this.DrawAtmosphericDetails();
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
   
if (this.showSettings) if (this.showSettings)
{ {
GUILayout.BeginVertical(this.areaSettingStyle); GUILayout.BeginVertical(this.areaSettingStyle);
this.DrawSettings(); this.DrawSettings();
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
} }
else // Draw only a few details when in compact mode. else // Draw only a few details when in compact mode.
{ {
GUILayout.BeginHorizontal(this.areaStyle); GUILayout.BeginHorizontal(this.areaStyle);
this.DrawStageNumbers(); this.DrawStageNumbers();
this.DrawTwr(); this.DrawTwr();
this.DrawDeltaV(); this.DrawDeltaV();
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
GUI.DragWindow(); GUI.DragWindow();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
   
using KerbalEngineer.Extensions; using KerbalEngineer.Extensions;
using KerbalEngineer.Helpers; using KerbalEngineer.Helpers;
   
using UnityEngine; using UnityEngine;
   
#endregion #endregion
   
namespace KerbalEngineer.Editor namespace KerbalEngineer.Editor
{ {
public class BuildOverlayPartInfo : MonoBehaviour public class BuildOverlayPartInfo : MonoBehaviour
{ {
#region Fields #region Fields
   
private static bool clickToOpen = true; private static bool clickToOpen = true;
private static bool namesOnly; private static bool namesOnly;
private static bool visible = true; private static bool visible = true;
   
private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>(); private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>();
   
private Rect position; private Rect position;
private Part selectedPart; private Part selectedPart;
private bool showInfo; private bool showInfo;
private bool skipFrame; private bool skipFrame;
   
#endregion #endregion
   
#region Properties #region Properties
   
public static bool ClickToOpen public static bool ClickToOpen
{ {
get { return clickToOpen; } get { return clickToOpen; }
set { clickToOpen = value; } set { clickToOpen = value; }
} }
   
public static bool Hidden { get; set; } public static bool Hidden { get; set; }
   
public static bool NamesOnly public static bool NamesOnly
{ {
get { return namesOnly; } get { return namesOnly; }
set { namesOnly = value; } set { namesOnly = value; }
} }
   
public static bool Visible public static bool Visible
{ {
get { return visible; } get { return visible; }
set { visible = value; } set { visible = value; }
} }
   
#endregion #endregion
   
#region Methods: protected #region Methods: protected
   
protected void OnGUI() protected void OnGUI()
{ {
try try
{ {
if (!Visible || Hidden || this.selectedPart == null) if (!Visible || Hidden || this.selectedPart == null)
{ {
return; return;
} }
   
this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, String.Empty, BuildOverlay.WindowStyle); this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, String.Empty, BuildOverlay.WindowStyle);
} }
catch (Exception ex) catch (Exception ex)
   
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
protected void Update() protected void Update()
{ {
try try
{ {
if (!Visible || Hidden || EditorLogic.RootPart == null || EditorLogic.fetch.editorScreen != EditorScreen.Parts) if (!Visible || Hidden || EditorLogic.RootPart == null || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
{ {
return; return;
} }
   
this.position.x = Mathf.Clamp(Input.mousePosition.x + 16.0f, 0.0f, Screen.width - this.position.width); this.position.x = Mathf.Clamp(Input.mousePosition.x + 16.0f, 0.0f, Screen.width - this.position.width);
this.position.y = Mathf.Clamp(Screen.height - Input.mousePosition.y, 0.0f, Screen.height - this.position.height); this.position.y = Mathf.Clamp(Screen.height - Input.mousePosition.y, 0.0f, Screen.height - this.position.height);
if (this.position.x < Input.mousePosition.x + 20.0f) if (this.position.x < Input.mousePosition.x + 20.0f)
{ {
this.position.y = Mathf.Clamp(this.position.y + 20.0f, 0.0f, Screen.height - this.position.height); this.position.y = Mathf.Clamp(this.position.y + 20.0f, 0.0f, Screen.height - this.position.height);
} }
if (this.position.x < Input.mousePosition.x + 16.0f && this.position.y < Screen.height - Input.mousePosition.y) if (this.position.x < Input.mousePosition.x + 16.0f && this.position.y < Screen.height - Input.mousePosition.y)
{ {
this.position.x = Input.mousePosition.x - 3 - this.position.width; this.position.x = Input.mousePosition.x - 3 - this.position.width;
} }
   
this.infoItems.Clear(); this.infoItems.Clear();
var part = EditorLogic.fetch.ship.parts.Find(p => p.stackIcon.highlightIcon) ?? EditorLogic.SelectedPart; var part = EditorLogic.fetch.ship.parts.Find(p => p.stackIcon.highlightIcon) ?? EditorLogic.SelectedPart;
if (part != null) if (part != null)
{ {
if (!part.Equals(this.selectedPart)) if (!part.Equals(this.selectedPart))
{ {
this.selectedPart = part; this.selectedPart = part;
this.ResetInfo(); this.ResetInfo();
} }
if (NamesOnly || this.skipFrame) if (NamesOnly || this.skipFrame)
{ {
this.skipFrame = false; this.skipFrame = false;
return; return;
} }
   
this.SetCostInfo(); this.SetCostInfo();
this.SetMassItems(); this.SetMassItems();
this.SetResourceItems(); this.SetResourceItems();
this.SetEngineInfo(); this.SetEngineInfo();
this.SetAlternatorInfo(); this.SetAlternatorInfo();
this.SetGimbalInfo(); this.SetGimbalInfo();
this.SetRcsInfo(); this.SetRcsInfo();
this.SetParachuteInfo(); this.SetParachuteInfo();
this.SetSasInfo(); this.SetSasInfo();
this.SetReactionWheelInfo(); this.SetReactionWheelInfo();
this.SetSolarPanelInfo(); this.SetSolarPanelInfo();
this.SetGeneratorInfo(); this.SetGeneratorInfo();
this.SetDecouplerInfo(); this.SetDecouplerInfo();
this.SetTransmitterInfo(); this.SetTransmitterInfo();
this.SetScienceExperimentInfo(); this.SetScienceExperimentInfo();
this.SetScienceContainerInfo(); this.SetScienceContainerInfo();
this.SetSingleActivationInfo(); this.SetSingleActivationInfo();
   
if (!this.showInfo && Input.GetMouseButtonDown(2)) if (!this.showInfo && Input.GetMouseButtonDown(2))
{ {
this.showInfo = true; this.showInfo = true;
} }
else if (ClickToOpen && this.showInfo && Input.GetMouseButtonDown(2)) else if (ClickToOpen && this.showInfo && Input.GetMouseButtonDown(2))
{ {
this.ResetInfo(); this.ResetInfo();
} }
} }
else else
{ {
this.selectedPart = null; this.selectedPart = null;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
   
#region Methods: private #region Methods: private
   
private void ResetInfo() private void ResetInfo()
{ {
this.showInfo = !clickToOpen; this.showInfo = !clickToOpen;
this.skipFrame = true; this.skipFrame = true;
this.position.width = namesOnly || clickToOpen ? 0.0f : 200.0f; this.position.width = namesOnly || clickToOpen ? 0.0f : 200.0f;
this.position.height = 0.0f; this.position.height = 0.0f;
} }
   
private void SetAlternatorInfo() private void SetAlternatorInfo()
{ {
if (!this.selectedPart.HasModule<ModuleAlternator>()) if (!this.selectedPart.HasModule<ModuleAlternator>())
{ {
return; return;
} }
   
var alternator = this.selectedPart.GetModule<ModuleAlternator>(); var alternator = this.selectedPart.GetModule<ModuleAlternator>();
this.infoItems.Add(new PartInfoItem("Alternator")); this.infoItems.Add(new PartInfoItem("Alternator"));
foreach (var resource in alternator.outputResources) foreach (var resource in alternator.outputResources)
{ {
this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate())); this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
} }
} }
   
private void SetCostInfo() private void SetCostInfo()
{ {
this.infoItems.Add(new PartInfoItem("Cost", Units.Concat(this.selectedPart.GetCostDry(), this.selectedPart.GetCostWet()))); this.infoItems.Add(new PartInfoItem("Cost", Units.ConcatF(this.selectedPart.GetCostDry(), this.selectedPart.GetCostWet())));
} }
   
private void SetDecouplerInfo() private void SetDecouplerInfo()
{ {
if (!this.selectedPart.IsDecoupler()) if (!this.selectedPart.IsDecoupler())
{ {
return; return;
} }
   
var decoupler = this.selectedPart.GetProtoModuleDecoupler(); var decoupler = this.selectedPart.GetProtoModuleDecoupler();
this.infoItems.Add(new PartInfoItem("Ejection Force", decoupler.EjectionForce.ToForce())); this.infoItems.Add(new PartInfoItem("Ejection Force", decoupler.EjectionForce.ToForce()));
if (decoupler.IsOmniDecoupler) if (decoupler.IsOmniDecoupler)
{ {
this.infoItems.Add(new PartInfoItem("Omni-directional")); this.infoItems.Add(new PartInfoItem("Omni-directional"));
} }
} }
   
private void SetEngineInfo() private void SetEngineInfo()
{ {
if (!this.selectedPart.IsEngine()) if (!this.selectedPart.IsEngine())
{ {
return; return;
} }
   
var engine = this.selectedPart.GetProtoModuleEngine(); var engine = this.selectedPart.GetProtoModuleEngine();
this.infoItems.Add(new PartInfoItem("Thrust", Units.ToForce(engine.MinimumThrust, engine.MaximumThrust))); this.infoItems.Add(new PartInfoItem("Thrust", Units.ToForce(engine.MinimumThrust, engine.MaximumThrust)));
this.infoItems.Add(new PartInfoItem("Isp", Units.Concat(engine.GetSpecificImpulse(1.0f), engine.GetSpecificImpulse(0.0f)) + "s")); this.infoItems.Add(new PartInfoItem("Isp", Units.ConcatF(engine.GetSpecificImpulse(1.0f), engine.GetSpecificImpulse(0.0f)) + "s"));
if (engine.Propellants.Count > 0) if (engine.Propellants.Count > 0)
{ {
this.infoItems.Add(new PartInfoItem("Propellants")); this.infoItems.Add(new PartInfoItem("Propellants"));
var totalRatio = engine.Propellants.Sum(p => p.ratio); var totalRatio = engine.Propellants.Sum(p => p.ratio);
foreach (var propellant in engine.Propellants) foreach (var propellant in engine.Propellants)
{ {
this.infoItems.Add(new PartInfoItem("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent())); this.infoItems.Add(new PartInfoItem("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent()));
} }
} }
} }
   
private void SetGeneratorInfo() private void SetGeneratorInfo()
{ {
if (!this.selectedPart.HasModule<ModuleGenerator>()) if (!this.selectedPart.HasModule<ModuleGenerator>())
{ {
return; return;
} }
   
var generator = this.selectedPart.GetModule<ModuleGenerator>(); var generator = this.selectedPart.GetModule<ModuleGenerator>();
if (generator.inputList.Count > 0) if (generator.inputList.Count > 0)
{ {
this.infoItems.Add(new PartInfoItem("Generator Input")); this.infoItems.Add(new PartInfoItem("Generator Input"));
foreach (var resource in generator.inputList) foreach (var resource in generator.inputList)
{ {
this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate())); this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
} }
} }
if (generator.outputList.Count > 0) if (generator.outputList.Count > 0)
{ {
this.infoItems.Add(new PartInfoItem("Generator Output")); this.infoItems.Add(new PartInfoItem("Generator Output"));
foreach (var resource in generator.outputList) foreach (var resource in generator.outputList)
{ {
this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate())); this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
} }
} }
if (generator.isAlwaysActive) if (generator.isAlwaysActive)
{ {
this.infoItems.Add(new PartInfoItem("Generator is Always Active")); this.infoItems.Add(new PartInfoItem("Generator is Always Active"));
} }
} }
   
private void SetGimbalInfo() private void SetGimbalInfo()
{ {
if (!this.selectedPart.HasModule<ModuleGimbal>()) if (!this.selectedPart.HasModule<ModuleGimbal>())
{ {
return; return;
} }
   
var gimbal = this.selectedPart.GetModule<ModuleGimbal>(); var gimbal = this.selectedPart.GetModule<ModuleGimbal>();
this.infoItems.Add(new PartInfoItem("Thrust Vectoring", gimbal.gimbalRange.ToString("F2"))); this.infoItems.Add(new PartInfoItem("Thrust Vectoring", gimbal.gimbalRange.ToString("F2")));
} }
   
private void SetMassItems() private void SetMassItems()
{ {
if (this.selectedPart.physicalSignificance == Part.PhysicalSignificance.FULL) if (this.selectedPart.physicalSignificance == Part.PhysicalSignificance.FULL)
{ {
this.infoItems.Add(new PartInfoItem("Mass", Units.ToMass(this.selectedPart.GetDryMass(), this.selectedPart.GetWetMass()))); this.infoItems.Add(new PartInfoItem("Mass", Units.ToMass(this.selectedPart.GetDryMass(), this.selectedPart.GetWetMass())));
} }
} }
   
private void SetParachuteInfo() private void SetParachuteInfo()
{ {
if (!this.selectedPart.HasModule<ModuleParachute>()) if (!this.selectedPart.HasModule<ModuleParachute>())
{ {
return; return;
} }
   
var parachute = this.selectedPart.GetModule<ModuleParachute>(); var parachute = this.selectedPart.GetModule<ModuleParachute>();
this.infoItems.Add(new PartInfoItem("Deployed Drag", Units.Concat(parachute.semiDeployedDrag, parachute.fullyDeployedDrag))); this.infoItems.Add(new PartInfoItem("Deployed Drag", Units.ConcatF(parachute.semiDeployedDrag, parachute.fullyDeployedDrag)));
this.infoItems.Add(new PartInfoItem("Deployment Altitude", parachute.deployAltitude.ToDistance())); this.infoItems.Add(new PartInfoItem("Deployment Altitude", parachute.deployAltitude.ToDistance()));
this.infoItems.Add(new PartInfoItem("Deployment Pressure", parachute.minAirPressureToOpen.ToString("F2"))); this.infoItems.Add(new PartInfoItem("Deployment Pressure", parachute.minAirPressureToOpen.ToString("F2")));
} }
   
private void SetRcsInfo() private void SetRcsInfo()
{ {
if (!this.selectedPart.HasModule<ModuleRCS>()) if (!this.selectedPart.HasModule<ModuleRCS>())
{ {
return; return;
} }
   
var rcs = this.selectedPart.GetModule<ModuleRCS>(); var rcs = this.selectedPart.GetModule<ModuleRCS>();
this.infoItems.Add(new PartInfoItem("Thruster Power", rcs.thrusterPower.ToForce())); this.infoItems.Add(new PartInfoItem("Thruster Power", rcs.thrusterPower.ToForce()));
this.infoItems.Add(new PartInfoItem("Specific Impulse", Units.Concat(rcs.atmosphereCurve.Evaluate(1.0f), rcs.atmosphereCurve.Evaluate(0.0f)) + "s")); this.infoItems.Add(new PartInfoItem("Specific Impulse", Units.ConcatF(rcs.atmosphereCurve.Evaluate(1.0f), rcs.atmosphereCurve.Evaluate(0.0f)) + "s"));
} }
   
private void SetReactionWheelInfo() private void SetReactionWheelInfo()
{ {
if (!this.selectedPart.HasModule<ModuleReactionWheel>()) if (!this.selectedPart.HasModule<ModuleReactionWheel>())
{ {
return; return;
} }
   
var reactionWheel = this.selectedPart.GetModule<ModuleReactionWheel>(); var reactionWheel = this.selectedPart.GetModule<ModuleReactionWheel>();
this.infoItems.Add(new PartInfoItem("Reaction Wheel Torque")); this.infoItems.Add(new PartInfoItem("Reaction Wheel Torque"));
this.infoItems.Add(new PartInfoItem("\tPitch", reactionWheel.PitchTorque.ToTorque())); this.infoItems.Add(new PartInfoItem("\tPitch", reactionWheel.PitchTorque.ToTorque()));
this.infoItems.Add(new PartInfoItem("\tRoll", reactionWheel.RollTorque.ToTorque())); this.infoItems.Add(new PartInfoItem("\tRoll", reactionWheel.RollTorque.ToTorque()));
this.infoItems.Add(new PartInfoItem("\tYaw", reactionWheel.YawTorque.ToTorque())); this.infoItems.Add(new PartInfoItem("\tYaw", reactionWheel.YawTorque.ToTorque()));
foreach (var resource in reactionWheel.inputResources) foreach (var resource in reactionWheel.inputResources)
{ {
this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate())); this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate()));
} }
} }
   
private void SetResourceItems() private void SetResourceItems()
{ {
if (this.selectedPart.Resources.list.Any(r => !r.hideFlow)) if (this.selectedPart.Resources.list.Any(r => !r.hideFlow))
{ {
this.infoItems.Add(new PartInfoItem("Resources")); this.infoItems.Add(new PartInfoItem("Resources"));
foreach (var resource in this.selectedPart.Resources.list.Where(r => !r.hideFlow)) foreach (var resource in this.selectedPart.Resources.list.Where(r => !r.hideFlow))
{ {
this.infoItems.Add(resource.GetDensity() > 0 this.infoItems.Add(resource.GetDensity() > 0
? new PartInfoItem("\t" + resource.info.name, "(" + resource.GetMass().ToMass() + ") " + resource.amount.ToString("F1")) ? new PartInfoItem("\t" + resource.info.name, "(" + resource.GetMass().ToMass() + ") " + resource.amount.ToString("F1"))
: new PartInfoItem("\t" + resource.info.name, resource.amount.ToString("F1"))); : new PartInfoItem("\t" + resource.info.name, resource.amount.ToString("F1")));
} }
} }
} }
   
private void SetSasInfo() private void SetSasInfo()
{ {
if (this.selectedPart.HasModule<ModuleSAS>()) if (this.selectedPart.HasModule<ModuleSAS>())
{ {
this.infoItems.Add(new PartInfoItem("SAS Equiped")); this.infoItems.Add(new PartInfoItem("SAS Equiped"));
} }
} }
   
private void SetScienceContainerInfo() private void SetScienceContainerInfo()
{ {
if (this.selectedPart.HasModule<ModuleScienceContainer>()) if (this.selectedPart.HasModule<ModuleScienceContainer>())
{ {
this.infoItems.Add(new PartInfoItem("Science Container")); this.infoItems.Add(new PartInfoItem("Science Container"));
} }
} }
   
private void SetScienceExperimentInfo() private void SetScienceExperimentInfo()
{ {
if (!this.selectedPart.HasModule<ModuleScienceExperiment>()) if (!this.selectedPart.HasModule<ModuleScienceExperiment>())
{ {
return; return;
} }
   
var experiment = this.selectedPart.GetModule<ModuleScienceExperiment>(); var experiment = this.selectedPart.GetModule<ModuleScienceExperiment>();
this.infoItems.Add(new PartInfoItem("Science Experiment", experiment.experimentActionName)); this.infoItems.Add(new PartInfoItem("Science Experiment", experiment.experimentActionName));
this.infoItems.Add(new PartInfoItem("\tTransmit Efficiency", experiment.xmitDataScalar.ToPercent())); this.infoItems.Add(new PartInfoItem("\tTransmit Efficiency", experiment.xmitDataScalar.ToPercent()));
if (!experiment.rerunnable) if (!experiment.rerunnable)
{ {
this.infoItems.Add(new PartInfoItem("\tSingle Usage")); this.infoItems.Add(new PartInfoItem("\tSingle Usage"));
} }
} }
   
private void SetSingleActivationInfo() private void SetSingleActivationInfo()
{ {
if (this.selectedPart.HasModule<ModuleAnimateGeneric>(m => m.isOneShot)) if (this.selectedPart.HasModule<ModuleAnimateGeneric>(m => m.isOneShot))
{ {
this.infoItems.Add(new PartInfoItem("Single Activation")); this.infoItems.Add(new PartInfoItem("Single Activation"));
} }
} }
   
private void SetSolarPanelInfo() private void SetSolarPanelInfo()
{ {
if (!this.selectedPart.HasModule<ModuleDeployableSolarPanel>()) if (!this.selectedPart.HasModule<ModuleDeployableSolarPanel>())
{ {
return; return;
} }
   
var solarPanel = this.selectedPart.GetModule<ModuleDeployableSolarPanel>(); var solarPanel = this.selectedPart.GetModule<ModuleDeployableSolarPanel>();
this.infoItems.Add(new PartInfoItem("Charge Rate", solarPanel.chargeRate.ToRate())); this.infoItems.Add(new PartInfoItem("Charge Rate", solarPanel.chargeRate.ToRate()));
if (solarPanel.isBreakable) if (solarPanel.isBreakable)
{ {
this.infoItems.Add(new PartInfoItem("Breakable")); this.infoItems.Add(new PartInfoItem("Breakable"));
} }
if (solarPanel.sunTracking) if (solarPanel.sunTracking)
{ {
this.infoItems.Add(new PartInfoItem("Sun Tracking")); this.infoItems.Add(new PartInfoItem("Sun Tracking"));
} }
} }
   
private void SetTransmitterInfo() private void SetTransmitterInfo()
{ {
if (!this.selectedPart.HasModule<ModuleDataTransmitter>()) if (!this.selectedPart.HasModule<ModuleDataTransmitter>())
{ {
return; return;
} }
   
var transmitter = this.selectedPart.GetModule<ModuleDataTransmitter>(); var transmitter = this.selectedPart.GetModule<ModuleDataTransmitter>();
this.infoItems.Add(new PartInfoItem("Packet Size", transmitter.packetSize.ToString("F2") + " Mits")); this.infoItems.Add(new PartInfoItem("Packet Size", transmitter.packetSize.ToString("F2") + " Mits"));
this.infoItems.Add(new PartInfoItem("Bandwidth", (transmitter.packetInterval * transmitter.packetSize).ToString("F2") + "Mits/sec")); this.infoItems.Add(new PartInfoItem("Bandwidth", (transmitter.packetInterval * transmitter.packetSize).ToString("F2") + "Mits/sec"));
this.infoItems.Add(new PartInfoItem(transmitter.requiredResource, transmitter.packetResourceCost.ToString("F2") + "/Packet")); this.infoItems.Add(new PartInfoItem(transmitter.requiredResource, transmitter.packetResourceCost.ToString("F2") + "/Packet"));
} }
   
private void Window(int windowId) private void Window(int windowId)
{ {
try try
{ {
GUILayout.Label(this.selectedPart.partInfo.title, BuildOverlay.TitleStyle); GUILayout.Label(this.selectedPart.partInfo.title, BuildOverlay.TitleStyle);
if (this.showInfo) if (this.showInfo)
{ {
foreach (var item in this.infoItems) foreach (var item in this.infoItems)
{ {
GUILayout.Space(2.0f); GUILayout.Space(2.0f);
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
if (item.Value != null) if (item.Value != null)
{ {
GUILayout.Label(item.Name + ":", BuildOverlay.NameStyle); GUILayout.Label(item.Name + ":", BuildOverlay.NameStyle);
GUILayout.Space(25.0f); GUILayout.Space(25.0f);
GUILayout.Label(item.Value, BuildOverlay.ValueStyle); GUILayout.Label(item.Value, BuildOverlay.ValueStyle);
} }
else else
{ {
GUILayout.Label(item.Name, BuildOverlay.NameStyle); GUILayout.Label(item.Name, BuildOverlay.NameStyle);
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
} }
else if (this.infoItems.Count > 0) else if (this.infoItems.Count > 0)
{ {
GUILayout.Space(2.0f); GUILayout.Space(2.0f);
GUILayout.Label("Click middle mouse to show more info...", BuildOverlay.NameStyle); GUILayout.Label("Click middle mouse to show more info...", BuildOverlay.NameStyle);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
#endregion #endregion
   
namespace KerbalEngineer.Editor namespace KerbalEngineer.Editor
{ {
#region Using Directives #region Using Directives
   
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Helpers; using Helpers;
using UnityEngine; using UnityEngine;
using VesselSimulator; using VesselSimulator;
   
#endregion #endregion
   
public class BuildOverlayVessel : MonoBehaviour public class BuildOverlayVessel : MonoBehaviour
{ {
#region Constants #region Constants
   
private const float Width = 175.0f; private const float Width = 175.0f;
   
#endregion #endregion
   
#region Fields #region Fields
   
private static bool visible = true; private static bool visible = true;
   
private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>(); private readonly List<PartInfoItem> infoItems = new List<PartInfoItem>();
   
private Stage lastStage; private Stage lastStage;
private bool open = true; private bool open = true;
private float openPercent; private float openPercent;
private GUIContent tabContent; private GUIContent tabContent;
private Rect tabPosition; private Rect tabPosition;
private Vector2 tabSize; private Vector2 tabSize;
private Rect windowPosition = new Rect(330.0f, 0.0f, Width, 0.0f); private Rect windowPosition = new Rect(330.0f, 0.0f, Width, 0.0f);
   
#endregion #endregion
   
#region Properties #region Properties
   
public static bool Visible public static bool Visible
{ {
get { return visible; } get { return visible; }
set { visible = value; } set { visible = value; }
} }
   
public bool Open public bool Open
{ {
get { return this.open; } get { return this.open; }
set { this.open = value; } set { this.open = value; }
} }
   
public Rect WindowPosition public Rect WindowPosition
{ {
get { return this.windowPosition; } get { return this.windowPosition; }
} }
   
public float WindowX public float WindowX
{ {
get { return this.windowPosition.x; } get { return this.windowPosition.x; }
set { this.windowPosition.x = value; } set { this.windowPosition.x = value; }
} }
   
#endregion #endregion
   
#region Methods #region Methods
   
protected void Awake() protected void Awake()
{ {
try try
{ {
SimManager.OnReady -= this.GetStageInfo; SimManager.OnReady -= this.GetStageInfo;
SimManager.OnReady += this.GetStageInfo; SimManager.OnReady += this.GetStageInfo;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
protected void OnGUI() protected void OnGUI()
{ {
try try
{ {
if (!Visible || EditorLogic.RootPart == null || EditorLogic.fetch.editorScreen != EditorScreen.Parts) if (!Visible || EditorLogic.RootPart == null || EditorLogic.fetch.editorScreen != EditorScreen.Parts)
{ {
return; return;
} }
   
this.open = GUI.Toggle(this.tabPosition, this.open, this.tabContent, BuildOverlay.TabStyle); this.open = GUI.Toggle(this.tabPosition, this.open, this.tabContent, BuildOverlay.TabStyle);
if (this.openPercent > 0.0) if (this.openPercent > 0.0)
{ {
this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.VesselWindow, String.Empty, BuildOverlay.WindowStyle); this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.VesselWindow, String.Empty, BuildOverlay.WindowStyle);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
protected void Start() protected void Start()
{ {
try try
{ {
this.tabContent = new GUIContent("VESSEL"); this.tabContent = new GUIContent("VESSEL");
this.tabSize = BuildOverlay.TabStyle.CalcSize(this.tabContent); this.tabSize = BuildOverlay.TabStyle.CalcSize(this.tabContent);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
protected void Update() protected void Update()
{ {
try try
{ {
if (!Visible || EditorLogic.RootPart == null) if (!Visible || EditorLogic.RootPart == null)
{ {
return; return;
} }
   
if (this.openPercent > 0.0) if (this.openPercent > 0.0)
{ {
this.SetVesselInfo(); this.SetVesselInfo();
} }
   
this.SetSlidePosition(); this.SetSlidePosition();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
private void GetStageInfo() private void GetStageInfo()
{ {
this.lastStage = SimManager.LastStage; this.lastStage = SimManager.LastStage;
} }
   
private void SetSlidePosition() private void SetSlidePosition()
{ {
if (this.open && this.openPercent < 1.0f) if (this.open && this.openPercent < 1.0f)
{ {
this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f); this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
} }
else if (!this.open && this.openPercent > 0.0f) else if (!this.open && this.openPercent > 0.0f)
{ {
this.openPercent = Mathf.Clamp(this.openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f); this.openPercent = Mathf.Clamp(this.openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f);
} }
   
this.windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - this.windowPosition.height, this.openPercent); this.windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - this.windowPosition.height, this.openPercent);
if (this.windowPosition.width < Width) if (this.windowPosition.width < Width)
{ {
this.windowPosition.width = Width; this.windowPosition.width = Width;
} }
this.tabPosition.width = this.tabSize.x; this.tabPosition.width = this.tabSize.x;
this.tabPosition.height = this.tabSize.y; this.tabPosition.height = this.tabSize.y;
this.tabPosition.x = this.windowPosition.x; this.tabPosition.x = this.windowPosition.x;
this.tabPosition.y = this.windowPosition.y - this.tabPosition.height; this.tabPosition.y = this.windowPosition.y - this.tabPosition.height;
} }
   
private void SetVesselInfo() private void SetVesselInfo()
{ {
SimManager.Gravity = CelestialBodies.SelectedBody.Gravity; SimManager.Gravity = CelestialBodies.SelectedBody.Gravity;
   
if (BuildAdvanced.Instance.ShowAtmosphericDetails) if (BuildAdvanced.Instance.ShowAtmosphericDetails)
{ {
SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01; SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01;
} }
else else
{ {
SimManager.Atmosphere = 0.0; SimManager.Atmosphere = 0.0;
} }
   
SimManager.RequestSimulation(); SimManager.RequestSimulation();
SimManager.TryStartSimulation(); SimManager.TryStartSimulation();
   
if (this.lastStage != null) if (this.lastStage != null)
{ {
this.infoItems.Clear(); this.infoItems.Clear();
this.infoItems.Add(new PartInfoItem("Delta-V", this.lastStage.deltaV.ToString("N0") + " / " + this.lastStage.totalDeltaV.ToString("N0") + "m/s")); this.infoItems.Add(new PartInfoItem("Delta-V", this.lastStage.deltaV.ToString("N0") + " / " + this.lastStage.totalDeltaV.ToString("N0") + "m/s"));
this.infoItems.Add(new PartInfoItem("Mass", Units.ToMass(this.lastStage.mass, this.lastStage.totalMass))); this.infoItems.Add(new PartInfoItem("Mass", Units.ToMass(this.lastStage.mass, this.lastStage.totalMass)));
this.infoItems.Add(new PartInfoItem("TWR", this.lastStage.thrustToWeight.ToString("F2") + " (" + this.lastStage.maxThrustToWeight.ToString("F2") + ")")); this.infoItems.Add(new PartInfoItem("TWR", this.lastStage.thrustToWeight.ToString("F2") + " (" + this.lastStage.maxThrustToWeight.ToString("F2") + ")"));
this.infoItems.Add(new PartInfoItem("Parts", this.lastStage.partCount + " / " + this.lastStage.totalPartCount)); this.infoItems.Add(new PartInfoItem("Parts", this.lastStage.partCount + " / " + this.lastStage.totalPartCount));
} }
} }
   
private void VesselWindow(int windowId) private void VesselWindow(int windowId)
{ {
try try
{ {
var firstItem = true; var firstItem = true;
foreach (var item in this.infoItems) foreach (var item in this.infoItems)
{ {
if (!firstItem) if (!firstItem)
{ {
GUILayout.Space(2.0f); GUILayout.Space(2.0f);
} }
firstItem = false; firstItem = false;
   
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
if (item.Value != null) if (item.Value != null)
{ {
GUILayout.Label(item.Name + ":", BuildOverlay.NameStyle); GUILayout.Label(item.Name + ":", BuildOverlay.NameStyle);
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
GUILayout.Label(item.Value, BuildOverlay.ValueStyle); GUILayout.Label(item.Value, BuildOverlay.ValueStyle);
} }
else else
{ {
GUILayout.Label(item.Name, BuildOverlay.NameStyle); GUILayout.Label(item.Name, BuildOverlay.NameStyle);
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
   
#endregion #endregion
   
namespace KerbalEngineer namespace KerbalEngineer
{ {
public class EngineerGlobals public class EngineerGlobals
{ {
#region Constants #region Constants
   
/// <summary> /// <summary>
/// Current version of the Kerbal Engineer assembly. /// Current version of the Kerbal Engineer assembly.
/// </summary> /// </summary>
public const string AssemblyVersion = "1.0.13.1"; public const string AssemblyVersion = "1.0.14.1";
   
#endregion #endregion
   
#region Fields #region Fields
   
private static string assemblyFile; private static string assemblyFile;
private static string assemblyName; private static string assemblyName;
private static string assemblyPath; private static string assemblyPath;
   
#endregion #endregion
   
#region Properties #region Properties
   
/// <summary> /// <summary>
/// Gets the Kerbal Engineer assembly's path including the file name. /// Gets the Kerbal Engineer assembly's path including the file name.
/// </summary> /// </summary>
public static string AssemblyFile public static string AssemblyFile
{ {
get { return assemblyFile ?? (assemblyFile = Assembly.GetExecutingAssembly().Location); } get { return assemblyFile ?? (assemblyFile = Assembly.GetExecutingAssembly().Location); }
} }
   
/// <summary> /// <summary>
/// Gets the Kerbal Engineer assembly's file name. /// Gets the Kerbal Engineer assembly's file name.
/// </summary> /// </summary>
public static string AssemblyName public static string AssemblyName
{ {
get { return assemblyName ?? (assemblyName = new FileInfo(AssemblyFile).Name); } get { return assemblyName ?? (assemblyName = new FileInfo(AssemblyFile).Name); }
} }
   
/// <summary> /// <summary>
/// Gets the Kerbal Engineer assembly's path excluding the file name. /// Gets the Kerbal Engineer assembly's path excluding the file name.
/// </summary> /// </summary>
public static string AssemblyPath public static string AssemblyPath
{ {
get { return assemblyPath ?? (assemblyPath = AssemblyFile.Replace(new FileInfo(AssemblyFile).Name, "")); } get { return assemblyPath ?? (assemblyPath = AssemblyFile.Replace(new FileInfo(AssemblyFile).Name, "")); }
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
using System; using System;
   
using UnityEngine; using UnityEngine;
   
#endregion #endregion
   
namespace KerbalEngineer.Flight namespace KerbalEngineer.Flight
{ {
/// <summary> /// <summary>
/// Graphical controller for section interaction in the form of a menu system. /// Graphical controller for section interaction in the form of a menu system.
/// </summary> /// </summary>
[KSPAddon(KSPAddon.Startup.Flight, false)] [KSPAddon(KSPAddon.Startup.Flight, false)]
public class ActionMenu : MonoBehaviour public class ActionMenu : MonoBehaviour
{ {
#region Fields #region Fields
   
private ActionMenuGui actionMenuGui; private ActionMenuGui actionMenuGui;
private ApplicationLauncherButton button; private ApplicationLauncherButton button;
   
#endregion #endregion
   
#region Methods: protected #region Methods: protected
   
protected void Awake() protected void Awake()
{ {
try try
{ {
GameEvents.onGUIApplicationLauncherReady.Add(this.OnGuiAppLauncherReady); GameEvents.onGUIApplicationLauncherReady.Add(this.OnGuiAppLauncherReady);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
Logger.Log("ActionMenu was created."); Logger.Log("ActionMenu was created.");
} }
   
protected void OnDestroy() protected void OnDestroy()
{ {
try try
{ {
GameEvents.onGUIApplicationLauncherReady.Remove(this.OnGuiAppLauncherReady); GameEvents.onGUIApplicationLauncherReady.Remove(this.OnGuiAppLauncherReady);
GameEvents.onHideUI.Remove(this.OnHide); GameEvents.onHideUI.Remove(this.OnHide);
GameEvents.onShowUI.Remove(this.OnShow); GameEvents.onShowUI.Remove(this.OnShow);
ApplicationLauncher.Instance.RemoveModApplication(this.button); ApplicationLauncher.Instance.RemoveModApplication(this.button);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
Logger.Log("ActionMenu was destroyed."); Logger.Log("ActionMenu was destroyed.");
} }
   
protected void Update() protected void Update()
{ {
try try
{ {
if (this.button == null) if (this.button == null)
{ {
return; return;
} }
if (FlightEngineerCore.Instance != null && this.button.State == RUIToggleButton.ButtonState.DISABLED) if (FlightEngineerCore.IsDisplayable && this.button.State == RUIToggleButton.ButtonState.DISABLED)
{ {
this.button.Enable(); this.button.Enable();
} }
else if (FlightEngineerCore.Instance == null && this.button.State != RUIToggleButton.ButtonState.DISABLED) else if (!FlightEngineerCore.IsDisplayable && this.button.State != RUIToggleButton.ButtonState.DISABLED)
{ {
this.button.Disable(); this.button.Disable();
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
   
#region Methods: private #region Methods: private
   
private void OnFalse() private void OnFalse()
{ {
try try
{ {
this.actionMenuGui.enabled = false; this.actionMenuGui.enabled = false;
this.actionMenuGui.StayOpen = false; this.actionMenuGui.StayOpen = false;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
private void OnGuiAppLauncherReady() private void OnGuiAppLauncherReady()
{ {
try try
{ {
this.button = ApplicationLauncher.Instance.AddModApplication( this.button = ApplicationLauncher.Instance.AddModApplication(
this.OnTrue, this.OnTrue,
this.OnFalse, this.OnFalse,
this.OnHover, this.OnHover,
this.OnHoverOut, this.OnHoverOut,
null, null,
null, null,
ApplicationLauncher.AppScenes.ALWAYS, ApplicationLauncher.AppScenes.ALWAYS,
GameDatabase.Instance.GetTexture("KerbalEngineer/Textures/ToolbarIcon", false)); GameDatabase.Instance.GetTexture("KerbalEngineer/Textures/ToolbarIcon", false));
this.actionMenuGui = this.button.gameObject.AddComponent<ActionMenuGui>(); this.actionMenuGui = this.button.gameObject.AddComponent<ActionMenuGui>();
this.actionMenuGui.transform.parent = this.button.transform; this.actionMenuGui.transform.parent = this.button.transform;
ApplicationLauncher.Instance.EnableMutuallyExclusive(this.button); ApplicationLauncher.Instance.EnableMutuallyExclusive(this.button);
GameEvents.onHideUI.Add(this.OnHide); GameEvents.onHideUI.Add(this.OnHide);
GameEvents.onShowUI.Add(this.OnShow); GameEvents.onShowUI.Add(this.OnShow);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
private void OnHide() private void OnHide()
{ {
try try
{ {
this.actionMenuGui.Hidden = true; this.actionMenuGui.Hidden = true;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
private void OnHover() private void OnHover()
{ {
try try
{ {
this.actionMenuGui.enabled = true; this.actionMenuGui.enabled = true;
this.actionMenuGui.Hovering = true; this.actionMenuGui.Hovering = true;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
private void OnHoverOut() private void OnHoverOut()
{ {
try try
{ {
this.actionMenuGui.Hovering = false; this.actionMenuGui.Hovering = false;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
private void OnShow() private void OnShow()
{ {
try try
{ {
this.actionMenuGui.Hidden = false; this.actionMenuGui.Hidden = false;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
private void OnTrue() private void OnTrue()
{ {
try try
{ {
this.actionMenuGui.enabled = true; this.actionMenuGui.enabled = true;
this.actionMenuGui.StayOpen = true; this.actionMenuGui.StayOpen = true;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
   
using KerbalEngineer.Flight.Sections; using KerbalEngineer.Flight.Sections;
   
using UnityEngine; using UnityEngine;
   
#endregion #endregion
   
namespace KerbalEngineer.Flight namespace KerbalEngineer.Flight
{ {
public class ActionMenuGui : MonoBehaviour public class ActionMenuGui : MonoBehaviour
{ {
#region Fields #region Fields
   
private int numberOfSections; private int numberOfSections;
private Rect position = new Rect(Screen.width, 38.0f, 300.0f, 0); private Rect position = new Rect(Screen.width, 38.0f, 300.0f, 0);
   
#endregion #endregion
   
#region Properties #region Properties
   
public bool StayOpen { get; set; } public bool StayOpen { get; set; }
   
public bool Hovering { get; set; } public bool Hovering { get; set; }
   
public bool Hidden { get; set; } public bool Hidden { get; set; }
   
#endregion #endregion
   
#region Initialisation #region Initialisation
   
private void Awake() private void Awake()
{ {
try try
{ {
this.enabled = false; this.enabled = false;
Logger.Log("ActionMenuGui was created."); Logger.Log("ActionMenuGui was created.");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
private void Start() private void Start()
{ {
try try
{ {
this.InitialiseStyles(); this.InitialiseStyles();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
   
#region GUIStyles #region GUIStyles
   
private GUIStyle buttonStyle; private GUIStyle buttonStyle;
private GUIStyle windowStyle; private GUIStyle windowStyle;
   
/// <summary> /// <summary>
/// Initialises all the styles required for this object. /// Initialises all the styles required for this object.
/// </summary> /// </summary>
private void InitialiseStyles() private void InitialiseStyles()
{ {
try try
{ {
this.windowStyle = new GUIStyle this.windowStyle = new GUIStyle
{ {
border = new RectOffset(10, 0, 20, 10), border = new RectOffset(10, 0, 20, 10),
margin = new RectOffset(0, 0, 3, 0), margin = new RectOffset(0, 0, 3, 0),
padding = new RectOffset(5, 5, 26, 5), padding = new RectOffset(5, 5, 26, 5),
normal = normal =
{ {
background = GameDatabase.Instance.GetTexture("KerbalEngineer/Textures/ToolbarBackground", false) background = GameDatabase.Instance.GetTexture("KerbalEngineer/Textures/ToolbarBackground", false)
} }
}; };
   
this.buttonStyle = new GUIStyle(HighLogic.Skin.button) this.buttonStyle = new GUIStyle(HighLogic.Skin.button)
{ {
normal = normal =
{ {
textColor = Color.white, textColor = Color.white,
}, },
margin = new RectOffset(), margin = new RectOffset(),
padding = new RectOffset(), padding = new RectOffset(),
alignment = TextAnchor.MiddleCenter, alignment = TextAnchor.MiddleCenter,
fontSize = 11, fontSize = 11,
fontStyle = FontStyle.Bold, fontStyle = FontStyle.Bold,
fixedHeight = 20.0f, fixedHeight = 20.0f,
}; };
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex, "ActionMenu->InitialiseStyles"); Logger.Exception(ex, "ActionMenu->InitialiseStyles");
} }
} }
   
#endregion #endregion
   
#region Drawing #region Drawing
   
/// <summary> /// <summary>
/// Called to draw the menu when the UI is enabled. /// Called to draw the menu when the UI is enabled.
/// </summary> /// </summary>
private void OnGUI() private void OnGUI()
{ {
try try
{ {
if (this.Hidden) if (this.Hidden || !FlightEngineerCore.IsDisplayable)
{ {
return; return;
} }
   
if (!this.position.Contains(Event.current.mousePosition) && !this.StayOpen && !this.Hovering) if (!this.position.Contains(Event.current.mousePosition) && !this.StayOpen && !this.Hovering)
{ {
this.enabled = false; this.enabled = false;
return; return;
} }
   
if (this.numberOfSections < SectionLibrary.NumberOfSections) if (this.numberOfSections < SectionLibrary.NumberOfSections)
{ {
this.numberOfSections = SectionLibrary.NumberOfSections; this.numberOfSections = SectionLibrary.NumberOfSections;
} }
else if (this.numberOfSections > SectionLibrary.NumberOfSections) else if (this.numberOfSections > SectionLibrary.NumberOfSections)
{ {
this.numberOfSections = SectionLibrary.NumberOfSections; this.numberOfSections = SectionLibrary.NumberOfSections;
this.position.height = 0; this.position.height = 0;
} }
   
GUI.skin = null; GUI.skin = null;
this.position.x = Mathf.Clamp(Screen.width * 0.5f + this.transform.parent.position.x - 19.0f, Screen.width * 0.5f, Screen.width - this.position.width); this.position.x = Mathf.Clamp(Screen.width * 0.5f + this.transform.parent.position.x - 19.0f, Screen.width * 0.5f, Screen.width - this.position.width);
this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, string.Empty, this.windowStyle); this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, string.Empty, this.windowStyle);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Draws the menu window. /// Draws the menu window.
/// </summary> /// </summary>
private void Window(int windowId) private void Window(int windowId)
{ {
try try
{ {
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
this.DrawControlBarButton(); this.DrawControlBarButton();
GUILayout.Space(5.0f); GUILayout.Space(5.0f);
this.DrawSections(SectionLibrary.StockSections); this.DrawSections(SectionLibrary.StockSections);
this.DrawSections(SectionLibrary.CustomSections); this.DrawSections(SectionLibrary.CustomSections);
GUILayout.Space(5.0f); GUILayout.Space(5.0f);
this.DrawNewButton(); this.DrawNewButton();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Draws and performs the control bar button action. /// Draws and performs the control bar button action.
/// </summary> /// </summary>
private void DrawControlBarButton() private void DrawControlBarButton()
{ {
try try
{ {
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
DisplayStack.Instance.Hidden = !GUILayout.Toggle(!DisplayStack.Instance.Hidden, "SHOW ENGINEER", this.buttonStyle); DisplayStack.Instance.Hidden = !GUILayout.Toggle(!DisplayStack.Instance.Hidden, "SHOW ENGINEER", this.buttonStyle);
if (GUILayout.Toggle(DisplayStack.Instance.ShowControlBar, "CONTROL BAR", this.buttonStyle) != DisplayStack.Instance.ShowControlBar) if (GUILayout.Toggle(DisplayStack.Instance.ShowControlBar, "CONTROL BAR", this.buttonStyle) != DisplayStack.Instance.ShowControlBar)
{ {
DisplayStack.Instance.ShowControlBar = !DisplayStack.Instance.ShowControlBar; DisplayStack.Instance.ShowControlBar = !DisplayStack.Instance.ShowControlBar;
DisplayStack.Instance.RequestResize(); DisplayStack.Instance.RequestResize();
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Draws an action list for the supplied sections. /// Draws an action list for the supplied sections.
/// </summary> /// </summary>
private void DrawSections(IEnumerable<SectionModule> sections) private void DrawSections(IEnumerable<SectionModule> sections)
{ {
try try
{ {
foreach (var section in sections) foreach (var section in sections)
{ {
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
section.IsVisible = GUILayout.Toggle(section.IsVisible, section.Name.ToUpper(), this.buttonStyle); section.IsVisible = GUILayout.Toggle(section.IsVisible, section.Name.ToUpper(), this.buttonStyle);
section.IsEditorVisible = GUILayout.Toggle(section.IsEditorVisible, "EDIT", this.buttonStyle, GUILayout.Width(50.0f)); section.IsEditorVisible = GUILayout.Toggle(section.IsEditorVisible, "EDIT", this.buttonStyle, GUILayout.Width(50.0f));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Draws and performs the new section button action. /// Draws and performs the new section button action.
/// </summary> /// </summary>
private void DrawNewButton() private void DrawNewButton()
{ {
try try
{ {
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
   
if (GUILayout.Button("NEW CUSTOM SECTION", this.buttonStyle)) if (GUILayout.Button("NEW CUSTOM SECTION", this.buttonStyle))
{ {
SectionLibrary.CustomSections.Add(new SectionModule SectionLibrary.CustomSections.Add(new SectionModule
{ {
Name = "Custom " + (SectionLibrary.CustomSections.Count + 1), Name = "Custom " + (SectionLibrary.CustomSections.Count + 1),
Abbreviation = "CUST " + (SectionLibrary.CustomSections.Count + 1), Abbreviation = "CUST " + (SectionLibrary.CustomSections.Count + 1),
IsVisible = true, IsVisible = true,
IsCustom = true, IsCustom = true,
IsEditorVisible = true IsEditorVisible = true
}); });
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
   
#region Destruction #region Destruction
   
private void OnDestroy() private void OnDestroy()
{ {
try try
{ {
Logger.Log("ActionMenuGui was destroyed."); Logger.Log("ActionMenuGui was destroyed.");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
   
using KerbalEngineer.Extensions; using KerbalEngineer.Extensions;
using KerbalEngineer.Flight.Sections; using KerbalEngineer.Flight.Sections;
using KerbalEngineer.Settings; using KerbalEngineer.Settings;
   
using UnityEngine; using UnityEngine;
   
#endregion #endregion
   
namespace KerbalEngineer.Flight namespace KerbalEngineer.Flight
{ {
  using Upgradeables;
   
/// <summary> /// <summary>
/// Graphical controller for displaying stacked sections. /// Graphical controller for displaying stacked sections.
/// </summary> /// </summary>
[KSPAddon(KSPAddon.Startup.Flight, false)] [KSPAddon(KSPAddon.Startup.Flight, false)]
public class DisplayStack : MonoBehaviour public class DisplayStack : MonoBehaviour
{ {
#region Fields #region Fields
   
private GUIStyle buttonStyle; private GUIStyle buttonStyle;
private int numberOfStackSections; private int numberOfStackSections;
private bool resizeRequested; private bool resizeRequested;
private bool showControlBar = true; private bool showControlBar = true;
private GUIStyle titleStyle; private GUIStyle titleStyle;
private int windowId; private int windowId;
private Rect windowPosition; private Rect windowPosition;
private GUIStyle windowStyle; private GUIStyle windowStyle;
   
#endregion #endregion
   
#region Properties #region Properties
   
/// <summary> /// <summary>
/// Gets the current instance of the DisplayStack. /// Gets the current instance of the DisplayStack.
/// </summary> /// </summary>
public static DisplayStack Instance { get; private set; } public static DisplayStack Instance { get; private set; }
   
public bool Hidden { get; set; } public bool Hidden { get; set; }
   
/// <summary> /// <summary>
/// Gets and sets the visibility of the control bar. /// Gets and sets the visibility of the control bar.
/// </summary> /// </summary>
public bool ShowControlBar public bool ShowControlBar
{ {
get { return this.showControlBar; } get { return this.showControlBar; }
set { this.showControlBar = value; } set { this.showControlBar = value; }
} }
   
#endregion #endregion
   
#region Methods: public #region Methods: public
   
/// <summary> /// <summary>
/// Request that the display stack's size is reset in the next draw call. /// Request that the display stack's size is reset in the next draw call.
/// </summary> /// </summary>
public void RequestResize() public void RequestResize()
{ {
this.resizeRequested = true; this.resizeRequested = true;
} }
   
#endregion #endregion
   
#region Methods: protected #region Methods: protected
   
/// <summary> /// <summary>
/// Sets the instance to this object. /// Sets the instance to this object.
/// </summary> /// </summary>
protected void Awake() protected void Awake()
{ {
try try
{ {
if (Instance == null) if (Instance == null)
{ {
Instance = this; Instance = this;
GuiDisplaySize.OnSizeChanged += this.OnSizeChanged; GuiDisplaySize.OnSizeChanged += this.OnSizeChanged;
Logger.Log("ActionMenu->Awake"); Logger.Log("ActionMenu->Awake");
} }
else else
{ {
Destroy(this); Destroy(this);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Runs when the object is destroyed. /// Runs when the object is destroyed.
/// </summary> /// </summary>
protected void OnDestroy() protected void OnDestroy()
{ {
try try
{ {
this.Save(); this.Save();
RenderingManager.RemoveFromPostDrawQueue(0, this.Draw); RenderingManager.RemoveFromPostDrawQueue(0, this.Draw);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
Logger.Log("ActionMenu->OnDestroy"); Logger.Log("ActionMenu->OnDestroy");
} }
   
/// <summary> /// <summary>
/// Initialises the object's state on creation. /// Initialises the object's state on creation.
/// </summary> /// </summary>
protected void Start() protected void Start()
{ {
try try
{ {
this.windowId = this.GetHashCode(); this.windowId = this.GetHashCode();
this.InitialiseStyles(); this.InitialiseStyles();
this.Load(); this.Load();
RenderingManager.AddToPostDrawQueue(0, this.Draw); RenderingManager.AddToPostDrawQueue(0, this.Draw);
Logger.Log("ActionMenu->Start"); Logger.Log("ActionMenu->Start");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
protected void Update() protected void Update()
{ {
try try
{ {
if (FlightEngineerCore.Instance == null) if (!FlightEngineerCore.IsDisplayable)
{ {
return; return;
} }
   
if (Input.GetKeyDown(KeyBinder.FlightShowHide)) if (Input.GetKeyDown(KeyBinder.FlightShowHide))
{ {
this.Hidden = !this.Hidden; this.Hidden = !this.Hidden;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
   
#region Methods: private #region Methods: private
   
/// <summary> /// <summary>
/// Called to draw the display stack when the UI is enabled. /// Called to draw the display stack when the UI is enabled.
/// </summary> /// </summary>
private void Draw() private void Draw()
{ {
try try
{ {
if (FlightEngineerCore.Instance == null) if (!FlightEngineerCore.IsDisplayable)
{ {
return; return;
} }
   
if (this.resizeRequested || this.numberOfStackSections != SectionLibrary.NumberOfStackSections) if (this.resizeRequested || this.numberOfStackSections != SectionLibrary.NumberOfStackSections)
{ {
this.numberOfStackSections = SectionLibrary.NumberOfStackSections; this.numberOfStackSections = SectionLibrary.NumberOfStackSections;
this.windowPosition.width = 0; this.windowPosition.width = 0;
this.windowPosition.height = 0; this.windowPosition.height = 0;
this.resizeRequested = false; this.resizeRequested = false;
} }
   
if (!this.Hidden && (SectionLibrary.NumberOfStackSections > 0 || this.ShowControlBar)) if (!this.Hidden && (SectionLibrary.NumberOfStackSections > 0 || this.ShowControlBar))
{ {
var shouldCentre = this.windowPosition.min == Vector2.zero; var shouldCentre = this.windowPosition.min == Vector2.zero;
GUI.skin = null; GUI.skin = null;
this.windowPosition = GUILayout.Window(this.windowId, this.windowPosition, this.Window, string.Empty, this.windowStyle).ClampToScreen(); this.windowPosition = GUILayout.Window(this.windowId, this.windowPosition, this.Window, string.Empty, this.windowStyle).ClampToScreen();
if (shouldCentre) if (shouldCentre)
{ {
this.windowPosition.center = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f); this.windowPosition.center = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
} }
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Draws the control bar. /// Draws the control bar.
/// </summary> /// </summary>
private void DrawControlBar() private void DrawControlBar()
{ {
GUILayout.Label("FLIGHT ENGINEER " + EngineerGlobals.AssemblyVersion, this.titleStyle); GUILayout.Label("FLIGHT ENGINEER " + EngineerGlobals.AssemblyVersion, this.titleStyle);
   
this.DrawControlBarButtons(SectionLibrary.StockSections); this.DrawControlBarButtons(SectionLibrary.StockSections);
this.DrawControlBarButtons(SectionLibrary.CustomSections); this.DrawControlBarButtons(SectionLibrary.CustomSections);
} }
   
/// <summary> /// <summary>
/// Draws a button list for a set of sections. /// Draws a button list for a set of sections.
/// </summary> /// </summary>
private void DrawControlBarButtons(IEnumerable<SectionModule> sections) private void DrawControlBarButtons(IEnumerable<SectionModule> sections)
{ {
var index = 0; var index = 0;
foreach (var section in sections.Where(s => !string.IsNullOrEmpty(s.Abbreviation) || !s.IsCustom)) foreach (var section in sections.Where(s => !string.IsNullOrEmpty(s.Abbreviation) || !s.IsCustom))
{ {
if (index % 4 == 0) if (index % 4 == 0)
{ {
if (index > 0) if (index > 0)
{ {
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
} }
section.IsVisible = GUILayout.Toggle(section.IsVisible, section.Abbreviation.ToUpper(), this.buttonStyle); section.IsVisible = GUILayout.Toggle(section.IsVisible, section.Abbreviation.ToUpper(), this.buttonStyle);
index++; index++;
} }
if (index > 0) if (index > 0)
{ {
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
} }
   
/// <summary> /// <summary>
/// Draws a list of sections. /// Draws a list of sections.
/// </summary> /// </summary>
private void DrawSections(IEnumerable<SectionModule> sections) private void DrawSections(IEnumerable<SectionModule> sections)
{ {
foreach (var section in sections) foreach (var section in sections)
{ {
if (!section.IsFloating) if (!section.IsFloating)
{ {
section.Draw(); section.Draw();
} }
} }
} }
   
/// <summary> /// <summary>
/// Initialises all the styles required for this object. /// Initialises all the styles required for this object.
/// </summary> /// </summary>
private void InitialiseStyles() private void InitialiseStyles()
{ {
this.windowStyle = new GUIStyle(HighLogic.Skin.window) this.windowStyle = new GUIStyle(HighLogic.Skin.window)
{ {
margin = new RectOffset(), margin = new RectOffset(),
padding = new RectOffset(5, 5, 0, 5) padding = new RectOffset(5, 5, 0, 5)
}; };
   
this.titleStyle = new GUIStyle(HighLogic.Skin.label) this.titleStyle = new GUIStyle(HighLogic.Skin.label)
{ {
margin = new RectOffset(0, 0, 5, 3), margin = new RectOffset(0, 0, 5, 3),
padding = new RectOffset(), padding = new RectOffset(),
alignment = TextAnchor.MiddleCenter, alignment = TextAnchor.MiddleCenter,
fontSize = (int)(13 * GuiDisplaySize.Offset), fontSize = (int)(13 * GuiDisplaySize.Offset),
fontStyle = FontStyle.Bold, fontStyle = FontStyle.Bold,
stretchWidth = true stretchWidth = true
}; };
   
this.buttonStyle = new GUIStyle(HighLogic.Skin.button) this.buttonStyle = new GUIStyle(HighLogic.Skin.button)
{ {
normal = normal =
{ {
textColor = Color.white textColor = Color.white
}, },
margin = new RectOffset(), margin = new RectOffset(),
padding = new RectOffset(), padding = new RectOffset(),
alignment = TextAnchor.MiddleCenter, alignment = TextAnchor.MiddleCenter,
fontSize = (int)(11 * GuiDisplaySize.Offset), fontSize = (int)(11 * GuiDisplaySize.Offset),
fontStyle = FontStyle.Bold, fontStyle = FontStyle.Bold,
fixedWidth = 60.0f * GuiDisplaySize.Offset, fixedWidth = 60.0f * GuiDisplaySize.Offset,
fixedHeight = 25.0f * GuiDisplaySize.Offset, fixedHeight = 25.0f * GuiDisplaySize.Offset,
}; };
} }
   
/// <summary> /// <summary>
/// Load the stack's state. /// Load the stack's state.
/// </summary> /// </summary>
private void Load() private void Load()
{ {
try try
{ {
var handler = SettingHandler.Load("DisplayStack.xml"); var handler = SettingHandler.Load("DisplayStack.xml");
this.Hidden = handler.Get("hidden", this.Hidden); this.Hidden = handler.Get("hidden", this.Hidden);
this.ShowControlBar = handler.Get("showControlBar", this.ShowControlBar); this.ShowControlBar = handler.Get("showControlBar", this.ShowControlBar);
this.windowPosition.x = handler.Get("windowPositionX", this.windowPosition.x); this.windowPosition.x = handler.Get("windowPositionX", this.windowPosition.x);
this.windowPosition.y = handler.Get("windowPositionY", this.windowPosition.y); this.windowPosition.y = handler.Get("windowPositionY", this.windowPosition.y);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex, "DisplayStack->Load"); Logger.Exception(ex, "DisplayStack->Load");
} }
} }
   
private void OnSizeChanged() private void OnSizeChanged()
{ {
this.InitialiseStyles(); this.InitialiseStyles();
this.RequestResize(); this.RequestResize();
} }
   
/// <summary> /// <summary>
/// Saves the stack's state. /// Saves the stack's state.
/// </summary> /// </summary>
private void Save() private void Save()
{ {
try try
{ {
var handler = new SettingHandler(); var handler = new SettingHandler();
handler.Set("hidden", this.Hidden); handler.Set("hidden", this.Hidden);
handler.Set("showControlBar", this.ShowControlBar); handler.Set("showControlBar", this.ShowControlBar);
handler.Set("windowPositionX", this.windowPosition.x); handler.Set("windowPositionX", this.windowPosition.x);
handler.Set("windowPositionY", this.windowPosition.y); handler.Set("windowPositionY", this.windowPosition.y);
handler.Save("DisplayStack.xml"); handler.Save("DisplayStack.xml");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex, "DisplayStack->Save"); Logger.Exception(ex, "DisplayStack->Save");
} }
} }
   
/// <summary> /// <summary>
/// Draws the display stack window. /// Draws the display stack window.
/// </summary> /// </summary>
private void Window(int windowId) private void Window(int windowId)
{ {
try try
{ {
if (this.ShowControlBar) if (this.ShowControlBar)
{ {
this.DrawControlBar(); this.DrawControlBar();
} }
   
if (SectionLibrary.NumberOfStackSections > 0) if (SectionLibrary.NumberOfStackSections > 0)
{ {
this.DrawSections(SectionLibrary.StockSections); this.DrawSections(SectionLibrary.StockSections);
this.DrawSections(SectionLibrary.CustomSections); this.DrawSections(SectionLibrary.CustomSections);
} }
   
GUI.DragWindow(); GUI.DragWindow();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex, "DisplayStack->Widnow"); Logger.Exception(ex, "DisplayStack->Widnow");
} }
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
using System;  
using System.Collections.Generic;  
   
using KerbalEngineer.Flight.Readouts;  
using KerbalEngineer.Flight.Sections;  
   
using UnityEngine;  
   
#endregion #endregion
   
namespace KerbalEngineer.Flight namespace KerbalEngineer.Flight
{ {
  #region Using Directives
   
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using Extensions;
  using Readouts;
  using Sections;
  using Settings;
  using UnityEngine;
  using VesselSimulator;
   
  #endregion
   
/// <summary> /// <summary>
/// Core management system for the Flight Engineer. /// Core management system for the Flight Engineer.
/// </summary> /// </summary>
  [KSPAddon(KSPAddon.Startup.Flight, false)]
public sealed class FlightEngineerCore : MonoBehaviour public sealed class FlightEngineerCore : MonoBehaviour
{ {
#region Instance #region Instance
   
/// <summary> /// <summary>
/// Gets the current instance of FlightEngineerCore. /// Gets the current instance of FlightEngineerCore.
/// </summary> /// </summary>
public static FlightEngineerCore Instance { get; private set; } public static FlightEngineerCore Instance { get; private set; }
   
#endregion #endregion
   
  #region Fields
   
  private static bool isCareerMode = true;
  private static bool isKerbalLimited = true;
  private static bool isTrackingStationLimited = true;
   
  #endregion
   
#region Constructors #region Constructors
   
  static FlightEngineerCore()
  {
  try
  {
  var handler = SettingHandler.Load("FlightEngineerCore.xml");
  handler.Get("isCareerMode", ref isCareerMode);
  handler.Get("isKerbalLimited", ref isKerbalLimited);
  handler.Get("isTrackingStationLimited", ref isTrackingStationLimited);
  }
  catch (Exception ex)
  {
  Logger.Exception(ex);
  }
  }
   
  #endregion
   
  #region Properties
   
  /// <summary>
  /// Gets and sets whether to the Flight Engineer should be run using career limitations.
  /// </summary>
  public static bool IsCareerMode
  {
  get { return isCareerMode; }
  set
  {
  try
  {
  if (isCareerMode != value)
  {
  var handler = SettingHandler.Load("FlightEngineerCore.xml");
  handler.Set("isCareerMode", value);
  handler.Save("FlightEngineerCore.xml");
  }
  isCareerMode = value;
  }
  catch (Exception ex)
  {
  Logger.Exception(ex);
  }
  }
  }
   
  /// <summary>
  /// Gets whether the FlightEngineer should be displayed.
  /// </summary>
  public static bool IsDisplayable
  {
  get
  {
  if (isCareerMode)
  {
  if (isKerbalLimited && FlightGlobals.ActiveVessel.GetVesselCrew().Exists(c => c.experienceTrait.TypeName == "Engineer"))
  {
  return true;
  }
  if (isTrackingStationLimited && ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) == 1.0f)
  {
  return true;
  }
  return FlightGlobals.ActiveVessel.parts.Any(p => p.HasModule<FlightEngineerModule>());
  }
   
  return true;
  }
  }
   
  /// <summary>
  /// Gets and sets whether to the Flight Engineer should be kerbal limited.
  /// </summary>
  public static bool IsKerbalLimited
  {
  get { return isKerbalLimited; }
  set
  {
  try
  {
  if (isKerbalLimited != value)
  {
  var handler = SettingHandler.Load("FlightEngineerCore.xml");
  handler.Set("isKerbalLimited", value);
  handler.Save("FlightEngineerCore.xml");
  }
  isKerbalLimited = value;
  }
  catch (Exception ex)
  {
  Logger.Exception(ex);
  }
  }
  }
   
  /// <summary>
  /// Gets and sets whether to the Flight Engineer should be tracking station limited.
  /// </summary>
  public static bool IsTrackingStationLimited
  {
  get { return isTrackingStationLimited; }
  set
  {
  try
  {
  if (isTrackingStationLimited != value)
  {
  var handler = SettingHandler.Load("FlightEngineerCore.xml");
  handler.Set("isTrackingStationLimited", value);
  handler.Save("FlightEngineerCore.xml");
  }
  isTrackingStationLimited = value;
  }
  catch (Exception ex)
  {
  Logger.Exception(ex);
  }
  }
  }
   
  /// <summary>
  /// Gets the editor windows for sections with open editors.
  /// </summary>
  public List<SectionEditor> SectionEditors { get; private set; }
   
  /// <summary>
  /// Gets the section windows for floating sections.
  /// </summary>
  public List<SectionWindow> SectionWindows { get; private set; }
   
  /// <summary>
  /// Gets the list of currently running updatable modules.
  /// </summary>
  public List<IUpdatable> UpdatableModules { get; private set; }
   
  #endregion
   
  #region Methods
   
  /// <summary>
  /// Creates a section editor, adds it to the FlightEngineerCore and returns a reference to it.
  /// </summary>
  public SectionEditor AddSectionEditor(SectionModule section)
  {
  try
  {
  var editor = this.gameObject.AddComponent<SectionEditor>();
  editor.ParentSection = section;
  editor.Position = new Rect(section.EditorPositionX, section.EditorPositionY, SectionEditor.Width, SectionEditor.Height);
  this.SectionEditors.Add(editor);
  return editor;
  }
  catch (Exception ex)
  {
  Logger.Exception(ex);
  return null;
  }
  }
   
  /// <summary>
  /// Creates a section window, adds it to the FlightEngineerCore and returns a reference to it.
  /// </summary>
  public SectionWindow AddSectionWindow(SectionModule section)
  {
  try
  {
  var window = this.gameObject.AddComponent<SectionWindow>();
  window.ParentSection = section;
  window.WindowPosition = new Rect(section.FloatingPositionX, section.FloatingPositionY, 0, 0);
  this.SectionWindows.Add(window);
  return window;
  }
  catch (Exception ex)
  {
  Logger.Exception(ex);
  return null;
  }
  }
   
  /// <summary>
  /// Adds an updatable object to be automatically updated every frame and will ignore duplicate objects.
  /// </summary>
  public void AddUpdatable(IUpdatable updatable)
  {
  try
  {
  if (!this.UpdatableModules.Contains(updatable))
  {
  this.UpdatableModules.Add(updatable);
  }
  }
  catch (Exception ex)
  {
  Logger.Exception(ex);
  }
  }
   
/// <summary> /// <summary>
/// Create base Flight Engineer child objects. /// Create base Flight Engineer child objects.
/// </summary> /// </summary>
private void Awake() private void Awake()
{ {
try try
{ {
Instance = this; Instance = this;
   
this.SectionWindows = new List<SectionWindow>(); this.SectionWindows = new List<SectionWindow>();
this.SectionEditors = new List<SectionEditor>(); this.SectionEditors = new List<SectionEditor>();
this.UpdatableModules = new List<IUpdatable>(); this.UpdatableModules = new List<IUpdatable>();
   
  SimManager.UpdateModSettings();
   
Logger.Log("FlightEngineerCore->Awake"); Logger.Log("FlightEngineerCore->Awake");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex, "FlightEngineerCore->Awake"); Logger.Exception(ex);
  }
  }
   
  /// <summary>
  /// Fixed update all required Flight Engineer objects.
  /// </summary>
  private void FixedUpdate()
  {
  try
  {
  SectionLibrary.FixedUpdate();
  }
  catch (Exception ex)
  {
  Logger.Exception(ex);
  }
  }
   
  /// <summary>
  /// Force the destruction of child objects on core destruction.
  /// </summary>
  private void OnDestroy()
  {
  try
  {
  SectionLibrary.Save();
   
  foreach (var window in this.SectionWindows)
  {
  print("[FlightEngineer]: Destroying Floating Window for " + window.ParentSection.Name);
  Destroy(window);
  }
   
  foreach (var editor in this.SectionEditors)
  {
  print("[FlightEngineer]: Destroying Editor Window for " + editor.ParentSection.Name);
  Destroy(editor);
  }
   
  Logger.Log("FlightEngineerCore->OnDestroy");
  }
  catch (Exception ex)
  {
  Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Initialises the object's state on creation. /// Initialises the object's state on creation.
/// </summary> /// </summary>
private void Start() private void Start()
{ {
try try
{ {
SectionLibrary.Load(); SectionLibrary.Load();
ReadoutLibrary.Reset(); ReadoutLibrary.Reset();
Logger.Log("FlightEngineerCore->Start"); Logger.Log("FlightEngineerCore->Start");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex, "FlightEngineerCore->Start");  
}  
}  
   
#endregion  
   
#region Properties  
   
/// <summary>  
/// Gets the section windows for floating sections.  
/// </summary>  
public List<SectionWindow> SectionWindows { get; private set; }  
   
/// <summary>  
/// Gets the editor windows for sections with open editors.  
/// </summary>  
public List<SectionEditor> SectionEditors { get; private set; }  
   
/// <summary>  
/// Gets the list of currently running updatable modules.  
/// </summary>  
public List<IUpdatable> UpdatableModules { get; private set; }  
   
#endregion  
   
#region Updating  
   
/// <summary>  
/// Fixed update all required Flight Engineer objects.  
/// </summary>  
private void FixedUpdate()  
{  
try  
{  
SectionLibrary.FixedUpdate();  
}  
catch (Exception ex)  
{  
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Update all required Flight Engineer objects. /// Update all required Flight Engineer objects.
/// </summary> /// </summary>
private void Update() private void Update()
{ {
try try
{ {
SectionLibrary.Update(); SectionLibrary.Update();
this.UpdateModules(); this.UpdateModules();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex, "FlightEngineerCore->Update"); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Update all updatable modules. /// Update all updatable modules.
/// </summary> /// </summary>
private void UpdateModules() private void UpdateModules()
{ {
try try
{ {
foreach (var updatable in this.UpdatableModules) foreach (var updatable in this.UpdatableModules)
{ {
if (updatable is IUpdateRequest) if (updatable is IUpdateRequest)
{ {
var request = updatable as IUpdateRequest; var request = updatable as IUpdateRequest;
if (request.UpdateRequested) if (request.UpdateRequested)
{ {
updatable.Update(); updatable.Update();
request.UpdateRequested = false; request.UpdateRequested = false;
} }
} }
else else
{ {
updatable.Update(); updatable.Update();
} }
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex, "FlightEngineerCore->UpdateModules"); Logger.Exception(ex);
}  
}  
   
#endregion  
   
#region Destruction  
   
/// <summary>  
/// Force the destruction of child objects on core destruction.  
/// </summary>  
private void OnDestroy()  
{  
try  
{  
SectionLibrary.Save();  
   
foreach (var window in this.SectionWindows)  
{  
print("[FlightEngineer]: Destroying Floating Window for " + window.ParentSection.Name);  
Destroy(window);  
}  
   
foreach (var editor in this.SectionEditors)  
{  
print("[FlightEngineer]: Destroying Editor Window for " + editor.ParentSection.Name);  
Destroy(editor);  
}  
   
Logger.Log("FlightEngineerCore->OnDestroy");  
}  
catch (Exception ex)  
{  
Logger.Exception(ex, "FlightEngineerCore->OnDestroy");  
}  
}  
   
#endregion  
   
#region Methods  
   
/// <summary>  
/// Creates a section window, adds it to the FlightEngineerCore and returns a reference to it.  
/// </summary>  
public SectionWindow AddSectionWindow(SectionModule section)  
{  
try  
{  
var window = this.gameObject.AddComponent<SectionWindow>();  
window.ParentSection = section;  
window.WindowPosition = new Rect(section.FloatingPositionX, section.FloatingPositionY, 0, 0);  
this.SectionWindows.Add(window);  
return window;  
}  
catch (Exception ex)  
{  
Logger.Exception(ex, "FlightEngineerCore->AddSectionWindow");  
return null;  
}  
}  
   
/// <summary>  
/// Creates a section editor, adds it to the FlightEngineerCore and returns a reference to it.  
/// </summary>  
public SectionEditor AddSectionEditor(SectionModule section)  
{  
try  
{  
var editor = this.gameObject.AddComponent<SectionEditor>();  
editor.ParentSection = section;  
editor.Position = new Rect(section.EditorPositionX, section.EditorPositionY, SectionEditor.Width, SectionEditor.Height);  
this.SectionEditors.Add(editor);  
return editor;  
}  
catch (Exception ex)  
{  
Logger.Exception(ex, "FlightEngineerCore->AddSectionEditor");  
return null;  
}  
}  
   
/// <summary>  
/// Adds an updatable object to be automatically updated every frame and will ignore duplicate objects.  
/// </summary>  
public void AddUpdatable(IUpdatable updatable)  
{  
try  
{  
if (!this.UpdatableModules.Contains(updatable))  
{  
this.UpdatableModules.Add(updatable);  
}  
}  
catch (Exception ex)  
{  
Logger.Exception(ex, "FlightEngineerCore->AddUpdatable");  
} }
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
using System;  
using System.Linq;  
   
#endregion #endregion
   
namespace KerbalEngineer.Flight namespace KerbalEngineer.Flight
{ {
/// <summary> /// <summary>
/// Module that can be attached to parts, giving them FlightEngineerCore management. /// Module that can be attached to parts, giving them FlightEngineerCore management.
/// </summary> /// </summary>
public sealed class FlightEngineerModule : PartModule public class FlightEngineerModule : PartModule { }
{  
#region Fields  
   
/// <summary>  
/// Contains the current FlightEngineerCore through the lifespan of this part.  
/// </summary>  
private FlightEngineerCore flightEngineerCore;  
   
#endregion  
   
#region Updating  
   
/// <summary>  
/// Logic to create and destroy the FlightEngineerCore.  
/// </summary>  
private void Update()  
{  
try  
{  
if (!HighLogic.LoadedSceneIsFlight || FlightEngineerPartless.IsPartless)  
{  
return;  
}  
   
if (this.vessel == FlightGlobals.ActiveVessel)  
{  
// Checks for an existing instance of FlightEngineerCore, and if this part is the first part containing FlightEngineerModule within the vessel.  
if (flightEngineerCore == null && this.part == this.vessel.parts.FirstOrDefault(p => p.Modules.Contains("FlightEngineerModule")))  
{  
this.flightEngineerCore = this.gameObject.AddComponent<FlightEngineerCore>();  
}  
}  
else if (flightEngineerCore != null)  
{  
// Using DestroyImmediate to force early destruction and keep saving/loading in synch when switching vessels.  
DestroyImmediate(flightEngineerCore);  
}  
}  
catch (Exception ex)  
{  
Logger.Exception(ex, "FlightEngineerModule->Update");  
}  
}  
   
#endregion  
   
#region Destruction  
   
/// <summary>  
/// Force the destruction of the FlightEngineerCore on part destruction.  
/// </summary>  
private void OnDestroy()  
{  
try  
{  
if (flightEngineerCore != null)  
{  
DestroyImmediate(flightEngineerCore);  
}  
}  
catch (Exception ex)  
{  
Logger.Exception(ex, "FlightEngineerModule->OnDestroy");  
}  
}  
   
#endregion  
}  
} }
//  
// Kerbal Engineer Redux  
//  
// Copyright (C) 2014 CYBUTEK  
//  
// 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/>.  
//  
 
#region Using Directives  
 
using System;  
 
using KerbalEngineer.Settings;  
 
using UnityEngine;  
 
#endregion  
 
namespace KerbalEngineer.Flight  
{  
[KSPAddon(KSPAddon.Startup.Flight, false)]  
public class FlightEngineerPartless : MonoBehaviour  
{  
#region Fields  
 
private FlightEngineerCore flightEngineerCore;  
 
#endregion  
 
#region Initialisation  
 
static FlightEngineerPartless()  
{  
try  
{  
var handler = SettingHandler.Load("FlightEngineerPartless.xml");  
handler.Get("isPartless", ref isPartless);  
}  
catch (Exception ex)  
{  
Logger.Exception(ex, "FlightEngineerPartless->FlightEngineerPartless");  
}  
}  
 
private void Awake()  
{  
try  
{  
if (isPartless)  
{  
this.flightEngineerCore = this.gameObject.AddComponent<FlightEngineerCore>();  
}  
}  
catch (Exception ex)  
{  
Logger.Exception(ex, "FlightEngineerPartless->Awake");  
}  
}  
 
#endregion  
 
#region Properties  
 
private static bool isPartless = true;  
 
public static bool IsPartless  
{  
get { return isPartless; }  
set  
{  
try  
{  
if (isPartless != value)  
{  
var handler = SettingHandler.Load("FlightEngineerPartless.xml");  
handler.Set("isPartless", value);  
handler.Save("FlightEngineerPartless.xml");  
}  
isPartless = value;  
}  
catch (Exception ex)  
{  
Logger.Exception(ex, "FlightEngineerPartless->IsPartless");  
}  
}  
}  
 
#endregion  
}  
}  
  //
  // Kerbal Engineer Redux
  //
  // Copyright (C) 2014 CYBUTEK
  //
  // 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/>.
  //
 
  #region Using Directives
 
  using System;
 
  using KerbalEngineer.Flight.Sections;
  using KerbalEngineer.Helpers;
 
  using UnityEngine;
 
  #endregion
 
  namespace KerbalEngineer.Flight.Readouts.Miscellaneous
  {
  public class SystemTime : ReadoutModule
  {
 
 
  #region Constructors
 
  public SystemTime()
  {
  this.Name = "System Time";
  this.Category = ReadoutCategory.GetCategory("Miscellaneous");
  this.HelpString = String.Empty;
  this.IsDefault = false;
  }
 
  #endregion
 
  #region Methods: public
 
  public override void Draw(SectionModule section)
  {
  this.DrawLine(DateTime.Now.ToLongTimeString(), section.IsHud);
  }
 
  #endregion
 
  }
  }
  //
  // Kerbal Engineer Redux
  //
  // Copyright (C) 2014 CYBUTEK
  //
  // 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/>.
  //
 
  #region Using Directives
 
  using System;
 
  using KerbalEngineer.Extensions;
  using KerbalEngineer.Flight.Sections;
 
  #endregion
 
  namespace KerbalEngineer.Flight.Readouts.Orbital
  {
  public class MeanAnomalyAtEpoc : ReadoutModule
  {
  #region Constructors
 
  public MeanAnomalyAtEpoc()
  {
  this.Name = "Mean Anomaly at Epoc";
  this.Category = ReadoutCategory.GetCategory("Orbital");
  this.HelpString = String.Empty;
  this.IsDefault = false;
  }
 
  #endregion
 
  #region Methods: public
 
  public override void Draw(SectionModule section)
  {
  this.DrawLine(FlightGlobals.ship_orbit.meanAnomalyAtEpoch.ToAngle(), section.IsHud);
  }
 
  #endregion
  }
  }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
namespace KerbalEngineer.Flight.Readouts namespace KerbalEngineer.Flight.Readouts
{ {
#region Using Directives #region Using Directives
   
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Miscellaneous; using Miscellaneous;
using Orbital; using Orbital;
using Orbital.ManoeuvreNode; using Orbital.ManoeuvreNode;
using Rendezvous; using Rendezvous;
using Settings; using Settings;
using Surface; using Surface;
using Vessel; using Vessel;
using AltitudeSeaLevel = Surface.AltitudeSeaLevel; using AltitudeSeaLevel = Surface.AltitudeSeaLevel;
using ApoapsisHeight = Orbital.ApoapsisHeight; using ApoapsisHeight = Orbital.ApoapsisHeight;
using OrbitalPeriod = Orbital.OrbitalPeriod; using OrbitalPeriod = Orbital.OrbitalPeriod;
using PeriapsisHeight = Orbital.PeriapsisHeight; using PeriapsisHeight = Orbital.PeriapsisHeight;
using SemiMajorAxis = Orbital.SemiMajorAxis; using SemiMajorAxis = Orbital.SemiMajorAxis;
using SemiMinorAxis = Orbital.SemiMinorAxis; using SemiMinorAxis = Orbital.SemiMinorAxis;
using TimeToApoapsis = Orbital.TimeToApoapsis; using TimeToApoapsis = Orbital.TimeToApoapsis;
using TimeToPeriapsis = Orbital.TimeToPeriapsis; using TimeToPeriapsis = Orbital.TimeToPeriapsis;
   
#endregion #endregion
   
public static class ReadoutLibrary public static class ReadoutLibrary
{ {
#region Fields #region Fields
   
private static List<ReadoutModule> readouts = new List<ReadoutModule>(); private static List<ReadoutModule> readouts = new List<ReadoutModule>();
   
#endregion #endregion
   
#region Constructors #region Constructors
   
/// <summary> /// <summary>
/// Sets up and populates the readout library with the stock readouts. /// Sets up and populates the readout library with the stock readouts.
/// </summary> /// </summary>
static ReadoutLibrary() static ReadoutLibrary()
{ {
try try
{ {
ReadoutCategory.SetCategory("Orbital", "Readout for orbital manovoeures."); ReadoutCategory.SetCategory("Orbital", "Readout for orbital manovoeures.");
ReadoutCategory.SetCategory("Surface", "Surface and atmospheric readouts."); ReadoutCategory.SetCategory("Surface", "Surface and atmospheric readouts.");
ReadoutCategory.SetCategory("Vessel", "Vessel performance statistics."); ReadoutCategory.SetCategory("Vessel", "Vessel performance statistics.");
ReadoutCategory.SetCategory("Rendezvous", "Readouts for rendezvous manovoeures."); ReadoutCategory.SetCategory("Rendezvous", "Readouts for rendezvous manovoeures.");
ReadoutCategory.SetCategory("Miscellaneous", "Miscellaneous readouts."); ReadoutCategory.SetCategory("Miscellaneous", "Miscellaneous readouts.");
ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital"); ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital");
   
// Orbital // Orbital
readouts.Add(new ApoapsisHeight()); readouts.Add(new ApoapsisHeight());
readouts.Add(new PeriapsisHeight()); readouts.Add(new PeriapsisHeight());
readouts.Add(new TimeToApoapsis()); readouts.Add(new TimeToApoapsis());
readouts.Add(new TimeToPeriapsis()); readouts.Add(new TimeToPeriapsis());
readouts.Add(new Inclination()); readouts.Add(new Inclination());
readouts.Add(new TimeToEquatorialAscendingNode()); readouts.Add(new TimeToEquatorialAscendingNode());
readouts.Add(new TimeToEquatorialDescendingNode()); readouts.Add(new TimeToEquatorialDescendingNode());
readouts.Add(new AngleToEquatorialAscendingNode()); readouts.Add(new AngleToEquatorialAscendingNode());
readouts.Add(new AngleToEquatorialDescendingNode()); readouts.Add(new AngleToEquatorialDescendingNode());
readouts.Add(new Eccentricity()); readouts.Add(new Eccentricity());
readouts.Add(new OrbitalSpeed()); readouts.Add(new OrbitalSpeed());
readouts.Add(new OrbitalPeriod()); readouts.Add(new OrbitalPeriod());
readouts.Add(new CurrentSoi()); readouts.Add(new CurrentSoi());
readouts.Add(new LongitudeOfAscendingNode()); readouts.Add(new LongitudeOfAscendingNode());
readouts.Add(new LongitudeOfPeriapsis()); readouts.Add(new LongitudeOfPeriapsis());
readouts.Add(new ArgumentOfPeriapsis()); readouts.Add(new ArgumentOfPeriapsis());
readouts.Add(new TrueAnomaly()); readouts.Add(new TrueAnomaly());
readouts.Add(new MeanAnomaly()); readouts.Add(new MeanAnomaly());
  readouts.Add(new MeanAnomalyAtEpoc());
readouts.Add(new EccentricAnomaly()); readouts.Add(new EccentricAnomaly());
readouts.Add(new SemiMajorAxis()); readouts.Add(new SemiMajorAxis());
readouts.Add(new SemiMinorAxis()); readouts.Add(new SemiMinorAxis());
readouts.Add(new AngleToPrograde()); readouts.Add(new AngleToPrograde());
readouts.Add(new AngleToRetrograde()); readouts.Add(new AngleToRetrograde());
readouts.Add(new NodeProgradeDeltaV()); readouts.Add(new NodeProgradeDeltaV());
readouts.Add(new NodeNormalDeltaV()); readouts.Add(new NodeNormalDeltaV());
readouts.Add(new NodeRadialDeltaV()); readouts.Add(new NodeRadialDeltaV());
readouts.Add(new NodeTotalDeltaV()); readouts.Add(new NodeTotalDeltaV());
readouts.Add(new NodeBurnTime()); readouts.Add(new NodeBurnTime());
readouts.Add(new NodeHalfBurnTime()); readouts.Add(new NodeHalfBurnTime());
readouts.Add(new NodeTimeToManoeuvre()); readouts.Add(new NodeTimeToManoeuvre());
readouts.Add(new NodeTimeToHalfBurn()); readouts.Add(new NodeTimeToHalfBurn());
readouts.Add(new NodeAngleToPrograde()); readouts.Add(new NodeAngleToPrograde());
readouts.Add(new NodeAngleToRetrograde()); readouts.Add(new NodeAngleToRetrograde());
   
// Surface // Surface
readouts.Add(new AltitudeSeaLevel()); readouts.Add(new AltitudeSeaLevel());
readouts.Add(new AltitudeTerrain()); readouts.Add(new AltitudeTerrain());
readouts.Add(new VerticalSpeed()); readouts.Add(new VerticalSpeed());
readouts.Add(new VerticalAcceleration()); readouts.Add(new VerticalAcceleration());
readouts.Add(new HorizontalSpeed()); readouts.Add(new HorizontalSpeed());
readouts.Add(new HorizontalAcceleration()); readouts.Add(new HorizontalAcceleration());
readouts.Add(new Latitude()); readouts.Add(new Latitude());
readouts.Add(new Longitude()); readouts.Add(new Longitude());
readouts.Add(new GeeForce()); readouts.Add(new GeeForce());
readouts.Add(new TerminalVelocity()); readouts.Add(new TerminalVelocity());
readouts.Add(new AtmosphericEfficiency()); readouts.Add(new AtmosphericEfficiency());
readouts.Add(new Biome()); readouts.Add(new Biome());
readouts.Add(new Situation()); readouts.Add(new Situation());
readouts.Add(new Slope()); readouts.Add(new Slope());
readouts.Add(new ImpactTime()); readouts.Add(new ImpactTime());
readouts.Add(new ImpactLongitude()); readouts.Add(new ImpactLongitude());
readouts.Add(new ImpactLatitude()); readouts.Add(new ImpactLatitude());
readouts.Add(new ImpactAltitude()); readouts.Add(new ImpactAltitude());
readouts.Add(new ImpactBiome()); readouts.Add(new ImpactBiome());
   
// Vessel // Vessel
readouts.Add(new DeltaVStaged()); readouts.Add(new DeltaVStaged());
readouts.Add(new DeltaVCurrent()); readouts.Add(new DeltaVCurrent());
readouts.Add(new DeltaVTotal()); readouts.Add(new DeltaVTotal());
readouts.Add(new DeltaVCurrentTotal()); readouts.Add(new DeltaVCurrentTotal());
readouts.Add(new SpecificImpulse()); readouts.Add(new SpecificImpulse());
readouts.Add(new Mass()); readouts.Add(new Mass());
readouts.Add(new Thrust()); readouts.Add(new Thrust());
readouts.Add(new ThrustToWeight()); readouts.Add(new ThrustToWeight());
readouts.Add(new ThrustOffsetAngle()); readouts.Add(new ThrustOffsetAngle());
readouts.Add(new ThrustTorque()); readouts.Add(new ThrustTorque());
readouts.Add(new SurfaceThrustToWeight()); readouts.Add(new SurfaceThrustToWeight());
readouts.Add(new Acceleration()); readouts.Add(new Acceleration());
readouts.Add(new SuicideBurnAltitude()); readouts.Add(new SuicideBurnAltitude());
readouts.Add(new SuicideBurnDistance()); readouts.Add(new SuicideBurnDistance());
readouts.Add(new SuicideBurnDeltaV()); readouts.Add(new SuicideBurnDeltaV());
readouts.Add(new IntakeAirUsage()); readouts.Add(new IntakeAirUsage());
readouts.Add(new IntakeAirDemand()); readouts.Add(new IntakeAirDemand());
readouts.Add(new IntakeAirSupply()); readouts.Add(new IntakeAirSupply());
readouts.Add(new IntakeAirDemandSupply()); readouts.Add(new IntakeAirDemandSupply());
readouts.Add(new PartCount()); readouts.Add(new PartCount());
readouts.Add(new Heading()); readouts.Add(new Heading());
readouts.Add(new Pitch()); readouts.Add(new Pitch());
readouts.Add(new Roll()); readouts.Add(new Roll());
readouts.Add(new HeadingRate()); readouts.Add(new HeadingRate());
readouts.Add(new PitchRate()); readouts.Add(new PitchRate());
readouts.Add(new RollRate()); readouts.Add(new RollRate());
   
// Rendezvous // Rendezvous
readouts.Add(new TargetSelector()); readouts.Add(new TargetSelector());
readouts.Add(new PhaseAngle()); readouts.Add(new PhaseAngle());
readouts.Add(new InterceptAngle()); readouts.Add(new InterceptAngle());
readouts.Add(new RelativeVelocity()); readouts.Add(new RelativeVelocity());
readouts.Add(new RelativeSpeed()); readouts.Add(new RelativeSpeed());
readouts.Add(new RelativeInclination()); readouts.Add(new RelativeInclination());
readouts.Add(new TimeToRelativeAscendingNode()); readouts.Add(new TimeToRelativeAscendingNode());
readouts.Add(new TimeToRelativeDescendingNode()); readouts.Add(new TimeToRelativeDescendingNode());
readouts.Add(new AngleToRelativeAscendingNode()); readouts.Add(new AngleToRelativeAscendingNode());
readouts.Add(new AngleToRelativeDescendingNode()); readouts.Add(new AngleToRelativeDescendingNode());
readouts.Add(new Rendezvous.AltitudeSeaLevel()); readouts.Add(new Rendezvous.AltitudeSeaLevel());
readouts.Add(new Rendezvous.ApoapsisHeight()); readouts.Add(new Rendezvous.ApoapsisHeight());
readouts.Add(new Rendezvous.PeriapsisHeight()); readouts.Add(new Rendezvous.PeriapsisHeight());
readouts.Add(new Rendezvous.TimeToApoapsis()); readouts.Add(new Rendezvous.TimeToApoapsis());
readouts.Add(new Rendezvous.TimeToPeriapsis()); readouts.Add(new Rendezvous.TimeToPeriapsis());
readouts.Add(new Distance()); readouts.Add(new Distance());
readouts.Add(new Rendezvous.OrbitalPeriod()); readouts.Add(new Rendezvous.OrbitalPeriod());
readouts.Add(new Rendezvous.SemiMajorAxis()); readouts.Add(new Rendezvous.SemiMajorAxis());
readouts.Add(new Rendezvous.SemiMinorAxis()); readouts.Add(new Rendezvous.SemiMinorAxis());
   
// Misc // Misc
readouts.Add(new Separator()); readouts.Add(new Separator());
readouts.Add(new GuiSizeAdjustor()); readouts.Add(new GuiSizeAdjustor());
readouts.Add(new SimulationDelay()); readouts.Add(new SimulationDelay());
readouts.Add(new TimeReference()); readouts.Add(new TimeReference());
readouts.Add(new VectoredThrustToggle()); readouts.Add(new VectoredThrustToggle());
  readouts.Add(new SystemTime());
   
LoadHelpStrings(); LoadHelpStrings();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
   
#region Properties #region Properties
   
/// <summary> /// <summary>
/// Gets and sets the available readout modules. /// Gets and sets the available readout modules.
/// </summary> /// </summary>
public static List<ReadoutModule> Readouts public static List<ReadoutModule> Readouts
{ {
get { return readouts; } get { return readouts; }
set { readouts = value; } set { readouts = value; }
} }
   
#endregion #endregion
   
#region Methods #region Methods
   
/// <summary> /// <summary>
/// Gets a list of readout modules which are associated with the specified category. /// Gets a list of readout modules which are associated with the specified category.
/// </summary> /// </summary>
public static List<ReadoutModule> GetCategory(ReadoutCategory category) public static List<ReadoutModule> GetCategory(ReadoutCategory category)
{ {
return readouts.Where(r => r.Category == category).ToList(); return readouts.Where(r => r.Category == category).ToList();
} }
   
/// <summary> /// <summary>
/// Gets a readout module with the specified name or class name. (Returns null if not found.) /// Gets a readout module with the specified name or class name. (Returns null if not found.)
/// </summary> /// </summary>
public static ReadoutModule GetReadout(string name) public static ReadoutModule GetReadout(string name)
{ {
return readouts.FirstOrDefault(r => r.Name == name || r.GetType().Name == name || r.Category + "." + r.GetType().Name == name); return readouts.FirstOrDefault(r => r.Name == name || r.GetType().Name == name || r.Category + "." + r.GetType().Name == name);
} }
   
/// <summary> /// <summary>
/// Resets all the readout modules. /// Resets all the readout modules.
/// </summary> /// </summary>
public static void Reset() public static void Reset()
{ {
foreach (var readout in readouts) foreach (var readout in readouts)
{ {
readout.Reset(); readout.Reset();
} }
} }
   
/// <summary> /// <summary>
/// Loads the help strings from file. /// Loads the help strings from file.
/// </summary> /// </summary>
private static void LoadHelpStrings() private static void LoadHelpStrings()
{ {
try try
{ {
var handler = SettingHandler.Load("HelpStrings.xml"); var handler = SettingHandler.Load("HelpStrings.xml");
foreach (var readout in readouts) foreach (var readout in readouts)
{ {
readout.HelpString = handler.GetSet(readout.Category + "." + readout.GetType().Name, readout.HelpString); readout.HelpString = handler.GetSet(readout.Category + "." + readout.GetType().Name, readout.HelpString);
} }
handler.Save("HelpStrings.xml"); handler.Save("HelpStrings.xml");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
namespace KerbalEngineer.Flight.Readouts.Vessel namespace KerbalEngineer.Flight.Readouts.Vessel
{ {
#region Using Directives #region Using Directives
   
using Helpers; using Helpers;
using Sections; using Sections;
   
#endregion #endregion
   
public class PartCount : ReadoutModule public class PartCount : ReadoutModule
{ {
#region Constructors #region Constructors
   
public PartCount() public PartCount()
{ {
this.Name = "Part Count"; this.Name = "Part Count";
this.Category = ReadoutCategory.GetCategory("Vessel"); this.Category = ReadoutCategory.GetCategory("Vessel");
this.HelpString = string.Empty; this.HelpString = string.Empty;
this.IsDefault = true; this.IsDefault = true;
} }
   
#endregion #endregion
   
#region Methods #region Methods
   
public override void Draw(SectionModule section) public override void Draw(SectionModule section)
{ {
if (SimulationProcessor.ShowDetails) if (SimulationProcessor.ShowDetails)
{ {
this.DrawLine(Units.Concat(SimulationProcessor.LastStage.partCount, SimulationProcessor.LastStage.totalPartCount), section.IsHud); this.DrawLine(Units.ConcatF(SimulationProcessor.LastStage.partCount, SimulationProcessor.LastStage.totalPartCount), section.IsHud);
} }
} }
   
public override void Reset() public override void Reset()
{ {
FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance); FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance);
} }
   
public override void Update() public override void Update()
{ {
SimulationProcessor.RequestUpdate(); SimulationProcessor.RequestUpdate();
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
using KerbalEngineer.Extensions; using KerbalEngineer.Extensions;
using KerbalEngineer.Helpers; using KerbalEngineer.Helpers;
   
using UnityEngine; using UnityEngine;
   
#endregion #endregion
   
namespace KerbalEngineer.Flight.Sections namespace KerbalEngineer.Flight.Sections
{ {
public class SectionWindow : MonoBehaviour public class SectionWindow : MonoBehaviour
{ {
#region Fields #region Fields
   
private bool resizeRequested; private bool resizeRequested;
private int windowId; private int windowId;
private Rect windowPosition; private Rect windowPosition;
   
#endregion #endregion
   
#region Properties #region Properties
   
/// <summary> /// <summary>
/// Gets and sets the parent section for the floating section window. /// Gets and sets the parent section for the floating section window.
/// </summary> /// </summary>
public SectionModule ParentSection { get; set; } public SectionModule ParentSection { get; set; }
   
/// <summary> /// <summary>
/// Gets and sets the window position. /// Gets and sets the window position.
/// </summary> /// </summary>
public Rect WindowPosition public Rect WindowPosition
{ {
get { return this.windowPosition; } get { return this.windowPosition; }
set { this.windowPosition = value; } set { this.windowPosition = value; }
} }
   
#endregion #endregion
   
#region GUIStyles #region GUIStyles
   
#region Fields #region Fields
   
private GUIStyle hudWindowBgStyle; private GUIStyle hudWindowBgStyle;
private GUIStyle hudWindowStyle; private GUIStyle hudWindowStyle;
private GUIStyle windowStyle; private GUIStyle windowStyle;
   
#endregion #endregion
   
/// <summary> /// <summary>
/// Initialises all the styles required for this object. /// Initialises all the styles required for this object.
/// </summary> /// </summary>
private void InitialiseStyles() private void InitialiseStyles()
{ {
this.windowStyle = new GUIStyle(HighLogic.Skin.window) this.windowStyle = new GUIStyle(HighLogic.Skin.window)
{ {
margin = new RectOffset(), margin = new RectOffset(),
padding = new RectOffset(5, 5, 0, 5), padding = new RectOffset(5, 5, 0, 5),
}; };
   
this.hudWindowStyle = new GUIStyle(this.windowStyle) this.hudWindowStyle = new GUIStyle(this.windowStyle)
{ {
normal = normal =
{ {
background = null background = null
}, },
onNormal = onNormal =
{ {
background = null background = null
}, },
padding = new RectOffset(5, 5, 0, 8), padding = new RectOffset(5, 5, 0, 8),
}; };
   
this.hudWindowBgStyle = new GUIStyle(this.hudWindowStyle) this.hudWindowBgStyle = new GUIStyle(this.hudWindowStyle)
{ {
normal = normal =
{ {
background = TextureHelper.CreateTextureFromColour(new Color(0.0f, 0.0f, 0.0f, 0.5f)) background = TextureHelper.CreateTextureFromColour(new Color(0.0f, 0.0f, 0.0f, 0.5f))
}, },
onNormal = onNormal =
{ {
background = TextureHelper.CreateTextureFromColour(new Color(0.0f, 0.0f, 0.0f, 0.5f)) background = TextureHelper.CreateTextureFromColour(new Color(0.0f, 0.0f, 0.0f, 0.5f))
} }
}; };
} }
   
private void OnSizeChanged() private void OnSizeChanged()
{ {
this.InitialiseStyles(); this.InitialiseStyles();
this.RequestResize(); this.RequestResize();
} }
   
#endregion #endregion
   
#region Drawing #region Drawing
   
/// <summary> /// <summary>
/// Called to draw the floating section window when the UI is enabled. /// Called to draw the floating section window when the UI is enabled.
/// </summary> /// </summary>
private void Draw() private void Draw()
{ {
if (this.ParentSection == null || !this.ParentSection.IsVisible || (DisplayStack.Instance.Hidden && !this.ParentSection.IsHud)) if (this.ParentSection == null || !this.ParentSection.IsVisible || (DisplayStack.Instance.Hidden && !this.ParentSection.IsHud) || !FlightEngineerCore.IsDisplayable)
{ {
return; return;
} }
   
if (this.resizeRequested) if (this.resizeRequested)
{ {
this.windowPosition.width = 0; this.windowPosition.width = 0;
this.windowPosition.height = 0; this.windowPosition.height = 0;
this.resizeRequested = false; this.resizeRequested = false;
} }
GUI.skin = null; GUI.skin = null;
this.windowPosition = GUILayout.Window(this.windowId, this.windowPosition, this.Window, string.Empty, this.windowPosition = GUILayout.Window(this.windowId, this.windowPosition, this.Window, string.Empty,
(!this.ParentSection.IsHud || this.ParentSection.IsEditorVisible) ? this.windowStyle (!this.ParentSection.IsHud || this.ParentSection.IsEditorVisible) ? this.windowStyle
: this.ParentSection.IsHudBackground && this.ParentSection.LineCount > 0 : this.ParentSection.IsHudBackground && this.ParentSection.LineCount > 0
? this.hudWindowBgStyle ? this.hudWindowBgStyle
: this.hudWindowStyle).ClampToScreen(); : this.hudWindowStyle).ClampToScreen();
this.ParentSection.FloatingPositionX = this.windowPosition.x; this.ParentSection.FloatingPositionX = this.windowPosition.x;
this.ParentSection.FloatingPositionY = this.windowPosition.y; this.ParentSection.FloatingPositionY = this.windowPosition.y;
} }
   
/// <summary> /// <summary>
/// Draws the floating section window. /// Draws the floating section window.
/// </summary> /// </summary>
private void Window(int windowId) private void Window(int windowId)
{ {
this.ParentSection.Draw(); this.ParentSection.Draw();
   
if (!this.ParentSection.IsHud || this.ParentSection.IsEditorVisible) if (!this.ParentSection.IsHud || this.ParentSection.IsEditorVisible)
{ {
GUI.DragWindow(); GUI.DragWindow();
} }
} }
   
#endregion #endregion
   
#region Destruction #region Destruction
   
/// <summary> /// <summary>
/// Runs when the object is destroyed. /// Runs when the object is destroyed.
/// </summary> /// </summary>
private void OnDestroy() private void OnDestroy()
{ {
RenderingManager.RemoveFromPostDrawQueue(0, this.Draw); RenderingManager.RemoveFromPostDrawQueue(0, this.Draw);
GuiDisplaySize.OnSizeChanged -= this.OnSizeChanged; GuiDisplaySize.OnSizeChanged -= this.OnSizeChanged;
} }
   
#endregion #endregion
   
#region Methods #region Methods
   
/// <summary> /// <summary>
/// Request that the floating section window's size is reset in the next draw call. /// Request that the floating section window's size is reset in the next draw call.
/// </summary> /// </summary>
public void RequestResize() public void RequestResize()
{ {
this.resizeRequested = true; this.resizeRequested = true;
} }
   
#endregion #endregion
   
#region Methods: private #region Methods: private
   
/// <summary> /// <summary>
/// Initialises the object's state on creation. /// Initialises the object's state on creation.
/// </summary> /// </summary>
private void Start() private void Start()
{ {
this.windowId = this.GetHashCode(); this.windowId = this.GetHashCode();
this.InitialiseStyles(); this.InitialiseStyles();
RenderingManager.AddToPostDrawQueue(0, this.Draw); RenderingManager.AddToPostDrawQueue(0, this.Draw);
GuiDisplaySize.OnSizeChanged += this.OnSizeChanged; GuiDisplaySize.OnSizeChanged += this.OnSizeChanged;
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
namespace KerbalEngineer.Helpers namespace KerbalEngineer.Helpers
{ {
#region Using Directives #region Using Directives
   
using System; using System;
   
#endregion #endregion
   
public static class Units public static class Units
{ {
#region Methods #region Methods
   
public static string Concat(int value1, int value2) public static string Concat(int value1, int value2)
{ {
return value1 + " / " + value2; return value1 + " / " + value2;
} }
   
public static string Concat(double value1, double value2, int decimals = 1) public static string ConcatF(double value1, double value2, int decimals = 1)
{ {
return value1.ToString("F" + decimals) + " / " + value2.ToString("F" + decimals); return value1.ToString("F" + decimals) + " / " + value2.ToString("F" + decimals);
} }
   
public static string Concat(double value1, double value2, double value3, int decimals = 1) public static string ConcatF(double value1, double value2, double value3, int decimals = 1)
{ {
return value1.ToString("F" + decimals) + " / " + value2.ToString("F" + decimals) + " / " + value3.ToString("F" + decimals); return value1.ToString("F" + decimals) + " / " + value2.ToString("F" + decimals) + " / " + value3.ToString("F" + decimals);
  }
   
  public static string ConcatN(double value1, double value2, int decimals = 1)
  {
  return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals);
  }
   
  public static string ConcatN(double value1, double value2, double value3, int decimals = 1)
  {
  return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + " / " + value3.ToString("N" + decimals);
  }
   
  public static string Cost(double value, int decimals = 1)
  {
  if (value >= 1000000.0)
  {
  return (value / 1000.0).ToString("N" + decimals) + "K";
  }
  return value.ToString("N" + decimals);
  }
   
  public static string Cost(double value1, double value2, int decimals = 1)
  {
  if (value1 >= 1000000.0 || value2 >= 1000000.0)
  {
  return (value1 / 1000.0).ToString("N" + decimals) + " / " + (value2 / 1000.0).ToString("N" + decimals) + "K";
  }
  return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals);
} }
   
public static string ToAcceleration(double value, int decimals = 2) public static string ToAcceleration(double value, int decimals = 2)
{ {
return value.ToString("N" + decimals) + "m/s²"; return value.ToString("N" + decimals) + "m/s²";
} }
   
public static string ToAcceleration(double value1, double value2, int decimals = 2) public static string ToAcceleration(double value1, double value2, int decimals = 2)
{ {
return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + "m/s²"; return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + "m/s²";
} }
   
public static string ToAngle(double value, int decimals = 5) public static string ToAngle(double value, int decimals = 5)
{ {
return value.ToString("F" + decimals) + "°"; return value.ToString("F" + decimals) + "°";
} }
   
public static string ToDistance(double value, int decimals = 1) public static string ToDistance(double value, int decimals = 1)
{ {
if (Math.Abs(value) < 1000000.0) if (Math.Abs(value) < 1000000.0)
{ {
if (Math.Abs(value) >= 10.0) if (Math.Abs(value) >= 10.0)
{ {
return value.ToString("N" + decimals) + "m"; return value.ToString("N" + decimals) + "m";
} }
   
value *= 100.0; value *= 100.0;
if (Math.Abs(value) >= 100.0) if (Math.Abs(value) >= 100.0)
{ {
return value.ToString("N" + decimals) + "cm"; return value.ToString("N" + decimals) + "cm";
} }
   
value *= 10.0; value *= 10.0;
return value.ToString("N" + decimals) + "mm"; return value.ToString("N" + decimals) + "mm";
} }
   
value /= 1000.0; value /= 1000.0;
if (Math.Abs(value) < 1000000.0) if (Math.Abs(value) < 1000000.0)
{ {
return value.ToString("N" + decimals) + "km"; return value.ToString("N" + decimals) + "km";
} }
   
value /= 1000.0; value /= 1000.0;
return value.ToString("N" + decimals) + "Mm"; return value.ToString("N" + decimals) + "Mm";
} }
   
public static string ToForce(double value) public static string ToForce(double value)
{ {
return value.ToString((value < 100000.0) ? (value < 10000.0) ? (value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0") + "kN"; return value.ToString((value < 100000.0) ? (value < 10000.0) ? (value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0") + "kN";
} }
   
public static string ToForce(double value1, double value2) public static string ToForce(double value1, double value2)
{ {
var format1 = (value1 < 100000.0) ? (value1 < 10000.0) ? (value1 < 100.0) ? (Math.Abs(value1) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0"; var format1 = (value1 < 100000.0) ? (value1 < 10000.0) ? (value1 < 100.0) ? (Math.Abs(value1) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
var format2 = (value2 < 100000.0) ? (value2 < 10000.0) ? (value2 < 100.0) ? (Math.Abs(value2) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0"; var format2 = (value2 < 100000.0) ? (value2 < 10000.0) ? (value2 < 100.0) ? (Math.Abs(value2) < Double.Epsilon) ? "N0" : "N3" : "N2" : "N1" : "N0";
return value1.ToString(format1) + " / " + value2.ToString(format2) + "kN"; return value1.ToString(format1) + " / " + value2.ToString(format2) + "kN";
} }
   
public static string ToMass(double value, int decimals = 0) public static string ToMass(double value, int decimals = 0)
{ {
  if (value >= 1000.0)
  {
  return value.ToString("N" + decimals + 2) + "t";
  }
   
value *= 1000.0; value *= 1000.0;
return value.ToString("N" + decimals) + "kg"; return value.ToString("N" + decimals) + "kg";
} }
   
public static string ToMass(double value1, double value2, int decimals = 0) public static string ToMass(double value1, double value2, int decimals = 0)
{ {
  if (value1 >= 1000.0f || value2 >= 1000.0f)
  {
  return value1.ToString("N" + decimals + 2) + " / " + value2.ToString("N" + decimals + 2) + "t";
  }
   
value1 *= 1000.0; value1 *= 1000.0;
value2 *= 1000.0; value2 *= 1000.0;
return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + "kg"; return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + "kg";
} }
   
public static string ToPercent(double value, int decimals = 2) public static string ToPercent(double value, int decimals = 2)
{ {
value *= 100.0; value *= 100.0;
return value.ToString("F" + decimals) + "%"; return value.ToString("F" + decimals) + "%";
} }
   
public static string ToRate(double value, int decimals = 1) public static string ToRate(double value, int decimals = 1)
{ {
return value < 1.0 ? (value * 60.0).ToString("F" + decimals) + "/min" : value.ToString("F" + decimals) + "/sec"; return value < 1.0 ? (value * 60.0).ToString("F" + decimals) + "/min" : value.ToString("F" + decimals) + "/sec";
} }
   
public static string ToSpeed(double value, int decimals = 2) public static string ToSpeed(double value, int decimals = 2)
{ {
if (Math.Abs(value) < 1.0) if (Math.Abs(value) < 1.0)
{ {
return (value * 1000.0).ToString("N" + decimals) + "mm/s"; return (value * 1000.0).ToString("N" + decimals) + "mm/s";
} }
return value.ToString("N" + decimals) + "m/s"; return value.ToString("N" + decimals) + "m/s";
} }
   
public static string ToTime(double value) public static string ToTime(double value)
{ {
return TimeFormatter.ConvertToString(value); return TimeFormatter.ConvertToString(value);
} }
   
public static string ToTorque(double value) public static string ToTorque(double value)
{ {
return value.ToString((value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N1" : "N0") + "kNm"; return value.ToString((value < 100.0) ? (Math.Abs(value) < Double.Epsilon) ? "N0" : "N1" : "N0") + "kNm";
} }
   
#endregion #endregion
} }
} }
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{39806613-E0B7-46E0-89A6-A569EC538CBB}</ProjectGuid> <ProjectGuid>{39806613-E0B7-46E0-89A6-A569EC538CBB}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>KerbalEngineer</RootNamespace> <RootNamespace>KerbalEngineer</RootNamespace>
<AssemblyName>KerbalEngineer</AssemblyName> <AssemblyName>KerbalEngineer</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>false</DebugSymbols> <DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType> <DebugType>none</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>..\Output\KerbalEngineer\</OutputPath> <OutputPath>..\Output\KerbalEngineer\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType> <DebugType>none</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>..\Output\KerbalEngineer\</OutputPath> <OutputPath>..\Output\KerbalEngineer\</OutputPath>
<DefineConstants> <DefineConstants>
</DefineConstants> </DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks> <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Control\IControlPanel.cs" /> <Compile Include="Control\IControlPanel.cs" />
<Compile Include="Control\Panels\BuildOverlayPanel.cs" /> <Compile Include="Control\Panels\BuildOverlayPanel.cs" />
<Compile Include="Control\Panels\BuildEngineerPanel.cs" /> <Compile Include="Control\Panels\BuildEngineerPanel.cs" />
<Compile Include="Editor\BuildAdvanced.cs" /> <Compile Include="Editor\BuildAdvanced.cs" />
<Compile Include="Editor\BuildOverlay.cs" /> <Compile Include="Editor\BuildOverlay.cs" />
<Compile Include="CelestialBodies.cs" /> <Compile Include="CelestialBodies.cs" />
<Compile Include="Editor\BuildOverlayPartInfo.cs" /> <Compile Include="Editor\BuildOverlayPartInfo.cs" />
<Compile Include="Editor\BuildOverlayResources.cs" /> <Compile Include="Editor\BuildOverlayResources.cs" />
<Compile Include="Editor\BuildOverlayVessel.cs" /> <Compile Include="Editor\BuildOverlayVessel.cs" />
<Compile Include="Editor\BuildToolbar.cs" /> <Compile Include="Editor\BuildToolbar.cs" />
<Compile Include="Editor\PartInfoItem.cs" /> <Compile Include="Editor\PartInfoItem.cs" />
<Compile Include="Editor\ResourceInfoItem.cs" /> <Compile Include="Editor\ResourceInfoItem.cs" />
<Compile Include="Extensions\FloatExtensions.cs" /> <Compile Include="Extensions\FloatExtensions.cs" />
<Compile Include="Extensions\OrbitExtensions.cs" /> <Compile Include="Extensions\OrbitExtensions.cs" />
<Compile Include="Flight\ActionMenuGui.cs" /> <Compile Include="Flight\ActionMenuGui.cs" />
<Compile Include="Flight\FlightEngineerPartless.cs" />  
<Compile Include="Flight\Presets\Preset.cs" /> <Compile Include="Flight\Presets\Preset.cs" />
  <Compile Include="Flight\Readouts\Miscellaneous\SystemTime.cs" />
<Compile Include="Flight\Readouts\Miscellaneous\VectoredThrustToggle.cs" /> <Compile Include="Flight\Readouts\Miscellaneous\VectoredThrustToggle.cs" />
<Compile Include="Flight\Readouts\Miscellaneous\TimeReference.cs" /> <Compile Include="Flight\Readouts\Miscellaneous\TimeReference.cs" />
<Compile Include="Flight\Readouts\Miscellaneous\Separator.cs" /> <Compile Include="Flight\Readouts\Miscellaneous\Separator.cs" />
<Compile Include="Flight\Readouts\Miscellaneous\GuiSizeAdjustor.cs" /> <Compile Include="Flight\Readouts\Miscellaneous\GuiSizeAdjustor.cs" />
<Compile Include="Flight\Readouts\Orbital\AngleToEquatorialDescendingNode.cs" /> <Compile Include="Flight\Readouts\Orbital\AngleToEquatorialDescendingNode.cs" />
<Compile Include="Flight\Readouts\Orbital\AngleToEquatorialAscendingNode.cs" /> <Compile Include="Flight\Readouts\Orbital\AngleToEquatorialAscendingNode.cs" />
<Compile Include="Flight\Readouts\Orbital\AngleToRetrograde.cs" /> <Compile Include="Flight\Readouts\Orbital\AngleToRetrograde.cs" />
<Compile Include="Flight\Readouts\Orbital\AngleToPrograde.cs" /> <Compile Include="Flight\Readouts\Orbital\AngleToPrograde.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeRadialDeltaV.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeRadialDeltaV.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\ManoeuvreProcessor.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\ManoeuvreProcessor.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTimeToHalfBurn.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTimeToHalfBurn.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTimeToManoeuvre.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTimeToManoeuvre.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeHalfBurnTime.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeHalfBurnTime.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeBurnTime.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeBurnTime.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeAngleToRetrograde.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeAngleToRetrograde.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeNormalDeltaV.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeNormalDeltaV.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeAngleToPrograde.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeAngleToPrograde.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTotalDeltaV.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeTotalDeltaV.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeProgradeDeltaV.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\NodeProgradeDeltaV.cs" />
  <Compile Include="Flight\Readouts\Orbital\MeanAnomalyAtEpoc.cs" />
<Compile Include="Flight\Readouts\Orbital\MeanAnomaly.cs" /> <Compile Include="Flight\Readouts\Orbital\MeanAnomaly.cs" />
<Compile Include="Flight\Readouts\Orbital\EccentricAnomaly.cs" /> <Compile Include="Flight\Readouts\Orbital\EccentricAnomaly.cs" />
<Compile Include="Flight\Readouts\Orbital\ArgumentOfPeriapsis.cs" /> <Compile Include="Flight\Readouts\Orbital\ArgumentOfPeriapsis.cs" />
<Compile Include="Flight\Readouts\Orbital\CurrentSoi.cs" /> <Compile Include="Flight\Readouts\Orbital\CurrentSoi.cs" />
<Compile Include="Flight\Readouts\Orbital\TrueAnomaly.cs" /> <Compile Include="Flight\Readouts\Orbital\TrueAnomaly.cs" />
<Compile Include="Flight\Readouts\Orbital\TimeToEquatorialAscendingNode.cs" /> <Compile Include="Flight\Readouts\Orbital\TimeToEquatorialAscendingNode.cs" />
<Compile Include="Flight\Readouts\Orbital\TimeToEquatorialDescendingNode.cs" /> <Compile Include="Flight\Readouts\Orbital\TimeToEquatorialDescendingNode.cs" />
<Compile Include="Flight\Readouts\Rendezvous\RelativeSpeed.cs" /> <Compile Include="Flight\Readouts\Rendezvous\RelativeSpeed.cs" />
<Compile Include="Flight\Readouts\Rendezvous\RelativeVelocity.cs" /> <Compile Include="Flight\Readouts\Rendezvous\RelativeVelocity.cs" />
<Compile Include="Flight\Readouts\Rendezvous\SemiMinorAxis.cs" /> <Compile Include="Flight\Readouts\Rendezvous\SemiMinorAxis.cs" />
<Compile Include="Flight\Readouts\Rendezvous\SemiMajorAxis.cs" /> <Compile Include="Flight\Readouts\Rendezvous\SemiMajorAxis.cs" />
<Compile Include="Flight\Readouts\Rendezvous\TimeToRelativeDescendingNode.cs" /> <Compile Include="Flight\Readouts\Rendezvous\TimeToRelativeDescendingNode.cs" />
<Compile Include="Flight\Readouts\Rendezvous\TimeToRelativeAscendingNode.cs" /> <Compile Include="Flight\Readouts\Rendezvous\TimeToRelativeAscendingNode.cs" />
<Compile Include="Flight\Readouts\Surface\ImpactBiome.cs" /> <Compile Include="Flight\Readouts\Surface\ImpactBiome.cs" />
<Compile Include="Flight\Readouts\Surface\Slope.cs" /> <Compile Include="Flight\Readouts\Surface\Slope.cs" />
<Compile Include="Flight\Readouts\Surface\Biome.cs" /> <Compile Include="Flight\Readouts\Surface\Biome.cs" />
<Compile Include="Flight\Readouts\Surface\HorizontalAcceleration.cs" /> <Compile Include="Flight\Readouts\Surface\HorizontalAcceleration.cs" />
<Compile Include="Flight\Readouts\Surface\VerticalAcceleration.cs" /> <Compile Include="Flight\Readouts\Surface\VerticalAcceleration.cs" />
<Compile Include="Flight\Readouts\Vessel\AttitudeProcessor.cs" /> <Compile Include="Flight\Readouts\Vessel\AttitudeProcessor.cs" />
<Compile Include="Flight\Readouts\Vessel\DeltaVCurrentTotal.cs" /> <Compile Include="Flight\Readouts\Vessel\DeltaVCurrentTotal.cs" />
<Compile Include="Flight\Readouts\Vessel\PitchRate.cs" /> <Compile Include="Flight\Readouts\Vessel\PitchRate.cs" />
<Compile Include="Flight\Readouts\Vessel\HeadingRate.cs" /> <Compile Include="Flight\Readouts\Vessel\HeadingRate.cs" />
<Compile Include="Flight\Readouts\Vessel\RollRate.cs" /> <Compile Include="Flight\Readouts\Vessel\RollRate.cs" />
<Compile Include="Flight\Readouts\Vessel\Roll.cs" /> <Compile Include="Flight\Readouts\Vessel\Roll.cs" />
<Compile Include="Flight\Readouts\Vessel\Pitch.cs" /> <Compile Include="Flight\Readouts\Vessel\Pitch.cs" />
<Compile Include="Flight\Readouts\Vessel\Heading.cs" /> <Compile Include="Flight\Readouts\Vessel\Heading.cs" />
<Compile Include="Flight\Readouts\Vessel\PartCount.cs" /> <Compile Include="Flight\Readouts\Vessel\PartCount.cs" />
<Compile Include="Flight\Readouts\Vessel\SuicideBurnDeltaV.cs" /> <Compile Include="Flight\Readouts\Vessel\SuicideBurnDeltaV.cs" />
<Compile Include="Flight\Readouts\Vessel\SuicideBurnAltitude.cs" /> <Compile Include="Flight\Readouts\Vessel\SuicideBurnAltitude.cs" />
<Compile Include="Flight\Readouts\Vessel\SuicideBurnDistance.cs" /> <Compile Include="Flight\Readouts\Vessel\SuicideBurnDistance.cs" />
<Compile Include="Flight\Readouts\Vessel\DeltaVCurrent.cs" /> <Compile Include="Flight\Readouts\Vessel\DeltaVCurrent.cs" />
<Compile Include="Flight\Readouts\Vessel\IntakeAirUsage.cs" /> <Compile Include="Flight\Readouts\Vessel\IntakeAirUsage.cs" />
<Compile Include="Flight\Readouts\Vessel\IntakeAirDemandSupply.cs" /> <Compile Include="Flight\Readouts\Vessel\IntakeAirDemandSupply.cs" />
<Compile Include="Flight\Readouts\Vessel\IntakeAirSupply.cs" /> <Compile Include="Flight\Readouts\Vessel\IntakeAirSupply.cs" />
<Compile Include="Flight\Readouts\Vessel\IntakeAirDemand.cs" /> <Compile Include="Flight\Readouts\Vessel\IntakeAirDemand.cs" />
<Compile Include="Flight\Readouts\Miscellaneous\SimulationDelay.cs" /> <Compile Include="Flight\Readouts\Miscellaneous\SimulationDelay.cs" />
<Compile Include="Flight\Readouts\Vessel\SimulationProcessor.cs" /> <Compile Include="Flight\Readouts\Vessel\SimulationProcessor.cs" />
<Compile Include="Flight\Readouts\Vessel\Acceleration.cs" /> <Compile Include="Flight\Readouts\Vessel\Acceleration.cs" />
<Compile Include="Flight\Presets\PresetLibrary.cs" /> <Compile Include="Flight\Presets\PresetLibrary.cs" />
<Compile Include="Flight\Readouts\Vessel\SuicideBurnProcessor.cs" /> <Compile Include="Flight\Readouts\Vessel\SuicideBurnProcessor.cs" />
<Compile Include="Flight\Readouts\Vessel\SurfaceThrustToWeight.cs" /> <Compile Include="Flight\Readouts\Vessel\SurfaceThrustToWeight.cs" />
<Compile Include="Flight\Readouts\Surface\Situation.cs" /> <Compile Include="Flight\Readouts\Surface\Situation.cs" />
<Compile Include="Flight\Readouts\Vessel\ThrustOffsetAngle.cs" /> <Compile Include="Flight\Readouts\Vessel\ThrustOffsetAngle.cs" />
<Compile Include="Flight\Readouts\Vessel\ThrustTorque.cs" /> <Compile Include="Flight\Readouts\Vessel\ThrustTorque.cs" />
<Compile Include="GuiDisplaySize.cs" /> <Compile Include="GuiDisplaySize.cs" />
<Compile Include="Helpers\AngleHelper.cs" /> <Compile Include="Helpers\AngleHelper.cs" />
<Compile Include="Helpers\Averager.cs" /> <Compile Include="Helpers\Averager.cs" />
<Compile Include="Helpers\ForceAccumulator.cs" /> <Compile Include="Helpers\ForceAccumulator.cs" />
<Compile Include="Helpers\TextureHelper.cs" /> <Compile Include="Helpers\TextureHelper.cs" />
<Compile Include="Helpers\Units.cs" /> <Compile Include="Helpers\Units.cs" />
<Compile Include="Helpers\TimeFormatter.cs" /> <Compile Include="Helpers\TimeFormatter.cs" />
<Compile Include="KeyBinder.cs" /> <Compile Include="KeyBinder.cs" />
<Compile Include="Control\ControlCentre.cs" /> <Compile Include="Control\ControlCentre.cs" />
<Compile Include="UIControls\DropDown.cs" /> <Compile Include="UIControls\DropDown.cs" />
<Compile Include="Logger.cs" /> <Compile Include="Logger.cs" />
<Compile Include="EngineerGlobals.cs" /> <Compile Include="EngineerGlobals.cs" />
<Compile Include="Extensions\DoubleExtensions.cs" /> <Compile Include="Extensions\DoubleExtensions.cs" />
<Compile Include="Extensions\PartExtensions.cs" /> <Compile Include="Extensions\PartExtensions.cs" />
<Compile Include="Extensions\PartResourceExtensions.cs" /> <Compile Include="Extensions\PartResourceExtensions.cs" />
<Compile Include="Extensions\RectExtensions.cs" /> <Compile Include="Extensions\RectExtensions.cs" />
<Compile Include="Flight\ActionMenu.cs" /> <Compile Include="Flight\ActionMenu.cs" />
<Compile Include="Flight\DisplayStack.cs" /> <Compile Include="Flight\DisplayStack.cs" />
<Compile Include="Flight\FlightEngineerCore.cs" /> <Compile Include="Flight\FlightEngineerCore.cs" />
<Compile Include="Flight\FlightEngineerModule.cs" /> <Compile Include="Flight\FlightEngineerModule.cs" />
<Compile Include="Flight\IUpdatable.cs" /> <Compile Include="Flight\IUpdatable.cs" />
<Compile Include="Flight\IUpdateRequest.cs" /> <Compile Include="Flight\IUpdateRequest.cs" />
<Compile Include="Flight\Readouts\Orbital\ApoapsisHeight.cs" /> <Compile Include="Flight\Readouts\Orbital\ApoapsisHeight.cs" />
<Compile Include="Flight\Readouts\Orbital\Eccentricity.cs" /> <Compile Include="Flight\Readouts\Orbital\Eccentricity.cs" />
<Compile Include="Flight\Readouts\Orbital\Inclination.cs" /> <Compile Include="Flight\Readouts\Orbital\Inclination.cs" />
<Compile Include="Flight\Readouts\Orbital\LongitudeOfAscendingNode.cs" /> <Compile Include="Flight\Readouts\Orbital\LongitudeOfAscendingNode.cs" />
<Compile Include="Flight\Readouts\Orbital\LongitudeOfPeriapsis.cs" /> <Compile Include="Flight\Readouts\Orbital\LongitudeOfPeriapsis.cs" />
<Compile Include="Flight\Readouts\Orbital\OrbitalPeriod.cs" /> <Compile Include="Flight\Readouts\Orbital\OrbitalPeriod.cs" />
<Compile Include="Flight\Readouts\Orbital\OrbitalSpeed.cs" /> <Compile Include="Flight\Readouts\Orbital\OrbitalSpeed.cs" />
<Compile Include="Flight\Readouts\Orbital\PeriapsisHeight.cs" /> <Compile Include="Flight\Readouts\Orbital\PeriapsisHeight.cs" />
<Compile Include="Flight\Readouts\Orbital\SemiMajorAxis.cs" /> <Compile Include="Flight\Readouts\Orbital\SemiMajorAxis.cs" />
<Compile Include="Flight\Readouts\Orbital\SemiMinorAxis.cs" /> <Compile Include="Flight\Readouts\Orbital\SemiMinorAxis.cs" />
<Compile Include="Flight\Readouts\Orbital\TimeToApoapsis.cs" /> <Compile Include="Flight\Readouts\Orbital\TimeToApoapsis.cs" />
<Compile Include="Flight\Readouts\Orbital\TimeToPeriapsis.cs" /> <Compile Include="Flight\Readouts\Orbital\TimeToPeriapsis.cs" />
<Compile Include="Flight\Readouts\ReadoutCategory.cs" /> <Compile Include="Flight\Readouts\ReadoutCategory.cs" />
<Compile Include="Flight\Readouts\ReadoutLibrary.cs" /> <Compile Include="Flight\Readouts\ReadoutLibrary.cs" />
<Compile Include="Flight\Readouts\ReadoutModule.cs" /> <Compile Include="Flight\Readouts\ReadoutModule.cs" />
<Compile Include="Flight\Readouts\Rendezvous\TimeToPeriapsis.cs" /> <Compile Include="Flight\Readouts\Rendezvous\TimeToPeriapsis.cs" />
<Compile Include="Flight\Readouts\Rendezvous\TimeToApoapsis.cs" /> <Compile Include="Flight\Readouts\Rendezvous\TimeToApoapsis.cs" />
<Compile Include="Flight\Readouts\Rendezvous\PeriapsisHeight.cs" /> <Compile Include="Flight\Readouts\Rendezvous\PeriapsisHeight.cs" />
<Compile Include="Flight\Readouts\Rendezvous\ApoapsisHeight.cs" /> <Compile Include="Flight\Readouts\Rendezvous\ApoapsisHeight.cs" />
<Compile Include="Flight\Readouts\Rendezvous\InterceptAngle.cs" /> <Compile Include="Flight\Readouts\Rendezvous\InterceptAngle.cs" />
<Compile Include="Flight\Readouts\Rendezvous\OrbitalPeriod.cs" /> <Compile Include="Flight\Readouts\Rendezvous\OrbitalPeriod.cs" />
<Compile Include="Flight\Readouts\Rendezvous\Distance.cs" /> <Compile Include="Flight\Readouts\Rendezvous\Distance.cs" />
<Compile Include="Flight\Readouts\Rendezvous\AltitudeSeaLevel.cs" /> <Compile Include="Flight\Readouts\Rendezvous\AltitudeSeaLevel.cs" />
<Compile Include="Flight\Readouts\Rendezvous\AngleToRelativeDescendingNode.cs" /> <Compile Include="Flight\Readouts\Rendezvous\AngleToRelativeDescendingNode.cs" />
<Compile Include="Flight\Readouts\Rendezvous\AngleToRelativeAscendingNode.cs" /> <Compile Include="Flight\Readouts\Rendezvous\AngleToRelativeAscendingNode.cs" />
<Compile Include="Flight\Readouts\Rendezvous\PhaseAngle.cs" /> <Compile Include="Flight\Readouts\Rendezvous\PhaseAngle.cs" />
<Compile Include="Flight\Readouts\Rendezvous\RelativeInclination.cs" /> <Compile Include="Flight\Readouts\Rendezvous\RelativeInclination.cs" />
<Compile Include="Flight\Readouts\Rendezvous\RendezvousProcessor.cs" /> <Compile Include="Flight\Readouts\Rendezvous\RendezvousProcessor.cs" />
<Compile Include="Flight\Readouts\Rendezvous\TargetSelector.cs" /> <Compile Include="Flight\Readouts\Rendezvous\TargetSelector.cs" />
<Compile Include="Flight\Readouts\Surface\AltitudeSeaLevel.cs" /> <Compile Include="Flight\Readouts\Surface\AltitudeSeaLevel.cs" />
<Compile Include="Flight\Readouts\Surface\AltitudeTerrain.cs" /> <Compile Include="Flight\Readouts\Surface\AltitudeTerrain.cs" />
<Compile Include="Flight\Readouts\Surface\ImpactLatitude.cs" /> <Compile Include="Flight\Readouts\Surface\ImpactLatitude.cs" />
<Compile Include="Flight\Readouts\Surface\ImpactAltitude.cs" /> <Compile Include="Flight\Readouts\Surface\ImpactAltitude.cs" />
<Compile Include="Flight\Readouts\Surface\ImpactLongitude.cs" /> <Compile Include="Flight\Readouts\Surface\ImpactLongitude.cs" />
<Compile Include="Flight\Readouts\Surface\ImpactTime.cs" /> <Compile Include="Flight\Readouts\Surface\ImpactTime.cs" />
<Compile Include="Flight\Readouts\Surface\AtmosphericProcessor.cs" /> <Compile Include="Flight\Readouts\Surface\AtmosphericProcessor.cs" />
<Compile Include="Flight\Readouts\Surface\AtmosphericEfficiency.cs" /> <Compile Include="Flight\Readouts\Surface\AtmosphericEfficiency.cs" />
<Compile Include="Flight\Readouts\Surface\GeeForce.cs" /> <Compile Include="Flight\Readouts\Surface\GeeForce.cs" />
<Compile Include="Flight\Readouts\Surface\HorizontalSpeed.cs" /> <Compile Include="Flight\Readouts\Surface\HorizontalSpeed.cs" />
<Compile Include="Flight\Readouts\Surface\ImpactProcessor.cs" /> <Compile Include="Flight\Readouts\Surface\ImpactProcessor.cs" />
<Compile Include="Flight\Readouts\Surface\Latitude.cs" /> <Compile Include="Flight\Readouts\Surface\Latitude.cs" />
<Compile Include="Flight\Readouts\Surface\Longitude.cs" /> <Compile Include="Flight\Readouts\Surface\Longitude.cs" />
<Compile Include="Flight\Readouts\Surface\TerminalVelocity.cs" /> <Compile Include="Flight\Readouts\Surface\TerminalVelocity.cs" />
<Compile Include="Flight\Readouts\Surface\VerticalSpeed.cs" /> <Compile Include="Flight\Readouts\Surface\VerticalSpeed.cs" />
<Compile Include="Flight\Readouts\Vessel\DeltaVStaged.cs" /> <Compile Include="Flight\Readouts\Vessel\DeltaVStaged.cs" />
<Compile Include="Flight\Readouts\Vessel\DeltaVTotal.cs" /> <Compile Include="Flight\Readouts\Vessel\DeltaVTotal.cs" />
<Compile Include="Flight\Readouts\Vessel\Mass.cs" /> <Compile Include="Flight\Readouts\Vessel\Mass.cs" />
<Compile Include="Flight\Readouts\Vessel\Thrust.cs" /> <Compile Include="Flight\Readouts\Vessel\Thrust.cs" />
<Compile Include="Flight\Readouts\Vessel\SpecificImpulse.cs" /> <Compile Include="Flight\Readouts\Vessel\SpecificImpulse.cs" />
<Compile Include="Flight\Readouts\Vessel\ThrustToWeight.cs" /> <Compile Include="Flight\Readouts\Vessel\ThrustToWeight.cs" />
<Compile Include="Flight\Sections\SectionEditor.cs" /> <Compile Include="Flight\Sections\SectionEditor.cs" />
<Compile Include="Flight\Sections\SectionLibrary.cs" /> <Compile Include="Flight\Sections\SectionLibrary.cs" />
<Compile Include="Flight\Sections\SectionModule.cs" /> <Compile Include="Flight\Sections\SectionModule.cs" />
<Compile Include="Flight\Sections\SectionWindow.cs" /> <Compile Include="Flight\Sections\SectionWindow.cs" />
<Compile Include="LogMsg.cs" /> <Compile Include="LogMsg.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Settings\SettingHandler.cs" /> <Compile Include="Settings\SettingHandler.cs" />
<Compile Include="Settings\SettingItem.cs" /> <Compile Include="Settings\SettingItem.cs" />
<Compile Include="TapeDriveAnimator.cs" /> <Compile Include="TapeDriveAnimator.cs" />
<Compile Include="UIControls\WindowObject.cs" /> <Compile Include="UIControls\WindowObject.cs" />
<Compile Include="VesselSimulator\AttachNodeSim.cs" /> <Compile Include="VesselSimulator\AttachNodeSim.cs" />
<Compile Include="VesselSimulator\EngineSim.cs" /> <Compile Include="VesselSimulator\EngineSim.cs" />
<Compile Include="VesselSimulator\PartSim.cs" /> <Compile Include="VesselSimulator\PartSim.cs" />
<Compile Include="VesselSimulator\ResourceContainer.cs" /> <Compile Include="VesselSimulator\ResourceContainer.cs" />
<Compile Include="VesselSimulator\SimManager.cs" /> <Compile Include="VesselSimulator\SimManager.cs" />
<Compile Include="VesselSimulator\Simulation.cs" /> <Compile Include="VesselSimulator\Simulation.cs" />
<Compile Include="VesselSimulator\Stage.cs" /> <Compile Include="VesselSimulator\Stage.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Assembly-CSharp"> <Reference Include="Assembly-CSharp">
<HintPath>..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath> <HintPath>..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System"> <Reference Include="System">
<HintPath>..\Game\KSP_Data\Managed\System.dll</HintPath> <HintPath>..\Game\KSP_Data\Managed\System.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System.Xml"> <Reference Include="System.Xml">
<HintPath>..\Game\KSP_Data\Managed\System.Xml.dll</HintPath> <HintPath>..\Game\KSP_Data\Managed\System.Xml.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="UnityEngine"> <Reference Include="UnityEngine">
<HintPath>..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath> <HintPath>..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="PostBuildMacros"> <Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)"> <GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="Targets" /> <Output TaskParameter="Assemblies" ItemName="Targets" />
</GetAssemblyIdentity> </GetAssemblyIdentity>
<ItemGroup> <ItemGroup>
<VersionNumber Include="@(Targets->'%(Version)')" /> <VersionNumber Include="@(Targets->'%(Version)')" />
</ItemGroup> </ItemGroup>
</Target> </Target>
<PropertyGroup> <PropertyGroup>
<PostBuildEventDependsOn> <PostBuildEventDependsOn>
$(PostBuildEventDependsOn); $(PostBuildEventDependsOn);
PostBuildMacros; PostBuildMacros;
</PostBuildEventDependsOn> </PostBuildEventDependsOn>
<PostBuildEvent>xcopy "$(SolutionDir)Output\*" "$(SolutionDir)Game\GameData\*" /E /Y <PostBuildEvent>xcopy "$(SolutionDir)Output\*" "$(SolutionDir)Game\GameData\*" /E /Y
del "$(SolutionDir)Release\*" /Q del "$(SolutionDir)Release\*" /Q
xcopy "$(SolutionDir)Documents\*" "$(SolutionDir)Release\Documents\*" /E /Y xcopy "$(SolutionDir)Documents\*" "$(SolutionDir)Release\Documents\*" /E /Y
7z.exe a -tzip -mx3 "$(SolutionDir)Release\$(ProjectName)-@(VersionNumber).zip" "$(SolutionDir)Output\*" 7z.exe a -tzip -mx3 "$(SolutionDir)Release\$(ProjectName)-@(VersionNumber).zip" "$(SolutionDir)Output\*"
7z.exe a -tzip -mx3 "$(SolutionDir)Release\$(ProjectName)-@(VersionNumber).zip" "$(SolutionDir)Documents\*"</PostBuildEvent> 7z.exe a -tzip -mx3 "$(SolutionDir)Release\$(ProjectName)-@(VersionNumber).zip" "$(SolutionDir)Documents\*"</PostBuildEvent>
</PropertyGroup> </PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
</Target> </Target>
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
   
using UnityEngine; using UnityEngine;
   
#endregion #endregion
   
namespace KerbalEngineer.VesselSimulator namespace KerbalEngineer.VesselSimulator
{ {
public class EngineSim public class EngineSim
{ {
private readonly ResourceContainer resourceConsumptions = new ResourceContainer(); private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
   
public double actualThrust = 0; public double actualThrust = 0;
public bool isActive = false; public bool isActive = false;
public double isp = 0; public double isp = 0;
public PartSim partSim; public PartSim partSim;
public List<AppliedForce> appliedForces; public List<AppliedForce> appliedForces;
   
public double thrust = 0; public double thrust = 0;
   
// Add thrust vector to account for directional losses // Add thrust vector to account for directional losses
public Vector3 thrustVec; public Vector3 thrustVec;
   
public EngineSim(PartSim theEngine, public EngineSim(PartSim theEngine,
double atmosphere, double atmosphere,
double velocity, double velocity,
float maxThrust, float maxThrust,
float minThrust, float minThrust,
float thrustPercentage, float thrustPercentage,
float requestedThrust, float requestedThrust,
Vector3 vecThrust, Vector3 vecThrust,
float realIsp, float realIsp,
FloatCurve atmosphereCurve, FloatCurve atmosphereCurve,
FloatCurve velocityCurve, FloatCurve velocityCurve,
bool throttleLocked, bool throttleLocked,
List<Propellant> propellants, List<Propellant> propellants,
bool active, bool active,
bool correctThrust, bool correctThrust,
List<Transform> thrustTransforms) List<Transform> thrustTransforms)
{ {
StringBuilder buffer = null; StringBuilder buffer = null;
//MonoBehaviour.print("Create EngineSim for " + theEngine.name); //MonoBehaviour.print("Create EngineSim for " + theEngine.name);
//MonoBehaviour.print("maxThrust = " + maxThrust); //MonoBehaviour.print("maxThrust = " + maxThrust);
//MonoBehaviour.print("minThrust = " + minThrust); //MonoBehaviour.print("minThrust = " + minThrust);
//MonoBehaviour.print("thrustPercentage = " + thrustPercentage); //MonoBehaviour.print("thrustPercentage = " + thrustPercentage);
//MonoBehaviour.print("requestedThrust = " + requestedThrust); //MonoBehaviour.print("requestedThrust = " + requestedThrust);
//MonoBehaviour.print("velocity = " + velocity); //MonoBehaviour.print("velocity = " + velocity);
   
this.partSim = theEngine; this.partSim = theEngine;
   
this.isActive = active; this.isActive = active;
this.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust; this.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust;
//MonoBehaviour.print("thrust = " + thrust); //MonoBehaviour.print("thrust = " + thrust);
   
this.thrustVec = vecThrust; this.thrustVec = vecThrust;
   
double flowRate = 0d; double flowRate = 0d;
if (this.partSim.hasVessel) if (this.partSim.hasVessel)
{ {
//MonoBehaviour.print("hasVessel is true"); //MonoBehaviour.print("hasVessel is true");
this.actualThrust = isActive ? requestedThrust : 0.0; this.actualThrust = isActive ? requestedThrust : 0.0;
if (velocityCurve != null) if (velocityCurve != null)
{ {
this.actualThrust *= velocityCurve.Evaluate((float)velocity); this.actualThrust *= velocityCurve.Evaluate((float)velocity);
//MonoBehaviour.print("actualThrust at velocity = " + actualThrust); //MonoBehaviour.print("actualThrust at velocity = " + actualThrust);
} }
   
this.isp = atmosphereCurve.Evaluate((float)this.partSim.part.staticPressureAtm); this.isp = atmosphereCurve.Evaluate((float)this.partSim.part.staticPressureAtm);
if (this.isp == 0d) if (this.isp == 0d)
{ {
MonoBehaviour.print("Isp at " + this.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN"); MonoBehaviour.print("Isp at " + this.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN");
} }
   
if (correctThrust && realIsp == 0) if (correctThrust && realIsp == 0)
{ {
float ispsl = atmosphereCurve.Evaluate(0); float ispsl = atmosphereCurve.Evaluate(0);
if (ispsl != 0) if (ispsl != 0)
{ {
this.thrust = this.thrust * this.isp / ispsl; this.thrust = this.thrust * this.isp / ispsl;
} }
else else
{ {
MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust."); MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust.");
} }
//MonoBehaviour.print("corrected thrust = " + thrust); //MonoBehaviour.print("corrected thrust = " + thrust);
} }
   
if (velocityCurve != null) if (velocityCurve != null)
{ {
this.thrust *= velocityCurve.Evaluate((float)velocity); this.thrust *= velocityCurve.Evaluate((float)velocity);
//MonoBehaviour.print("thrust at velocity = " + thrust); //MonoBehaviour.print("thrust at velocity = " + thrust);
} }
   
if (throttleLocked) if (throttleLocked)
{ {
//MonoBehaviour.print("throttleLocked is true"); //MonoBehaviour.print("throttleLocked is true");
flowRate = this.thrust / (this.isp * 9.82); flowRate = this.thrust / (this.isp * 9.82);
} }
else else
{ {
if (this.partSim.isLanded) if (this.partSim.isLanded)
{ {
//MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle); //MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle);
flowRate = Math.Max(0.000001d, this.thrust * FlightInputHandler.state.mainThrottle) / (this.isp * 9.82); flowRate = Math.Max(0.000001d, this.thrust * FlightInputHandler.state.mainThrottle) / (this.isp * 9.82);
} }
else else
{ {
if (requestedThrust > 0) if (requestedThrust > 0)
{ {
if (velocityCurve != null) if (velocityCurve != null)
{ {
requestedThrust *= velocityCurve.Evaluate((float)velocity); requestedThrust *= velocityCurve.Evaluate((float)velocity);
//MonoBehaviour.print("requestedThrust at velocity = " + requestedThrust); //MonoBehaviour.print("requestedThrust at velocity = " + requestedThrust);
} }
   
//MonoBehaviour.print("requestedThrust > 0"); //MonoBehaviour.print("requestedThrust > 0");
flowRate = requestedThrust / (this.isp * 9.82); flowRate = requestedThrust / (this.isp * 9.82);
} }
else else
{ {
//MonoBehaviour.print("requestedThrust <= 0"); //MonoBehaviour.print("requestedThrust <= 0");
flowRate = this.thrust / (this.isp * 9.82); flowRate = this.thrust / (this.isp * 9.82);
} }
} }
} }
} }
else else
{ {
//MonoBehaviour.print("hasVessel is false"); //MonoBehaviour.print("hasVessel is false");
this.isp = atmosphereCurve.Evaluate((float)atmosphere); this.isp = atmosphereCurve.Evaluate((float)atmosphere);
if (this.isp == 0d) if (this.isp == 0d)
{ {
MonoBehaviour.print("Isp at " + atmosphere + " is zero. Flow rate will be NaN"); MonoBehaviour.print("Isp at " + atmosphere + " is zero. Flow rate will be NaN");
} }
if (correctThrust) if (correctThrust)
{ {
float ispsl = atmosphereCurve.Evaluate(0); float ispsl = atmosphereCurve.Evaluate(0);
if (ispsl != 0) if (ispsl != 0)
{ {
this.thrust = this.thrust * this.isp / ispsl; this.thrust = this.thrust * this.isp / ispsl;
} }
else else
{ {
MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust."); MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust.");
} }
//MonoBehaviour.print("corrected thrust = " + thrust); //MonoBehaviour.print("corrected thrust = " + thrust);
} }
   
if (velocityCurve != null) if (velocityCurve != null)
{ {
this.thrust *= velocityCurve.Evaluate((float)velocity); this.thrust *= velocityCurve.Evaluate((float)velocity);
//MonoBehaviour.print("thrust at velocity = " + thrust); //MonoBehaviour.print("thrust at velocity = " + thrust);
} }
   
flowRate = this.thrust / (this.isp * 9.82); flowRate = this.thrust / (this.isp * 9.82);
} }
   
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
buffer = new StringBuilder(1024); buffer = new StringBuilder(1024);
buffer.AppendFormat("flowRate = {0:g6}\n", flowRate); buffer.AppendFormat("flowRate = {0:g6}\n", flowRate);
} }
   
float flowMass = 0f; float flowMass = 0f;
foreach (Propellant propellant in propellants) foreach (Propellant propellant in propellants)
{ {
flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id); flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
} }
   
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
buffer.AppendFormat("flowMass = {0:g6}\n", flowMass); buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);
} }
   
foreach (Propellant propellant in propellants) foreach (Propellant propellant in propellants)
{ {
if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir") if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
{ {
continue; continue;
} }
   
double consumptionRate = propellant.ratio * flowRate / flowMass; double consumptionRate = propellant.ratio * flowRate / flowMass;
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
buffer.AppendFormat("Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate); buffer.AppendFormat("Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate);
} }
this.resourceConsumptions.Add(propellant.id, consumptionRate); this.resourceConsumptions.Add(propellant.id, consumptionRate);
} }
   
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
MonoBehaviour.print(buffer); MonoBehaviour.print(buffer);
} }
   
appliedForces = new List<AppliedForce>(); appliedForces = new List<AppliedForce>();
double thrustPerThrustTransform = thrust / thrustTransforms.Count; double thrustPerThrustTransform = thrust / thrustTransforms.Count;
foreach (Transform thrustTransform in thrustTransforms) { foreach (Transform thrustTransform in thrustTransforms) {
Vector3d direction = thrustTransform.forward.normalized; Vector3d direction = thrustTransform.forward.normalized;
Vector3d position = thrustTransform.position; Vector3d position = thrustTransform.position;
appliedForces.Add(new AppliedForce(direction * thrustPerThrustTransform, position)); appliedForces.Add(new AppliedForce(direction * thrustPerThrustTransform, position));
} }
} }
   
public ResourceContainer ResourceConsumptions public ResourceContainer ResourceConsumptions
{ {
get { return this.resourceConsumptions; } get { return this.resourceConsumptions; }
} }
   
public bool SetResourceDrains(List<PartSim> allParts, List<PartSim> allFuelLines, HashSet<PartSim> drainingParts) public bool SetResourceDrains(List<PartSim> allParts, List<PartSim> allFuelLines, HashSet<PartSim> drainingParts)
{ {
LogMsg log = null; LogMsg log = null;
   
// A dictionary to hold a set of parts for each resource // A dictionary to hold a set of parts for each resource
Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>(); Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>();
   
foreach (int type in this.resourceConsumptions.Types) foreach (int type in this.resourceConsumptions.Types)
{ {
HashSet<PartSim> sourcePartSet = null; HashSet<PartSim> sourcePartSet = null;
switch (ResourceContainer.GetResourceFlowMode(type)) switch (ResourceContainer.GetResourceFlowMode(type))
{ {
case ResourceFlowMode.NO_FLOW: case ResourceFlowMode.NO_FLOW:
if (this.partSim.resources[type] > SimManager.RESOURCE_MIN) if (this.partSim.resources[type] > SimManager.RESOURCE_MIN)
{ {
sourcePartSet = new HashSet<PartSim>(); sourcePartSet = new HashSet<PartSim>();
//MonoBehaviour.print("SetResourceDrains(" + name + ":" + partId + ") setting sources to just this"); //MonoBehaviour.print("SetResourceDrains(" + name + ":" + partId + ") setting sources to just this");
sourcePartSet.Add(this.partSim); sourcePartSet.Add(this.partSim);
} }
break; break;
   
case ResourceFlowMode.ALL_VESSEL: case ResourceFlowMode.ALL_VESSEL:
foreach (PartSim aPartSim in allParts) foreach (PartSim aPartSim in allParts)
{ {
if (aPartSim.resources[type] > SimManager.RESOURCE_MIN) if (aPartSim.resources[type] > SimManager.RESOURCE_MIN)
{ {
if (sourcePartSet == null) if (sourcePartSet == null)
{ {
sourcePartSet = new HashSet<PartSim>(); sourcePartSet = new HashSet<PartSim>();
} }
   
sourcePartSet.Add(aPartSim); sourcePartSet.Add(aPartSim);
} }
} }
break; break;
   
case ResourceFlowMode.STAGE_PRIORITY_FLOW: case ResourceFlowMode.STAGE_PRIORITY_FLOW:
var stagePartSets = new Dictionary<int, HashSet<PartSim>>(); var stagePartSets = new Dictionary<int, HashSet<PartSim>>();
var maxStage = -1; var maxStage = -1;
   
Logger.Log(type); Logger.Log(type);
foreach (var aPartSim in allParts) foreach (var aPartSim in allParts)
{ {
if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN) continue; if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0) continue;
   
var stage = aPartSim.DecouplerCount(); var stage = aPartSim.DecouplerCount();
if (stage > maxStage) if (stage > maxStage)
{ {
maxStage = stage; maxStage = stage;
} }
   
if (!stagePartSets.TryGetValue(stage, out sourcePartSet)) if (!stagePartSets.TryGetValue(stage, out sourcePartSet))
{ {
sourcePartSet = new HashSet<PartSim>(); sourcePartSet = new HashSet<PartSim>();
stagePartSets.Add(stage, sourcePartSet); stagePartSets.Add(stage, sourcePartSet);
} }
sourcePartSet.Add(aPartSim); sourcePartSet.Add(aPartSim);
} }
   
for (var i = 0; i <= maxStage; i++) for (var i = 0; i <= maxStage; i++)
{ {
HashSet<PartSim> stagePartSet; HashSet<PartSim> stagePartSet;
if (stagePartSets.TryGetValue(i, out stagePartSet) && stagePartSet.Count > 0) if (stagePartSets.TryGetValue(i, out stagePartSet) && stagePartSet.Count > 0)
{ {
sourcePartSet = stagePartSet; sourcePartSet = stagePartSet;
} }
} }
break; break;
   
case ResourceFlowMode.STACK_PRIORITY_SEARCH: case ResourceFlowMode.STACK_PRIORITY_SEARCH:
HashSet<PartSim> visited = new HashSet<PartSim>(); HashSet<PartSim> visited = new HashSet<PartSim>();
   
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
log = new LogMsg(); log = new LogMsg();
log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + this.partSim.name + ":" + this.partSim.partId); log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + this.partSim.name + ":" + this.partSim.partId);
} }
sourcePartSet = this.partSim.GetSourceSet(type, allParts, visited, log, ""); sourcePartSet = this.partSim.GetSourceSet(type, allParts, visited, log, "");
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
MonoBehaviour.print(log.buf); MonoBehaviour.print(log.buf);
} }
break; break;
   
default: default:
MonoBehaviour.print("SetResourceDrains(" + this.partSim.name + ":" + this.partSim.partId + ") Unexpected flow type for " + ResourceContainer.GetResourceName(type) + ")"); MonoBehaviour.print("SetResourceDrains(" + this.partSim.name + ":" + this.partSim.partId + ") Unexpected flow type for " + ResourceContainer.GetResourceName(type) + ")");
break; break;
} }
   
if (sourcePartSet != null && sourcePartSet.Count > 0) if (sourcePartSet != null && sourcePartSet.Count > 0)
{ {
sourcePartSets[type] = sourcePartSet; sourcePartSets[type] = sourcePartSet;
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
log = new LogMsg(); log = new LogMsg();
log.buf.AppendLine("Source parts for " + ResourceContainer.GetResourceName(type) + ":"); log.buf.AppendLine("Source parts for " + ResourceContainer.GetResourceName(type) + ":");
foreach (PartSim partSim in sourcePartSet) foreach (PartSim partSim in sourcePartSet)
{ {
log.buf.AppendLine(partSim.name + ":" + partSim.partId); log.buf.AppendLine(partSim.name + ":" + partSim.partId);
} }
MonoBehaviour.print(log.buf); MonoBehaviour.print(log.buf);
} }
} }
} }
   
// If we don't have sources for all the needed resources then return false without setting up any drains // If we don't have sources for all the needed resources then return false without setting up any drains
foreach (int type in this.resourceConsumptions.Types) foreach (int type in this.resourceConsumptions.Types)
{ {
if (!sourcePartSets.ContainsKey(type)) if (!sourcePartSets.ContainsKey(type))
{ {
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
MonoBehaviour.print("No source of " + ResourceContainer.GetResourceName(type)); MonoBehaviour.print("No source of " + ResourceContainer.GetResourceName(type));
} }
   
this.isActive = false; this.isActive = false;
return false; return false;
} }
} }
   
// Now we set the drains on the members of the sets and update the draining parts set // Now we set the drains on the members of the sets and update the draining parts set
foreach (int type in this.resourceConsumptions.Types) foreach (int type in this.resourceConsumptions.Types)
{ {
HashSet<PartSim> sourcePartSet = sourcePartSets[type]; HashSet<PartSim> sourcePartSet = sourcePartSets[type];
// Loop through the members of the set // Loop through the members of the set
double amount = this.resourceConsumptions[type] / sourcePartSet.Count; double amount = this.resourceConsumptions[type] / sourcePartSet.Count;
foreach (PartSim partSim in sourcePartSet) foreach (PartSim partSim in sourcePartSet)
{ {
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
MonoBehaviour.print("Adding drain of " + amount + " " + ResourceContainer.GetResourceName(type) + " to " + partSim.name + ":" + partSim.partId); MonoBehaviour.print("Adding drain of " + amount + " " + ResourceContainer.GetResourceName(type) + " to " + partSim.name + ":" + partSim.partId);
} }
   
partSim.resourceDrains.Add(type, amount); partSim.resourceDrains.Add(type, amount);
drainingParts.Add(partSim); drainingParts.Add(partSim);
} }
} }
   
return true; return true;
} }
   
public void DumpEngineToBuffer(StringBuilder buffer, String prefix) public void DumpEngineToBuffer(StringBuilder buffer, String prefix)
{ {
buffer.Append(prefix); buffer.Append(prefix);
buffer.AppendFormat("[thrust = {0:g6}, actual = {1:g6}, isp = {2:g6}\n", this.thrust, this.actualThrust, this.isp); buffer.AppendFormat("[thrust = {0:g6}, actual = {1:g6}, isp = {2:g6}\n", this.thrust, this.actualThrust, this.isp);
} }
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
namespace KerbalEngineer.VesselSimulator namespace KerbalEngineer.VesselSimulator
{ {
#region Using Directives #region Using Directives
   
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using UnityEngine; using UnityEngine;
   
#endregion #endregion
   
public class SimManager public class SimManager
{ {
#region Constants #region Constants
   
public const double RESOURCE_MIN = 0.0001; public const double RESOURCE_MIN = 0.0001;
   
#endregion #endregion
   
#region Fields #region Fields
   
public static bool dumpTree = false; public static bool dumpTree = false;
public static bool logOutput = false; public static bool logOutput = false;
public static TimeSpan minSimTime = new TimeSpan(0, 0, 0, 0, 150); public static TimeSpan minSimTime = new TimeSpan(0, 0, 0, 0, 150);
public static bool vectoredThrust = false; public static bool vectoredThrust = false;
private static readonly object locker = new object(); private static readonly object locker = new object();
private static readonly Stopwatch timer = new Stopwatch(); private static readonly Stopwatch timer = new Stopwatch();
   
// Support for RealFuels using reflection to check localCorrectThrust without dependency  
   
private static FieldInfo RF_ModuleEngineConfigs_locaCorrectThrust;  
private static FieldInfo RF_ModuleHybridEngine_locaCorrectThrust;  
private static FieldInfo RF_ModuleHybridEngines_locaCorrectThrust;  
private static bool bRequested; private static bool bRequested;
private static bool bRunning; private static bool bRunning;
private static TimeSpan delayBetweenSims; private static TimeSpan delayBetweenSims;
private static bool hasCheckedForRealFuels;  
  // Support for RealFuels using reflection to check localCorrectThrust without dependency
   
  private static bool hasCheckedForMods;
private static bool hasInstalledRealFuels; private static bool hasInstalledRealFuels;
  private static FieldInfo RF_ModuleEngineConfigs_localCorrectThrust;
  private static FieldInfo RF_ModuleHybridEngine_localCorrectThrust;
  private static FieldInfo RF_ModuleHybridEngines_localCorrectThrust;
  private static bool hasInstalledKIDS;
  private static MethodInfo KIDS_Utils_GetIspMultiplier;
  private static bool bKIDSThrustISP = false;
#endregion #endregion
   
#region Delegates #region Delegates
   
public delegate void ReadyEvent(); public delegate void ReadyEvent();
   
#endregion #endregion
   
#region Events #region Events
   
public static event ReadyEvent OnReady; public static event ReadyEvent OnReady;
   
#endregion #endregion
   
#region Properties #region Properties
   
public static double Atmosphere { get; set; } public static double Atmosphere { get; set; }
   
public static double Gravity { get; set; } public static double Gravity { get; set; }
   
public static Stage LastStage { get; private set; } public static Stage LastStage { get; private set; }
   
public static Stage[] Stages { get; private set; } public static Stage[] Stages { get; private set; }
   
public static double Velocity { get; set; } public static double Velocity { get; set; }
   
public static String failMessage { get; private set; } public static String failMessage { get; private set; }
   
#endregion #endregion
   
#region Methods #region Methods
   
  private static void CheckForMods()
  {
  hasCheckedForMods = true;
   
  foreach (var assembly in AssemblyLoader.loadedAssemblies)
  {
  MonoBehaviour.print("Assembly:" + assembly.assembly);
   
  var name = assembly.assembly.ToString().Split(',')[0];
   
  if (name == "RealFuels")
  {
  MonoBehaviour.print("Found RealFuels mod");
   
  var RF_ModuleEngineConfigs_Type = assembly.assembly.GetType("RealFuels.ModuleEngineConfigs");
  if (RF_ModuleEngineConfigs_Type != null)
  {
  RF_ModuleEngineConfigs_localCorrectThrust = RF_ModuleEngineConfigs_Type.GetField("localCorrectThrust");
  }
   
  var RF_ModuleHybridEngine_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngine");
  if (RF_ModuleHybridEngine_Type != null)
  {
  RF_ModuleHybridEngine_localCorrectThrust = RF_ModuleHybridEngine_Type.GetField("localCorrectThrust");
  }
   
  var RF_ModuleHybridEngines_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngines");
  if (RF_ModuleHybridEngines_Type != null)
  {
  RF_ModuleHybridEngines_localCorrectThrust = RF_ModuleHybridEngines_Type.GetField("localCorrectThrust");
  }
   
  hasInstalledRealFuels = true;
  break;
  }
  else if (name == "KerbalIspDifficultyScaler")
  {
  var KIDS_Utils_Type = assembly.assembly.GetType("KerbalIspDifficultyScaler.KerbalIspDifficultyScalerUtils");
  if (KIDS_Utils_Type != null)
  {
  KIDS_Utils_GetIspMultiplier = KIDS_Utils_Type.GetMethod("GetIspMultiplier");
  }
   
  hasInstalledKIDS = true;
  }
  }
  }
   
public static bool DoesEngineUseCorrectedThrust(Part theEngine) public static bool DoesEngineUseCorrectedThrust(Part theEngine)
{ {
if (!hasInstalledRealFuels /*|| HighLogic.LoadedSceneIsFlight*/) if (hasInstalledRealFuels)
{ {
return false; // Look for any of the Real Fuels engine modules and call the relevant method to find out
} if (RF_ModuleEngineConfigs_localCorrectThrust != null && theEngine.Modules.Contains("ModuleEngineConfigs"))
  {
// Look for any of the Real Fuels engine modules and call the relevant method to find out var modEngineConfigs = theEngine.Modules["ModuleEngineConfigs"];
if (RF_ModuleEngineConfigs_locaCorrectThrust != null && theEngine.Modules.Contains("ModuleEngineConfigs")) if (modEngineConfigs != null)
{ {
var modEngineConfigs = theEngine.Modules["ModuleEngineConfigs"]; // Return the localCorrectThrust
if (modEngineConfigs != null) return (bool)RF_ModuleEngineConfigs_localCorrectThrust.GetValue(modEngineConfigs);
{ }
// Check the localCorrectThrust }
if ((bool)RF_ModuleEngineConfigs_locaCorrectThrust.GetValue(modEngineConfigs))  
{ if (RF_ModuleHybridEngine_localCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngine"))
return true; {
} var modHybridEngine = theEngine.Modules["ModuleHybridEngine"];
} if (modHybridEngine != null)
} {
  // Return the localCorrectThrust
if (RF_ModuleHybridEngine_locaCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngine")) return (bool)RF_ModuleHybridEngine_localCorrectThrust.GetValue(modHybridEngine);
{ }
var modHybridEngine = theEngine.Modules["ModuleHybridEngine"]; }
if (modHybridEngine != null)  
{ if (RF_ModuleHybridEngines_localCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngines"))
// Check the localCorrectThrust {
if ((bool)RF_ModuleHybridEngine_locaCorrectThrust.GetValue(modHybridEngine)) var modHybridEngines = theEngine.Modules["ModuleHybridEngines"];
{ if (modHybridEngines != null)
return true; {
} // Return the localCorrectThrust
} return (bool)RF_ModuleHybridEngines_localCorrectThrust.GetValue(modHybridEngines);
} }
  }
if (RF_ModuleHybridEngines_locaCorrectThrust != null && theEngine.Modules.Contains("ModuleHybridEngines")) }
{  
var modHybridEngines = theEngine.Modules["ModuleHybridEngines"]; if (hasInstalledKIDS && HighLogic.LoadedSceneIsEditor)
if (modHybridEngines != null) {
{ return bKIDSThrustISP;
// Check the localCorrectThrust  
if ((bool)RF_ModuleHybridEngines_locaCorrectThrust.GetValue(modHybridEngines))  
{  
return true;  
}  
}  
} }
   
return false; return false;
  }
   
  public static void UpdateModSettings()
  {
  if (!hasCheckedForMods)
  {
  CheckForMods();
  }
   
  if (hasInstalledKIDS)
  {
  // (out ispMultiplierVac, out ispMultiplierAtm, out extendToZeroIsp, out thrustCorrection, out ispCutoff, out thrustCutoff);
  object[] parameters = new object[6];
  KIDS_Utils_GetIspMultiplier.Invoke(null, parameters);
  bKIDSThrustISP = (bool)parameters[3];
  }
} }
   
public static String GetVesselTypeString(VesselType vesselType) public static String GetVesselTypeString(VesselType vesselType)
{ {
switch (vesselType) switch (vesselType)
{ {
case VesselType.Debris: case VesselType.Debris:
return "Debris"; return "Debris";
case VesselType.SpaceObject: case VesselType.SpaceObject:
return "SpaceObject"; return "SpaceObject";
case VesselType.Unknown: case VesselType.Unknown:
return "Unknown"; return "Unknown";
case VesselType.Probe: case VesselType.Probe:
return "Probe"; return "Probe";
case VesselType.Rover: case VesselType.Rover:
return "Rover"; return "Rover";
case VesselType.Lander: case VesselType.Lander:
return "Lander"; return "Lander";
case VesselType.Ship: case VesselType.Ship:
return "Ship"; return "Ship";
case VesselType.Station: case VesselType.Station:
return "Station"; return "Station";
case VesselType.Base: case VesselType.Base:
return "Base"; return "Base";
case VesselType.EVA: case VesselType.EVA:
return "EVA"; return "EVA";
case VesselType.Flag: case VesselType.Flag:
return "Flag"; return "Flag";
} }
return "Undefined"; return "Undefined";
} }
   
public static void RequestSimulation() public static void RequestSimulation()
{ {
if (!hasCheckedForRealFuels) if (!hasCheckedForMods)
{ {
GetRealFuelsTypes(); CheckForMods();
} }
   
lock (locker) lock (locker)
{ {
bRequested = true; bRequested = true;
if (!timer.IsRunning) if (!timer.IsRunning)
{ {
timer.Start(); timer.Start();
} }
} }
} }
   
public static bool ResultsReady() public static bool ResultsReady()
{ {
lock (locker) lock (locker)
{ {
return !bRunning; return !bRunning;
} }
} }
   
public static void TryStartSimulation() public static void TryStartSimulation()
{ {
lock (locker) lock (locker)
{ {
if (!bRequested || bRunning || (timer.Elapsed < delayBetweenSims && timer.Elapsed >= TimeSpan.Zero) || (!HighLogic.LoadedSceneIsEditor && FlightGlobals.ActiveVessel == null)) if (!bRequested || bRunning || (timer.Elapsed < delayBetweenSims && timer.Elapsed >= TimeSpan.Zero) || (!HighLogic.LoadedSceneIsEditor && FlightGlobals.ActiveVessel == null))
{ {
return; return;
} }
   
bRequested = false; bRequested = false;
timer.Reset(); timer.Reset();
} }
   
StartSimulation(); StartSimulation();
} }
   
private static void ClearResults() private static void ClearResults()
{ {
failMessage = ""; failMessage = "";
Stages = null; Stages = null;
LastStage = null; LastStage = null;
}  
   
private static void GetRealFuelsTypes()  
{  
hasCheckedForRealFuels = true;  
   
foreach (var assembly in AssemblyLoader.loadedAssemblies)  
{  
MonoBehaviour.print("Assembly:" + assembly.assembly);  
   
if (assembly.assembly.ToString().Split(',')[0] == "RealFuels")  
{  
MonoBehaviour.print("Found RealFuels mod");  
   
var RF_ModuleEngineConfigs_Type = assembly.assembly.GetType("RealFuels.ModuleEngineConfigs");  
if (RF_ModuleEngineConfigs_Type != null)  
{  
RF_ModuleEngineConfigs_locaCorrectThrust = RF_ModuleEngineConfigs_Type.GetField("localCorrectThrust");  
}  
   
var RF_ModuleHybridEngine_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngine");  
if (RF_ModuleHybridEngine_Type != null)  
{  
RF_ModuleHybridEngine_locaCorrectThrust = RF_ModuleHybridEngine_Type.GetField("localCorrectThrust");  
}  
   
var RF_ModuleHybridEngines_Type = assembly.assembly.GetType("RealFuels.ModuleHybridEngines");  
if (RF_ModuleHybridEngines_Type != null)  
{  
RF_ModuleHybridEngines_locaCorrectThrust = RF_ModuleHybridEngines_Type.GetField("localCorrectThrust");  
}  
   
hasInstalledRealFuels = true;  
break;  
}  
}  
} }
   
private static void RunSimulation(object simObject) private static void RunSimulation(object simObject)
{ {
try try
{ {
Stages = (simObject as Simulation).RunSimulation(); Stages = (simObject as Simulation).RunSimulation();
if (Stages != null && Stages.Length > 0) if (Stages != null && Stages.Length > 0)
{ {
if (logOutput) if (logOutput)
{ {
foreach (var stage in Stages) foreach (var stage in Stages)
{ {
stage.Dump(); stage.Dump();
} }
} }
LastStage = Stages[Stages.Length - 1]; LastStage = Stages[Stages.Length - 1];
} }
} }
catch (Exception e) catch (Exception e)
{ {
MonoBehaviour.print("Exception in RunSimulation: " + e); MonoBehaviour.print("Exception in RunSimulation: " + e);
Logger.Exception(e); Logger.Exception(e);
Stages = null; Stages = null;
LastStage = null; LastStage = null;
failMessage = e.ToString(); failMessage = e.ToString();
} }
lock (locker) lock (locker)
{ {
timer.Stop(); timer.Stop();
#if TIMERS #if TIMERS
MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms"); MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
#else #else
if (logOutput) if (logOutput)
{ {
MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms"); MonoBehaviour.print("Total simulation time: " + timer.ElapsedMilliseconds + "ms");
} }
#endif #endif
   
delayBetweenSims = minSimTime - timer.Elapsed; delayBetweenSims = minSimTime - timer.Elapsed;
if (delayBetweenSims < TimeSpan.Zero) if (delayBetweenSims < TimeSpan.Zero)
{ {
delayBetweenSims = TimeSpan.Zero; delayBetweenSims = TimeSpan.Zero;
} }
   
timer.Reset(); timer.Reset();
timer.Start(); timer.Start();
   
bRunning = false; bRunning = false;
if (OnReady != null) if (OnReady != null)
{ {
OnReady(); OnReady();
} }
} }
   
logOutput = false; logOutput = false;
} }
   
private static void StartSimulation() private static void StartSimulation()
{ {
try try
{ {
lock (locker) lock (locker)
{ {
bRunning = true; bRunning = true;
} }
   
ClearResults(); ClearResults();
   
lock (locker) lock (locker)
{ {
timer.Start(); timer.Start();
} }
   
var parts = HighLogic.LoadedSceneIsEditor ? EditorLogic.fetch.ship.parts : FlightGlobals.ActiveVessel.Parts; var parts = HighLogic.LoadedSceneIsEditor ? EditorLogic.fetch.ship.parts : FlightGlobals.ActiveVessel.Parts;
   
// Create the Simulation object in this thread // Create the Simulation object in this thread
var sim = new Simulation(); var sim = new Simulation();
   
// This call doesn't ever fail at the moment but we'll check and return a sensible error for display // This call doesn't ever fail at the moment but we'll check and return a sensible error for display
if (sim.PrepareSimulation(parts, Gravity, Atmosphere, Velocity, dumpTree, vectoredThrust)) if (sim.PrepareSimulation(parts, Gravity, Atmosphere, Velocity, dumpTree, vectoredThrust))
{ {
ThreadPool.QueueUserWorkItem(RunSimulation, sim); ThreadPool.QueueUserWorkItem(RunSimulation, sim);
} }
else else
{ {
failMessage = "PrepareSimulation failed"; failMessage = "PrepareSimulation failed";
lock (locker) lock (locker)
{ {
bRunning = false; bRunning = false;
} }
logOutput = false; logOutput = false;
} }
} }
catch (Exception e) catch (Exception e)
{ {
MonoBehaviour.print("Exception in StartSimulation: " + e); MonoBehaviour.print("Exception in StartSimulation: " + e);
Logger.Exception(e); Logger.Exception(e);
failMessage = e.ToString(); failMessage = e.ToString();
lock (locker) lock (locker)
{ {
bRunning = false; bRunning = false;
} }
logOutput = false; logOutput = false;
} }
dumpTree = false; dumpTree = false;
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// 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/>.
// //
   
#region Using Directives #region Using Directives
   
using System.Text; using System.Text;
   
using UnityEngine; using UnityEngine;
   
#endregion #endregion
   
namespace KerbalEngineer.VesselSimulator namespace KerbalEngineer.VesselSimulator
{ {
public class Stage public class Stage
{ {
public double actualThrust = 0f; public double actualThrust = 0.0;
public double actualThrustToWeight = 0f; public double actualThrustToWeight = 0.0;
public double cost = 0d; public double cost = 0.0;
public double deltaV = 0f; public double deltaV = 0.0;
public double inverseTotalDeltaV = 0f; public double inverseTotalDeltaV = 0.0;
public double isp = 0f; public double isp = 0.0;
public double mass = 0f; public double mass = 0.0;
public double maxThrustToWeight = 0f; public double rcsMass = 0.0;
  public double maxThrustToWeight = 0.0;
public int number = 0; public int number = 0;
public double thrust = 0f; public double thrust = 0.0;
public double thrustToWeight = 0f; public double thrustToWeight = 0.0;
public double time = 0f; public double time = 0.0;
public double totalCost = 0; public double totalCost = 0.0;
public double totalDeltaV = 0f; public double totalDeltaV = 0.0;
public double totalMass = 0f; public double totalMass = 0.0;
public double totalTime = 0f; public double totalTime = 0.0;
public int totalPartCount = 0; public int totalPartCount = 0;
public int partCount = 0; public int partCount = 0;
public double resourceMass = 0.0; public double resourceMass = 0.0;
public double maxThrustTorque = 0f; public double maxThrustTorque = 0.0;
public double thrustOffsetAngle = 0f; public double thrustOffsetAngle = 0.0;
   
public void Dump() public void Dump()
{ {
StringBuilder str = new StringBuilder("", 512); StringBuilder str = new StringBuilder("", 512);
str.AppendFormat("number : {0:d}\n", this.number); str.AppendFormat("number : {0:d}\n", this.number);
str.AppendFormat("cost : {0:g6}\n", this.cost); str.AppendFormat("cost : {0:g6}\n", this.cost);
str.AppendFormat("totalCost : {0:g6}\n", this.totalCost); str.AppendFormat("totalCost : {0:g6}\n", this.totalCost);
str.AppendFormat("time : {0:g6}\n", this.time); str.AppendFormat("time : {0:g6}\n", this.time);
str.AppendFormat("totalTime : {0:g6}\n", this.totalTime); str.AppendFormat("totalTime : {0:g6}\n", this.totalTime);
str.AppendFormat("mass : {0:g6}\n", this.mass); str.AppendFormat("mass : {0:g6}\n", this.mass);
str.AppendFormat("totalMass : {0:g6}\n", this.totalMass); str.AppendFormat("totalMass : {0:g6}\n", this.totalMass);
str.AppendFormat("isp : {0:g6}\n", this.isp); str.AppendFormat("isp : {0:g6}\n", this.isp);
str.AppendFormat("thrust : {0:g6}\n", this.thrust); str.AppendFormat("thrust : {0:g6}\n", this.thrust);
str.AppendFormat("actualThrust : {0:g6}\n", this.actualThrust); str.AppendFormat("actualThrust : {0:g6}\n", this.actualThrust);
str.AppendFormat("thrustToWeight: {0:g6}\n", this.thrustToWeight); str.AppendFormat("thrustToWeight: {0:g6}\n", this.thrustToWeight);
str.AppendFormat("maxTWR : {0:g6}\n", this.maxThrustToWeight); str.AppendFormat("maxTWR : {0:g6}\n", this.maxThrustToWeight);
str.AppendFormat("actualTWR : {0:g6}\n", this.actualThrustToWeight); str.AppendFormat("actualTWR : {0:g6}\n", this.actualThrustToWeight);
str.AppendFormat("ThrustTorque : {0:g6}\n", this.maxThrustTorque); str.AppendFormat("ThrustTorque : {0:g6}\n", this.maxThrustTorque);
str.AppendFormat("ThrustOffset : {0:g6}\n", this.thrustOffsetAngle); str.AppendFormat("ThrustOffset : {0:g6}\n", this.thrustOffsetAngle);
str.AppendFormat("deltaV : {0:g6}\n", this.deltaV); str.AppendFormat("deltaV : {0:g6}\n", this.deltaV);
str.AppendFormat("totalDeltaV : {0:g6}\n", this.totalDeltaV); str.AppendFormat("totalDeltaV : {0:g6}\n", this.totalDeltaV);
str.AppendFormat("invTotDeltaV : {0:g6}\n", this.inverseTotalDeltaV); str.AppendFormat("invTotDeltaV : {0:g6}\n", this.inverseTotalDeltaV);
   
MonoBehaviour.print(str); MonoBehaviour.print(str);
} }
} }
} }
 Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ
{ {
"NAME":"Kerbal Engineer Redux 1.0", "NAME":"Kerbal Engineer Redux 1.0",
"URL":"http://ksp-avc.cybutek.net/version.php?id=6", "URL":"http://ksp-avc.cybutek.net/version.php?id=6",
"VERSION": "VERSION":
{ {
"MAJOR":1, "MAJOR":1,
"MINOR":0, "MINOR":0,
"PATCH":13, "PATCH":14,
"BUILD":1 "BUILD":1
}, },
"KSP_VERSION": "KSP_VERSION":
{ {
"MAJOR":0, "MAJOR":0,
"MINOR":90, "MINOR":90,
"PATCH":0 "PATCH":0
} }
} }
 Binary files /dev/null and b/Output/KerbalEngineer/Parts/Engineer7500/model000.mbm differ
PART PART
{ {
// --- general parameters --- // --- general parameters ---
name = Engineer7500 name = Engineer7500
module = Part module = Part
author = CYBUTEK (Code) || Keptin (Part) author = CYBUTEK (Code) || Keptin (Part)
// --- asset parameters --- // --- asset parameters ---
mesh = model.mu mesh = model.mu
texture = model000.mbm  
rescaleFactor = 0.8 rescaleFactor = 0.8
   
PhysicsSignificance = 1 PhysicsSignificance = 1
// --- editor parameters --- // --- editor parameters ---
TechRequired = start TechRequired = start
entryCost = 0 entryCost = 0
cost = 500 cost = 500
category = Science category = Science
subcategory = 0 subcategory = 0
title = ER-7500 Computer Flight Unit title = ER-7500 Computer Flight Unit
manufacturer = CYBUTEK Solutions Ltd. manufacturer = CYBUTEK Solutions Ltd.
description = The ER-7500 goes back to roots with the Kerbal Engineering System. This unit has been proven to be at least 1x10^-5 times faster than a standard hard drive. description = The ER-7500 goes back to roots with the Kerbal Engineering System. This unit has been proven to be at least 1x10^-5 times faster than a standard hard drive.
   
// attachment rules: stack, srfAttach, allowStack, allowSrfAttach, allowCollision // attachment rules: stack, srfAttach, allowStack, allowSrfAttach, allowCollision
attachRules = 0,1,0,1,1 attachRules = 0,1,0,1,1
// --- node definitions --- // --- node definitions ---
// definition format is Position X, Position Y, Position Z, Up X, Up Y, Up Z // definition format is Position X, Position Y, Position Z, Up X, Up Y, Up Z
node_attach = 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 node_attach = 0.0, 0.0, 0.0, 1.0, 0.0, 0.0
// --- standard part parameters --- // --- standard part parameters ---
mass = 0.005 mass = 0.005
dragModelType = override dragModelType = override
maximum_drag = 0 maximum_drag = 0
minimum_drag = 0 minimum_drag = 0
angularDrag = 0 angularDrag = 0
crashTolerance = 15 crashTolerance = 15
maxTemp = 3400 maxTemp = 3400
MODULE MODULE
{ {
name = FlightEngineerModule name = FlightEngineerModule
} }
MODULE MODULE
{ {
name = TapeDriveAnimator name = TapeDriveAnimator
UseBakedAnimation = false UseBakedAnimation = false
MinReelSpeed = -30 MinReelSpeed = -30
MaxReelSpeed = 30 MaxReelSpeed = 30
SpeedStopZone = 10 SpeedStopZone = 10
SpeedDeadZone = 2.5 SpeedDeadZone = 2.5
SpeedChangeAmount = 30 SpeedChangeAmount = 30
MinRepeatTime = 1 MinRepeatTime = 1
MaxRepeatTime = 6 MaxRepeatTime = 6
RepeatTimeDenominator = 8 RepeatTimeDenominator = 8
Reel1 = geo_reel1 Reel1 = geo_reel1
Reel2 = geo_reel2 Reel2 = geo_reel2
Reel1SpeedRatio = 1 Reel1SpeedRatio = 1
Reel2SpeedRatio = 0.75 Reel2SpeedRatio = 0.75
Lights1 = geo_buttonSet1 Lights1 = geo_buttonSet1
Lights2 = geo_buttonSet2 Lights2 = geo_buttonSet2
Lights3 = geo_buttonSet3 Lights3 = geo_buttonSet3
Lights4 = geo_buttonSet4 Lights4 = geo_buttonSet4
Lights5 = geo_buttonSet5 Lights5 = geo_buttonSet5
Lights6 = geo_buttonSet6 Lights6 = geo_buttonSet6
Lights1Speed = 0 Lights1Speed = 0
Lights2Speed = -2.5 Lights2Speed = -2.5
Lights3Speed = 2.5 Lights3Speed = 2.5
Lights4Speed = 10 Lights4Speed = 10
Lights5Speed = -15 Lights5Speed = -15
Lights6Speed = 17.5 Lights6Speed = 17.5
} }
} }
 Binary files a/Output/KerbalEngineer/Parts/Engineer7500/textures/model000.mbm and /dev/null differ