Binary files a/Assets/CurseLogo.png and b/Assets/CurseLogo.png differ
Binary files a/Assets/CurseLogo.psd and b/Assets/CurseLogo.psd differ
1.0.16.6, 02-05-15 | |
Fixed: Separately staged fairing mass jettisons are now calculated in the editor. | |
1.0.16.5, 02-05-2015 | |
Fixed: Delta-V not being correctly calculated. | |
Changed: Editor locking now uses the InputLockManager. | |
1.0.16.4, 01-05-2015 | |
Fixed: Physically insignificant part mass is now accounted for. | |
Changed: Module mass accounted for as it now makes its way onto the launch pad (e.g. fairings). | |
Various optimisations: | |
Object pooling. | |
Removed LINQ expressions. | |
Converted foreach to for loops. | |
1.0.16.3, 27-04-2015 | |
Fixed issue with the toolbar icons not being created. | |
Removed superfluous 'm/s' on the mach slider in the build engineer. | |
1.0.16.2, 27-04-2015 | |
Changed the atmospheric slider on the build engineer to default to 0km when changing bodies. | |
1.0.16.1, 26-04-2015, KSP Build #828 | |
Merged Sarbian's mach adjustments. | |
Fixed bugs relating to thrust and atmosphere/velocity curves. | |
Changed the atmospheric slider on the Build Engineer to work based on altitude. | |
Changed the atmospheric slider to clamp to the maximum altitude for the selected body. | |
Changed the velocity slider to clamp to the maximum usable mach value for the current vessel. | |
1.0.16.0, 25-04-2015, KSP Build #821 | |
Fixed errors relating to KSP 1.0 update. | |
Fixed fuel simulation to account for new thrust system. | |
Fixed atmospheric engines to use the new velocity curve. | |
Fixed atmospheric readouts to work with the new atmospheric model. | |
1.0.15.2, 13-02-2015 | |
Padishar's Fixes: | |
Fixed: Calculation of per-stage resource mass. | |
1.0.15.1, 13-02-2015 | 1.0.15.1, 13-02-2015 |
Rebuild | Rebuild |
1.0.15.0, 08-02-2015 | 1.0.15.0, 08-02-2015 |
Padishar's Fixes: | Padishar's Fixes: |
Added: Support KIDS ISP thrust correction. | Added: Support KIDS ISP thrust correction. |
Fixed: Log spam for stage priority mode. | Fixed: Log spam for stage priority mode. |
Fixed: Locked tanks preventing simulation from staging. | Fixed: Locked tanks preventing simulation from staging. |
Fixed: No flow and all vessel modes to respect flow states. | Fixed: No flow and all vessel modes to respect flow states. |
1.0.14.1, 28-12-2014 | 1.0.14.1, 28-12-2014 |
Fixed: Missing texture on the ER-7500 model. | Fixed: Missing texture on the ER-7500 model. |
1.0.14.0, 28-12-2014 | 1.0.14.0, 28-12-2014 |
Added: Career mode that limits the Flight Engineer by: | 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. | - 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. | - Tracking station level 3 enables Flight Engineer everywhere. |
Added: New readouts to the orbital category: | Added: New readouts to the orbital category: |
- Mean Anomaly at Epoc | - Mean Anomaly at Epoc |
Added: New readouts to the miscellaneous category: | Added: New readouts to the miscellaneous category: |
- System Time | - 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. | 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: Bug where STAGE_PRIORITY_FLOW resources would not be corrently disabled/enabled. |
Fixed: Issue with the formatting large Mass and Cost values. | Fixed: Issue with the formatting large Mass and Cost values. |
Fixed: Error when loading the Engineer7500 part model. | 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/>. |
// | // |
#region Using Directives | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
#endregion | |
namespace KerbalEngineer | namespace KerbalEngineer |
{ | { |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
/* | /* |
* | * |
* With thanks to Nathaniel R. Lewis (aka. Teknoman117) (linux.robotdude@gmail.com) for working out | * With thanks to Nathaniel R. Lewis (aka. Teknoman117) (linux.robotdude@gmail.com) for working out |
* the best way of getting the celestial body information dynamically using PSystemManager. | * the best way of getting the celestial body information dynamically using PSystemManager. |
* | * |
*/ | */ |
public static class CelestialBodies | public static class CelestialBodies |
{ | { |
#region Constructors | |
static CelestialBodies() | static CelestialBodies() |
{ | { |
try | try |
{ | { |
SystemBody = new BodyInfo(PSystemManager.Instance.localBodies.Find(b => b.referenceBody == null || b.referenceBody == b)); | SystemBody = new BodyInfo(PSystemManager.Instance.localBodies.Find(b => b.referenceBody == null || b.referenceBody == b)); |
if (!SetSelectedBody("Kerbin")) | if (!SetSelectedBody("Kerbin")) |
{ | { |
SelectedBody = SystemBody; | SelectedBody = SystemBody; |
SelectedBody.SetSelected(true); | SelectedBody.SetSelected(true); |
} | } |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex); |
} | } |
} | } |
#endregion | |
#region Properties | |
public static BodyInfo SelectedBody { get; private set; } | public static BodyInfo SelectedBody { get; private set; } |
public static BodyInfo SystemBody { get; private set; } | public static BodyInfo SystemBody { get; private set; } |
#endregion | |
#region Public Methods | |
/// <summary> | /// <summary> |
/// Gets a body given a supplied body name. | /// Gets a body given a supplied body name. |
/// </summary> | /// </summary> |
public static BodyInfo GetBodyInfo(string bodyName) | public static BodyInfo GetBodyInfo(string bodyName) |
{ | { |
try | try |
{ | { |
return SystemBody.GetBodyInfo(bodyName); | return SystemBody.GetBodyInfo(bodyName); |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex); |
} | } |
return null; | return null; |
} | } |
/// <summary> | /// <summary> |
/// Sets the selected body to one matching the supplied body name. Returns true if successful. | /// Sets the selected body to one matching the supplied body name. Returns true if successful. |
/// </summary> | /// </summary> |
public static bool SetSelectedBody(string bodyName) | public static bool SetSelectedBody(string bodyName) |
{ | { |
try | try |
{ | { |
var body = GetBodyInfo(bodyName); | BodyInfo body = GetBodyInfo(bodyName); |
if (body != null) | if (body != null) |
{ | { |
if (SelectedBody != null) | if (SelectedBody != null) |
{ | { |
SelectedBody.SetSelected(false); | SelectedBody.SetSelected(false); |
} | } |
SelectedBody = body; | SelectedBody = body; |
SelectedBody.SetSelected(true); | SelectedBody.SetSelected(true); |
return true; | return true; |
} | } |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex); |
} | } |
return false; | return false; |
} | } |
#endregion | |
#region Nested type: BodyInfo | |
public class BodyInfo | public class BodyInfo |
{ | { |
#region Constructors | |
public BodyInfo(CelestialBody body, BodyInfo parent = null) | public BodyInfo(CelestialBody body, BodyInfo parent = null) |
{ | { |
try | try |
{ | { |
// Set the body information. | // Set the body information. |
this.CelestialBody = body; | CelestialBody = body; |
this.Name = body.bodyName; | Name = body.bodyName; |
this.Gravity = 9.81 * body.GeeASL; | Gravity = 9.81 * body.GeeASL; |
this.Atmosphere = body.atmosphere ? 101.325 * body.atmosphereMultiplier : 0; | Parent = parent; |
this.Parent = parent; | |
// Set orbiting bodies information. | // Set orbiting bodies information. |
this.Children = new List<BodyInfo>(); | Children = new List<BodyInfo>(); |
foreach (var orbitingBody in body.orbitingBodies) | foreach (CelestialBody orbitingBody in body.orbitingBodies) |
{ | { |
this.Children.Add(new BodyInfo(orbitingBody, this)); | Children.Add(new BodyInfo(orbitingBody, this)); |
} | } |
this.SelectedDepth = 0; | SelectedDepth = 0; |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex); |
} | } |
} | } |
#endregion | public CelestialBody CelestialBody { get; private set; } |
public List<BodyInfo> Children { get; private set; } | |
#region Properties | public double Gravity { get; private set; } |
public string Name { get; private set; } | public string Name { get; private set; } |
public double Gravity { get; private set; } | |
public double Atmosphere { get; private set; } | |
public BodyInfo Parent { get; private set; } | public BodyInfo Parent { get; private set; } |
public List<BodyInfo> Children { get; private set; } | |
public CelestialBody CelestialBody { get; private set; } | |
public bool Selected { get; private set; } | public bool Selected { get; private set; } |
public int SelectedDepth { get; private set; } | public int SelectedDepth { get; private set; } |
#endregion | |
#region Public Methods | |
public BodyInfo GetBodyInfo(string bodyName) | public BodyInfo GetBodyInfo(string bodyName) |
{ | { |
try | try |
{ | { |
// This is the searched body. | // This is the searched body. |
if (String.Equals(this.Name, bodyName, StringComparison.CurrentCultureIgnoreCase)) | if (String.Equals(Name, bodyName, StringComparison.CurrentCultureIgnoreCase)) |
{ | { |
return this; | return this; |
} | } |
// Check to see if any of this bodies children are the searched body. | // Check to see if any of this bodies children are the searched body. |
foreach (var child in this.Children) | foreach (BodyInfo child in Children) |
{ | { |
var body = child.GetBodyInfo(bodyName); | BodyInfo body = child.GetBodyInfo(bodyName); |
if (body != null) | if (body != null) |
{ | { |
return body; | return body; |
} | } |
} | } |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex); |
} | } |
// A body with the specified name was not found. | // A body with the specified name was not found. |
return null; | return null; |
} | } |
public double GetDensity(double altitude) | |
{ | |
return CelestialBody.GetDensity(GetPressure(altitude), GetTemperature(altitude)); | |
} | |
public double GetPressure(double altitude) | |
{ | |
return CelestialBody.GetPressure(altitude); | |
} | |
public double GetTemperature(double altitude) | |
{ | |
return CelestialBody.GetTemperature(altitude); | |
} | |
public double GetAtmospheres(double altitude) | |
{ | |
return GetPressure(altitude) * PhysicsGlobals.KpaToAtmospheres; | |
} | |
public void SetSelected(bool state, int depth = 0) | public void SetSelected(bool state, int depth = 0) |
{ | { |
this.Selected = state; | Selected = state; |
this.SelectedDepth = depth; | SelectedDepth = depth; |
if (this.Parent != null) | if (Parent != null) |
{ | { |
this.Parent.SetSelected(state, depth + 1); | Parent.SetSelected(state, depth + 1); |
} | } |
} | } |
#endregion | |
#region Debugging | |
public override string ToString() | public override string ToString() |
{ | { |
var log = "\n" + this.Name + | string log = "\n" + Name + |
"\n\tGravity: " + this.Gravity + | "\n\tGravity: " + Gravity + |
"\n\tAtmosphere: " + this.Atmosphere + | "\n\tSelected: " + Selected; |
"\n\tSelected: " + this.Selected; | |
return Children.Aggregate(log, (current, child) => current + "\n" + child); | |
return this.Children.Aggregate(log, (current, child) => current + "\n" + child); | } |
} | } |
#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.Editor | namespace KerbalEngineer.Editor |
{ | { |
#region Using Directives | #region Using Directives |
using System; | using System; |
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 |
public static float Altitude = 0.0f; | |
private GUIStyle areaSettingStyle; | private GUIStyle areaSettingStyle; |
private GUIStyle areaStyle; | private GUIStyle areaStyle; |
private float atmosphericPercentage = 1.0f; | private float atmosphericMach; |
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 float maxMach; | |
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 |
set { this.compactMode = value; } | { |
return compactMode; | |
} | |
set | |
{ | |
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 |
set { this.showAllStages = value; } | { |
return showAllStages; | |
} | |
set | |
{ | |
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 |
set { this.showAtmosphericDetails = value; } | { |
return showAtmosphericDetails; | |
} | |
set | |
{ | |
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 |
set { this.showSettings = value; } | { |
return showSettings; | |
} | |
set | |
{ | |
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 |
set { this.visible = value; } | { |
} | return visible; |
} | |
set | |
{ | |
visible = value; | |
} | |
} | |
#endregion | #endregion |
#region Methods | #region Methods |
private static Rect compactModeRect = new Rect(0.0f, 5.0f, 0.0f, 20.0f); | |
private static Stage stage; | |
private static int stagesCount; | |
private static int stagesLength; | |
private static string title; | |
protected void Awake() | protected void Awake() |
{ | { |
try | try |
{ | { |
Instance = this; | Instance = this; |
this.bodiesList = this.gameObject.AddComponent<DropDown>(); | bodiesList = gameObject.AddComponent<DropDown>(); |
this.bodiesList.DrawCallback = this.DrawBodiesList; | bodiesList.DrawCallback = DrawBodiesList; |
this.Load(); | Load(); |
SimManager.UpdateModSettings(); | SimManager.UpdateModSettings(); |
SimManager.OnReady -= this.GetStageInfo; | SimManager.OnReady -= GetStageInfo; |
SimManager.OnReady += this.GetStageInfo; | SimManager.OnReady += GetStageInfo; |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex, "BuildAdvanced.Awake()"); |
} | } |
} | } |
/// <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(); | SettingHandler handler = new SettingHandler(); |
handler.Set("visible", this.visible); | handler.Set("visible", visible); |
handler.Set("windowPositionX", this.position.x); | handler.Set("windowPositionX", position.x); |
handler.Set("windowPositionY", this.position.y); | handler.Set("windowPositionY", position.y); |
handler.Set("compactMode", this.compactMode); | handler.Set("compactMode", compactMode); |
handler.Set("compactCollapseRight", this.compactCollapseRight); | handler.Set("compactCollapseRight", compactCollapseRight); |
handler.Set("showAllStages", this.showAllStages); | handler.Set("showAllStages", showAllStages); |
handler.Set("showAtmosphericDetails", this.showAtmosphericDetails); | handler.Set("showAtmosphericDetails", showAtmosphericDetails); |
handler.Set("showSettings", this.showSettings); | handler.Set("showSettings", 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 -= OnSizeChanged; |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex, "BuildAdvanced.OnDestroy()"); |
} | } |
} | } |
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 (!visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts) |
{ | { |
return; | return; |
} | } |
if (this.stages == null) | if (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); | title = !compactMode ? "KERBAL ENGINEER REDUX " + EngineerGlobals.AssemblyVersion : "K.E.R. " + EngineerGlobals.AssemblyVersion; |
// 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); | stagesLength = stages.Length; |
if (this.hasChanged || stageCount != this.numberOfStages) | if (showAllStages) |
{ | { |
this.hasChanged = false; | stagesCount = stagesLength; |
this.numberOfStages = stageCount; | } |
if (showAllStages == false) | |
this.position.width = 0; | { |
this.position.height = 0; | stagesCount = 0; |
for (int i = 0; i < stagesLength; ++i) | |
{ | |
if (stages[i].deltaV > 0.0f) | |
{ | |
stagesCount = stagesCount + 1; | |
} | |
} | |
} | |
if (hasChanged || stagesCount != numberOfStages) | |
{ | |
hasChanged = false; | |
numberOfStages = stagesCount; | |
position.width = 0; | |
position.height = 0; | |
} | } |
GUI.skin = null; | GUI.skin = null; |
this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, title, this.windowStyle).ClampToScreen(); | position = GUILayout.Window(GetInstanceID(), position, Window, title, windowStyle).ClampToScreen(); |
if (this.compactCheck > 0 && this.compactCollapseRight) | if (compactCheck > 0 && compactCollapseRight) |
{ | { |
this.position.x = this.compactRight - this.position.width; | position.x = compactRight - position.width; |
this.compactCheck--; | compactCheck--; |
} | } |
else if (this.compactCheck > 0) | else if (compactCheck > 0) |
{ | { |
this.compactCheck = 0; | compactCheck = 0; |
} | } |
// Check editor lock to manage click-through. | // Check editor lock to manage click-through. |
this.CheckEditorLock(); | CheckEditorLock(); |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex, "BuildAdvanced.OnGUI()"); |
} | } |
} | } |
protected void Start() | protected void Start() |
{ | { |
try | try |
{ | { |
this.InitialiseStyles(); | InitialiseStyles(); |
GuiDisplaySize.OnSizeChanged += this.OnSizeChanged; | GuiDisplaySize.OnSizeChanged += OnSizeChanged; |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex, "BuildAdvanced.Start()"); |
} | } |
} | } |
protected void Update() | protected void Update() |
{ | { |
try | try |
{ | { |
if (Input.GetKeyDown(KeyBinder.EditorShowHide)) | if (Input.GetKeyDown(KeyBinder.EditorShowHide)) |
{ | { |
this.visible = !this.visible; | visible = !visible; |
if (!this.visible) | if (!visible) |
{ | { |
this.EditorLock(false); | EditorLock(false); |
} | } |
} | } |
if (!this.visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0) | if (!visible || EditorLogic.fetch == null || EditorLogic.fetch.ship.parts.Count == 0) |
{ | { |
this.bodiesList.enabled = false; | 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 (showAtmosphericDetails) |
{ | { |
SimManager.Atmosphere = CelestialBodies.SelectedBody.Atmosphere * 0.01d * this.atmosphericPercentage; | SimManager.Atmosphere = CelestialBodies.SelectedBody.GetAtmospheres(Altitude); |
} | } |
else | else |
{ | { |
SimManager.Atmosphere = 0; | SimManager.Atmosphere = 0; |
} | } |
SimManager.Velocity = this.atmosphericVelocity; | SimManager.Mach = atmosphericMach; |
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 ((position.MouseIsOver() || bodiesList.Position.MouseIsOver()) && !isEditorLocked) |
{ | { |
this.EditorLock(true); | EditorLock(true); |
} | } |
else if (!this.position.MouseIsOver() && !this.bodiesList.Position.MouseIsOver() && this.isEditorLocked) | else if (!position.MouseIsOver() && !bodiesList.Position.MouseIsOver() && isEditorLocked) |
{ | { |
this.EditorLock(false); | EditorLock(false); |
} | } |
} | } |
/// <summary> | /// <summary> |
/// Draws the atmospheric settings. | /// Draws the atmospheric settings. |
/// </summary> | /// </summary> |
private void DrawAtmosphericDetails() | private void DrawAtmosphericDetails() |
{ | { |
GUILayout.BeginHorizontal(); | try |
GUILayout.BeginVertical(); | { |
GUILayout.Label("Pressure: " + (this.atmosphericPercentage * 100.0f).ToString("F1") + "%", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset)); | GUILayout.BeginHorizontal(); |
GUI.skin = HighLogic.Skin; | GUILayout.BeginVertical(); |
this.atmosphericPercentage = GUILayout.HorizontalSlider(this.atmosphericPercentage, 0, 1.0f); | GUILayout.Label("Altitude: " + (Altitude * 0.001f).ToString("F1") + "km", settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset)); |
GUI.skin = null; | GUI.skin = HighLogic.Skin; |
GUILayout.EndVertical(); | Altitude = GUILayout.HorizontalSlider(Altitude, 0.0f, (float)(CelestialBodies.SelectedBody.CelestialBody.atmosphereDepth)); |
GUI.skin = null; | |
GUILayout.Space(5.0f); | GUILayout.EndVertical(); |
GUILayout.BeginVertical(); | GUILayout.Space(5.0f); |
GUILayout.Label("Velocity: " + this.atmosphericVelocity.ToString("F1") + "m/s", this.settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset)); | |
GUI.skin = HighLogic.Skin; | GUILayout.BeginVertical(); |
this.atmosphericVelocity = GUILayout.HorizontalSlider(this.atmosphericVelocity, 0, 2500f); | GUILayout.Label("Mach: " + atmosphericMach.ToString("F2"), settingAtmoStyle, GUILayout.Width(125.0f * GuiDisplaySize.Offset)); |
GUI.skin = null; | GUI.skin = HighLogic.Skin; |
GUILayout.EndVertical(); | atmosphericMach = GUILayout.HorizontalSlider(Mathf.Clamp(atmosphericMach, 0.0f, maxMach), 0.0f, maxMach); |
GUILayout.EndHorizontal(); | GUI.skin = null; |
GUILayout.EndVertical(); | |
GUILayout.EndHorizontal(); | |
} | |
catch (Exception ex) | |
{ | |
Logger.Exception(ex, "BuildAdvanced.DrawAtmosphericDetails()"); | |
} | |
} | } |
private void DrawBodiesList() | private void DrawBodiesList() |
{ | { |
if (CelestialBodies.SystemBody == CelestialBodies.SelectedBody) | if (CelestialBodies.SystemBody == CelestialBodies.SelectedBody) |
{ | { |
this.DrawBody(CelestialBodies.SystemBody); | DrawBody(CelestialBodies.SystemBody); |
} | } |
else | else |
{ | { |
foreach (var body in CelestialBodies.SystemBody.Children) | foreach (CelestialBodies.BodyInfo body in CelestialBodies.SystemBody.Children) |
{ | { |
this.DrawBody(body); | 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 ? bodiesButtonActiveStyle : bodiesButtonStyle)) |
{ | { |
CelestialBodies.SetSelectedBody(bodyInfo.Name); | CelestialBodies.SetSelectedBody(bodyInfo.Name); |
this.bodiesList.Resize = true; | Altitude = 0.0f; |
bodiesList.Resize = true; | |
} | } |
GUILayout.EndHorizontal(); | GUILayout.EndHorizontal(); |
if (bodyInfo.Selected) | if (bodyInfo.Selected) |
{ | { |
foreach (var body in bodyInfo.Children) | for (int i = 0; i < bodyInfo.Children.Count; ++i) |
{ | { |
this.DrawBody(body, depth + 1); | DrawBody(bodyInfo.Children[i], 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", titleStyle); |
foreach (var stage in this.stages) | for (int i = 0; i < stagesLength; ++i) |
{ | { |
if (this.showAllStages || stage.deltaV > 0) | stage = stages[i]; |
{ | if (showAllStages || stage.deltaV > 0.0) |
GUILayout.Label(TimeFormatter.ConvertToString(stage.time), this.infoStyle); | { |
GUILayout.Label(TimeFormatter.ConvertToString(stage.time), 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", titleStyle); |
foreach (var stage in this.stages) | for (int i = 0; i < stagesLength; ++i) |
{ | { |
if (this.showAllStages || stage.deltaV > 0) | stage = stages[i]; |
{ | if (showAllStages || stage.deltaV > 0.0) |
GUILayout.Label(Units.Cost(stage.cost, stage.totalCost), this.infoStyle); | { |
GUILayout.Label(Units.Cost(stage.cost, stage.totalCost), 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", titleStyle); |
foreach (var stage in this.stages) | for (int i = 0; i < stagesLength; ++i) |
{ | { |
if (this.showAllStages || stage.deltaV > 0) | stage = stages[i]; |
{ | if (showAllStages || stage.deltaV > 0.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", 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", titleStyle); |
foreach (var stage in this.stages) | for (int i = 0; i < stagesLength; ++i) |
{ | { |
if (this.showAllStages || stage.deltaV > 0) | stage = stages[i]; |
{ | if (showAllStages || stage.deltaV > 0.0) |
GUILayout.Label(stage.isp.ToString("F1") + "s", this.infoStyle); | { |
GUILayout.Label(stage.isp.ToString("F1") + "s", 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", titleStyle); |
foreach (var stage in this.stages) | for (int i = 0; i < stagesLength; ++i) |
{ | { |
if (this.showAllStages || stage.deltaV > 0) | stage = stages[i]; |
{ | if (showAllStages || stage.deltaV > 0.0) |
GUILayout.Label(Units.ToMass(stage.mass, stage.totalMass), this.infoStyle); | { |
GUILayout.Label(Units.ToMass(stage.mass, stage.totalMass), 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", titleStyle); |
foreach (var stage in this.stages) | for (int i = 0; i < stagesLength; ++i) |
{ | { |
if (this.showAllStages || stage.deltaV > 0) | stage = stages[i]; |
{ | if (showAllStages || stage.deltaV > 0.0) |
GUILayout.Label(stage.partCount + " / " + stage.totalPartCount, this.infoStyle); | { |
GUILayout.Label(stage.partCount + " / " + stage.totalPartCount, 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:", settingStyle); |
this.compactCollapseRight = !GUILayout.Toggle(!this.compactCollapseRight, "LEFT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); | compactCollapseRight = !GUILayout.Toggle(!compactCollapseRight, "LEFT", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); |
this.compactCollapseRight = GUILayout.Toggle(this.compactCollapseRight, "RIGHT", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); | compactCollapseRight = GUILayout.Toggle(compactCollapseRight, "RIGHT", 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", 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:", settingStyle); |
BuildOverlay.Visible = GUILayout.Toggle(BuildOverlay.Visible, "VISIBLE", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); | BuildOverlay.Visible = GUILayout.Toggle(BuildOverlay.Visible, "VISIBLE", 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", 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", 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:", settingStyle); |
FlightEngineerCore.IsCareerMode = GUILayout.Toggle(FlightEngineerCore.IsCareerMode, "CAREER", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); | FlightEngineerCore.IsCareerMode = GUILayout.Toggle(FlightEngineerCore.IsCareerMode, "CAREER", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); |
FlightEngineerCore.IsCareerMode = !GUILayout.Toggle(!FlightEngineerCore.IsCareerMode, "PARTLESS", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); | FlightEngineerCore.IsCareerMode = !GUILayout.Toggle(!FlightEngineerCore.IsCareerMode, "PARTLESS", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); |
GUILayout.EndHorizontal(); | GUILayout.EndHorizontal(); |
GUILayout.BeginHorizontal(); | GUILayout.BeginHorizontal(); |
GUILayout.Label("Flight Engineer Career Limitations:", this.settingStyle); | GUILayout.Label("Flight Engineer Career Limitations:", settingStyle); |
FlightEngineerCore.IsKerbalLimited = GUILayout.Toggle(FlightEngineerCore.IsKerbalLimited, "KERBAL", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); | FlightEngineerCore.IsKerbalLimited = GUILayout.Toggle(FlightEngineerCore.IsKerbalLimited, "KERBAL", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); |
FlightEngineerCore.IsTrackingStationLimited = GUILayout.Toggle(FlightEngineerCore.IsTrackingStationLimited, "TRACKING", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset)); | FlightEngineerCore.IsTrackingStationLimited = GUILayout.Toggle(FlightEngineerCore.IsTrackingStationLimited, "TRACKING", 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, settingStyle); |
if (GUILayout.Button("<", this.buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset))) | if (GUILayout.Button("<", 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(">", 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", 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, titleStyle); |
foreach (var stage in this.stages) | for (int i = 0; i < stagesLength; ++i) |
{ | { |
if (this.showAllStages || stage.deltaV > 0) | stage = stages[i]; |
{ | if (showAllStages || stage.deltaV > 0.0) |
GUILayout.Label("S" + stage.number, this.titleStyle); | { |
GUILayout.Label("S" + stage.number, 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", titleStyle); |
foreach (var stage in this.stages) | for (int i = 0; i < stagesLength; ++i) |
{ | { |
if (this.showAllStages || stage.deltaV > 0) | stage = stages[i]; |
{ | if (showAllStages || stage.deltaV > 0.0) |
GUILayout.Label(stage.thrust.ToForce(), this.infoStyle); | { |
GUILayout.Label(stage.thrust.ToForce(), 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", titleStyle); |
foreach (var stage in this.stages) | for (int i = 0; i < stagesLength; ++i) |
{ | { |
if (this.showAllStages || stage.deltaV > 0) | stage = stages[i]; |
{ | if (showAllStages || stage.deltaV > 0.0) |
GUILayout.Label(stage.maxThrustTorque.ToTorque(), this.infoStyle); | { |
GUILayout.Label(stage.maxThrustTorque.ToTorque(), 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)", titleStyle); |
foreach (var stage in this.stages) | for (int i = 0; i < stagesLength; ++i) |
{ | { |
if (this.showAllStages || stage.deltaV > 0) | stage = stages[i]; |
{ | if (showAllStages || stage.deltaV > 0.0) |
GUILayout.Label(stage.thrustToWeight.ToString("F2") + " (" + stage.maxThrustToWeight.ToString("F2") + ")", this.infoStyle); | { |
GUILayout.Label(stage.thrustToWeight.ToString("F2") + " (" + stage.maxThrustToWeight.ToString("F2") + ")", 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"); | InputLockManager.SetControlLock(ControlTypes.All, "KER_BuildAdvanced"); |
BuildOverlayPartInfo.Hidden = true; | BuildOverlayPartInfo.Hidden = true; |
this.isEditorLocked = true; | isEditorLocked = true; |
} | } |
else | else |
{ | { |
EditorLogic.fetch.Unlock("KER_BuildAdvanced"); | InputLockManager.SetControlLock(ControlTypes.None, "KER_BuildAdvanced"); |
BuildOverlayPartInfo.Hidden = false; | BuildOverlayPartInfo.Hidden = false; |
this.isEditorLocked = false; | isEditorLocked = false; |
} | } |
} | } |
private void GetStageInfo() | private void GetStageInfo() |
{ | { |
this.stages = SimManager.Stages; | stages = SimManager.Stages; |
if (stages != null && stages.Length > 0) | |
{ | |
maxMach = stages[stages.Length - 1].maxMach; | |
} | |
} | } |
/// <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) | windowStyle = new GUIStyle(HighLogic.Skin.window) |
{ | { |
alignment = TextAnchor.UpperLeft | alignment = TextAnchor.UpperLeft |
}; | }; |
this.areaStyle = new GUIStyle(HighLogic.Skin.box) | 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) | 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) | 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) | 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) | 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) | settingStyle = new GUIStyle(titleStyle) |
{ | { |
alignment = TextAnchor.MiddleLeft, | alignment = TextAnchor.MiddleLeft, |
stretchWidth = true, | stretchWidth = true, |
stretchHeight = true | stretchHeight = true |
}; | }; |
this.settingAtmoStyle = new GUIStyle(this.titleStyle) | settingAtmoStyle = new GUIStyle(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) | 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) | bodiesButtonActiveStyle = new GUIStyle(bodiesButtonStyle) |
{ | { |
normal = this.bodiesButtonStyle.onNormal, | normal = bodiesButtonStyle.onNormal, |
hover = this.bodiesButtonStyle.onHover | hover = 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"); | SettingHandler handler = SettingHandler.Load("BuildAdvanced.xml"); |
handler.Get("visible", ref this.visible); | handler.Get("visible", ref visible); |
this.position.x = handler.Get("windowPositionX", this.position.x); | position.x = handler.Get("windowPositionX", position.x); |
this.position.y = handler.Get("windowPositionY", this.position.y); | position.y = handler.Get("windowPositionY", position.y); |
handler.Get("compactMode", ref this.compactMode); | handler.Get("compactMode", ref compactMode); |
handler.Get("compactCollapseRight", ref this.compactCollapseRight); | handler.Get("compactCollapseRight", ref compactCollapseRight); |
handler.Get("showAllStages", ref this.showAllStages); | handler.Get("showAllStages", ref showAllStages); |
handler.Get("showAtmosphericDetails", ref this.showAtmosphericDetails); | handler.Get("showAtmosphericDetails", ref showAtmosphericDetails); |
handler.Get("showSettings", ref this.showSettings); | handler.Get("showSettings", ref 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(); | InitialiseStyles(); |
this.hasChanged = true; | 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 |
{ | { |
compactModeRect = new Rect(position.width - 70.0f * GuiDisplaySize.Offset, 5.0f, 65.0f * GuiDisplaySize.Offset, 20.0f); | |
// 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(compactModeRect, compactMode, "COMPACT", buttonStyle) != compactMode) |
{ | { |
this.hasChanged = true; | hasChanged = true; |
this.compactCheck = 2; | compactCheck = 2; |
this.compactRight = this.position.xMax; | compactRight = position.xMax; |
this.compactMode = !this.compactMode; | compactMode = !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 (!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(position.width - 143.0f * GuiDisplaySize.Offset, 5.0f, 70.0f * GuiDisplaySize.Offset, 20.0f), showSettings, "SETTINGS", buttonStyle) != showSettings) |
{ | { |
this.hasChanged = true; | hasChanged = true; |
this.showSettings = !this.showSettings; | showSettings = !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(position.width - 226.0f * GuiDisplaySize.Offset, 5.0f, 80.0f * GuiDisplaySize.Offset, 20.0f), showAllStages, "ALL STAGES", buttonStyle) != showAllStages) |
{ | { |
this.hasChanged = true; | hasChanged = true; |
this.showAllStages = !this.showAllStages; | showAllStages = !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(position.width - 324.0f * GuiDisplaySize.Offset, 5.0f, 95.0f * GuiDisplaySize.Offset, 20.0f), showAtmosphericDetails, "ATMOSPHERIC", buttonStyle) != showAtmosphericDetails) |
{ | { |
this.hasChanged = true; | hasChanged = true; |
this.showAtmosphericDetails = !this.showAtmosphericDetails; | showAtmosphericDetails = !showAtmosphericDetails; |
} | } |
this.bodiesListPosition = new Rect(this.position.width - 452.0f * GuiDisplaySize.Offset, 5.0f, 125.0f * GuiDisplaySize.Offset, 20.0f); | bodiesListPosition = new Rect(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); | bodiesList.enabled = GUI.Toggle(bodiesListPosition, bodiesList.enabled, "BODY: " + CelestialBodies.SelectedBody.Name.ToUpper(), buttonStyle); |
this.bodiesList.SetPosition(this.bodiesListPosition.Translate(this.position)); | bodiesList.SetPosition(bodiesListPosition.Translate(position)); |
} | |
else | |
{ | |
if (GUI.Toggle(new Rect(position.width - 133.0f * GuiDisplaySize.Offset, 5.0f, 60.0f * GuiDisplaySize.Offset, 20.0f), showAtmosphericDetails, "ATMO", buttonStyle) != showAtmosphericDetails) | |
{ | |
hasChanged = true; | |
showAtmosphericDetails = !showAtmosphericDetails; | |
} | |
} | } |
// Draw the main informational display box. | // Draw the main informational display box. |
if (!this.compactMode) | if (!compactMode) |
{ | { |
GUILayout.BeginHorizontal(this.areaStyle); | GUILayout.BeginHorizontal(areaStyle); |
this.DrawStageNumbers(); | DrawStageNumbers(); |
this.DrawPartCount(); | DrawPartCount(); |
this.DrawCost(); | DrawCost(); |
this.DrawMass(); | DrawMass(); |
this.DrawIsp(); | DrawIsp(); |
this.DrawThrust(); | DrawThrust(); |
this.DrawTorque(); | DrawTorque(); |
this.DrawTwr(); | DrawTwr(); |
this.DrawDeltaV(); | DrawDeltaV(); |
this.DrawBurnTime(); | DrawBurnTime(); |
GUILayout.EndHorizontal(); | GUILayout.EndHorizontal(); |
if (this.showAtmosphericDetails) | if (showAtmosphericDetails && !compactMode) |
{ | { |
GUILayout.BeginVertical(this.areaSettingStyle); | GUILayout.BeginVertical(areaSettingStyle); |
this.DrawAtmosphericDetails(); | DrawAtmosphericDetails(); |
GUILayout.EndVertical(); | GUILayout.EndVertical(); |
} | } |
if (this.showSettings) | if (showSettings) |
{ | { |
GUILayout.BeginVertical(this.areaSettingStyle); | GUILayout.BeginVertical(areaSettingStyle); |
this.DrawSettings(); | 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(areaStyle); |
this.DrawStageNumbers(); | DrawStageNumbers(); |
this.DrawTwr(); | DrawTwr(); |
this.DrawDeltaV(); | DrawDeltaV(); |
GUILayout.EndHorizontal(); | GUILayout.EndHorizontal(); |
} | } |
GUI.DragWindow(); | GUI.DragWindow(); |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex, "BuildAdvanced.Window()"); |
} | } |
} | } |
#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 | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using KerbalEngineer.Extensions; | |
using KerbalEngineer.Helpers; | |
using UnityEngine; | |
#endregion | |
namespace KerbalEngineer.Editor | namespace KerbalEngineer.Editor |
{ | { |
using System; | |
using System.Collections.Generic; | |
using Extensions; | |
using Helpers; | |
using UnityEngine; | |
public class BuildOverlayPartInfo : MonoBehaviour | public class BuildOverlayPartInfo : MonoBehaviour |
{ | { |
#region Fields | |
private static bool clickToOpen = true; | private static bool clickToOpen = true; |
private static ModuleGenerator.GeneratorResource generatorResource; | |
private static ModuleAlternator moduleAlternator; | |
private static ModuleDataTransmitter moduleDataTransmitter; | |
private static ModuleDeployableSolarPanel moduleDeployableSolarPanel; | |
private static ModuleGenerator moduleGenerator; | |
private static ModuleGimbal moduleGimbal; | |
private static ModuleParachute moduleParachute; | |
private static ModuleRCS moduleRcs; | |
private static ModuleReactionWheel moduleReactionWheel; | |
private static ModuleResource moduleResource; | |
private static ModuleScienceExperiment moduleScienceExperiment; | |
private static bool namesOnly; | private static bool namesOnly; |
private static Part part; | |
private static PartInfoItem partInfoItem; | |
private static PartResource partResource; | |
private static Propellant propellant; | |
private static PartExtensions.ProtoModuleDecoupler protoModuleDecoupler; | |
private static PartExtensions.ProtoModuleEngine protoModuleEngine; | |
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 | |
#region Properties | |
public static bool ClickToOpen | public static bool ClickToOpen |
{ | { |
get { return clickToOpen; } | get |
set { clickToOpen = value; } | { |
return clickToOpen; | |
} | |
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 |
set { namesOnly = value; } | { |
return namesOnly; | |
} | |
set | |
{ | |
namesOnly = value; | |
} | |
} | } |
public static bool Visible | public static bool Visible |
{ | { |
get { return visible; } | get |
set { visible = value; } | { |
} | return visible; |
} | |
#endregion | set |
{ | |
#region Methods: protected | visible = value; |
} | |
} | |
protected void OnGUI() | protected void OnGUI() |
{ | { |
try | try |
{ | { |
if (!Visible || Hidden || this.selectedPart == null) | if (!Visible || Hidden || selectedPart == null) |
{ | { |
return; | return; |
} | } |
this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, String.Empty, BuildOverlay.WindowStyle); | position = GUILayout.Window(GetInstanceID(), position, 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); | position.x = Mathf.Clamp(Input.mousePosition.x + 16.0f, 0.0f, Screen.width - position.width); |
this.position.y = Mathf.Clamp(Screen.height - Input.mousePosition.y, 0.0f, Screen.height - this.position.height); | position.y = Mathf.Clamp(Screen.height - Input.mousePosition.y, 0.0f, Screen.height - position.height); |
if (this.position.x < Input.mousePosition.x + 20.0f) | if (position.x < Input.mousePosition.x + 20.0f) |
{ | { |
this.position.y = Mathf.Clamp(this.position.y + 20.0f, 0.0f, Screen.height - this.position.height); | position.y = Mathf.Clamp(position.y + 20.0f, 0.0f, Screen.height - position.height); |
} | } |
if (this.position.x < Input.mousePosition.x + 16.0f && this.position.y < Screen.height - Input.mousePosition.y) | if (position.x < Input.mousePosition.x + 16.0f && position.y < Screen.height - Input.mousePosition.y) |
{ | { |
this.position.x = Input.mousePosition.x - 3 - this.position.width; | position.x = Input.mousePosition.x - 3 - position.width; |
} | } |
this.infoItems.Clear(); | 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(selectedPart)) |
{ | { |
this.selectedPart = part; | selectedPart = part; |
this.ResetInfo(); | ResetInfo(); |
} | } |
if (NamesOnly || this.skipFrame) | if (NamesOnly || skipFrame) |
{ | { |
this.skipFrame = false; | skipFrame = false; |
return; | return; |
} | } |
this.SetCostInfo(); | if (!showInfo && Input.GetMouseButtonDown(2)) |
this.SetMassItems(); | { |
this.SetResourceItems(); | showInfo = true; |
this.SetEngineInfo(); | } |
this.SetAlternatorInfo(); | else if (ClickToOpen && showInfo && Input.GetMouseButtonDown(2)) |
this.SetGimbalInfo(); | { |
this.SetRcsInfo(); | ResetInfo(); |
this.SetParachuteInfo(); | } |
this.SetSasInfo(); | |
this.SetReactionWheelInfo(); | if (showInfo) |
this.SetSolarPanelInfo(); | { |
this.SetGeneratorInfo(); | PartInfoItem.Release(infoItems); |
this.SetDecouplerInfo(); | infoItems.Clear(); |
this.SetTransmitterInfo(); | SetCostInfo(); |
this.SetScienceExperimentInfo(); | SetMassItems(); |
this.SetScienceContainerInfo(); | SetResourceItems(); |
this.SetSingleActivationInfo(); | SetEngineInfo(); |
SetAlternatorInfo(); | |
if (!this.showInfo && Input.GetMouseButtonDown(2)) | SetGimbalInfo(); |
{ | SetRcsInfo(); |
this.showInfo = true; | SetParachuteInfo(); |
} | SetSasInfo(); |
else if (ClickToOpen && this.showInfo && Input.GetMouseButtonDown(2)) | SetReactionWheelInfo(); |
{ | SetSolarPanelInfo(); |
this.ResetInfo(); | SetGeneratorInfo(); |
SetDecouplerInfo(); | |
SetTransmitterInfo(); | |
SetScienceExperimentInfo(); | |
SetScienceContainerInfo(); | |
SetSingleActivationInfo(); | |
} | } |
} | } |
else | else |
{ | { |
this.selectedPart = null; | selectedPart = null; |
} | } |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex); |
} | } |
} | } |
#endregion | |
#region Methods: private | |
private void ResetInfo() | private void ResetInfo() |
{ | { |
this.showInfo = !clickToOpen; | showInfo = !clickToOpen; |
this.skipFrame = true; | skipFrame = true; |
this.position.width = namesOnly || clickToOpen ? 0.0f : 200.0f; | position.width = namesOnly || clickToOpen ? 0.0f : 200.0f; |
this.position.height = 0.0f; | position.height = 0.0f; |
} | } |
private void SetAlternatorInfo() | private void SetAlternatorInfo() |
{ | { |
if (!this.selectedPart.HasModule<ModuleAlternator>()) | moduleAlternator = selectedPart.GetModule<ModuleAlternator>(); |
{ | if (moduleAlternator != null) |
return; | { |
} | infoItems.Add(PartInfoItem.Create("Alternator")); |
for (int i = 0; i < moduleAlternator.outputResources.Count; ++i) | |
var alternator = this.selectedPart.GetModule<ModuleAlternator>(); | { |
this.infoItems.Add(new PartInfoItem("Alternator")); | moduleResource = moduleAlternator.outputResources[i]; |
foreach (var resource in alternator.outputResources) | infoItems.Add(PartInfoItem.Create("\t" + moduleResource.name, moduleResource.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.ConcatF(this.selectedPart.GetCostDry(), this.selectedPart.GetCostWet()))); | infoItems.Add(PartInfoItem.Create("Cost", Units.ConcatF(selectedPart.GetCostDry(), selectedPart.GetCostWet()))); |
} | } |
private void SetDecouplerInfo() | private void SetDecouplerInfo() |
{ | { |
if (!this.selectedPart.IsDecoupler()) | protoModuleDecoupler = selectedPart.GetProtoModuleDecoupler(); |
{ | if (protoModuleDecoupler != null) |
return; | { |
} | infoItems.Add(PartInfoItem.Create("Ejection Force", protoModuleDecoupler.EjectionForce.ToForce())); |
if (protoModuleDecoupler.IsOmniDecoupler) | |
var decoupler = this.selectedPart.GetProtoModuleDecoupler(); | { |
this.infoItems.Add(new PartInfoItem("Ejection Force", decoupler.EjectionForce.ToForce())); | infoItems.Add(PartInfoItem.Create("Omni-directional")); |
if (decoupler.IsOmniDecoupler) | } |
{ | |
this.infoItems.Add(new PartInfoItem("Omni-directional")); | |
} | } |
} | } |
private void SetEngineInfo() | private void SetEngineInfo() |
{ | { |
if (!this.selectedPart.IsEngine()) | protoModuleEngine = selectedPart.GetProtoModuleEngine(); |
{ | if (protoModuleEngine != null) |
return; | { |
} | infoItems.Add(PartInfoItem.Create("Thrust", Units.ToForce(protoModuleEngine.MinimumThrust, protoModuleEngine.MaximumThrust))); |
infoItems.Add(PartInfoItem.Create("Isp", Units.ConcatF(protoModuleEngine.GetSpecificImpulse(1.0f), protoModuleEngine.GetSpecificImpulse(0.0f)) + "s")); | |
var engine = this.selectedPart.GetProtoModuleEngine(); | if (protoModuleEngine.Propellants.Count > 0) |
this.infoItems.Add(new PartInfoItem("Thrust", Units.ToForce(engine.MinimumThrust, engine.MaximumThrust))); | { |
this.infoItems.Add(new PartInfoItem("Isp", Units.ConcatF(engine.GetSpecificImpulse(1.0f), engine.GetSpecificImpulse(0.0f)) + "s")); | infoItems.Add(PartInfoItem.Create("Propellants")); |
if (engine.Propellants.Count > 0) | |
{ | float totalRatio = 0.0f; |
this.infoItems.Add(new PartInfoItem("Propellants")); | for (int i = 0; i < protoModuleEngine.Propellants.Count; ++i) |
var totalRatio = engine.Propellants.Sum(p => p.ratio); | { |
foreach (var propellant in engine.Propellants) | totalRatio = totalRatio + protoModuleEngine.Propellants[i].ratio; |
{ | } |
this.infoItems.Add(new PartInfoItem("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent())); | |
for (int i = 0; i < protoModuleEngine.Propellants.Count; ++i) | |
{ | |
propellant = protoModuleEngine.Propellants[i]; | |
infoItems.Add(PartInfoItem.Create("\t" + propellant.name, (propellant.ratio / totalRatio).ToPercent())); | |
} | |
} | } |
} | } |
} | } |
private void SetGeneratorInfo() | private void SetGeneratorInfo() |
{ | { |
if (!this.selectedPart.HasModule<ModuleGenerator>()) | moduleGenerator = selectedPart.GetModule<ModuleGenerator>(); |
{ | if (moduleGenerator != null) |
return; | { |
} | if (moduleGenerator.inputList.Count > 0) |
{ | |
var generator = this.selectedPart.GetModule<ModuleGenerator>(); | infoItems.Add(PartInfoItem.Create("Generator Input")); |
if (generator.inputList.Count > 0) | for (int i = 0; i < moduleGenerator.inputList.Count; ++i) |
{ | { |
this.infoItems.Add(new PartInfoItem("Generator Input")); | generatorResource = moduleGenerator.inputList[i]; |
foreach (var resource in generator.inputList) | infoItems.Add(PartInfoItem.Create("\t" + generatorResource.name, generatorResource.rate.ToRate())); |
{ | } |
this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate())); | } |
} | if (moduleGenerator.outputList.Count > 0) |
} | { |
if (generator.outputList.Count > 0) | infoItems.Add(PartInfoItem.Create("Generator Output")); |
{ | for (int i = 0; i < moduleGenerator.outputList.Count; ++i) |
this.infoItems.Add(new PartInfoItem("Generator Output")); | { |
foreach (var resource in generator.outputList) | generatorResource = moduleGenerator.outputList[i]; |
{ | infoItems.Add(PartInfoItem.Create("\t" + generatorResource.name, generatorResource.rate.ToRate())); |
this.infoItems.Add(new PartInfoItem("\t" + resource.name, resource.rate.ToRate())); | } |
} | } |
} | if (moduleGenerator.isAlwaysActive) |
if (generator.isAlwaysActive) | { |
{ | infoItems.Add(PartInfoItem.Create("Generator is Always Active")); |
this.infoItems.Add(new PartInfoItem("Generator is Always Active")); | } |
} | } |
} | } |
private void SetGimbalInfo() | private void SetGimbalInfo() |
{ | { |
if (!this.selectedPart.HasModule<ModuleGimbal>()) | moduleGimbal = selectedPart.GetModule<ModuleGimbal>(); |
{ | if (moduleGimbal != null) |
return; | { |
} | infoItems.Add(PartInfoItem.Create("Thrust Vectoring", moduleGimbal.gimbalRange.ToString("F2"))); |
} | |
var gimbal = this.selectedPart.GetModule<ModuleGimbal>(); | |
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 (selectedPart.physicalSignificance == Part.PhysicalSignificance.FULL) |
{ | { |
this.infoItems.Add(new PartInfoItem("Mass", Units.ToMass(this.selectedPart.GetDryMass(), this.selectedPart.GetWetMass()))); | infoItems.Add(PartInfoItem.Create("Mass", Units.ToMass(selectedPart.GetDryMass(), selectedPart.GetWetMass()))); |
} | } |
} | } |
private void SetParachuteInfo() | private void SetParachuteInfo() |
{ | { |
if (!this.selectedPart.HasModule<ModuleParachute>()) | moduleParachute = selectedPart.GetModule<ModuleParachute>(); |
{ | if (moduleParachute != null) |
return; | { |
} | infoItems.Add(PartInfoItem.Create("Deployed Drag", Units.ConcatF(moduleParachute.semiDeployedDrag, moduleParachute.fullyDeployedDrag))); |
infoItems.Add(PartInfoItem.Create("Deployment Altitude", moduleParachute.deployAltitude.ToDistance())); | |
var parachute = this.selectedPart.GetModule<ModuleParachute>(); | infoItems.Add(PartInfoItem.Create("Deployment Pressure", moduleParachute.minAirPressureToOpen.ToString("F2"))); |
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 Pressure", parachute.minAirPressureToOpen.ToString("F2"))); | |
} | } |
private void SetRcsInfo() | private void SetRcsInfo() |
{ | { |
if (!this.selectedPart.HasModule<ModuleRCS>()) | moduleRcs = selectedPart.GetModule<ModuleRCS>(); |
{ | if (moduleRcs != null) |
return; | { |
} | infoItems.Add(PartInfoItem.Create("Thruster Power", moduleRcs.thrusterPower.ToForce())); |
infoItems.Add(PartInfoItem.Create("Specific Impulse", Units.ConcatF(moduleRcs.atmosphereCurve.Evaluate(1.0f), moduleRcs.atmosphereCurve.Evaluate(0.0f)) + "s")); | |
var rcs = this.selectedPart.GetModule<ModuleRCS>(); | } |
this.infoItems.Add(new PartInfoItem("Thruster Power", rcs.thrusterPower.ToForce())); | |
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>()) | moduleReactionWheel = selectedPart.GetModule<ModuleReactionWheel>(); |
{ | if (moduleReactionWheel != null) |
return; | { |
} | infoItems.Add(PartInfoItem.Create("Reaction Wheel Torque")); |
infoItems.Add(PartInfoItem.Create("\tPitch", moduleReactionWheel.PitchTorque.ToTorque())); | |
var reactionWheel = this.selectedPart.GetModule<ModuleReactionWheel>(); | infoItems.Add(PartInfoItem.Create("\tRoll", moduleReactionWheel.RollTorque.ToTorque())); |
this.infoItems.Add(new PartInfoItem("Reaction Wheel Torque")); | infoItems.Add(PartInfoItem.Create("\tYaw", moduleReactionWheel.YawTorque.ToTorque())); |
this.infoItems.Add(new PartInfoItem("\tPitch", reactionWheel.PitchTorque.ToTorque())); | for (int i = 0; i < moduleReactionWheel.inputResources.Count; ++i) |
this.infoItems.Add(new PartInfoItem("\tRoll", reactionWheel.RollTorque.ToTorque())); | { |
this.infoItems.Add(new PartInfoItem("\tYaw", reactionWheel.YawTorque.ToTorque())); | moduleResource = moduleReactionWheel.inputResources[i]; |
foreach (var resource in reactionWheel.inputResources) | infoItems.Add(PartInfoItem.Create("\t" + moduleResource.name, moduleResource.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)) | bool visibleResources = false; |
{ | for (int i = 0; i < selectedPart.Resources.list.Count; ++i) |
this.infoItems.Add(new PartInfoItem("Resources")); | { |
foreach (var resource in this.selectedPart.Resources.list.Where(r => !r.hideFlow)) | if (selectedPart.Resources.list[i].hideFlow == false) |
{ | { |
this.infoItems.Add(resource.GetDensity() > 0 | visibleResources = true; |
? new PartInfoItem("\t" + resource.info.name, "(" + resource.GetMass().ToMass() + ") " + resource.amount.ToString("F1")) | break; |
: new PartInfoItem("\t" + resource.info.name, resource.amount.ToString("F1"))); | } |
} | |
if (visibleResources) | |
{ | |
infoItems.Add(PartInfoItem.Create("Resources")); | |
for (int i = 0; i < selectedPart.Resources.list.Count; ++i) | |
{ | |
partResource = selectedPart.Resources.list[i]; | |
if (partResource.hideFlow == false) | |
{ | |
infoItems.Add(partResource.GetDensity() > 0 | |
? PartInfoItem.Create("\t" + partResource.info.name, "(" + partResource.GetMass().ToMass() + ") " + partResource.amount.ToString("F1")) | |
: PartInfoItem.Create("\t" + partResource.info.name, partResource.amount.ToString("F1"))); | |
} | |
} | } |
} | } |
} | } |
private void SetSasInfo() | private void SetSasInfo() |
{ | { |
if (this.selectedPart.HasModule<ModuleSAS>()) | if (selectedPart.HasModule<ModuleSAS>()) |
{ | { |
this.infoItems.Add(new PartInfoItem("SAS Equiped")); | infoItems.Add(PartInfoItem.Create("SAS Equiped")); |
} | } |
} | } |
private void SetScienceContainerInfo() | private void SetScienceContainerInfo() |
{ | { |
if (this.selectedPart.HasModule<ModuleScienceContainer>()) | if (selectedPart.HasModule<ModuleScienceContainer>()) |
{ | { |
this.infoItems.Add(new PartInfoItem("Science Container")); | infoItems.Add(PartInfoItem.Create("Science Container")); |
} | } |
} | } |
private void SetScienceExperimentInfo() | private void SetScienceExperimentInfo() |
{ | { |
if (!this.selectedPart.HasModule<ModuleScienceExperiment>()) | moduleScienceExperiment = selectedPart.GetModule<ModuleScienceExperiment>(); |
{ | if (moduleScienceExperiment != null) |
return; | { |
} | infoItems.Add(PartInfoItem.Create("Science Experiment", moduleScienceExperiment.experimentActionName)); |
infoItems.Add(PartInfoItem.Create("\tTransmit Efficiency", moduleScienceExperiment.xmitDataScalar.ToPercent())); | |
var experiment = this.selectedPart.GetModule<ModuleScienceExperiment>(); | if (moduleScienceExperiment.rerunnable == false) |
this.infoItems.Add(new PartInfoItem("Science Experiment", experiment.experimentActionName)); | { |
this.infoItems.Add(new PartInfoItem("\tTransmit Efficiency", experiment.xmitDataScalar.ToPercent())); | infoItems.Add(PartInfoItem.Create("\tSingle Usage")); |
if (!experiment.rerunnable) | } |
{ | |
this.infoItems.Add(new PartInfoItem("\tSingle Usage")); | |
} | } |
} | } |
private void SetSingleActivationInfo() | private void SetSingleActivationInfo() |
{ | { |
if (this.selectedPart.HasModule<ModuleAnimateGeneric>(m => m.isOneShot)) | if (selectedPart.HasModule<ModuleAnimateGeneric>(m => m.isOneShot)) |
{ | { |
this.infoItems.Add(new PartInfoItem("Single Activation")); | infoItems.Add(PartInfoItem.Create("Single Activation")); |
} | } |
} | } |
private void SetSolarPanelInfo() | private void SetSolarPanelInfo() |
{ | { |
if (!this.selectedPart.HasModule<ModuleDeployableSolarPanel>()) | moduleDeployableSolarPanel = selectedPart.GetModule<ModuleDeployableSolarPanel>(); |
{ | if (moduleDeployableSolarPanel != null) |
return; | { |
} | infoItems.Add(PartInfoItem.Create("Charge Rate", moduleDeployableSolarPanel.chargeRate.ToRate())); |
if (moduleDeployableSolarPanel.isBreakable) | |
var solarPanel = this.selectedPart.GetModule<ModuleDeployableSolarPanel>(); | { |
this.infoItems.Add(new PartInfoItem("Charge Rate", solarPanel.chargeRate.ToRate())); | infoItems.Add(PartInfoItem.Create("Breakable")); |
if (solarPanel.isBreakable) | } |
{ | if (moduleDeployableSolarPanel.sunTracking) |
this.infoItems.Add(new PartInfoItem("Breakable")); | { |
} | infoItems.Add(PartInfoItem.Create("Sun Tracking")); |
if (solarPanel.sunTracking) | } |
{ | |
this.infoItems.Add(new PartInfoItem("Sun Tracking")); | |
} | } |
} | } |
private void SetTransmitterInfo() | private void SetTransmitterInfo() |
{ | { |
if (!this.selectedPart.HasModule<ModuleDataTransmitter>()) | moduleDataTransmitter = selectedPart.GetModule<ModuleDataTransmitter>(); |
{ | if (moduleDataTransmitter != null) |
return; | { |
} | infoItems.Add(PartInfoItem.Create("Packet Size", moduleDataTransmitter.packetSize.ToString("F2") + " Mits")); |
infoItems.Add(PartInfoItem.Create("Bandwidth", (moduleDataTransmitter.packetInterval * moduleDataTransmitter.packetSize).ToString("F2") + "Mits/sec")); | |
var transmitter = this.selectedPart.GetModule<ModuleDataTransmitter>(); | infoItems.Add(PartInfoItem.Create(moduleDataTransmitter.requiredResource, moduleDataTransmitter.packetResourceCost.ToString("F2") + "/Packet")); |
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(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(selectedPart.partInfo.title, BuildOverlay.TitleStyle); |
if (this.showInfo) | if (showInfo) |
{ | { |
foreach (var item in this.infoItems) | for (int i = 0; i < infoItems.Count; ++i) |
{ | { |
partInfoItem = infoItems[i]; | |
GUILayout.Space(2.0f); | GUILayout.Space(2.0f); |
GUILayout.BeginHorizontal(); | GUILayout.BeginHorizontal(); |
if (item.Value != null) | if (partInfoItem.Value != null) |
{ | { |
GUILayout.Label(item.Name + ":", BuildOverlay.NameStyle); | GUILayout.Label(partInfoItem.Name + ":", BuildOverlay.NameStyle); |
GUILayout.Space(25.0f); | GUILayout.Space(25.0f); |
GUILayout.Label(item.Value, BuildOverlay.ValueStyle); | GUILayout.Label(partInfoItem.Value, BuildOverlay.ValueStyle); |
} | } |
else | else |
{ | { |
GUILayout.Label(item.Name, BuildOverlay.NameStyle); | GUILayout.Label(partInfoItem.Name, BuildOverlay.NameStyle); |
} | } |
GUILayout.EndHorizontal(); | GUILayout.EndHorizontal(); |
} | } |
} | } |
else if (this.infoItems.Count > 0) | else if (clickToOpen && namesOnly == false) |
{ | { |
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 | |
} | } |
} | } |
// | // |
// 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 System.Linq; | |
using KerbalEngineer.Extensions; | |
using UnityEngine; | |
#endregion | #endregion |
namespace KerbalEngineer.Editor | namespace KerbalEngineer.Editor |
{ | { |
using System; | |
using System.Collections.Generic; | |
using Extensions; | |
using UnityEngine; | |
public class BuildOverlayResources : MonoBehaviour | public class BuildOverlayResources : MonoBehaviour |
{ | { |
#region Fields | #region Fields |
private static bool visible = true; | private static bool visible = true; |
private readonly Dictionary<int, ResourceInfoItem> resources = new Dictionary<int, ResourceInfoItem>(); | private readonly Dictionary<int, ResourceInfoItem> resources = new Dictionary<int, ResourceInfoItem>(); |
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(0.0f, 0.0f, BuildOverlay.MinimumWidth, 0.0f); | private Rect windowPosition = new Rect(0.0f, 0.0f, BuildOverlay.MinimumWidth, 0.0f); |
#endregion | #endregion |
#region Properties | #region Properties |
public static bool Visible | public static bool Visible |
{ | { |
get { return visible; } | get |
set { visible = value; } | { |
return visible; | |
} | |
set | |
{ | |
visible = value; | |
} | |
} | } |
public bool Open | public bool Open |
{ | { |
get { return this.open; } | get |
set { this.open = value; } | { |
} | return open; |
} | |
set | |
{ | |
open = value; | |
} | |
} | |
#endregion | #endregion |
#region Methods: protected | #region Methods: protected |
protected void OnGUI() | protected void OnGUI() |
{ | { |
try | try |
{ | { |
if (!Visible || this.resources.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts) | if (!Visible || resources.Count == 0 || EditorLogic.fetch.editorScreen != EditorScreen.Parts) |
{ | { |
return; | return; |
} | } |
this.open = GUI.Toggle(this.tabPosition, this.open, this.tabContent, BuildOverlay.TabStyle); | open = GUI.Toggle(tabPosition, open, tabContent, BuildOverlay.TabStyle); |
if (this.openPercent > 0.0) | if (openPercent > 0.0) |
{ | { |
this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.Window, String.Empty, BuildOverlay.WindowStyle); | windowPosition = GUILayout.Window(GetInstanceID(), windowPosition, Window, 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("RESOURCES"); | tabContent = new GUIContent("RESOURCES"); |
this.tabSize = BuildOverlay.TabStyle.CalcSize(this.tabContent); | tabSize = BuildOverlay.TabStyle.CalcSize(tabContent); |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex); |
} | } |
} | } |
protected void Update() | protected void Update() |
{ | { |
try | try |
{ | { |
if (!Visible) | if (!Visible) |
{ | { |
return; | return; |
} | } |
this.SetResources(); | SetResources(); |
this.SetSlidePosition(); | SetSlidePosition(); |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex); |
} | } |
} | } |
#endregion | #endregion |
#region Methods: private | #region Methods: private |
private static Part part; | |
private static PartResource partResource; | |
private void SetResources() | private void SetResources() |
{ | { |
var previousCount = this.resources.Count; | int previousCount = resources.Count; |
this.resources.Clear(); | resources.Clear(); |
foreach (var resource in EditorLogic.fetch.ship.parts.SelectMany(p => p.Resources.list).Where(r => r.amount > 0.0)) | |
{ | for (int i = 0; i < EditorLogic.fetch.ship.parts.Count; ++i) |
if (this.resources.ContainsKey(resource.info.id)) | { |
{ | part = EditorLogic.fetch.ship.parts[i]; |
this.resources[resource.info.id].Amount += resource.amount; | for (int j = 0; j < part.Resources.list.Count; ++j) |
} | { |
else | partResource = part.Resources.list[j]; |
{ | |
this.resources.Add(resource.info.id, new ResourceInfoItem(resource)); | if (resources.ContainsKey(partResource.info.id)) |
} | { |
} | resources[partResource.info.id].Amount += partResource.amount; |
} | |
if (this.resources.Count < previousCount) | else |
{ | { |
this.windowPosition.height = 0; | resources.Add(partResource.info.id, new ResourceInfoItem(partResource)); |
} | |
} | |
} | |
if (resources.Count < previousCount) | |
{ | |
windowPosition.height = 0; | |
} | } |
} | } |
private void SetSlidePosition() | private void SetSlidePosition() |
{ | { |
if (this.open && this.openPercent < 1.0f) | if (open && openPercent < 1.0f) |
{ | { |
this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f); | openPercent = Mathf.Clamp(openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f); |
} | } |
else if (!this.open && this.openPercent > 0.0f) | else if (!open && openPercent > 0.0f) |
{ | { |
this.openPercent = Mathf.Clamp(this.openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f); | openPercent = Mathf.Clamp(openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f); |
} | } |
this.windowPosition.x = BuildOverlay.BuildOverlayVessel.WindowPosition.xMax + 5.0f; | windowPosition.x = BuildOverlay.BuildOverlayVessel.WindowPosition.xMax + 5.0f; |
this.windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - this.windowPosition.height, this.openPercent); | windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - windowPosition.height, openPercent); |
this.tabPosition.width = this.tabSize.x; | tabPosition.width = tabSize.x; |
this.tabPosition.height = this.tabSize.y; | tabPosition.height = tabSize.y; |
this.tabPosition.x = this.windowPosition.x; | tabPosition.x = windowPosition.x; |
this.tabPosition.y = this.windowPosition.y - this.tabPosition.height; | tabPosition.y = windowPosition.y - tabPosition.height; |
} | } |
private void Window(int windowId) | private void Window(int windowId) |
{ | { |
try | try |
{ | { |
var firstItem = true; | bool firstItem = true; |
foreach (var resource in this.resources) | foreach (KeyValuePair<int, ResourceInfoItem> resource in resources) |
{ | { |
if (!firstItem) | if (!firstItem) |
{ | { |
GUILayout.Space(2.0f); | GUILayout.Space(2.0f); |
} | } |
firstItem = false; | firstItem = false; |
GUILayout.BeginHorizontal(); | GUILayout.BeginHorizontal(); |
GUILayout.Label(resource.Value.Name + ":", BuildOverlay.NameStyle); | GUILayout.Label(resource.Value.Name + ":", BuildOverlay.NameStyle); |
GUILayout.Space(50.0f); | GUILayout.Space(50.0f); |
if (resource.Value.Mass > 0.0) | if (resource.Value.Mass > 0.0) |
{ | { |
GUILayout.Label("(" + resource.Value.Mass.ToMass() + ") " + resource.Value.Amount.ToString("N1"), BuildOverlay.ValueStyle); | GUILayout.Label("(" + resource.Value.Mass.ToMass() + ") " + resource.Value.Amount.ToString("N1"), BuildOverlay.ValueStyle); |
} | } |
else | else |
{ | { |
GUILayout.Label(resource.Value.Amount.ToString("N1"), BuildOverlay.ValueStyle); | GUILayout.Label(resource.Value.Amount.ToString("N1"), BuildOverlay.ValueStyle); |
} | } |
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 |
#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 |
set { visible = value; } | { |
return visible; | |
} | |
set | |
{ | |
visible = value; | |
} | |
} | } |
public bool Open | public bool Open |
{ | { |
get { return this.open; } | get |
set { this.open = value; } | { |
return open; | |
} | |
set | |
{ | |
open = value; | |
} | |
} | } |
public Rect WindowPosition | public Rect WindowPosition |
{ | { |
get { return this.windowPosition; } | get |
{ | |
return windowPosition; | |
} | |
} | } |
public float WindowX | public float WindowX |
{ | { |
get { return this.windowPosition.x; } | get |
set { this.windowPosition.x = value; } | { |
} | return windowPosition.x; |
} | |
set | |
{ | |
windowPosition.x = value; | |
} | |
} | |
#endregion | #endregion |
#region Methods | #region Methods |
protected void Awake() | protected void Awake() |
{ | { |
try | try |
{ | { |
SimManager.OnReady -= this.GetStageInfo; | SimManager.OnReady -= GetStageInfo; |
SimManager.OnReady += this.GetStageInfo; | SimManager.OnReady += 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); | open = GUI.Toggle(tabPosition, open, tabContent, BuildOverlay.TabStyle); |
if (this.openPercent > 0.0) | if (openPercent > 0.0) |
{ | { |
this.windowPosition = GUILayout.Window(this.GetInstanceID(), this.windowPosition, this.VesselWindow, String.Empty, BuildOverlay.WindowStyle); | windowPosition = GUILayout.Window(GetInstanceID(), windowPosition, 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"); | tabContent = new GUIContent("VESSEL"); |
this.tabSize = BuildOverlay.TabStyle.CalcSize(this.tabContent); | tabSize = BuildOverlay.TabStyle.CalcSize(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 (openPercent > 0.0) |
{ | { |
this.SetVesselInfo(); | SetVesselInfo(); |
} | } |
this.SetSlidePosition(); | SetSlidePosition(); |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex); | Logger.Exception(ex); |
} | } |
} | } |
private void GetStageInfo() | private void GetStageInfo() |
{ | { |
this.lastStage = SimManager.LastStage; | lastStage = SimManager.LastStage; |
} | } |
private void SetSlidePosition() | private void SetSlidePosition() |
{ | { |
if (this.open && this.openPercent < 1.0f) | if (open && openPercent < 1.0f) |
{ | { |
this.openPercent = Mathf.Clamp(this.openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f); | openPercent = Mathf.Clamp(openPercent + Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f); |
} | } |
else if (!this.open && this.openPercent > 0.0f) | else if (!open && openPercent > 0.0f) |
{ | { |
this.openPercent = Mathf.Clamp(this.openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f); | openPercent = Mathf.Clamp(openPercent - Time.deltaTime * BuildOverlay.TabSpeed, 0.0f, 1.0f); |
} | } |
this.windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - this.windowPosition.height, this.openPercent); | windowPosition.y = Mathf.Lerp(Screen.height, Screen.height - windowPosition.height, openPercent); |
if (this.windowPosition.width < Width) | if (windowPosition.width < Width) |
{ | { |
this.windowPosition.width = Width; | windowPosition.width = Width; |
} | } |
this.tabPosition.width = this.tabSize.x; | tabPosition.width = tabSize.x; |
this.tabPosition.height = this.tabSize.y; | tabPosition.height = tabSize.y; |
this.tabPosition.x = this.windowPosition.x; | tabPosition.x = windowPosition.x; |
this.tabPosition.y = this.windowPosition.y - this.tabPosition.height; | tabPosition.y = windowPosition.y - 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.GetAtmospheres(BuildAdvanced.Altitude); |
} | } |
else | else |
{ | { |
SimManager.Atmosphere = 0.0; | SimManager.Atmosphere = 0.0; |
} | } |
SimManager.RequestSimulation(); | SimManager.RequestSimulation(); |
SimManager.TryStartSimulation(); | SimManager.TryStartSimulation(); |
if (this.lastStage != null) | if (lastStage != null) |
{ | { |
this.infoItems.Clear(); | PartInfoItem.Release(infoItems); |
this.infoItems.Add(new PartInfoItem("Delta-V", this.lastStage.deltaV.ToString("N0") + " / " + this.lastStage.totalDeltaV.ToString("N0") + "m/s")); | infoItems.Clear(); |
this.infoItems.Add(new PartInfoItem("Mass", Units.ToMass(this.lastStage.mass, this.lastStage.totalMass))); | infoItems.Add(PartInfoItem.Create("Delta-V", lastStage.deltaV.ToString("N0") + " / " + lastStage.totalDeltaV.ToString("N0") + "m/s")); |
this.infoItems.Add(new PartInfoItem("TWR", this.lastStage.thrustToWeight.ToString("F2") + " (" + this.lastStage.maxThrustToWeight.ToString("F2") + ")")); | infoItems.Add(PartInfoItem.Create("Mass", Units.ToMass(lastStage.mass, lastStage.totalMass))); |
this.infoItems.Add(new PartInfoItem("Parts", this.lastStage.partCount + " / " + this.lastStage.totalPartCount)); | infoItems.Add(PartInfoItem.Create("TWR", lastStage.thrustToWeight.ToString("F2") + " (" + lastStage.maxThrustToWeight.ToString("F2") + ")")); |
infoItems.Add(PartInfoItem.Create("Parts", lastStage.partCount + " / " + lastStage.totalPartCount)); | |
} | } |
} | } |
private void VesselWindow(int windowId) | private void VesselWindow(int windowId) |
{ | { |
try | try |
{ | { |
var firstItem = true; | bool firstItem = true; |
foreach (var item in this.infoItems) | foreach (PartInfoItem item in 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; | using System; |
using UnityEngine; | using UnityEngine; |
#endregion | #endregion |
namespace KerbalEngineer.Editor | namespace KerbalEngineer.Editor |
{ | { |
[KSPAddon(KSPAddon.Startup.EditorAny, false)] | [KSPAddon(KSPAddon.Startup.EditorAny, false)] |
public class BuildToolbar : MonoBehaviour | public class BuildToolbar : MonoBehaviour |
{ | { |
#region Fields | #region Fields |
private ApplicationLauncherButton button; | private ApplicationLauncherButton button; |
#endregion | #endregion |
#region Methods: private | #region Methods: private |
private void Awake() | private void Awake() |
{ | { |
GameEvents.onGUIApplicationLauncherReady.Add(this.OnGuiAppLauncherReady); | GameEvents.onGUIApplicationLauncherReady.Add(this.OnGuiAppLauncherReady); |
Logger.Log("BuildToolbar->Awake"); | Logger.Log("BuildToolbar->Awake"); |
} | |
private void Start() | |
{ | |
if (button == null) | |
{ | |
OnGuiAppLauncherReady(); | |
} | |
} | } |
private void OnDestroy() | private void OnDestroy() |
{ | { |
GameEvents.onGUIApplicationLauncherReady.Remove(this.OnGuiAppLauncherReady); | GameEvents.onGUIApplicationLauncherReady.Remove(this.OnGuiAppLauncherReady); |
if (this.button != null) | if (this.button != null) |
{ | { |
ApplicationLauncher.Instance.RemoveModApplication(this.button); | ApplicationLauncher.Instance.RemoveModApplication(this.button); |
} | } |
Logger.Log("BuildToolbar->OnDestroy"); | Logger.Log("BuildToolbar->OnDestroy"); |
} | } |
private void OnGuiAppLauncherReady() | private void OnGuiAppLauncherReady() |
{ | { |
try | try |
{ | { |
this.button = ApplicationLauncher.Instance.AddModApplication( | this.button = ApplicationLauncher.Instance.AddModApplication( |
() => BuildAdvanced.Instance.Visible = true, | () => BuildAdvanced.Instance.Visible = true, |
() => BuildAdvanced.Instance.Visible = false, | () => BuildAdvanced.Instance.Visible = false, |
null, | null, |
null, | null, |
null, | null, |
null, | null, |
ApplicationLauncher.AppScenes.ALWAYS, | ApplicationLauncher.AppScenes.ALWAYS, |
GameDatabase.Instance.GetTexture("KerbalEngineer/Textures/ToolbarIcon", false) | GameDatabase.Instance.GetTexture("KerbalEngineer/Textures/ToolbarIcon", false) |
); | ); |
Logger.Log("BuildToolbar->OnGuiAppLauncherReady"); | Logger.Log("BuildToolbar->OnGuiAppLauncherReady"); |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex, "BuildToolbar->OnGuiAppLauncherReady"); | Logger.Exception(ex, "BuildToolbar->OnGuiAppLauncherReady"); |
} | } |
} | } |
private void Update() | private void Update() |
{ | { |
try | try |
{ | { |
if (this.button == null) | if (this.button == null) |
{ | { |
return; | return; |
} | } |
if (EditorLogic.fetch != null && EditorLogic.fetch.ship.parts.Count > 0) | if (EditorLogic.fetch != null && EditorLogic.fetch.ship.parts.Count > 0) |
{ | { |
if (BuildAdvanced.Instance.Visible && this.button.State != RUIToggleButton.ButtonState.TRUE) | if (BuildAdvanced.Instance.Visible && this.button.State != RUIToggleButton.ButtonState.TRUE) |
{ | { |
this.button.SetTrue(); | this.button.SetTrue(); |
} | } |
else if (!BuildAdvanced.Instance.Visible && this.button.State != RUIToggleButton.ButtonState.FALSE) | else if (!BuildAdvanced.Instance.Visible && this.button.State != RUIToggleButton.ButtonState.FALSE) |
{ | { |
this.button.SetFalse(); | this.button.SetFalse(); |
} | } |
} | } |
else if (this.button.State != RUIToggleButton.ButtonState.DISABLED) | else if (this.button.State != RUIToggleButton.ButtonState.DISABLED) |
{ | { |
this.button.Disable(); | this.button.Disable(); |
} | } |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex, "BuildToolbar->Update"); | Logger.Exception(ex, "BuildToolbar->Update"); |
} | } |
} | } |
#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.Editor | namespace KerbalEngineer.Editor |
{ | { |
using System.Collections.Generic; | |
using VesselSimulator; | |
public class PartInfoItem | public class PartInfoItem |
{ | { |
#region Constructors | private static readonly Pool<PartInfoItem> pool = new Pool<PartInfoItem>(Create, Reset); |
public PartInfoItem(string name) | |
{ | |
this.Name = name; | |
} | |
public PartInfoItem(string name, string value) | |
{ | |
this.Name = name; | |
this.Value = value; | |
} | |
#endregion | |
#region Properties | |
public string Name { get; set; } | public string Name { get; set; } |
public string Value { get; set; } | public string Value { get; set; } |
#endregion | private static PartInfoItem Create() |
{ | |
return new PartInfoItem(); | |
} | |
public void Release() | |
{ | |
pool.Release(this); | |
} | |
public static void Release(List<PartInfoItem> objList) | |
{ | |
for (int i = 0; i < objList.Count; ++i) | |
{ | |
objList[i].Release(); | |
} | |
} | |
private static void Reset(PartInfoItem obj) | |
{ | |
obj.Name = string.Empty; | |
obj.Value = string.Empty; | |
} | |
public static PartInfoItem Create(string name) | |
{ | |
return New(name); | |
} | |
public static PartInfoItem Create(string name, string value) | |
{ | |
return New(name, value); | |
} | |
public static PartInfoItem New(string name) | |
{ | |
PartInfoItem obj = pool.Borrow(); | |
obj.Name = name; | |
obj.Value = string.Empty; | |
return obj; | |
} | |
public static PartInfoItem New(string name, string value) | |
{ | |
PartInfoItem obj = pool.Borrow(); | |
obj.Name = name; | |
obj.Value = value; | |
return obj; | |
} | |
} | } |
} | } |
// | // |
// 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.15.1"; | public const string AssemblyVersion = "1.0.16.6"; |
#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 | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
#endregion | |
namespace KerbalEngineer.Extensions | namespace KerbalEngineer.Extensions |
{ | { |
using System; | |
using System.Collections.Generic; | |
using CompoundParts; | using CompoundParts; |
public static class PartExtensions | public static class PartExtensions |
{ | { |
#region Methods: public | //private static Part cachePart; |
//private static PartModule cachePartModule; | |
//private static PartResource cachePartResource; | |
/// <summary> | /// <summary> |
/// Gets whether the part contains a specific resource. | /// Gets whether the part contains a specific resource. |
/// </summary> | /// </summary> |
public static bool ContainsResource(this Part part, int resourceId) | public static bool ContainsResource(this Part part, int resourceId) |
{ | { |
return part.Resources.Contains(resourceId); | return part.Resources.Contains(resourceId); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part contains resources. | /// Gets whether the part contains resources. |
/// </summary> | /// </summary> |
public static bool ContainsResources(this Part part) | public static bool ContainsResources(this Part part) |
{ | { |
return part.Resources.list.Count(p => p.amount > 0d) > 0; | for (int i = 0; i < part.Resources.list.Count; ++i) |
{ | |
if (part.Resources.list[i].amount > 0.0) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part has fuel. | /// Gets whether the part has fuel. |
/// </summary> | /// </summary> |
public static bool EngineHasFuel(this Part part) | public static bool EngineHasFuel(this Part part) |
{ | { |
if (part.HasModule<ModuleEngines>()) | PartModule cachePartModule = GetModule<ModuleEngines>(part); |
{ | if (cachePartModule != null) |
return part.GetModuleEngines().getFlameoutState; | { |
} | return (cachePartModule as ModuleEngines).getFlameoutState; |
if (part.HasModule<MultiModeEngine>()) | } |
{ | |
return part.GetModuleMultiModeEngine().getFlameoutState; | cachePartModule = GetModuleMultiModeEngine(part); |
if (cachePartModule != null) | |
{ | |
return (cachePartModule as ModuleEnginesFX).getFlameoutState; | |
} | } |
return false; | return false; |
} | } |
/// <summary> | /// <summary> |
/// Gets the cost of the part excluding resources. | /// Gets the cost of the part excluding resources. |
/// </summary> | /// </summary> |
public static double GetCostDry(this Part part) | public static double GetCostDry(this Part part) |
{ | { |
return part.partInfo.cost - GetResourceCostMax(part) + part.GetModuleCosts(0.0f); | return part.partInfo.cost - GetResourceCostMax(part) + part.GetModuleCosts(0.0f); |
} | } |
/// <summary> | /// <summary> |
/// Gets the cost of the part including maximum resources. | /// Gets the cost of the part including maximum resources. |
/// </summary> | /// </summary> |
public static double GetCostMax(this Part part) | public static double GetCostMax(this Part part) |
{ | { |
return part.partInfo.cost + part.GetModuleCosts(0.0f); | return part.partInfo.cost + part.GetModuleCosts(0.0f); |
} | } |
/// <summary> | /// <summary> |
/// Gets the cost of the part modules | |
/// Same as stock but without mem allocation | |
/// </summary> | |
public static double GetModuleCostsNoAlloc(this Part part, float defaultCost) | |
{ | |
float cost = 0f; | |
for (int i = 0; i < part.Modules.Count; i++) | |
{ | |
PartModule pm = part.Modules[i]; | |
if (pm is IPartCostModifier) | |
cost += (pm as IPartCostModifier).GetModuleCost(defaultCost); | |
} | |
return cost; | |
} | |
/// <summary> | |
/// Gets the cost of the part including resources. | /// Gets the cost of the part including resources. |
/// </summary> | /// </summary> |
public static double GetCostWet(this Part part) | public static double GetCostWet(this Part part) |
{ | { |
return part.partInfo.cost - GetResourceCostInverted(part) + part.GetModuleCosts(0.0f); | return part.partInfo.cost - GetResourceCostInverted(part) + part.GetModuleCostsNoAlloc(0.0f); // part.GetModuleCosts allocate 44B per call. |
} | } |
/// <summary> | /// <summary> |
/// Gets the dry mass of the part. | /// Gets the dry mass of the part. |
/// </summary> | /// </summary> |
public static double GetDryMass(this Part part) | public static double GetDryMass(this Part part) |
{ | { |
return (part.physicalSignificance == Part.PhysicalSignificance.FULL) ? part.mass : 0d; | return (part.physicalSignificance == Part.PhysicalSignificance.FULL) ? part.mass : 0d; |
} | } |
/// <summary> | /// <summary> |
/// Gets the maximum thrust of the part if it's an engine. | /// Gets the maximum thrust of the part if it's an engine. |
/// </summary> | /// </summary> |
public static double GetMaxThrust(this Part part) | public static double GetMaxThrust(this Part part) |
{ | { |
if (part.HasModule<ModuleEngines>()) | PartModule cachePartModule = GetModule<ModuleEngines>(part); |
{ | if (cachePartModule != null) |
return part.GetModuleEngines().maxThrust; | { |
} | return (cachePartModule as ModuleEngines).maxThrust; |
if (part.HasModule<MultiModeEngine>()) | } |
{ | |
return part.GetModuleMultiModeEngine().maxThrust; | cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part); |
} | if (cachePartModule != null) |
if (part.HasModule<ModuleEnginesFX>()) | { |
{ | return (cachePartModule as ModuleEnginesFX).maxThrust; |
return part.GetModuleEnginesFx().maxThrust; | } |
} | |
return 0.0; | |
return 0d; | |
} | } |
/// <summary> | /// <summary> |
/// Gets the first typed PartModule in the part's module list. | /// Gets the first typed PartModule in the part's module list. |
/// </summary> | /// </summary> |
public static T GetModule<T>(this Part part) where T : PartModule | public static T GetModule<T>(this Part part) where T : PartModule |
{ | { |
return part.Modules.OfType<T>().FirstOrDefault(); | for (int i = 0; i < part.Modules.Count; i++) |
{ | |
PartModule pm = part.Modules[i]; | |
if (pm is T) | |
return (T)pm; | |
} | |
return null; | |
} | } |
/// <summary> | /// <summary> |
/// Gets a typed PartModule. | /// Gets a typed PartModule. |
/// </summary> | /// </summary> |
public static T GetModule<T>(this Part part, string className) where T : PartModule | public static T GetModule<T>(this Part part, string className) where T : PartModule |
{ | { |
return (T)Convert.ChangeType(part.Modules[className], typeof(T)); | return part.Modules[className] as T; |
} | } |
/// <summary> | /// <summary> |
/// Gets a typed PartModule. | /// Gets a typed PartModule. |
/// </summary> | /// </summary> |
public static T GetModule<T>(this Part part, int classId) where T : PartModule | public static T GetModule<T>(this Part part, int classId) where T : PartModule |
{ | { |
return (T)Convert.ChangeType(part.Modules[classId], typeof(T)); | return part.Modules[classId] as T; |
} | } |
/// <summary> | /// <summary> |
/// Gets a ModuleAlternator typed PartModule. | /// Gets a ModuleAlternator typed PartModule. |
/// </summary> | /// </summary> |
public static ModuleAlternator GetModuleAlternator(this Part part) | public static ModuleAlternator GetModuleAlternator(this Part part) |
{ | { |
return part.GetModule<ModuleAlternator>(); | return GetModule<ModuleAlternator>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets a ModuleDeployableSolarPanel typed PartModule. | /// Gets a ModuleDeployableSolarPanel typed PartModule. |
/// </summary> | /// </summary> |
public static ModuleDeployableSolarPanel GetModuleDeployableSolarPanel(this Part part) | public static ModuleDeployableSolarPanel GetModuleDeployableSolarPanel(this Part part) |
{ | { |
return part.GetModule<ModuleDeployableSolarPanel>(); | return GetModule<ModuleDeployableSolarPanel>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets a ModuleEngines typed PartModule. | /// Gets a ModuleEngines typed PartModule. |
/// </summary> | /// </summary> |
public static ModuleEngines GetModuleEngines(this Part part) | public static ModuleEngines GetModuleEngines(this Part part) |
{ | { |
return part.GetModule<ModuleEngines>(); | return GetModule<ModuleEngines>(part); |
} | } |
public static ModuleEnginesFX GetModuleEnginesFx(this Part part) | public static ModuleEnginesFX GetModuleEnginesFx(this Part part) |
{ | { |
return part.GetModule<ModuleEnginesFX>(); | return GetModule<ModuleEnginesFX>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets a ModuleGenerator typed PartModule. | /// Gets a ModuleGenerator typed PartModule. |
/// </summary> | /// </summary> |
public static ModuleGenerator GetModuleGenerator(this Part part) | public static ModuleGenerator GetModuleGenerator(this Part part) |
{ | { |
return part.GetModule<ModuleGenerator>(); | return GetModule<ModuleGenerator>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets a ModuleGimbal typed PartModule. | /// Gets a ModuleGimbal typed PartModule. |
/// </summary> | /// </summary> |
public static ModuleGimbal GetModuleGimbal(this Part part) | public static ModuleGimbal GetModuleGimbal(this Part part) |
{ | { |
return part.GetModule<ModuleGimbal>(); | return GetModule<ModuleGimbal>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets the current selected ModuleEnginesFX. | /// Gets the current selected ModuleEnginesFX. |
/// </summary> | /// </summary> |
public static ModuleEnginesFX GetModuleMultiModeEngine(this Part part) | public static ModuleEnginesFX GetModuleMultiModeEngine(this Part part) |
{ | { |
var mode = part.GetModule<MultiModeEngine>().mode; | ModuleEnginesFX moduleEngineFx; |
return part.Modules.OfType<ModuleEnginesFX>().FirstOrDefault(engine => engine.engineID == mode); | string mode = GetModule<MultiModeEngine>(part).mode; |
for (int i = 0; i < part.Modules.Count; ++i) | |
{ | |
moduleEngineFx = part.Modules[i] as ModuleEnginesFX; | |
if (moduleEngineFx != null && moduleEngineFx.engineID == mode) | |
{ | |
return moduleEngineFx; | |
} | |
} | |
return null; | |
} | } |
/// <summary> | /// <summary> |
/// Gets a ModuleParachute typed PartModule. | /// Gets a ModuleParachute typed PartModule. |
/// </summary> | /// </summary> |
public static ModuleParachute GetModuleParachute(this Part part) | public static ModuleParachute GetModuleParachute(this Part part) |
{ | { |
return part.GetModule<ModuleParachute>(); | return GetModule<ModuleParachute>(part); |
} | } |
public static ModuleRCS GetModuleRcs(this Part part) | public static ModuleRCS GetModuleRcs(this Part part) |
{ | { |
return part.GetModule<ModuleRCS>(); | return GetModule<ModuleRCS>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets a typed list of PartModules. | /// Gets a typed list of PartModules. |
/// </summary> | /// </summary> |
public static List<T> GetModules<T>(this Part part) where T : PartModule | public static List<T> GetModules<T>(this Part part) where T : PartModule |
{ | { |
return part.Modules.OfType<T>().ToList(); | List<T> list = new List<T>(); |
for (int i = 0; i < part.Modules.Count; ++i) | |
{ | |
T module = part.Modules[i] as T; | |
if (module != null) | |
{ | |
list.Add(module); | |
} | |
} | |
return list; | |
} | } |
public static ProtoModuleDecoupler GetProtoModuleDecoupler(this Part part) | public static ProtoModuleDecoupler GetProtoModuleDecoupler(this Part part) |
{ | { |
if (HasModule<ModuleDecouple>(part)) | PartModule cachePartModule = GetModule<ModuleDecouple>(part); |
{ | if (cachePartModule == null) |
return new ProtoModuleDecoupler(GetModule<ModuleDecouple>(part)); | { |
} | cachePartModule = GetModule<ModuleAnchoredDecoupler>(part); |
if (HasModule<ModuleAnchoredDecoupler>(part)) | } |
{ | if (cachePartModule != null) |
return new ProtoModuleDecoupler(GetModule<ModuleAnchoredDecoupler>(part)); | { |
} | return new ProtoModuleDecoupler(cachePartModule); |
} | |
return null; | return null; |
} | } |
/// <summary> | /// <summary> |
/// Gets a generic proto engine for the current engine module attached to the part. | /// Gets a generic proto engine for the current engine module attached to the part. |
/// </summary> | /// </summary> |
public static ProtoModuleEngine GetProtoModuleEngine(this Part part) | public static ProtoModuleEngine GetProtoModuleEngine(this Part part) |
{ | { |
if (HasModule<ModuleEngines>(part)) | PartModule cachePartModule = GetModule<ModuleEngines>(part); |
{ | if (cachePartModule != null) |
return new ProtoModuleEngine(GetModule<ModuleEngines>(part)); | { |
} | return new ProtoModuleEngine(cachePartModule); |
if (HasModule<MultiModeEngine>(part)) | } |
{ | |
return new ProtoModuleEngine(GetModuleMultiModeEngine(part)); | cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part); |
} | if (cachePartModule != null) |
if (HasModule<ModuleEnginesFX>(part)) | { |
{ | return new ProtoModuleEngine(cachePartModule); |
return new ProtoModuleEngine(GetModule<ModuleEnginesFX>(part)); | } |
} | |
return null; | return null; |
} | } |
/// <summary> | /// <summary> |
/// Gets the cost of the part's contained resources. | /// Gets the cost of the part's contained resources. |
/// </summary> | /// </summary> |
public static double GetResourceCost(this Part part) | public static double GetResourceCost(this Part part) |
{ | { |
return part.Resources.list.Sum(r => r.amount * r.info.unitCost); | double cost = 0.0; |
for (int i = 0; i < part.Resources.list.Count; ++i) | |
{ | |
PartResource cachePartResource = part.Resources.list[i]; | |
cost = cost + (cachePartResource.amount * cachePartResource.info.unitCost); | |
} | |
return cost; | |
} | } |
/// <summary> | /// <summary> |
/// Gets the cost of the part's contained resources, inverted. | /// Gets the cost of the part's contained resources, inverted. |
/// </summary> | /// </summary> |
public static double GetResourceCostInverted(this Part part) | public static double GetResourceCostInverted(this Part part) |
{ | { |
return part.Resources.list.Sum(r => (r.maxAmount - r.amount) * r.info.unitCost); | double sum = 0; |
for (int i = 0; i < part.Resources.list.Count; i++) | |
{ | |
PartResource r = part.Resources.list[i]; | |
sum += (r.maxAmount - r.amount) * r.info.unitCost; | |
} | |
return sum; | |
} | } |
/// <summary> | /// <summary> |
/// Gets the cost of the part's maximum contained resources. | /// Gets the cost of the part's maximum contained resources. |
/// </summary> | /// </summary> |
public static double GetResourceCostMax(this Part part) | public static double GetResourceCostMax(this Part part) |
{ | { |
return part.Resources.list.Sum(r => r.maxAmount * r.info.unitCost); | double cost = 0.0; |
for (int i = 0; i < part.Resources.list.Count; ++i) | |
{ | |
PartResource cachePartResource = part.Resources.list[i]; | |
cost = cost + (cachePartResource.maxAmount * cachePartResource.info.unitCost); | |
} | |
return cost; | |
} | } |
/// <summary> | /// <summary> |
/// Gets the current specific impulse for the engine. | /// Gets the current specific impulse for the engine. |
/// </summary> | /// </summary> |
public static double GetSpecificImpulse(this Part part, float atmosphere) | public static double GetSpecificImpulse(this Part part, float atmosphere) |
{ | { |
if (part.HasModule<ModuleEngines>()) | PartModule cachePartModule = GetModule<ModuleEngines>(part); |
{ | if (cachePartModule != null) |
return part.GetModuleEngines().atmosphereCurve.Evaluate(atmosphere); | { |
} | return (cachePartModule as ModuleEngines).atmosphereCurve.Evaluate(atmosphere); |
if (part.HasModule<MultiModeEngine>()) | } |
{ | |
return part.GetModuleMultiModeEngine().atmosphereCurve.Evaluate(atmosphere); | cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part); |
} | if (cachePartModule != null) |
if (part.HasModule<ModuleEnginesFX>()) | { |
{ | return (cachePartModule as ModuleEnginesFX).atmosphereCurve.Evaluate(atmosphere); |
return part.GetModuleEnginesFx().atmosphereCurve.Evaluate(atmosphere); | } |
} | |
return 0.0; | |
return 0d; | |
} | } |
/// <summary> | /// <summary> |
/// Gets the total mass of the part including resources. | /// Gets the total mass of the part including resources. |
/// </summary> | /// </summary> |
public static double GetWetMass(this Part part) | public static double GetWetMass(this Part part) |
{ | { |
return (part.physicalSignificance == Part.PhysicalSignificance.FULL) ? part.mass + part.GetResourceMass() : part.GetResourceMass(); | return (part.physicalSignificance == Part.PhysicalSignificance.FULL) ? part.mass + part.GetResourceMass() : part.GetResourceMass(); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part contains a PartModule. | /// Gets whether the part contains a PartModule. |
/// </summary> | /// </summary> |
public static bool HasModule<T>(this Part part) where T : PartModule | public static bool HasModule<T>(this Part part) where T : PartModule |
{ | { |
return part.Modules.OfType<T>().Any(); | for (int i = 0; i < part.Modules.Count; i++) |
{ | |
if (part.Modules[i] is T) | |
return true; | |
} | |
return false; | |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part contains a PartModule conforming to the supplied predicate. | /// Gets whether the part contains a PartModule conforming to the supplied predicate. |
/// </summary> | /// </summary> |
public static bool HasModule<T>(this Part part, Func<T, bool> predicate) where T : PartModule | public static bool HasModule<T>(this Part part, Func<T, bool> predicate) where T : PartModule |
{ | { |
return part.Modules.OfType<T>().Any(predicate); | for (int i = 0; i < part.Modules.Count; i++) |
{ | |
PartModule pm = part.Modules[i]; | |
if (pm is T && predicate(pm as T)) | |
return true; | |
} | |
return false; | |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part contains a PartModule. | /// Gets whether the part contains a PartModule. |
/// </summary> | /// </summary> |
public static bool HasModule(this Part part, string className) | public static bool HasModule(this Part part, string className) |
{ | { |
return part.Modules.Contains(className); | return part.Modules.Contains(className); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part contains a PartModule. | /// Gets whether the part contains a PartModule. |
/// </summary> | /// </summary> |
public static bool HasModule(this Part part, int moduleId) | public static bool HasModule(this Part part, int moduleId) |
{ | { |
return part.Modules.Contains(moduleId); | return part.Modules.Contains(moduleId); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part has a one shot animation. | /// Gets whether the part has a one shot animation. |
/// </summary> | /// </summary> |
public static bool HasOneShotAnimation(this Part part) | public static bool HasOneShotAnimation(this Part part) |
{ | { |
return part.HasModule<ModuleAnimateGeneric>() && part.GetModule<ModuleAnimateGeneric>().isOneShot; | PartModule cachePartModule = GetModule<ModuleAnimateGeneric>(part); |
return cachePartModule != null && (cachePartModule as ModuleAnimateGeneric).isOneShot; | |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is a command module. | /// Gets whether the part is a command module. |
/// </summary> | /// </summary> |
public static bool IsCommandModule(this Part part) | public static bool IsCommandModule(this Part part) |
{ | { |
return part.HasModule<ModuleCommand>(); | return HasModule<ModuleCommand>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is decoupled in a specified stage. | /// Gets whether the part is decoupled in a specified stage. |
/// </summary> | /// </summary> |
public static bool IsDecoupledInStage(this Part part, int stage) | public static bool IsDecoupledInStage(this Part part, int stage) |
{ | { |
if ((part.IsDecoupler() || part.IsLaunchClamp()) && part.inverseStage == stage) | if ((IsDecoupler(part) || IsLaunchClamp(part)) && part.inverseStage == stage) |
{ | { |
return true; | return true; |
} | } |
if (part.parent == null) | if (part.parent == null) |
{ | { |
return false; | return false; |
} | } |
return part.parent.IsDecoupledInStage(stage); | return IsDecoupledInStage(part.parent, stage); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is a decoupler. | /// Gets whether the part is a decoupler. |
/// </summary> | /// </summary> |
public static bool IsDecoupler(this Part part) | public static bool IsDecoupler(this Part part) |
{ | { |
return part.HasModule<ModuleDecouple>() || part.HasModule<ModuleAnchoredDecoupler>(); | return HasModule<ModuleDecouple>(part) || HasModule<ModuleAnchoredDecoupler>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is an active engine. | /// Gets whether the part is an active engine. |
/// </summary> | /// </summary> |
public static bool IsEngine(this Part part) | public static bool IsEngine(this Part part) |
{ | { |
return part.HasModule<ModuleEngines>() || part.HasModule<ModuleEnginesFX>(); | return HasModule<ModuleEngines>(part) || HasModule<ModuleEnginesFX>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is a fuel line. | /// Gets whether the part is a fuel line. |
/// </summary> | /// </summary> |
public static bool IsFuelLine(this Part part) | public static bool IsFuelLine(this Part part) |
{ | { |
return (HasModule<CModuleFuelLine>(part)); | return HasModule<CModuleFuelLine>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is a generator. | /// Gets whether the part is a generator. |
/// </summary> | /// </summary> |
public static bool IsGenerator(this Part part) | public static bool IsGenerator(this Part part) |
{ | { |
return part.HasModule<ModuleGenerator>(); | return HasModule<ModuleGenerator>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is a launch clamp. | /// Gets whether the part is a launch clamp. |
/// </summary> | /// </summary> |
public static bool IsLaunchClamp(this Part part) | public static bool IsLaunchClamp(this Part part) |
{ | { |
return part.HasModule<LaunchClamp>(); | return HasModule<LaunchClamp>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is a parachute. | /// Gets whether the part is a parachute. |
/// </summary> | /// </summary> |
public static bool IsParachute(this Part part) | public static bool IsParachute(this Part part) |
{ | { |
return part.HasModule<ModuleParachute>(); | return HasModule<ModuleParachute>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is considered a primary part on the vessel. | /// Gets whether the part is considered a primary part on the vessel. |
/// </summary> | /// </summary> |
public static bool IsPrimary(this Part part, List<Part> partsList, PartModule module) | public static bool IsPrimary(this Part part, List<Part> partsList, PartModule module) |
{ | { |
foreach (var vesselPart in partsList) | for (int i = 0; i < partsList.Count; i++) |
{ | { |
var vesselPart = partsList[i]; | |
if (!vesselPart.HasModule(module.ClassID)) | if (!vesselPart.HasModule(module.ClassID)) |
{ | { |
continue; | continue; |
} | } |
if (vesselPart == part) | if (vesselPart == part) |
{ | { |
return true; | return true; |
} | } |
break; | break; |
} | } |
return false; | return false; |
} | } |
public static bool IsRcsModule(this Part part) | public static bool IsRcsModule(this Part part) |
{ | { |
return part.HasModule<ModuleRCS>(); | return HasModule<ModuleRCS>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is a sepratron. | /// Gets whether the part is a sepratron. |
/// </summary> | /// </summary> |
public static bool IsSepratron(this Part part) | public static bool IsSepratron(this Part part) |
{ | { |
return (part.IsSolidRocket() && part.ActivatesEvenIfDisconnected && part.IsDecoupledInStage(part.inverseStage)); | return IsSolidRocket(part) && part.ActivatesEvenIfDisconnected && IsDecoupledInStage(part, part.inverseStage); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is a deployable solar panel. | /// Gets whether the part is a deployable solar panel. |
/// </summary> | /// </summary> |
public static bool IsSolarPanel(this Part part) | public static bool IsSolarPanel(this Part part) |
{ | { |
return part.HasModule<ModuleDeployableSolarPanel>(); | return HasModule<ModuleDeployableSolarPanel>(part); |
} | } |
/// <summary> | /// <summary> |
/// Gets whether the part is a solid rocket motor. | /// Gets whether the part is a solid rocket motor. |
/// </summary> | /// </summary> |
public static bool IsSolidRocket(this Part part) | public static bool IsSolidRocket(this Part part) |
{ | { |
return part.HasModule<ModuleEngines>() && part.GetModuleEngines().throttleLocked; | return (part.HasModule<ModuleEngines>() && part.GetModuleEngines().throttleLocked) || (part.HasModule<ModuleEnginesFX>() && part.GetModuleEnginesFx().throttleLocked); |
} | } |
#endregion | |
#region Nested Type: ProtoModuleDecoupler | |
public class ProtoModuleDecoupler | public class ProtoModuleDecoupler |
{ | { |
#region Fields | |
private readonly PartModule module; | private readonly PartModule module; |
#endregion | |
#region Constructors | |
public ProtoModuleDecoupler(PartModule module) | public ProtoModuleDecoupler(PartModule module) |
{ | { |
this.module = module; | this.module = module; |
if (this.module is ModuleDecouple) | if (this.module is ModuleDecouple) |
{ | { |
this.SetModuleDecouple(); | SetModuleDecouple(); |
} | } |
else if (this.module is ModuleAnchoredDecoupler) | else if (this.module is ModuleAnchoredDecoupler) |
{ | { |
this.SetModuleAnchoredDecoupler(); | SetModuleAnchoredDecoupler(); |
} | } |
} | } |
#endregion | |
#region Properties | |
public double EjectionForce { get; private set; } | public double EjectionForce { get; private set; } |
public bool IsOmniDecoupler { get; private set; } | public bool IsOmniDecoupler { get; private set; } |
#endregion | |
#region Methods: private | |
private void SetModuleAnchoredDecoupler() | private void SetModuleAnchoredDecoupler() |
{ | { |
var decoupler = this.module as ModuleAnchoredDecoupler; | ModuleAnchoredDecoupler decoupler = module as ModuleAnchoredDecoupler; |
if (decoupler == null) | if (decoupler == null) |
{ | { |
return; | return; |
} | } |
this.EjectionForce = decoupler.ejectionForce; | EjectionForce = decoupler.ejectionForce; |
} | } |
private void SetModuleDecouple() | private void SetModuleDecouple() |
{ | { |
var decoupler = this.module as ModuleDecouple; | ModuleDecouple decoupler = module as ModuleDecouple; |
if (decoupler == null) | if (decoupler == null) |
{ | { |
return; | return; |
} | } |
this.EjectionForce = decoupler.ejectionForce; | EjectionForce = decoupler.ejectionForce; |
this.IsOmniDecoupler = decoupler.isOmniDecoupler; | IsOmniDecoupler = decoupler.isOmniDecoupler; |
} | } |
} | |
#endregion | |
} | |
#endregion | |
#region Nested Type: ProtoModuleEngine | |
public class ProtoModuleEngine | public class ProtoModuleEngine |
{ | { |
#region Fields | |
private readonly PartModule module; | private readonly PartModule module; |
#endregion | |
#region Constructors | |
public ProtoModuleEngine(PartModule module) | public ProtoModuleEngine(PartModule module) |
{ | { |
this.module = module; | this.module = module; |
if (module is ModuleEngines) | if (module is ModuleEngines) |
{ | { |
this.SetModuleEngines(); | SetModuleEngines(); |
} | } |
else if (module is ModuleEnginesFX) | } |
{ | |
this.SetModuleEnginesFx(); | |
} | |
} | |
#endregion | |
#region Properties | |
public double MaximumThrust { get; private set; } | public double MaximumThrust { get; private set; } |
public double MinimumThrust { get; private set; } | public double MinimumThrust { get; private set; } |
public List<Propellant> Propellants { get; private set; } | public List<Propellant> Propellants { get; private set; } |
#endregion | |
#region Methods: public | |
public float GetSpecificImpulse(float atmosphere) | public float GetSpecificImpulse(float atmosphere) |
{ | { |
if (this.module is ModuleEngines) | if (module is ModuleEngines) |
{ | { |
return (this.module as ModuleEngines).atmosphereCurve.Evaluate(atmosphere); | return (module as ModuleEngines).atmosphereCurve.Evaluate(atmosphere); |
} | |
if (this.module is ModuleEnginesFX) | |
{ | |
return (this.module as ModuleEnginesFX).atmosphereCurve.Evaluate(atmosphere); | |
} | } |
return 0.0f; | return 0.0f; |
} | } |
#endregion | |
#region Methods: private | |
private void SetModuleEngines() | private void SetModuleEngines() |
{ | { |
var engine = this.module as ModuleEngines; | ModuleEngines engine = module as ModuleEngines; |
if (engine == null) | if (engine == null) |
{ | { |
return; | return; |
} | } |
this.MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01); | MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01); |
this.MinimumThrust = engine.minThrust; | MinimumThrust = engine.minThrust; |
this.Propellants = engine.propellants; | Propellants = engine.propellants; |
} | } |
private void SetModuleEnginesFx() | private void SetModuleEnginesFx() |
{ | { |
var engine = this.module as ModuleEnginesFX; | ModuleEnginesFX engine = module as ModuleEnginesFX; |
if (engine == null) | if (engine == null) |
{ | { |
return; | return; |
} | } |
this.MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01); | MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01); |
this.MinimumThrust = engine.minThrust; | MinimumThrust = engine.minThrust; |
this.Propellants = engine.propellants; | Propellants = engine.propellants; |
} | } |
} | |
#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 Start() | |
{ | |
if (button == null) | |
{ | |
OnGuiAppLauncherReady(); | |
} | |
} | |
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); | if (button != null) |
{ | |
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.IsDisplayable && this.button.State == RUIToggleButton.ButtonState.DISABLED) | if (FlightEngineerCore.IsDisplayable && this.button.State == RUIToggleButton.ButtonState.DISABLED) |
{ | { |
this.button.Enable(); | this.button.Enable(); |
} | } |
else if (!FlightEngineerCore.IsDisplayable && 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.Linq; | using System.Linq; |
using System.Reflection; | using System.Reflection; |
using KerbalEngineer.Extensions; | using KerbalEngineer.Extensions; |
#endregion | #endregion |
namespace KerbalEngineer.Flight.Readouts.Surface | namespace KerbalEngineer.Flight.Readouts.Surface |
{ | { |
using UnityEngine; | |
public class AtmosphericProcessor : IUpdatable, IUpdateRequest | public class AtmosphericProcessor : IUpdatable, IUpdateRequest |
{ | { |
#region Instance | #region Instance |
#region Fields | #region Fields |
private static readonly AtmosphericProcessor instance = new AtmosphericProcessor(); | private static readonly AtmosphericProcessor instance = new AtmosphericProcessor(); |
#endregion | #endregion |
#region Properties | #region Properties |
/// <summary> | /// <summary> |
/// Gets the current instance of the atmospheric processor. | /// Gets the current instance of the atmospheric processor. |
/// </summary> | /// </summary> |
public static AtmosphericProcessor Instance | public static AtmosphericProcessor Instance |
{ | { |
get { return instance; } | get |
{ | |
return instance; | |
} | |
} | } |
#endregion | #endregion |
#endregion | #endregion |
#region Fields | #region Fields |
private MethodInfo farTerminalVelocity; | private MethodInfo farTerminalVelocity; |
private bool hasCheckedAeroMods; | private bool hasCheckedAeroMods; |
#endregion | #endregion |
#region Properties | #region Properties |
/// <summary> | /// <summary> |
/// Gets the deceleration caused by drag. | /// Gets the deceleration caused by drag. |
/// </summary> | /// </summary> |
public static double Deceleration { get; private set; } | public static double Deceleration { get; private set; } |
/// <summary> | /// <summary> |
/// Gets the difference between current velocity and terminal velocity. | /// Gets the difference between current velocity and terminal velocity. |
/// </summary> | /// </summary> |
public static double Efficiency { get; private set; } | public static double Efficiency { get; private set; } |
/// <summary> | /// <summary> |
/// Gets whether FAR is installed. | /// Gets whether FAR is installed. |
/// </summary> | /// </summary> |
public static bool FarInstalled { get; private set; } | public static bool FarInstalled { get; private set; } |
/// <summary> | /// <summary> |
/// Gets whether NEAR is installed. | /// Gets whether NEAR is installed. |
/// </summary> | /// </summary> |
public static bool NearInstalled { get; private set; } | public static bool NearInstalled { get; private set; } |
/// <summary> | /// <summary> |
/// Gets whether the details are ready to be shown. | /// Gets whether the details are ready to be shown. |
/// </summary> | /// </summary> |
public static bool ShowDetails { get; private set; } | public static bool ShowDetails { get; private set; } |
/// <summary> | /// <summary> |
/// Gets the terminal velocity of the active vessel. | /// Gets the terminal velocity of the active vessel. |
/// </summary> | /// </summary> |
public static double TerminalVelocity { get; private set; } | public static double TerminalVelocity { get; private set; } |
#endregion | #endregion |
#region IUpdatable Members | #region IUpdatable Members |
/// <summary> | /// <summary> |
/// Updates the details by recalculating if requested. | /// Updates the details by recalculating if requested. |
/// </summary> | /// </summary> |
public void Update() | public void Update() |
{ | { |
try | try |
{ | { |
if (!this.hasCheckedAeroMods) | if (!this.hasCheckedAeroMods) |
{ | { |
this.CheckAeroMods(); | this.CheckAeroMods(); |
} | } |
if (FlightGlobals.ActiveVessel.atmDensity < double.Epsilon || NearInstalled) | if (FlightGlobals.ActiveVessel.atmDensity < double.Epsilon || NearInstalled) |
{ | { |
ShowDetails = false; | ShowDetails = false; |
return; | return; |
} | } |
ShowDetails = true; | ShowDetails = true; |
if (FarInstalled) | if (FarInstalled) |
{ | { |
TerminalVelocity = (double)this.farTerminalVelocity.Invoke(null, null); | TerminalVelocity = (double)this.farTerminalVelocity.Invoke(null, null); |
} | } |
else | else |
{ | { |
var mass = FlightGlobals.ActiveVessel.parts.Sum(p => p.GetWetMass()); | var m = FlightGlobals.ActiveVessel.parts.Sum(part => part.GetWetMass()) * 1000.0; |
var drag = FlightGlobals.ActiveVessel.parts.Sum(p => p.GetWetMass() * p.maximum_drag); | var g = FlightGlobals.getGeeForceAtPosition(FlightGlobals.ship_position).magnitude; |
var grav = FlightGlobals.getGeeForceAtPosition(FlightGlobals.ship_position).magnitude; | var a = FlightGlobals.ActiveVessel.parts.Sum(part => part.DragCubes.AreaDrag) * PhysicsGlobals.DragCubeMultiplier; |
var atmo = FlightGlobals.ActiveVessel.atmDensity; | var p = FlightGlobals.ActiveVessel.atmDensity; |
var coef = FlightGlobals.DragMultiplier; | var c = PhysicsGlobals.DragMultiplier; |
TerminalVelocity = Math.Sqrt((2 * mass * grav) / (atmo * drag * coef)); | TerminalVelocity = Math.Sqrt((2.0 * m * g) / (p * a * c)); |
} | } |
Efficiency = FlightGlobals.ship_srfSpeed / TerminalVelocity; | Efficiency = FlightGlobals.ship_srfSpeed / TerminalVelocity; |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex, "AtmosphericProcessor->Update"); | Logger.Exception(ex, "AtmosphericProcessor->Update"); |
} | } |
} | } |
#endregion | #endregion |
#region IUpdateRequest Members | #region IUpdateRequest Members |
/// <summary> | /// <summary> |
/// Gets and sets whether the updatable object should be updated. | /// Gets and sets whether the updatable object should be updated. |
/// </summary> | /// </summary> |
public bool UpdateRequested { get; set; } | public bool UpdateRequested { get; set; } |
#endregion | #endregion |
#region Methods: public | #region Methods: public |
/// <summary> | /// <summary> |
/// Request an update to calculate the details. | /// Request an update to calculate the details. |
/// </summary> | /// </summary> |
public static void RequestUpdate() | public static void RequestUpdate() |
{ | { |
instance.UpdateRequested = true; | instance.UpdateRequested = true; |
} | } |
#endregion | #endregion |
#region Private Methods | #region Private Methods |
private void CheckAeroMods() | private void CheckAeroMods() |
{ | { |
try | try |
{ | { |
this.hasCheckedAeroMods = true; | this.hasCheckedAeroMods = true; |
foreach (var loadedAssembly in AssemblyLoader.loadedAssemblies) | foreach (var loadedAssembly in AssemblyLoader.loadedAssemblies) |
{ | { |
switch (loadedAssembly.name) | switch (loadedAssembly.name) |
{ | { |
case "FerramAerospaceResearch": | case "FerramAerospaceResearch": |
this.farTerminalVelocity = loadedAssembly.assembly.GetType("ferram4.FARAPI").GetMethod("GetActiveControlSys_TermVel"); | this.farTerminalVelocity = loadedAssembly.assembly.GetType("ferram4.FARAPI").GetMethod("GetActiveControlSys_TermVel"); |
FarInstalled = true; | FarInstalled = true; |
Logger.Log("FAR detected!"); | Logger.Log("FAR detected!"); |
break; | break; |
case "NEAR": | case "NEAR": |
NearInstalled = true; | NearInstalled = true; |
Logger.Log("NEAR detected! Turning off atmospheric details!"); | Logger.Log("NEAR detected! Turning off atmospheric details!"); |
break; | break; |
} | } |
} | } |
} | } |
catch (Exception ex) | catch (Exception ex) |
{ | { |
Logger.Exception(ex, "AtmosphericProcessor->CheckAeroMods"); | Logger.Exception(ex, "AtmosphericProcessor->CheckAeroMods"); |
} | } |
} | } |
#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 UnityEngine; | using UnityEngine; |
#endregion | #endregion |
public class AttitudeProcessor : IUpdatable, IUpdateRequest | public class AttitudeProcessor : IUpdatable, IUpdateRequest |
{ | { |
#region Fields | #region Fields |
private static readonly AttitudeProcessor instance = new AttitudeProcessor(); | private static readonly AttitudeProcessor instance = new AttitudeProcessor(); |
private Vector3 centreOfMass = Vector3.zero; | private Vector3 centreOfMass = Vector3.zero; |
private double heading; | private double heading; |
private double headingRate; | private double headingRate; |
private Vector3 north = Vector3.zero; | private Vector3 north = Vector3.zero; |
private double pitch; | private double pitch; |
private double pitchRate; | private double pitchRate; |
private double previousHeading; | private double previousHeading; |
private double previousPitch; | private double previousPitch; |
private double previousRoll; | private double previousRoll; |
private double roll; | private double roll; |
private double rollRate; | private double rollRate; |
private Quaternion surfaceRotation; | private Quaternion surfaceRotation; |
private Vector3 up = Vector3.zero; | private Vector3 up = Vector3.zero; |
#endregion | #endregion |
#region Properties | #region Properties |
public static double Heading | public static double Heading |
{ | { |
get { return instance.heading; } | get { return instance.heading; } |
} | } |
public static double HeadingRate | public static double HeadingRate |
{ | { |
get { return instance.headingRate; } | get { return instance.headingRate; } |
} | } |
public static AttitudeProcessor Instance | public static AttitudeProcessor Instance |
{ | { |
get { return instance; } | get { return instance; } |
} | } |
public static double Pitch | public static double Pitch |
{ | { |
get { return instance.pitch; } | get { return instance.pitch; } |
} | } |
public static double PitchRate | public static double PitchRate |
{ | { |
get { return instance.pitchRate; } | get { return instance.pitchRate; } |
} | } |
public static double Roll | public static double Roll |
{ | { |
get { return instance.roll; } | get { return instance.roll; } |
} | } |
public static double RollRate | public static double RollRate |
{ | { |
get { return instance.rollRate; } | get { return instance.rollRate; } |
} | } |
public bool UpdateRequested { get; set; } | public bool UpdateRequested { get; set; } |
#endregion | #endregion |
#region Methods | #region Methods |
public static void RequestUpdate() | public static void RequestUpdate() |
{ | { |
instance.UpdateRequested = true; | instance.UpdateRequested = true; |
} | } |
public void Update() | public void Update() |
{ | { |
this.surfaceRotation = this.GetSurfaceRotation(); | this.surfaceRotation = this.GetSurfaceRotation(); |
this.previousHeading = this.heading; | this.previousHeading = this.heading; |
this.previousPitch = this.pitch; | this.previousPitch = this.pitch; |
this.previousRoll = this.roll; | this.previousRoll = this.roll; |
// This code was derived from MechJeb2's implementation for getting the vessel's surface relative rotation. | // This code was derived from MechJeb2's implementation for getting the vessel's surface relative rotation. |
this.heading = this.surfaceRotation.eulerAngles.y; | this.heading = this.surfaceRotation.eulerAngles.y; |
this.pitch = this.surfaceRotation.eulerAngles.x > 180.0f | this.pitch = this.surfaceRotation.eulerAngles.x > 180.0f |
? 360.0f - this.surfaceRotation.eulerAngles.x | ? 360.0f - this.surfaceRotation.eulerAngles.x |
: -this.surfaceRotation.eulerAngles.x; | : -this.surfaceRotation.eulerAngles.x; |
this.roll = this.surfaceRotation.eulerAngles.z > 180.0f | this.roll = this.surfaceRotation.eulerAngles.z > 180.0f |
? this.surfaceRotation.eulerAngles.z - 360.0f | ? this.surfaceRotation.eulerAngles.z - 360.0f |
: this.surfaceRotation.eulerAngles.z; | : this.surfaceRotation.eulerAngles.z; |
this.headingRate = this.heading - this.previousHeading; | this.headingRate = this.heading - this.previousHeading; |
this.pitchRate = this.pitch - this.previousPitch; | this.pitchRate = this.pitch - this.previousPitch; |
this.rollRate = this.roll - this.previousRoll; | this.rollRate = this.roll - this.previousRoll; |
} | } |
private Quaternion GetSurfaceRotation() | private Quaternion GetSurfaceRotation() |
{ | { |
// This code was derived from MechJeb2's implementation for getting the vessel's surface relative rotation. | // This code was derived from MechJeb2's implementation for getting the vessel's surface relative rotation. |
this.centreOfMass = FlightGlobals.ActiveVessel.findWorldCenterOfMass(); | this.centreOfMass = FlightGlobals.ActiveVessel.findWorldCenterOfMass(); |
this.up = (this.centreOfMass - FlightGlobals.ActiveVessel.mainBody.position).normalized; | this.up = (this.centreOfMass - FlightGlobals.ActiveVessel.mainBody.position).normalized; |
this.north = Vector3.Exclude(this.up, (FlightGlobals.ActiveVessel.mainBody.position + FlightGlobals.ActiveVessel.mainBody.transform.up * (float)FlightGlobals.ActiveVessel.mainBody.Radius) - this.centreOfMass).normalized; | this.north = Vector3.ProjectOnPlane((FlightGlobals.ActiveVessel.mainBody.position + FlightGlobals.ActiveVessel.mainBody.transform.up * (float)FlightGlobals.ActiveVessel.mainBody.Radius) - this.centreOfMass, this.up).normalized; |
return Quaternion.Inverse(Quaternion.Euler(90.0f, 0.0f, 0.0f) * Quaternion.Inverse(FlightGlobals.ActiveVessel.transform.rotation) * Quaternion.LookRotation(this.north, this.up)); | return Quaternion.Inverse(Quaternion.Euler(90.0f, 0.0f, 0.0f) * Quaternion.Inverse(FlightGlobals.ActiveVessel.transform.rotation) * Quaternion.LookRotation(this.north, this.up)); |
} | } |
#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.ConcatF(SimulationProcessor.LastStage.partCount, SimulationProcessor.LastStage.totalPartCount), section.IsHud); | this.DrawLine(Units.ConcatF(SimulationProcessor.LastStage.partCount, SimulationProcessor.LastStage.totalPartCount, 0), 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 |
#endregion | #endregion |
namespace KerbalEngineer.Flight.Readouts.Vessel | namespace KerbalEngineer.Flight.Readouts.Vessel |
{ | { |
#region Using Directives | #region Using Directives |
using System; | using System; |
using VesselSimulator; | using VesselSimulator; |
#endregion | #endregion |
public class SimulationProcessor : IUpdatable, IUpdateRequest | public class SimulationProcessor : IUpdatable, IUpdateRequest |
{ | { |
#region Instance | #region Instance |
#region Fields | #region Fields |
private static readonly SimulationProcessor instance = new SimulationProcessor(); | private static readonly SimulationProcessor instance = new SimulationProcessor(); |
#endregion | #endregion |
#region Constructors | #region Constructors |
static SimulationProcessor() | static SimulationProcessor() |
{ | { |
SimManager.OnReady += GetStageInfo; | SimManager.OnReady += GetStageInfo; |
} | } |
#endregion | #endregion |
#region Properties | #region Properties |
/// <summary> | /// <summary> |
/// Gets the current instance of the simulation processor. | /// Gets the current instance of the simulation processor. |
/// </summary> | /// </summary> |
public static SimulationProcessor Instance | public static SimulationProcessor Instance |
{ | { |
get { return instance; } | get { return instance; } |
} | } |
#endregion | #endregion |
#endregion | #endregion |
#region Properties | #region Properties |
/// <summary> | /// <summary> |
/// Gets the currently active vessel stage. | /// Gets the currently active vessel stage. |
/// </summary> | /// </summary> |
public static Stage LastStage { get; private set; } | public static Stage LastStage { get; private set; } |
/// <summary> | /// <summary> |
/// Gets whether the details are ready to be shown. | /// Gets whether the details are ready to be shown. |
/// </summary> | /// </summary> |
public static bool ShowDetails { get; private set; } | public static bool ShowDetails { get; private set; } |
/// <summary> | /// <summary> |
/// Gets an array of the vessel stages. | /// Gets an array of the vessel stages. |
/// </summary> | /// </summary> |
public static Stage[] Stages { get; private set; } | public static Stage[] Stages { get; private set; } |
public bool UpdateRequested { get; set; } | public bool UpdateRequested { get; set; } |
#endregion | #endregion |
#region Methods | #region Methods |
private static void GetStageInfo() | private static void GetStageInfo() |
{ | { |
Stages = SimManager.Stages; | Stages = SimManager.Stages; |
LastStage = SimManager.LastStage; | LastStage = SimManager.LastStage; |
} | } |
public static void RequestUpdate() | public static void RequestUpdate() |
{ | { |
instance.UpdateRequested = true; | instance.UpdateRequested = true; |
} | } |
public void Update() | public void Update() |
{ | { |
SimManager.RequestSimulation(); | SimManager.RequestSimulation(); |
SimManager.TryStartSimulation(); | SimManager.TryStartSimulation(); |
if (!SimManager.ResultsReady()) | if (!SimManager.ResultsReady()) |
{ | { |
return; | return; |
} | } |
if (Stages != null && LastStage != null) | if (Stages != null && LastStage != null) |
{ | { |
ShowDetails = true; | ShowDetails = true; |
} | } |
if (FlightGlobals.ActiveVessel != null) | if (FlightGlobals.ActiveVessel != null) |
{ | { |
SimManager.Gravity = FlightGlobals.ActiveVessel.mainBody.gravParameter / | SimManager.Gravity = FlightGlobals.ActiveVessel.mainBody.gravParameter / |
Math.Pow(FlightGlobals.ActiveVessel.mainBody.Radius + | Math.Pow(FlightGlobals.ActiveVessel.mainBody.Radius + |
FlightGlobals.ActiveVessel.mainBody.GetAltitude(FlightGlobals.ActiveVessel.CoM), 2); | FlightGlobals.ActiveVessel.mainBody.GetAltitude(FlightGlobals.ActiveVessel.CoM), 2); |
SimManager.Velocity = FlightGlobals.ActiveVessel.srfSpeed; | SimManager.Mach = FlightGlobals.ActiveVessel.mach; |
} | } |
} | } |
#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/>. |
// | // |
using System; | using System; |
namespace KerbalEngineer | namespace KerbalEngineer |
{ | { |
public class VectorAverager | public class VectorAverager |
{ | { |
private Vector3d sum = Vector3d.zero; | private Vector3d sum = Vector3d.zero; |
private uint count = 0; | private uint count = 0; |
public void Add(Vector3d v) { | public void Add(Vector3d v) { |
sum += v; | sum += v; |
count += 1; | count += 1; |
} | } |
public Vector3d Get() { | public Vector3d Get() { |
if (count > 0) { | if (count > 0) { |
return sum / count; | return sum / count; |
} else { | } else { |
return Vector3d.zero; | return Vector3d.zero; |
} | } |
} | } |
public void Reset() | |
{ | |
sum = Vector3d.zero; | |
count = 0; | |
} | |
} | } |
public class WeightedVectorAverager | public class WeightedVectorAverager |
{ | { |
private Vector3d sum = Vector3d.zero; | private Vector3d sum = Vector3d.zero; |
private double totalweight = 0; | private double totalweight = 0; |
public void Add(Vector3d v, double weight) { | public void Add(Vector3d v, double weight) { |
sum += v * weight; | sum += v * weight; |
totalweight += weight; | totalweight += weight; |
} | } |
public Vector3d Get() { | public Vector3d Get() { |
if (totalweight > 0) { | if (totalweight > 0) { |
return sum / totalweight; | return sum / totalweight; |
} else { | } else { |
return Vector3d.zero; | return Vector3d.zero; |
} | } |
} | } |
public double GetTotalWeight() { | public double GetTotalWeight() { |
return totalweight; | return totalweight; |
} | } |
public void Reset() | |
{ | |
sum = Vector3d.zero; | |
totalweight = 0.0; | |
} | |
} | } |
} | } |
// | // |
// 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/>. |
// | // |
using System; | using System; |
using System.Collections.Generic; | using System.Collections.Generic; |
using KerbalEngineer.VesselSimulator; | |
namespace KerbalEngineer | namespace KerbalEngineer |
{ | { |
// a (force, application point) tuple | // a (force, application point) tuple |
public class AppliedForce | public class AppliedForce |
{ | { |
private static readonly Pool<AppliedForce> pool = new Pool<AppliedForce>(Create, Reset); | |
public Vector3d vector; | public Vector3d vector; |
public Vector3d applicationPoint; | public Vector3d applicationPoint; |
public AppliedForce(Vector3d vector, Vector3d applicationPoint) { | static private AppliedForce Create() |
this.vector = vector; | { |
this.applicationPoint = applicationPoint; | return new AppliedForce(); |
} | } |
static private void Reset(AppliedForce appliedForce) { } | |
static public AppliedForce New(Vector3d vector, Vector3d applicationPoint) | |
{ | |
AppliedForce force = pool.Borrow(); | |
force.vector = vector; | |
force.applicationPoint = applicationPoint; | |
return force; | |
} | |
public void Release() | |
{ | |
pool.Release(this); | |
} | |
} | } |
// This class was mostly adapted from FARCenterQuery, part of FAR, by ferram4, GPLv3 | // This class was mostly adapted from FARCenterQuery, part of FAR, by ferram4, GPLv3 |
// https://github.com/ferram4/Ferram-Aerospace-Research/blob/master/FerramAerospaceResearch/FARCenterQuery.cs | // https://github.com/ferram4/Ferram-Aerospace-Research/blob/master/FerramAerospaceResearch/FARCenterQuery.cs |
// Also see https://en.wikipedia.org/wiki/Resultant_force | // Also see https://en.wikipedia.org/wiki/Resultant_force |
// It accumulates forces and their points of applications, and provides methods for | // It accumulates forces and their points of applications, and provides methods for |
// calculating the effective torque at any position, as well as the minimum-torque net force application point. | // calculating the effective torque at any position, as well as the minimum-torque net force application point. |
// | // |
// The latter is a non-trivial issue; there is a 1-dimensional line of physically-equivalent solutions parallel | // The latter is a non-trivial issue; there is a 1-dimensional line of physically-equivalent solutions parallel |
// to the resulting force vector; the solution closest to the weighted average of force positions is chosen. | // to the resulting force vector; the solution closest to the weighted average of force positions is chosen. |
// In the case of non-parallel forces, there usually is an infinite number of such lines, all of which have | // In the case of non-parallel forces, there usually is an infinite number of such lines, all of which have |
// some amount of residual torque. The line with the least amount of residual torque is chosen. | // some amount of residual torque. The line with the least amount of residual torque is chosen. |
public class ForceAccumulator | public class ForceAccumulator |
{ | { |
// Total force. | // Total force. |
private Vector3d totalForce = Vector3d.zero; | private Vector3d totalForce = Vector3d.zero; |
// Torque needed to compensate if force were applied at origin. | // Torque needed to compensate if force were applied at origin. |
private Vector3d totalZeroOriginTorque = Vector3d.zero; | private Vector3d totalZeroOriginTorque = Vector3d.zero; |
// Weighted average of force application points. | // Weighted average of force application points. |
private WeightedVectorAverager avgApplicationPoint = new WeightedVectorAverager(); | private WeightedVectorAverager avgApplicationPoint = new WeightedVectorAverager(); |
// Feed an force to the accumulator. | // Feed an force to the accumulator. |
public void AddForce(Vector3d applicationPoint, Vector3d force) | public void AddForce(Vector3d applicationPoint, Vector3d force) |
{ | { |
totalForce += force; | totalForce += force; |
totalZeroOriginTorque += Vector3d.Cross(applicationPoint, force); | totalZeroOriginTorque += Vector3d.Cross(applicationPoint, force); |
avgApplicationPoint.Add(applicationPoint, force.magnitude); | avgApplicationPoint.Add(applicationPoint, force.magnitude); |
} | } |
public Vector3d GetAverageForceApplicationPoint() { | public Vector3d GetAverageForceApplicationPoint() { |
return avgApplicationPoint.Get(); | return avgApplicationPoint.Get(); |
} | } |
public void AddForce(AppliedForce force) { | public void AddForce(AppliedForce force) { |
AddForce(force.applicationPoint, force.vector); | AddForce(force.applicationPoint, force.vector); |
} | } |
// Residual torque for given force application point. | // Residual torque for given force application point. |
public Vector3d TorqueAt(Vector3d origin) | public Vector3d TorqueAt(Vector3d origin) |
{ | { |
return totalZeroOriginTorque - Vector3d.Cross(origin, totalForce); | return totalZeroOriginTorque - Vector3d.Cross(origin, totalForce); |
} | } |
// Total force vector. | // Total force vector. |
public Vector3d GetTotalForce() | public Vector3d GetTotalForce() |
{ | { |
return totalForce; | return totalForce; |
} | } |
// Returns the minimum-residual-torque force application point that is closest to origin. | // Returns the minimum-residual-torque force application point that is closest to origin. |
// Note that TorqueAt(GetMinTorquePos()) is always parallel to totalForce. | // Note that TorqueAt(GetMinTorquePos()) is always parallel to totalForce. |
public Vector3d GetMinTorqueForceApplicationPoint(Vector3d origin) | public Vector3d GetMinTorqueForceApplicationPoint(Vector3d origin) |
{ | { |
double fmag = totalForce.sqrMagnitude; | double fmag = totalForce.sqrMagnitude; |
if (fmag <= 0) { | if (fmag <= 0) { |
return origin; | return origin; |
} | } |
return origin + Vector3d.Cross(totalForce, TorqueAt(origin)) / fmag; | return origin + Vector3d.Cross(totalForce, TorqueAt(origin)) / fmag; |
} | } |
public Vector3d GetMinTorqueForceApplicationPoint() | public Vector3d GetMinTorqueForceApplicationPoint() |
{ | { |
return GetMinTorqueForceApplicationPoint(avgApplicationPoint.Get()); | return GetMinTorqueForceApplicationPoint(avgApplicationPoint.Get()); |
} | } |
public void Reset() | |
{ | |
totalForce = Vector3d.zero; | |
totalZeroOriginTorque = Vector3d.zero; | |
avgApplicationPoint.Reset(); | |
} | |
} | } |
} | } |
using System.Collections.Generic; | |
namespace KerbalEngineer | |
{ | |
/// <summary> | |
/// Pool of object | |
/// </summary> | |
public class Pool<T> { | |
private readonly Stack<T> values = new Stack<T>(); | |
private readonly CreateDelegate<T> create; | |
private readonly ResetDelegate<T> reset; | |
public delegate R CreateDelegate<out R>(); | |
public delegate void ResetDelegate<in T1>(T1 a); | |
/// <summary> | |
/// Creates an empty pool with the specified object creation and reset delegates. | |
/// </summary> | |
public Pool(CreateDelegate<T> create, ResetDelegate<T> reset) { | |
this.create = create; | |
this.reset = reset; | |
} | |
/// <summary> | |
/// Borrows an object from the pool. | |
/// </summary> | |
public T Borrow() { | |
lock (values) { | |
return values.Count > 0 ? values.Pop() : create(); | |
} | |
} | |
/// <summary> | |
/// Release an object, reset it and returns it to the pool. | |
/// </summary> | |
public void Release(T value) { | |
reset(value); | |
lock (values) { | |
values.Push(value); | |
} | |
} | |
/// <summary> | |
/// Current size of the pool. | |
/// </summary> | |
public int Count() | |
{ | |
return values.Count; | |
} | |
} | |
} |
// | // |
// 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 const double GRAVITY = 9.80665; | |
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 ConcatF(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 ConcatF(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) | public static string ConcatN(double value1, double value2, int decimals = 1) |
{ | { |
return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals); | return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals); |
} | } |
public static string ConcatN(double value1, double value2, double value3, int decimals = 1) | 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); | return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + " / " + value3.ToString("N" + decimals); |
} | } |
public static string Cost(double value, int decimals = 1) | public static string Cost(double value, int decimals = 1) |
{ | { |
if (value >= 1000000.0) | if (value >= 1000000.0) |
{ | { |
return (value / 1000.0).ToString("N" + decimals) + "K"; | return (value / 1000.0).ToString("N" + decimals) + "K"; |
} | } |
return value.ToString("N" + decimals); | return value.ToString("N" + decimals); |
} | } |
public static string Cost(double value1, double value2, int decimals = 1) | public static string Cost(double value1, double value2, int decimals = 1) |
{ | { |
if (value1 >= 1000000.0 || value2 >= 1000000.0) | if (value1 >= 1000000.0 || value2 >= 1000000.0) |
{ | { |
return (value1 / 1000.0).ToString("N" + decimals) + " / " + (value2 / 1000.0).ToString("N" + decimals) + "K"; | return (value1 / 1000.0).ToString("N" + decimals) + " / " + (value2 / 1000.0).ToString("N" + decimals) + "K"; |
} | } |
return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals); | 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"; | string 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"; | string 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) | if (value >= 1000.0) |
{ | { |
return value.ToString("N" + decimals + 2) + "t"; | 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) | if (value1 >= 1000.0f || value2 >= 1000.0f) |
{ | { |
return value1.ToString("N" + decimals + 2) + " / " + value2.ToString("N" + decimals + 2) + "t"; | 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\Presets\Preset.cs" /> | <Compile Include="Flight\Presets\Preset.cs" /> |
<Compile Include="Flight\Readouts\Miscellaneous\SystemTime.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\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="Helpers\Pool.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>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\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>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\UnityEngine.dll</HintPath> |
<Private>False</Private> | <Private>False</Private> |
</Reference> | </Reference> |
</ItemGroup> | </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.Text; | |
#endregion | #endregion |
namespace KerbalEngineer.VesselSimulator | namespace KerbalEngineer.VesselSimulator |
{ | { |
using System; | |
using System.Text; | |
internal class AttachNodeSim | internal class AttachNodeSim |
{ | { |
private static readonly Pool<AttachNodeSim> pool = new Pool<AttachNodeSim>(Create, Reset); | |
public PartSim attachedPartSim; | public PartSim attachedPartSim; |
public String id; | public String id; |
public AttachNode.NodeType nodeType; | public AttachNode.NodeType nodeType; |
public AttachNodeSim(PartSim partSim, String newId, AttachNode.NodeType newNodeType) | private static AttachNodeSim Create() |
{ | { |
this.attachedPartSim = partSim; | return new AttachNodeSim(); |
this.nodeType = newNodeType; | } |
this.id = newId; | |
public static AttachNodeSim New(PartSim partSim, String newId, AttachNode.NodeType newNodeType) | |
{ | |
AttachNodeSim nodeSim = pool.Borrow(); | |
nodeSim.attachedPartSim = partSim; | |
nodeSim.nodeType = newNodeType; | |
nodeSim.id = newId; | |
return nodeSim; | |
} | |
static private void Reset(AttachNodeSim attachNodeSim) { } | |
public void Release() | |
{ | |
pool.Release(this); | |
} | } |
public void DumpToBuffer(StringBuilder buffer) | public void DumpToBuffer(StringBuilder buffer) |
{ | { |
if (this.attachedPartSim == null) | if (attachedPartSim == null) |
{ | { |
buffer.Append("<staged>:<n>"); | buffer.Append("<staged>:<n>"); |
} | } |
else | else |
{ | { |
buffer.Append(this.attachedPartSim.name); | buffer.Append(attachedPartSim.name); |
buffer.Append(":"); | buffer.Append(":"); |
buffer.Append(this.attachedPartSim.partId); | buffer.Append(attachedPartSim.partId); |
} | } |
buffer.Append("#"); | buffer.Append("#"); |
buffer.Append(this.nodeType); | buffer.Append(nodeType); |
buffer.Append(":"); | buffer.Append(":"); |
buffer.Append(this.id); | buffer.Append(id); |
} | } |
} | } |
} | } |
// | // |
// 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 | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using UnityEngine; | |
#endregion | |
namespace KerbalEngineer.VesselSimulator | namespace KerbalEngineer.VesselSimulator |
{ | { |
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
using Editor; | |
using Helpers; | |
using UnityEngine; | |
public class EngineSim | public class EngineSim |
{ | { |
private static readonly Pool<EngineSim> pool = new Pool<EngineSim>(Create, Reset); | |
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 = new List<AppliedForce>(); |
public float maxMach; | |
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, | private static EngineSim Create() |
{ | |
return new EngineSim(); | |
} | |
private static void Reset(EngineSim engineSim) | |
{ | |
engineSim.resourceConsumptions.Reset(); | |
engineSim.actualThrust = 0; | |
engineSim.isActive = false; | |
engineSim.isp = 0; | |
for (int i = 0; i < engineSim.appliedForces.Count; i++) | |
{ | |
engineSim.appliedForces[i].Release(); | |
} | |
engineSim.appliedForces.Clear(); | |
engineSim.thrust = 0; | |
engineSim.maxMach = 0f; | |
} | |
public void Release() | |
{ | |
pool.Release(this); | |
} | |
public static EngineSim New(PartSim theEngine, | |
double atmosphere, | double atmosphere, |
double velocity, | float machNumber, |
float maxThrust, | float maxFuelFlow, |
float minThrust, | float minFuelFlow, |
float thrustPercentage, | float thrustPercentage, |
float requestedThrust, | |
Vector3 vecThrust, | Vector3 vecThrust, |
float realIsp, | |
FloatCurve atmosphereCurve, | FloatCurve atmosphereCurve, |
FloatCurve velocityCurve, | bool atmChangeFlow, |
FloatCurve atmCurve, | |
FloatCurve velCurve, | |
float currentThrottle, | |
float IspG, | |
bool throttleLocked, | bool throttleLocked, |
List<Propellant> propellants, | List<Propellant> propellants, |
bool active, | bool active, |
bool correctThrust, | float resultingThrust, |
List<Transform> thrustTransforms) | List<Transform> thrustTransforms) |
{ | { |
EngineSim engineSim = pool.Borrow(); | |
StringBuilder buffer = null; | StringBuilder buffer = null; |
//MonoBehaviour.print("Create EngineSim for " + theEngine.name); | |
//MonoBehaviour.print("maxThrust = " + maxThrust); | engineSim.isp = 0.0; |
//MonoBehaviour.print("minThrust = " + minThrust); | engineSim.maxMach = 0.0f; |
//MonoBehaviour.print("thrustPercentage = " + thrustPercentage); | engineSim.actualThrust = 0.0; |
//MonoBehaviour.print("requestedThrust = " + requestedThrust); | engineSim.partSim = theEngine; |
//MonoBehaviour.print("velocity = " + velocity); | engineSim.isActive = active; |
engineSim.thrustVec = vecThrust; | |
this.partSim = theEngine; | engineSim.resourceConsumptions.Reset(); |
engineSim.appliedForces.Clear(); | |
this.isActive = active; | |
this.thrust = (maxThrust - minThrust) * (thrustPercentage / 100f) + minThrust; | double flowRate = 0.0; |
//MonoBehaviour.print("thrust = " + thrust); | if (engineSim.partSim.hasVessel) |
{ | |
this.thrustVec = vecThrust; | float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, ref engineSim.maxMach); |
engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); | |
double flowRate = 0d; | engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); |
if (this.partSim.hasVessel) | engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0; |
{ | |
//MonoBehaviour.print("hasVessel is true"); | if (throttleLocked) |
this.actualThrust = isActive ? requestedThrust : 0.0; | { |
if (velocityCurve != null) | flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); |
{ | } |
this.actualThrust *= velocityCurve.Evaluate((float)velocity); | else |
//MonoBehaviour.print("actualThrust at velocity = " + actualThrust); | { |
} | if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false) |
this.isp = atmosphereCurve.Evaluate((float)this.partSim.part.staticPressureAtm); | |
if (this.isp == 0d) | |
{ | |
MonoBehaviour.print("Isp at " + this.partSim.part.staticPressureAtm + " is zero. Flow rate will be NaN"); | |
} | |
if (correctThrust && realIsp == 0) | |
{ | |
float ispsl = atmosphereCurve.Evaluate(0); | |
if (ispsl != 0) | |
{ | { |
this.thrust = this.thrust * this.isp / ispsl; | flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp); |
} | } |
else | else |
{ | { |
MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust."); | flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); |
} | } |
//MonoBehaviour.print("corrected thrust = " + thrust); | |
} | |
if (velocityCurve != null) | |
{ | |
this.thrust *= velocityCurve.Evaluate((float)velocity); | |
//MonoBehaviour.print("thrust at velocity = " + thrust); | |
} | |
if (throttleLocked) | |
{ | |
//MonoBehaviour.print("throttleLocked is true"); | |
flowRate = this.thrust / (this.isp * 9.82); | |
} | |
else | |
{ | |
if (this.partSim.isLanded) | |
{ | |
//MonoBehaviour.print("partSim.isLanded is true, mainThrottle = " + FlightInputHandler.state.mainThrottle); | |
flowRate = Math.Max(0.000001d, this.thrust * FlightInputHandler.state.mainThrottle) / (this.isp * 9.82); | |
} | |
else | |
{ | |
if (requestedThrust > 0) | |
{ | |
if (velocityCurve != null) | |
{ | |
requestedThrust *= velocityCurve.Evaluate((float)velocity); | |
//MonoBehaviour.print("requestedThrust at velocity = " + requestedThrust); | |
} | |
//MonoBehaviour.print("requestedThrust > 0"); | |
flowRate = requestedThrust / (this.isp * 9.82); | |
} | |
else | |
{ | |
//MonoBehaviour.print("requestedThrust <= 0"); | |
flowRate = this.thrust / (this.isp * 9.82); | |
} | |
} | |
} | } |
} | } |
else | else |
{ | { |
//MonoBehaviour.print("hasVessel is false"); | float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, CelestialBodies.SelectedBody.GetDensity(BuildAdvanced.Altitude), velCurve, machNumber, ref engineSim.maxMach); |
this.isp = atmosphereCurve.Evaluate((float)atmosphere); | engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); |
if (this.isp == 0d) | engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); |
{ | flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); |
MonoBehaviour.print("Isp at " + atmosphere + " is zero. Flow rate will be NaN"); | |
} | |
if (correctThrust) | |
{ | |
float ispsl = atmosphereCurve.Evaluate(0); | |
if (ispsl != 0) | |
{ | |
this.thrust = this.thrust * this.isp / ispsl; | |
} | |
else | |
{ | |
MonoBehaviour.print("Isp at sea level is zero. Unable to correct thrust."); | |
} | |
//MonoBehaviour.print("corrected thrust = " + thrust); | |
} | |
if (velocityCurve != null) | |
{ | |
this.thrust *= velocityCurve.Evaluate((float)velocity); | |
//MonoBehaviour.print("thrust at velocity = " + thrust); | |
} | |
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); |
} | } |
engineSim.thrust = flowRate * (engineSim.isp * IspG); | |
// I did not look into the diff between those 2 so I made them equal... | |
engineSim.actualThrust = engineSim.thrust; | |
float flowMass = 0f; | float flowMass = 0f; |
foreach (Propellant propellant in propellants) | for (int i = 0; i < propellants.Count; ++i) |
{ | { |
Propellant propellant = propellants[i]; | |
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) | for (int i = 0; i < propellants.Count; ++i) |
{ | { |
Propellant propellant = propellants[i]; | |
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", |
this.resourceConsumptions.Add(propellant.id, consumptionRate); | ResourceContainer.GetResourceName(propellant.id), |
theEngine.name, | |
theEngine.partId, | |
consumptionRate); | |
} | |
engineSim.resourceConsumptions.Add(propellant.id, consumptionRate); | |
} | } |
if (SimManager.logOutput) | if (SimManager.logOutput) |
{ | { |
MonoBehaviour.print(buffer); | MonoBehaviour.print(buffer); |
} | } |
appliedForces = new List<AppliedForce>(); | double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count; |
double thrustPerThrustTransform = thrust / thrustTransforms.Count; | for (int i = 0; i < thrustTransforms.Count; i++) |
foreach (Transform thrustTransform in thrustTransforms) { | { |
Transform thrustTransform = thrustTransforms[i]; | |
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)); | |
} | AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position); |
engineSim.appliedForces.Add(appliedForce); | |
} | |
return engineSim; | |
} | } |
public ResourceContainer ResourceConsumptions | public ResourceContainer ResourceConsumptions |
{ | { |
get { return this.resourceConsumptions; } | get |
} | { |
return resourceConsumptions; | |
} | |
} | |
public static double GetExhaustVelocity(double isp) | |
{ | |
return isp * Units.GRAVITY; | |
} | |
public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, ref float maxMach) | |
{ | |
float flowModifier = 1.0f; | |
if (atmChangeFlow) | |
{ | |
flowModifier = (float)(atmDensity / 1.225); | |
if (atmCurve != null) | |
{ | |
flowModifier = atmCurve.Evaluate(flowModifier); | |
} | |
} | |
if (velCurve != null) | |
{ | |
flowModifier = flowModifier * velCurve.Evaluate(machNumber); | |
maxMach = velCurve.maxTime; | |
} | |
if (flowModifier < float.Epsilon) | |
{ | |
flowModifier = float.Epsilon; | |
} | |
return flowModifier; | |
} | |
public static double GetFlowRate(double thrust, double isp) | |
{ | |
return thrust / GetExhaustVelocity(isp); | |
} | |
public static float GetThrottlePercent(float currentThrottle, float thrustPercentage) | |
{ | |
return currentThrottle * GetThrustPercent(thrustPercentage); | |
} | |
public static double GetThrust(double flowRate, double isp) | |
{ | |
return flowRate * GetExhaustVelocity(isp); | |
} | |
public static float GetThrustPercent(float thrustPercentage) | |
{ | |
return thrustPercentage * 0.01f; | |
} | |
public void DumpEngineToBuffer(StringBuilder buffer, String prefix) | |
{ | |
buffer.Append(prefix); | |
buffer.AppendFormat("[thrust = {0:g6}, actual = {1:g6}, isp = {2:g6}\n", thrust, actualThrust, isp); | |
} | |
// 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>> stagePartSets = new Dictionary<int, HashSet<PartSim>>(); | |
HashSet<PartSim> visited = new HashSet<PartSim>(); | |
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 | foreach (HashSet<PartSim> sourcePartSet in sourcePartSets.Values) |
Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>(); | { |
sourcePartSet.Clear(); | |
foreach (int type in this.resourceConsumptions.Types) | } |
{ | |
HashSet<PartSim> sourcePartSet = null; | for (int index = 0; index < this.resourceConsumptions.Types.Count; index++) |
{ | |
int type = this.resourceConsumptions.Types[index]; | |
HashSet<PartSim> sourcePartSet; | |
if (!sourcePartSets.TryGetValue(type, out sourcePartSet)) | |
{ | |
sourcePartSet = new HashSet<PartSim>(); | |
sourcePartSets.Add(type, sourcePartSet); | |
} | |
switch (ResourceContainer.GetResourceFlowMode(type)) | switch (ResourceContainer.GetResourceFlowMode(type)) |
{ | { |
case ResourceFlowMode.NO_FLOW: | case ResourceFlowMode.NO_FLOW: |
if (this.partSim.resources[type] > SimManager.RESOURCE_MIN && this.partSim.resourceFlowStates[type] != 0) | if (partSim.resources[type] > SimManager.RESOURCE_MIN && partSim.resourceFlowStates[type] != 0) |
{ | { |
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(partSim); |
} | } |
break; | break; |
case ResourceFlowMode.ALL_VESSEL: | case ResourceFlowMode.ALL_VESSEL: |
foreach (PartSim aPartSim in allParts) | for (int i = 0; i < allParts.Count; i++) |
{ | { |
PartSim aPartSim = allParts[i]; | |
if (aPartSim.resources[type] > SimManager.RESOURCE_MIN && aPartSim.resourceFlowStates[type] != 0) | if (aPartSim.resources[type] > SimManager.RESOURCE_MIN && aPartSim.resourceFlowStates[type] != 0) |
{ | { |
if (sourcePartSet == null) | |
{ | |
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>>(); | |
foreach (HashSet<PartSim> stagePartSet in stagePartSets.Values) | |
{ | |
stagePartSet.Clear(); | |
} | |
var maxStage = -1; | var maxStage = -1; |
//Logger.Log(type); | //Logger.Log(type); |
foreach (var aPartSim in allParts) | for (int i = 0; i < allParts.Count; i++) |
{ | { |
if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0) continue; | var aPartSim = allParts[i]; |
if (aPartSim.resources[type] <= SimManager.RESOURCE_MIN || aPartSim.resourceFlowStates[type] == 0) | |
var stage = aPartSim.DecouplerCount(); | { |
continue; | |
} | |
int 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 (int j = 0; j <= maxStage; j++) |
{ | { |
HashSet<PartSim> stagePartSet; | HashSet<PartSim> stagePartSet; |
if (stagePartSets.TryGetValue(i, out stagePartSet) && stagePartSet.Count > 0) | if (stagePartSets.TryGetValue(j, 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>(); | visited.Clear(); |
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 " + partSim.name + ":" + partSim.partId); |
} | } |
sourcePartSet = this.partSim.GetSourceSet(type, allParts, visited, log, ""); | partSim.GetSourceSet(type, allParts, visited, sourcePartSet, 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(" + partSim.name + ":" + partSim.partId + ") Unexpected flow type for " + ResourceContainer.GetResourceName(type) + ")"); |
break; | break; |
} | } |
if (sourcePartSet != null && sourcePartSet.Count > 0) | |
if (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) | for (int i = 0; i < this.resourceConsumptions.Types.Count; i++) |
{ | { |
if (!sourcePartSets.ContainsKey(type)) | int type = this.resourceConsumptions.Types[i]; |
HashSet<PartSim> sourcePartSet; | |
if (!sourcePartSets.TryGetValue(type, out sourcePartSet) || sourcePartSet.Count == 0) | |
{ | { |
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; | 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) | for (int i = 0; i < this.resourceConsumptions.Types.Count; i++) |
{ | { |
int type = this.resourceConsumptions.Types[i]; | |
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 = 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) | |
{ | |
buffer.Append(prefix); | |
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/>. |
// | // |
#region Using Directives | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using KerbalEngineer.Extensions; | |
using UnityEngine; | |
#endregion | |
namespace KerbalEngineer.VesselSimulator | namespace KerbalEngineer.VesselSimulator |
{ | { |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using CompoundParts; | using CompoundParts; |
using Extensions; | |
using UnityEngine; | |
public class PartSim | public class PartSim |
{ | { |
private static readonly Pool<PartSim> pool = new Pool<PartSim>(Create, Reset); | |
private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>(); | private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>(); |
public double baseMass; | |
public Vector3d centerOfMass; | public Vector3d centerOfMass; |
public double baseMass = 0d; | |
public double cost; | public double cost; |
public int decoupledInStage; | public int decoupledInStage; |
public bool fuelCrossFeed; | public bool fuelCrossFeed; |
public List<PartSim> fuelTargets = new List<PartSim>(); | public List<PartSim> fuelTargets = new List<PartSim>(); |
public bool hasModuleEngines; | public bool hasModuleEngines; |
public bool hasModuleEnginesFX; | public bool hasModuleEnginesFX; |
public bool hasMultiModeEngine; | public bool hasMultiModeEngine; |
public bool hasVessel; | public bool hasVessel; |
public String initialVesselName; | public String initialVesselName; |
public int inverseStage; | public int inverseStage; |
public bool isDecoupler; | public bool isDecoupler; |
public bool isEngine; | public bool isEngine; |
public bool isFuelLine; | public bool isFuelLine; |
public bool isFuelTank; | public bool isFuelTank; |
public bool isLanded; | public bool isLanded; |
public bool isNoPhysics; | public bool isNoPhysics; |
public bool isSepratron; | public bool isSepratron; |
public bool isFairing; | |
public bool localCorrectThrust; | public bool localCorrectThrust; |
public float moduleMass; | |
public int stageIndex; | |
public String name; | public String name; |
public String noCrossFeedNodeKey; | public String noCrossFeedNodeKey; |
public PartSim parent; | public PartSim parent; |
public AttachModes parentAttach; | public AttachModes parentAttach; |
public Part part; // This is only set while the data structures are being initialised | public Part part; // This is only set while the data structures are being initialised |
public int partId = 0; | public int partId = 0; |
public ResourceContainer resourceDrains = new ResourceContainer(); | public ResourceContainer resourceDrains = new ResourceContainer(); |
public ResourceContainer resourceFlowStates = new ResourceContainer(); | public ResourceContainer resourceFlowStates = new ResourceContainer(); |
public ResourceContainer resources = new ResourceContainer(); | public ResourceContainer resources = new ResourceContainer(); |
public double startMass = 0d; | public double startMass = 0d; |
public String vesselName; | public String vesselName; |
public VesselType vesselType; | public VesselType vesselType; |
public PartSim(Part thePart, int id, double atmosphere, LogMsg log) | |
{ | private static PartSim Create() |
this.part = thePart; | { |
this.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset); | return new PartSim(); |
this.partId = id; | } |
this.name = this.part.partInfo.name; | |
private static void Reset(PartSim partSim) | |
{ | |
for (int i = 0; i < partSim.attachNodes.Count; i++) | |
{ | |
partSim.attachNodes[i].Release(); | |
} | |
partSim.attachNodes.Clear(); | |
partSim.fuelTargets.Clear(); | |
partSim.resourceDrains.Reset(); | |
partSim.resourceFlowStates.Reset(); | |
partSim.resources.Reset(); | |
partSim.baseMass = 0d; | |
partSim.startMass = 0d; | |
} | |
public void Release() | |
{ | |
pool.Release(this); | |
} | |
public static PartSim New(Part thePart, int id, double atmosphere, LogMsg log) | |
{ | |
PartSim partSim = pool.Borrow(); | |
partSim.part = thePart; | |
partSim.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset); | |
partSim.partId = id; | |
partSim.name = partSim.part.partInfo.name; | |
if (log != null) | if (log != null) |
{ | { |
log.buf.AppendLine("Create PartSim for " + this.name); | log.buf.AppendLine("Create PartSim for " + partSim.name); |
} | } |
this.parent = null; | partSim.parent = null; |
this.parentAttach = part.attachMode; | partSim.parentAttach = partSim.part.attachMode; |
this.fuelCrossFeed = this.part.fuelCrossFeed; | partSim.fuelCrossFeed = partSim.part.fuelCrossFeed; |
this.noCrossFeedNodeKey = this.part.NoCrossFeedNodeKey; | partSim.noCrossFeedNodeKey = partSim.part.NoCrossFeedNodeKey; |
this.decoupledInStage = this.DecoupledInStage(this.part); | partSim.decoupledInStage = partSim.DecoupledInStage(partSim.part); |
this.isFuelLine = this.part.HasModule<CModuleFuelLine>(); | partSim.isFuelLine = partSim.part.HasModule<CModuleFuelLine>(); |
this.isFuelTank = this.part is FuelTank; | partSim.isFuelTank = partSim.part is FuelTank; |
this.isSepratron = this.IsSepratron(); | partSim.isSepratron = partSim.IsSepratron(); |
this.inverseStage = this.part.inverseStage; | partSim.inverseStage = partSim.part.inverseStage; |
//MonoBehaviour.print("inverseStage = " + inverseStage); | //MonoBehaviour.print("inverseStage = " + inverseStage); |
this.cost = this.part.GetCostWet(); | partSim.cost = partSim.part.GetCostWet(); |
// Work out if the part should have no physical significance | // Work out if the part should have no physical significance |
this.isNoPhysics = this.part.HasModule<LaunchClamp>() || | partSim.isNoPhysics = partSim.part.HasModule<LaunchClamp>() || |
this.part.physicalSignificance == Part.PhysicalSignificance.NONE || | partSim.part.physicalSignificance == Part.PhysicalSignificance.NONE || |
this.part.PhysicsSignificance == 1; | partSim.part.PhysicsSignificance == 1; |
if (!this.isNoPhysics) | if (!partSim.isNoPhysics) |
{ | { |
this.baseMass = this.part.mass; | partSim.baseMass = partSim.part.mass; |
} | } |
if (SimManager.logOutput) | if (SimManager.logOutput) |
{ | { |
MonoBehaviour.print((this.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + this.part.mass); | MonoBehaviour.print((partSim.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + partSim.part.mass); |
} | } |
foreach (PartResource resource in this.part.Resources) | for (int i = 0; i < partSim.part.Resources.Count; i++) |
{ | { |
PartResource resource = partSim.part.Resources[i]; | |
// Make sure it isn't NaN as this messes up the part mass and hence most of the values | // Make sure it isn't NaN as this messes up the part mass and hence most of the values |
// This can happen if a resource capacity is 0 and tweakable | // This can happen if a resource capacity is 0 and tweakable |
if (!Double.IsNaN(resource.amount)) | if (!Double.IsNaN(resource.amount)) |
{ | { |
if (SimManager.logOutput) | if (SimManager.logOutput) |
{ | { |
MonoBehaviour.print(resource.resourceName + " = " + resource.amount); | MonoBehaviour.print(resource.resourceName + " = " + resource.amount); |
} | } |
this.resources.Add(resource.info.id, resource.amount); | partSim.resources.Add(resource.info.id, resource.amount); |
this.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0); | partSim.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0); |
} | } |
else | else |
{ | { |
MonoBehaviour.print(resource.resourceName + " is NaN. Skipping."); | MonoBehaviour.print(resource.resourceName + " is NaN. Skipping."); |
} | } |
} | } |
this.startMass = this.GetMass(); | partSim.startMass = partSim.GetMass(-1); |
this.hasVessel = (this.part.vessel != null); | partSim.hasVessel = (partSim.part.vessel != null); |
this.isLanded = this.hasVessel && this.part.vessel.Landed; | partSim.isLanded = partSim.hasVessel && partSim.part.vessel.Landed; |
if (this.hasVessel) | if (partSim.hasVessel) |
{ | { |
this.vesselName = this.part.vessel.vesselName; | partSim.vesselName = partSim.part.vessel.vesselName; |
this.vesselType = this.part.vesselType; | partSim.vesselType = partSim.part.vesselType; |
} | } |
this.initialVesselName = this.part.initialVesselName; | partSim.initialVesselName = partSim.part.initialVesselName; |
this.hasMultiModeEngine = this.part.HasModule<MultiModeEngine>(); | partSim.hasMultiModeEngine = partSim.part.HasModule<MultiModeEngine>(); |
this.hasModuleEnginesFX = this.part.HasModule<ModuleEnginesFX>(); | partSim.hasModuleEnginesFX = partSim.part.HasModule<ModuleEnginesFX>(); |
this.hasModuleEngines = this.part.HasModule<ModuleEngines>(); | partSim.hasModuleEngines = partSim.part.HasModule<ModuleEngines>(); |
this.isEngine = this.hasMultiModeEngine || this.hasModuleEnginesFX || this.hasModuleEngines; | partSim.isEngine = partSim.hasMultiModeEngine || partSim.hasModuleEnginesFX || partSim.hasModuleEngines; |
if (SimManager.logOutput) | if (SimManager.logOutput) |
{ | { |
MonoBehaviour.print("Created " + this.name + ". Decoupled in stage " + this.decoupledInStage); | MonoBehaviour.print("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage); |
} | |
return partSim; | |
} | |
public ResourceContainer ResourceDrains | |
{ | |
get | |
{ | |
return resourceDrains; | |
} | } |
} | } |
public ResourceContainer Resources | public ResourceContainer Resources |
{ | { |
get { return this.resources; } | get |
} | { |
return resources; | |
public ResourceContainer ResourceDrains | } |
{ | } |
get { return this.resourceDrains; } | |
} | public void CreateEngineSims(List<EngineSim> allEngines, double atmosphere, double mach, bool vectoredThrust, bool fullThrust, LogMsg log) |
{ | |
public void CreateEngineSims(List<EngineSim> allEngines, double atmosphere, double velocity, bool vectoredThrust, LogMsg log) | bool correctThrust = SimManager.DoesEngineUseCorrectedThrust(part); |
{ | |
bool correctThrust = SimManager.DoesEngineUseCorrectedThrust(this.part); | |
if (log != null) | if (log != null) |
{ | { |
log.buf.AppendLine("CreateEngineSims for " + this.name); | log.buf.AppendLine("CreateEngineSims for " + this.name); |
for (int i = 0; i < this.part.Modules.Count; i++) | |
foreach (PartModule partMod in this.part.Modules) | { |
{ | PartModule partMod = this.part.Modules[i]; |
log.buf.AppendLine("Module: " + partMod.moduleName); | log.buf.AppendLine("Module: " + partMod.moduleName); |
} | } |
log.buf.AppendLine("correctThrust = " + correctThrust); | log.buf.AppendLine("correctThrust = " + correctThrust); |
} | } |
if (this.hasMultiModeEngine) | if (hasMultiModeEngine) |
{ | { |
// A multi-mode engine has multiple ModuleEnginesFX but only one is active at any point | // A multi-mode engine has multiple ModuleEnginesFX but only one is active at any point |
// The mode of the engine is the engineID of the ModuleEnginesFX that is active | // The mode of the engine is the engineID of the ModuleEnginesFX that is active |
string mode = this.part.GetModule<MultiModeEngine>().mode; | string mode = part.GetModule<MultiModeEngine>().mode; |
foreach (ModuleEnginesFX engine in this.part.GetModules<ModuleEnginesFX>()) | List<ModuleEnginesFX> engines = part.GetModules<ModuleEnginesFX>(); |
{ | for (int i = 0; i < engines.Count; ++i) |
{ | |
ModuleEnginesFX engine = engines[i]; | |
if (engine.engineID == mode) | if (engine.engineID == mode) |
{ | { |
if (log != null) | if (log != null) |
{ | { |
log.buf.AppendLine("Module: " + engine.moduleName); | log.buf.AppendLine("Module: " + engine.moduleName); |
} | } |
Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log); | Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log); |
EngineSim engineSim = new EngineSim(this, | EngineSim engineSim = EngineSim.New( |
atmosphere, | this, |
velocity, | atmosphere, |
engine.maxThrust, | (float)mach, |
engine.minThrust, | engine.maxFuelFlow, |
engine.thrustPercentage, | engine.minFuelFlow, |
engine.requestedThrust, | engine.thrustPercentage, |
thrustvec, | thrustvec, |
engine.realIsp, | engine.atmosphereCurve, |
engine.atmosphereCurve, | engine.atmChangeFlow, |
engine.useVelocityCurve ? engine.velocityCurve : null, | engine.useAtmCurve ? engine.atmCurve : null, |
engine.throttleLocked, | engine.useVelCurve ? engine.velCurve : null, |
engine.propellants, | engine.currentThrottle, |
engine.isOperational, | engine.g, |
correctThrust, | engine.throttleLocked || fullThrust, |
engine.thrustTransforms); | engine.propellants, |
engine.isOperational, | |
engine.resultingThrust, | |
engine.thrustTransforms); | |
allEngines.Add(engineSim); | allEngines.Add(engineSim); |
} | } |
} | } |
} | } |
else | else |
{ | { |
if (this.hasModuleEnginesFX) | if (hasModuleEngines) |
{ | { |
foreach (ModuleEnginesFX engine in this.part.GetModules<ModuleEnginesFX>()) | List<ModuleEngines> engines = part.GetModules<ModuleEngines>(); |
{ | for (int i = 0; i < engines.Count; ++i) |
{ | |
ModuleEngines engine = engines[i]; | |
if (log != null) | if (log != null) |
{ | { |
log.buf.AppendLine("Module: " + engine.moduleName); | log.buf.AppendLine("Module: " + engine.moduleName); |
} | } |
Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log); | Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log); |
EngineSim engineSim = new EngineSim(this, | EngineSim engineSim = EngineSim.New( |
atmosphere, | this, |
velocity, | atmosphere, |
engine.maxThrust, | (float)mach, |
engine.minThrust, | engine.maxFuelFlow, |
engine.thrustPercentage, | engine.minFuelFlow, |
engine.requestedThrust, | engine.thrustPercentage, |
thrustvec, | thrustvec, |
engine.realIsp, | engine.atmosphereCurve, |
engine.atmosphereCurve, | engine.atmChangeFlow, |
engine.useVelocityCurve ? engine.velocityCurve : null, | engine.useAtmCurve ? engine.atmCurve : null, |
engine.throttleLocked, | engine.useVelCurve ? engine.velCurve : null, |
engine.propellants, | engine.currentThrottle, |
engine.isOperational, | engine.g, |
correctThrust, | engine.throttleLocked || fullThrust, |
engine.thrustTransforms); | engine.propellants, |
engine.isOperational, | |
engine.resultingThrust, | |
engine.thrustTransforms); | |
allEngines.Add(engineSim); | allEngines.Add(engineSim); |
} | } |
} | } |
if (this.hasModuleEngines) | |
{ | |
foreach (ModuleEngines engine in this.part.GetModules<ModuleEngines>()) | |
{ | |
if (log != null) | |
{ | |
log.buf.AppendLine("Module: " + engine.moduleName); | |
} | |
Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log); | |
EngineSim engineSim = new EngineSim(this, | |
atmosphere, | |
velocity, | |
engine.maxThrust, | |
engine.minThrust, | |
engine.thrustPercentage, | |
engine.requestedThrust, | |
thrustvec, | |
engine.realIsp, | |
engine.atmosphereCurve, | |
engine.useVelocityCurve ? engine.velocityCurve : null, | |
engine.throttleLocked, | |
engine.propellants, | |
engine.isOperational, | |
correctThrust, | |
engine.thrustTransforms); | |
allEngines.Add(engineSim); | |
} | |
} | |
} | } |
if (log != null) | if (log != null) |
{ | { |
log.Flush(); | log.Flush(); |
} | } |
} | } |
private Vector3 CalculateThrustVector(List<Transform> thrustTransforms, LogMsg log) | public int DecouplerCount() |
{ | { |
if (thrustTransforms == null) | int count = 0; |
{ | PartSim partSim = this; |
return Vector3.forward; | while (partSim != null) |
} | { |
if (partSim.isDecoupler) | |
Vector3 thrustvec = Vector3.zero; | { |
foreach (Transform trans in thrustTransforms) | count++; |
{ | } |
if (log != null) | |
{ | partSim = partSim.parent; |
log.buf.AppendFormat("Transform = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", trans.forward.x, trans.forward.y, trans.forward.z, trans.forward.magnitude); | } |
} | return count; |
} | |
thrustvec -= trans.forward; | |
} | public void DrainResources(double time) |
{ | |
if (log != null) | //MonoBehaviour.print("DrainResources(" + name + ":" + partId + ", " + time + ")"); |
{ | for (int i = 0; i < resourceDrains.Types.Count; ++i) |
log.buf.AppendFormat("ThrustVec = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude); | { |
} | int type = resourceDrains.Types[i]; |
thrustvec.Normalize(); | //MonoBehaviour.print("draining " + (time * resourceDrains[type]) + " " + ResourceContainer.GetResourceName(type)); |
resources.Add(type, -time * resourceDrains[type]); | |
if (log != null) | //MonoBehaviour.print(ResourceContainer.GetResourceName(type) + " left = " + resources[type]); |
{ | } |
log.buf.AppendFormat("ThrustVecN = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude); | } |
} | |
public String DumpPartAndParentsToBuffer(StringBuilder buffer, String prefix) | |
return thrustvec; | { |
} | if (parent != null) |
{ | |
public void SetupParent(Dictionary<Part, PartSim> partSimLookup, LogMsg log) | prefix = parent.DumpPartAndParentsToBuffer(buffer, prefix) + " "; |
{ | } |
if (this.part.parent != null) | |
{ | DumpPartToBuffer(buffer, prefix); |
this.parent = null; | |
if (partSimLookup.TryGetValue(this.part.parent, out this.parent)) | return prefix; |
{ | } |
if (log != null) | |
{ | public void DumpPartToBuffer(StringBuilder buffer, String prefix, List<PartSim> allParts = null) |
log.buf.AppendLine("Parent part is " + this.parent.name + ":" + this.parent.partId); | { |
} | buffer.Append(prefix); |
} | buffer.Append(name); |
else | buffer.AppendFormat(":[id = {0:d}, decouple = {1:d}, invstage = {2:d}", partId, decoupledInStage, inverseStage); |
{ | |
if (log != null) | buffer.AppendFormat(", vesselName = '{0}'", vesselName); |
{ | buffer.AppendFormat(", vesselType = {0}", SimManager.GetVesselTypeString(vesselType)); |
log.buf.AppendLine("No PartSim for parent part (" + this.part.parent.partInfo.name + ")"); | buffer.AppendFormat(", initialVesselName = '{0}'", initialVesselName); |
} | |
} | buffer.AppendFormat(", fuelCF = {0}", fuelCrossFeed); |
} | buffer.AppendFormat(", noCFNKey = '{0}'", noCrossFeedNodeKey); |
} | |
buffer.AppendFormat(", isSep = {0}", isSepratron); | |
public void SetupAttachNodes(Dictionary<Part, PartSim> partSimLookup, LogMsg log) | |
{ | foreach (int type in resources.Types) |
if (log != null) | { |
{ | buffer.AppendFormat(", {0} = {1:g6}", ResourceContainer.GetResourceName(type), resources[type]); |
log.buf.AppendLine("SetupAttachNodes for " + this.name + ":" + this.partId + ""); | } |
} | |
if (attachNodes.Count > 0) | |
this.attachNodes.Clear(); | { |
foreach (AttachNode attachNode in this.part.attachNodes) | buffer.Append(", attached = <"); |
{ | attachNodes[0].DumpToBuffer(buffer); |
if (log != null) | for (int i = 1; i < attachNodes.Count; i++) |
{ | { |
log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null")); | buffer.Append(", "); |
} | attachNodes[i].DumpToBuffer(buffer); |
} | |
if (attachNode.attachedPart != null && attachNode.id != "Strut") | buffer.Append(">"); |
{ | } |
PartSim attachedSim; | |
if (partSimLookup.TryGetValue(attachNode.attachedPart, out attachedSim)) | // Add more info here |
{ | |
if (log != null) | buffer.Append("]\n"); |
{ | |
log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + ""); | if (allParts != null) |
} | { |
String newPrefix = prefix + " "; | |
this.attachNodes.Add(new AttachNodeSim(attachedSim, attachNode.id, attachNode.nodeType)); | foreach (PartSim partSim in allParts) |
} | { |
else | if (partSim.parent == this) |
{ | { |
if (log != null) | partSim.DumpPartToBuffer(buffer, newPrefix, allParts); |
{ | } |
log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")"); | } |
} | } |
} | } |
} | |
} | public bool EmptyOf(HashSet<int> types) |
{ | |
foreach (Part p in this.part.fuelLookupTargets) | foreach (int type in types) |
{ | { |
if (p != null) | if (resources.HasType(type) && resourceFlowStates[type] != 0 && resources[type] > SimManager.RESOURCE_MIN) |
{ | { |
PartSim targetSim; | return false; |
if (partSimLookup.TryGetValue(p, out targetSim)) | } |
{ | } |
if (log != null) | |
{ | return true; |
log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId); | } |
} | |
public double GetMass(int currentStage) | |
this.fuelTargets.Add(targetSim); | { |
} | double mass = baseMass; |
else | |
{ | for (int i = 0; i < resources.Types.Count; ++i) |
if (log != null) | { |
{ | mass += resources.GetResourceMass(resources.Types[i]); |
log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")"); | } |
} | |
} | if (hasVessel == false && isFairing && inverseStage < currentStage) |
} | { |
} | mass = mass + moduleMass; |
} | } |
private int DecoupledInStage(Part thePart, int stage = -1) | return mass; |
{ | } |
if (this.IsDecoupler(thePart)) | |
{ | |
if (thePart.inverseStage > stage) | |
{ | |
stage = thePart.inverseStage; | |
} | |
} | |
if (thePart.parent != null) | |
{ | |
stage = this.DecoupledInStage(thePart.parent, stage); | |
} | |