Moved ActiveVessel check from UpdateModules to FixedUpdate
Moved ActiveVessel check from UpdateModules to FixedUpdate

file:a/.gitignore -> file:b/.gitignore
# Build Folders (you can keep bin if you'd like, to store dlls and pdbs) # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
[Bb]in/ [Bb]in/
[Oo]bj/ [Oo]bj/
   
# Unity specific # Unity specific
[Ll]ibrary/ [Ll]ibrary/
[Tt]emp/ [Tt]emp/
*.unityproj *.unityproj
   
# mstest test results # mstest test results
TestResults TestResults
   
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
   
# User-specific files # User-specific files
*.suo *.suo
*.user *.user
*.sln.docstates *.sln.docstates
   
# Build results # Build results
[Dd]ebug/ [Dd]ebug/
x64/ x64/
*_i.c *_i.c
*_p.c *_p.c
*.ilk *.ilk
*.meta  
*.obj *.obj
*.pch *.pch
*.pdb *.pdb
*.pgc *.pgc
*.pgd *.pgd
*.rsp *.rsp
*.sbr *.sbr
*.tlb *.tlb
*.tli *.tli
*.tlh *.tlh
*.tmp *.tmp
*.log *.log
*.vspscc *.vspscc
*.vssscc *.vssscc
.builds .builds
   
# Visual C++ cache files # Visual C++ cache files
ipch/ ipch/
*.aps *.aps
*.ncb *.ncb
*.opensdf *.opensdf
*.sdf *.sdf
   
# Visual Studio profiler # Visual Studio profiler
*.psess *.psess
*.vsp *.vsp
*.vspx *.vspx
   
# Guidance Automation Toolkit # Guidance Automation Toolkit
*.gpState *.gpState
   
# ReSharper is a .NET coding add-in # ReSharper is a .NET coding add-in
_ReSharper* _ReSharper*
   
# Mindbench SASS cache # Mindbench SASS cache
.sass-cache/ .sass-cache/
   
# NCrunch # NCrunch
*.ncrunch* *.ncrunch*
.*crunch*.local.xml .*crunch*.local.xml
   
# Installshield output folder # Installshield output folder
[Ee]xpress [Ee]xpress
   
# DocProject is a documentation generator add-in # DocProject is a documentation generator add-in
DocProject/buildhelp/ DocProject/buildhelp/
DocProject/Help/*.HxT DocProject/Help/*.HxT
DocProject/Help/*.HxC DocProject/Help/*.HxC
DocProject/Help/*.hhc DocProject/Help/*.hhc
DocProject/Help/*.hhk DocProject/Help/*.hhk
DocProject/Help/*.hhp DocProject/Help/*.hhp
DocProject/Help/Html2 DocProject/Help/Html2
DocProject/Help/html DocProject/Help/html
   
# Click-Once directory # Click-Once directory
publish publish
   
# Publish Web Output # Publish Web Output
*.Publish.xml *.Publish.xml
   
# NuGet Packages Directory # NuGet Packages Directory
packages packages
   
# Windows Azure Build Output # Windows Azure Build Output
csx csx
*.build.csdef *.build.csdef
   
# Windows Store app package directory # Windows Store app package directory
AppPackages/ AppPackages/
   
# Others # Others
sql sql
TestResults TestResults
[Tt]est[Rr]esult* [Tt]est[Rr]esult*
*.Cache *.Cache
ClientBin ClientBin
[Ss]tyle[Cc]op.* [Ss]tyle[Cc]op.*
~$* ~$*
*.dbmdl *.dbmdl
Generated_Code #added for RIA/Silverlight projects Generated_Code #added for RIA/Silverlight projects
   
# Backup & report files from converting an old project file to a newer # Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-) # Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/ _UpgradeReport_Files/
Backup*/ Backup*/
UpgradeLog*.XML UpgradeLog*.XML
   
# SQL Server files # SQL Server files
App_Data/*.mdf App_Data/*.mdf
App_Data/*.ldf App_Data/*.ldf
   
[Gg]ame/ [Gg]ame/
[Rr]elease/ [Rr]elease/
  fileFormatVersion: 2
  guid: 3e6865de7d6b77640961d0da684aa385
  folderAsset: yes
  timeCreated: 1457221974
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName: images
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 9b641aac8f6b8d442a1d9e317ac542f9
  timeCreated: 1457613015
  licenseType: Free
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 0
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 2048
  textureSettings:
  filterMode: -1
  aniso: 16
  mipBias: -1
  wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: b0b9654f43265a049b8697f74bb0849c
  timeCreated: 1457613015
  licenseType: Free
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 1
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 2048
  textureSettings:
  filterMode: -1
  aniso: -1
  mipBias: -1
  wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 58f5bc9b7425c6345a4d4d4606f9ac8e
  timeCreated: 1457613015
  licenseType: Free
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 1
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 2048
  textureSettings:
  filterMode: -1
  aniso: -1
  mipBias: -1
  wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 875d74857184ef6439f113ed1f885aa6
  folderAsset: yes
  timeCreated: 1459538298
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 6825d390ddd6a104ab08bbef4144ea9d
  folderAsset: yes
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: f25203942364fe847885998615141196
  MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: ec0ca0dfc44166742a8df645cae06a42
  MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 399da387f38a32d43a8c29af87908f97
  MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: b94b712974ed85e448020fb2a316991d
  MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: eafc25f2da5fd1645934e987f4c7aff3
  MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 7aac1871fcd83264a93348d747b113d6
  folderAsset: yes
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 90118262cf80c7549ab37dd61d08c605
  PluginImporter:
  serializedVersion: 1
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  platformData:
  Any:
  enabled: 1
  settings: {}
  Editor:
  enabled: 0
  settings:
  DefaultValueInitialized: true
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: e4331bf5e4a45a4488507f28195caf59
  PluginImporter:
  serializedVersion: 1
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  platformData:
  Any:
  enabled: 1
  settings: {}
  Editor:
  enabled: 0
  settings:
  DefaultValueInitialized: true
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: f576d8acaf7e5e846ba0cab5c556ee3b
  folderAsset: yes
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 91f6e47e2b98cb344bf578969233905c
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 6203aefd0f9f41e439681638e43b2602
  timeCreated: 1448468481
  licenseType: Free
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 5e5bd0c65e5edba469513d146dbd61f9
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 32714c7f3312f3a4f8728c7ad5fbfd6e
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 03614ee71852fb74c8e7a1042975206f
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 1559851e491ace04180a0025375a30ff
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 9db68454b5978314184a231e296a74c9
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 90b3f11cfafacdb458ea8f85df8f35a0
  timeCreated: 1457700589
  licenseType: Free
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: dfa5576d281e6484790ed88b05bf6c15
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 37a01900db115ab4781976bceb4f7057
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 857ba6549eff78c4e9e8faafbc93b15e
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 9bb4f07ad47d6044590bf8e2546a6658
  timeCreated: 1448128444
  licenseType: Free
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 7c0652604e6b38842b3cdf1ee486761e
  timeCreated: 1458202379
  licenseType: Free
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: b53675eb8ece2834bbe8d2edd1ce3ba9
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 1752db0aa4762064fa141b2b41eb3eae
  ShaderImporter:
  defaultTextures: []
  userData:
 
  fileFormatVersion: 2
  guid: 6766600fc1203e447be7a1fdcabadea5
  timeCreated: 1455115714
  licenseType: Free
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 2563106331ba0f844b342a439bd0837b
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 9952cedaea0c1b84a82b97271046a88d
  folderAsset: yes
  timeCreated: 1448566539
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 9e273bc4aa80cca4aa7b1d829cece604
  timeCreated: 1456319206
  licenseType: Free
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: a45acd8adee64ea4cac55b22bfebe6cb
  ShaderImporter:
  defaultTextures: []
  userData:
 
  fileFormatVersion: 2
  guid: 2319550d1ff59fa4c8fe967d9b6b5adc
  timeCreated: 1446560191
  licenseType: Free
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 0119f0967dbebbc42bc9f4a0f8224c0b
  ShaderImporter:
  defaultTextures: []
  userData:
 
  fileFormatVersion: 2
  guid: fecf7d1b793420b42bd7aceca03cc705
  timeCreated: 1457959736
  licenseType: Free
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 1c305ae90596a6446a4ccb724cab1d13
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 2ebca85d3473f60439b7ab95440e83d8
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: a300027f5fc1d00408c43714110ed874
  ShaderImporter:
  defaultTextures: []
  userData:
 
  fileFormatVersion: 2
  guid: 9734ff0747239d44db81bfccdd6b3eee
  ShaderImporter:
  defaultTextures: []
  userData:
 
  fileFormatVersion: 2
  guid: bb8ca88c4046c074bb3f3af45d9c855b
  ShaderImporter:
  userData:
 
  fileFormatVersion: 2
  guid: 37009ed9069dfce43a12d30fc381f931
  timeCreated: 1457970059
  licenseType: Free
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: f7dfb55ef5c52b14c9c18cf4ac48bb24
  ShaderImporter:
  userData:
 
file:b/Assets/Parts.meta (new)
  fileFormatVersion: 2
  guid: b2511734b411fd244b463113e5f5c57f
  folderAsset: yes
  timeCreated: 1459537564
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 1d5671e027f0be444a8ddeff7715a3f7
  folderAsset: yes
  timeCreated: 1459539095
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: ba92dc968cd43984281a4466efba7b6e
  timeCreated: 1459539468
  licenseType: Free
  ModelImporter:
  serializedVersion: 18
  fileIDToRecycleName:
  100000: Camera
  100002: //RootNode
  100004: EngineerChip
  100006: Lamp
  100008: node_collider
  400000: Camera
  400002: //RootNode
  400004: EngineerChip
  400006: Lamp
  400008: node_collider
  2300000: EngineerChip
  2300002: node_collider
  3300000: EngineerChip
  3300002: node_collider
  4300000: node_collider
  4300002: EngineerChip
  9500000: //RootNode
  materials:
  importMaterials: 0
  materialName: 0
  materialSearch: 1
  animations:
  legacyGenerateAnimations: 4
  bakeSimulation: 0
  optimizeGameObjects: 0
  motionNodeName:
  animationImportErrors:
  animationImportWarnings:
  animationRetargetingWarnings:
  animationDoRetargetingWarnings: 0
  animationCompression: 1
  animationRotationError: .5
  animationPositionError: .5
  animationScaleError: .5
  animationWrapMode: 0
  extraExposedTransformPaths: []
  clipAnimations: []
  isReadable: 1
  meshes:
  lODScreenPercentages: []
  globalScale: 1
  meshCompression: 0
  addColliders: 0
  importBlendShapes: 1
  swapUVChannels: 0
  generateSecondaryUV: 0
  useFileUnits: 1
  optimizeMeshForGPU: 1
  keepQuads: 0
  weldVertices: 1
  secondaryUVAngleDistortion: 8
  secondaryUVAreaDistortion: 15.000001
  secondaryUVHardAngle: 88
  secondaryUVPackMargin: 4
  useFileScale: 1
  tangentSpace:
  normalSmoothAngle: 60
  splitTangentsAcrossUV: 1
  normalImportMode: 0
  tangentImportMode: 1
  importAnimation: 0
  copyAvatar: 0
  humanDescription:
  human: []
  skeleton: []
  armTwist: .5
  foreArmTwist: .5
  upperLegTwist: .5
  legTwist: .5
  armStretch: .0500000007
  legStretch: .0500000007
  feetSpacing: 0
  rootMotionBoneName:
  hasTranslationDoF: 0
  lastHumanDescriptionAvatarSource: {instanceID: 0}
  animationType: 0
  humanoidOversampling: 1
  additionalBone: 0
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 508aa968b16438c438042fefca86dcc9
  timeCreated: 1459539468
  licenseType: Free
  NativeFormatImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 59f78834f4b43ba4f849098d80347825
  timeCreated: 1459540984
  licenseType: Free
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 1
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 2048
  textureSettings:
  filterMode: -1
  aniso: 16
  mipBias: -1
  wrapMode: 1
  nPOTScale: 1
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 0
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 0
  textureType: 0
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 7e9829171b5503e44bed3ac61e6e7a18
  timeCreated: 1459539385
  licenseType: Free
  NativeFormatImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 5301f1a87c4751f4eab615946f0935ff
  folderAsset: yes
  timeCreated: 1446757351
  licenseType: Pro
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 7810c03ce9571f74183306825d39e103
  folderAsset: yes
  timeCreated: 1456139982
  licenseType: Pro
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 0890400b9503e704f8990f50af9b31e0
  timeCreated: 1454319587
  licenseType: Pro
  PluginImporter:
  serializedVersion: 1
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  platformData:
  Android:
  enabled: 0
  settings:
  CPU: AnyCPU
  Any:
  enabled: 0
  settings: {}
  Editor:
  enabled: 1
  settings:
  CPU: AnyCPU
  DefaultValueInitialized: true
  OS: AnyOS
  Linux:
  enabled: 0
  settings:
  CPU: x86
  Linux64:
  enabled: 0
  settings:
  CPU: x86_64
  OSXIntel:
  enabled: 0
  settings:
  CPU: AnyCPU
  OSXIntel64:
  enabled: 0
  settings:
  CPU: AnyCPU
  SamsungTV:
  enabled: 0
  settings:
  STV_MODEL: STANDARD_13
  WP8:
  enabled: 0
  settings:
  CPU: AnyCPU
  DontProcess: False
  PlaceholderPath:
  Win:
  enabled: 0
  settings:
  CPU: AnyCPU
  Win64:
  enabled: 0
  settings:
  CPU: AnyCPU
  WindowsStoreApps:
  enabled: 0
  settings:
  CPU: AnyCPU
  DontProcess: False
  PlaceholderPath:
  SDK: AnySDK
  iOS:
  enabled: 0
  settings:
  CompileFlags:
  FrameworkDependencies:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 7f5bed1f9aa762b41942b1832536a846
  timeCreated: 1454319588
  licenseType: Pro
  PluginImporter:
  serializedVersion: 1
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  platformData:
  Any:
  enabled: 1
  settings: {}
  Editor:
  enabled: 0
  settings:
  DefaultValueInitialized: true
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 3ee644d0f5d6a744f9d2f7ab6e346c0f
  timeCreated: 1456140045
  licenseType: Pro
  TextScriptImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
 Binary files a/Assets/Plugins/KerbalEngineer.Unity.dll and b/Assets/Plugins/KerbalEngineer.Unity.dll differ
  fileFormatVersion: 2
  guid: 4ffb1bf511e31af45bdeaa3d272d49d4
  timeCreated: 1457613014
  licenseType: Free
  PluginImporter:
  serializedVersion: 1
  iconMap: {}
  executionOrder: {}
  isPreloaded: 0
  platformData:
  Any:
  enabled: 1
  settings: {}
  Editor:
  enabled: 0
  settings:
  DefaultValueInitialized: true
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 0c33c8c1a93dd2249b4d1bf169077a78
  folderAsset: yes
  timeCreated: 1457222170
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName: prefabs
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 2a64d6ba13a07d7438fd2e141e4157a8
  timeCreated: 1457613015
  licenseType: Free
  NativeFormatImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 2147dc5ac8aa16a4ca2003dfcd024533
  timeCreated: 1457613015
  licenseType: Free
  NativeFormatImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 16146381062142047981225587168076
  timeCreated: 1457710740
  licenseType: Free
  NativeFormatImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 345debd9876196a4e95d8718febe5301
  timeCreated: 1457710933
  licenseType: Free
  NativeFormatImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: b0b78ee2755669241a6e82c70b5988cf
  timeCreated: 1457710992
  licenseType: Free
  NativeFormatImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 1146896f042c04546abd10ef08dc0354
  timeCreated: 1457632616
  licenseType: Free
  NativeFormatImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 2e4ab16a0164fdf4f84c814ca9495a27
  folderAsset: yes
  timeCreated: 1457227379
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: ad19e4eab46995a49bb549b93716d17a
  timeCreated: 1457613013
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 7acc810afbef3ad4d806529a3dcb56bd
  timeCreated: 1459539554
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 1f7422cd34745d649bb149b57dee13af
  folderAsset: yes
  timeCreated: 1457221965
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 81f5a3b513213974c9c2438bbf0fd0c4
  folderAsset: yes
  timeCreated: 1457222059
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: bd4e722ff5c69f34a90381d01b1376a2
  timeCreated: 1457613014
  licenseType: Free
  MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 405aeda35f216a14c88580cad5a58e75
  folderAsset: yes
  timeCreated: 1447334757
  licenseType: Pro
  DefaultImporter:
  userData:
  assetBundleName: squadcore
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: ea681fdd8e1bcc2449f008a8ac4fdc92
  folderAsset: yes
  timeCreated: 1448011261
  licenseType: Pro
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 47990fb03129e824caf678339b9eff94
  folderAsset: yes
  timeCreated: 1448011267
  licenseType: Pro
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: b1fc6fdc0f80cbf49b77f83ad3db33aa
  timeCreated: 1455648612
  licenseType: Pro
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 0
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 1024
  textureSettings:
  filterMode: -1
  aniso: 16
  mipBias: -1
  wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag: KSPedia
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: e8621dd15bfcce340b91d8bbc8d9f084
  timeCreated: 1455648613
  licenseType: Pro
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 0
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 1024
  textureSettings:
  filterMode: -1
  aniso: 16
  mipBias: -1
  wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 647bbf5cf6c08c04c8d4b753202b0808
  timeCreated: 1455648610
  licenseType: Pro
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 0
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 1024
  textureSettings:
  filterMode: -1
  aniso: 16
  mipBias: -1
  wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: cdbc96a0c719a1d48901892fcf30182f
  timeCreated: 1455648613
  licenseType: Pro
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 0
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 1024
  textureSettings:
  filterMode: -1
  aniso: 16
  mipBias: -1
  wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 7fbafb50c77e28d49a117a7810a321bf
  timeCreated: 1455648611
  licenseType: Pro
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 0
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 1024
  textureSettings:
  filterMode: -1
  aniso: 16
  mipBias: -1
  wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag: KSPedia
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: bfea133dc2cd936468fd26de9985455d
  folderAsset: yes
  timeCreated: 1447334764
  licenseType: Pro
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 6d85e30bba4b9974ab34d7d199c19c39
  timeCreated: 1447334820
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 5342206a32fc49a44b5aa0b52a72a8b0
  timeCreated: 1447334820
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: c9da217290ee74a43907fc1205e4c146
  timeCreated: 1447334822
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: ac859b44038643d40b88f24aceac191c
  timeCreated: 1447334821
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: b3b035681f285f740b32cf2bc12a8de6
  timeCreated: 1447334822
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: bbe7a2e17e83a9a45bc517140d3ca1a6
  timeCreated: 1447334822
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 4eb23d6a8a22cd2408ed28ac1ce15ed3
  timeCreated: 1447334819
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 59fa1cb2eebf7564ebb45f1250bba1d0
  timeCreated: 1447334820
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 8deb5d99e5582cb4fa66782c19ee43ad
  timeCreated: 1447334821
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 0785b2a0f9690d44dbdf4e24de04ca3e
  timeCreated: 1447334818
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 57cb714d3a5ee604bb1098b92cdce428
  timeCreated: 1447334820
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: db1d6aee2b6c25c4fbf0e07e9076c6b5
  timeCreated: 1447334822
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: a785e1a01d15b0345ac27359a32c9857
  timeCreated: 1447334821
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 28d4a56e9512d05479c0952c7b2fa008
  timeCreated: 1447334818
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 440ec76b6cd2107448cec7a61105b099
  timeCreated: 1447334819
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: ab0281620a104dd4ca96a6bf906f8011
  timeCreated: 1447334821
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 4270ab78ac4263e4dba328c5b4c6eafb
  timeCreated: 1447334819
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: ea11f8443dca92f4f816a6cddd06b775
  timeCreated: 1447334823
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: e4d5952eef9f9814c8dddd4e0da8347a
  timeCreated: 1447334823
  licenseType: Pro
  ShaderImporter:
  defaultTextures: []
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 8bb88b5ef17b72442a504c8ab8cb6910
  folderAsset: yes
  timeCreated: 1457227463
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 696e4ea6d01cf324889c1a7fa0c2fb06
  timeCreated: 1457613015
  licenseType: Free
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 1
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 2048
  textureSettings:
  filterMode: -1
  aniso: -1
  mipBias: -1
  wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag:
  userData:
  assetBundleName:
  assetBundleVariant:
 
  fileFormatVersion: 2
  guid: 4105bbb9c3877934f99f89c091ba0b8b
  timeCreated: 1457613015
  licenseType: Free
  TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
  mipMapMode: 0
  enableMipMap: 1
  linearTexture: 0
  correctGamma: 0
  fadeOut: 0
  borderMipMap: 0
  mipMapFadeDistanceStart: 1
  mipMapFadeDistanceEnd: 3
  bumpmap:
  convertToNormalMap: 0
  externalNormalMap: 0
  heightScale: .25
  normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 2048
  textureSettings:
  filterMode: -1
  aniso: -1
  mipBias: -1
  wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
  sprites: []
  spritePackingTag:
  userData:
  assetBundleName:
  assetBundleVariant:
 
file:b/Assets/XML.meta (new)
  fileFormatVersion: 2
  guid: fef14382d4de3d34ca7abdf5eee105c2
  folderAsset: yes
  timeCreated: 1459537692
  licenseType: Free
  DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
 
1.1.0.2 1.1.0.2, 2016-04-19, KSP Build #1230
  Added: Altitude (terrain) readout now shows the altitude above underwater terrain when splashed down.
  Added: Usage of the stock IPartMassModifier for handling the modifying of part module staged mass.
  Added: Support for thrustTranformMultipliers
  Changed: Fairing specific mass adjustments now make use of the generic staged mass modifier implementation.
  Changed: App launcher button handling works with KSP build 1205 changes.
  Changed: Impact lat/long readouts to use DMS form.
Fixed: Log spam and physics issue caused when using the EngineerChip part due to a convex mesh collider (now uses a box collider). Fixed: Log spam and physics issue caused when using the EngineerChip part due to a convex mesh collider (now uses a box collider).
  Fixed: Issues with the disabling/enabling of the toolbar app launcher button in flight when in career mode.
  Fixed: Bug with impact calculations.
   
1.1.0.1, 2016-04-01, KSP Build #1179 1.1.0.1, 2016-04-01, KSP Build #1179
Fixed: Heat shields acting as staged decouplers when not set to be staged. Fixed: Heat shields acting as staged decouplers when not set to be staged.
Fixed: Enabling and disabling of decouplers in staging is now correctly handled. Fixed: Enabling and disabling of decouplers in staging is now correctly handled.
Fixed: Issue in simulation staging that caused no deltaV above a fairing whilst landed. Fixed: Issue in simulation staging that caused no deltaV above a fairing whilst landed.
Fixed: Fairing mass calculations to work using module mass only (Changed from 1.0.5). Fixed: Fairing mass calculations to work using module mass only (Changed from 1.0.5).
   
1.1.0.0, 2016-03-30, KSP Build #1171 1.1.0.0, 2016-03-30, KSP Build #1171
Added: Asset bundle loading and integration. Added: Asset bundle loading and integration.
Added: Styling system so that Unity UI objects can use KSP stock styles. Added: Styling system so that Unity UI objects can use KSP stock styles.
Added: Unity UI window system. Added: Unity UI window system.
Changed: Thermal flux is now correctly indicated in kilowatts. Changed: Thermal flux is now correctly indicated in kilowatts.
Changed: Complete rewrite of code underpinning the stock toolbar icons. Changed: Complete rewrite of code underpinning the stock toolbar icons.
Changed: Flight Engineer toolbar menu recreated using Unity UI. Changed: Flight Engineer toolbar menu recreated using Unity UI.
Changed: Replaced occurances of IMGUI using RenderingManager to use OnGUI directly. Changed: Replaced occurances of IMGUI using RenderingManager to use OnGUI directly.
Fixed: Toggling the 'Control Bar' now appropriately resizes the display stack. Fixed: Toggling the 'Control Bar' now appropriately resizes the display stack.
Fixed: Part info tooltips in the editor remaining open when no part is selected. Fixed: Part info tooltips in the editor remaining open when no part is selected.
   
1.0.19.4, 2016-02-12 1.0.19.4, 2016-02-12
Fixed: Only 'STAGE_STACK_FLOW' and 'STAGE_STACK_FLOW_BALANCE' resources include surface mounted parts as fuel targets. Fixed: Only 'STAGE_STACK_FLOW' and 'STAGE_STACK_FLOW_BALANCE' resources include surface mounted parts as fuel targets.
Fixed: Fairing mass being doubled in the VAB (removed workaround for a KSP bug which has been fixed). Fixed: Fairing mass being doubled in the VAB (removed workaround for a KSP bug which has been fixed).
   
1.0.19.3, 2016-02-09 1.0.19.3, 2016-02-09
Fixed: Fuel cross-feed from surface attached parts. Fixed: Fuel cross-feed from surface attached parts.
   
1.0.19.2, 2016-11-19 1.0.19.2, 2016-11-19
Rebuild for KSP 1.0.5.1028 silent update. Rebuild for KSP 1.0.5.1028 silent update.
1.0.19.1, 2016-11-09 1.0.19.1, 2016-11-09
Added: Key binding editor accessible under 'Settings' on the Build Engineer. Added: Key binding editor accessible under 'Settings' on the Build Engineer.
Added: Added current vessel name readout. (antplant) Added: Added current vessel name readout. (antplant)
Added: 'Relative Radial Velocity' and 'Time To Rendezvous' readouts. (itwtx) Added: 'Relative Radial Velocity' and 'Time To Rendezvous' readouts. (itwtx)
Added: Readout help strings. (harryyoung) Added: Readout help strings. (harryyoung)
Changed: The 'Torque' value in the editor is now precise to two decimal places. Changed: The 'Torque' value in the editor is now precise to two decimal places.
Changed: Time formatting reference (Kerbin/Earth) is now based on the in-game setting. Changed: Time formatting reference (Kerbin/Earth) is now based on the in-game setting.
Changed: Eccentric Anomaly, Mean Anomaly and Mean Anomaly At Epoc now display in degrees rather than radians. Changed: Eccentric Anomaly, Mean Anomaly and Mean Anomaly At Epoc now display in degrees rather than radians.
Fixed: Optimised time formatting. (itwtx) Fixed: Optimised time formatting. (itwtx)
Fixed: TimeToAtmosphere checks that the Apoapsis is outside atmosphere. (Kerbas-ad-astra) Fixed: TimeToAtmosphere checks that the Apoapsis is outside atmosphere. (Kerbas-ad-astra)
Fixed: Issue with stage priority flow. Caused Rapier calculations to fail if LF and O are drawn from different tanks. (Padishar) Fixed: Issue with stage priority flow. Caused Rapier calculations to fail if LF and O are drawn from different tanks. (Padishar)
Fixed: Issue with angle to prograde/retrograde calculations on highly inclined orbits. Fixed: Issue with angle to prograde/retrograde calculations on highly inclined orbits.
Fixed: Editor input locks not being reset when a scene change is forced (e.g. via Kerbal Construction Time). Fixed: Editor input locks not being reset when a scene change is forced (e.g. via Kerbal Construction Time).
Fixed: Roll axis readout now shows the correct sign. Fixed: Roll axis readout now shows the correct sign.
Removed: Time Formatter readout as it's not required anymore. Removed: Time Formatter readout as it's not required anymore.
   
1.0.18.0 1.0.18.0
Added: Orbital readouts - "Speed at Periapsis" and "Speed at Apoapsis". (Padishar) Added: Orbital readouts - "Speed at Periapsis" and "Speed at Apoapsis". (Padishar)
Added: Manoeuvre readouts - "Post-burn Apoapsis" and "Post-burn Periapsis". (Padishar) Added: Manoeuvre readouts - "Post-burn Apoapsis" and "Post-burn Periapsis". (Padishar)
Added: Orbital readout - "Time to Atmosphere". Added: Orbital readout - "Time to Atmosphere".
Fixed: Synched the minimum simulation time sliders and stopped them from snapping back after 999ms. (saybur) Fixed: Synched the minimum simulation time sliders and stopped them from snapping back after 999ms. (saybur)
Fixed: Added workaround for the bug in Vessel.horizontalSrfSpeed (Padishar) Fixed: Added workaround for the bug in Vessel.horizontalSrfSpeed (Padishar)
Fixed: Physically insignificant part mass was not being correctly cascaded down through multiple parent parts. Fixed: Physically insignificant part mass was not being correctly cascaded down through multiple parent parts.
Fixed: Intake air demand calculation not working. Fixed: Intake air demand calculation not working.
Fixed: Some build engineer settings labels do not scale with UI size. Fixed: Some build engineer settings labels do not scale with UI size.
   
1.0.17.0 1.0.17.0
Added: 'Mach Number' readout under the 'Surface' category and included it on the default surface HUD. Added: 'Mach Number' readout under the 'Surface' category and included it on the default surface HUD.
Added: Stock sections in the Flight Engineer can now become HUDs. Added: Stock sections in the Flight Engineer can now become HUDs.
Added 'Thermal' readouts category including: Added 'Thermal' readouts category including:
Internal Flux Internal Flux
Convection Flux Convection Flux
Radiation Flux Radiation Flux
Critical Part Name Critical Part Name
Critical Part Temperature Critical Part Temperature
Critical Part Skin Temperature Critical Part Skin Temperature
Critical Part Thermal Percentage of Max Temperature Critical Part Thermal Percentage of Max Temperature
Hottest Part Name Hottest Part Name
Hottest Part Temperature Hottest Part Temperature
Hottest Part Skin Temperature Hottest Part Skin Temperature
Coldest Part Name Coldest Part Name
Coldest Part Temperature Coldest Part Temperature
Coldest Part Skin Temperature Coldest Part Skin Temperature
   
Changed: Mach on the Build Engineer now accurate to 2 decimal places. Changed: Mach on the Build Engineer now accurate to 2 decimal places.
Changed: Max mach in the Build Engineer defaults to 1.00 even when no jet engines are present. Changed: Max mach in the Build Engineer defaults to 1.00 even when no jet engines are present.
Changed: Increased eccentricity readout to 5 decimal places. Changed: Increased eccentricity readout to 5 decimal places.
Changed: Implemented Sarbian's object pooling. Changed: Implemented Sarbian's object pooling.
Changed: The default selected body is now assigned via 'Planitarium.Home'. Changed: The default selected body is now assigned via 'Planitarium.Home'.
Changed: HUDs to clamp fully inside the screen instead of allowing them to run off the edge by a certain amount. Changed: HUDs to clamp fully inside the screen instead of allowing them to run off the edge by a certain amount.
Fixed: Physically insignificant part mass is now associated with the parent part. Fixed: Physically insignificant part mass is now associated with the parent part.
Fixed: Longitude and Latitude readouts now use a KER formatter instead of Squad's incorrect implementation. Fixed: Longitude and Latitude readouts now use a KER formatter instead of Squad's incorrect implementation.
Fixed: Possible null reference in the Rendezvous Processor. Fixed: Possible null reference in the Rendezvous Processor.
Fixed: Fairing mass issues introduced with regards to simulation changes. Fixed: Fairing mass issues introduced with regards to simulation changes.
Fixed: Use of per-propellant fuel flow mode override. Fixed: Use of per-propellant fuel flow mode override.
Fixed: Burn times calculated for jet engines. Fixed: Burn times calculated for jet engines.
Fixed: Thrust issues introduced with Sarbian's simulation alterations. Fixed: Thrust issues introduced with Sarbian's simulation alterations.
Fixed: Issue where HUDs positioned close to the top/bottom of the screen could be pushed out of position. Fixed: Issue where HUDs positioned close to the top/bottom of the screen could be pushed out of position.
   
1.0.16.6, 2015-05-02 1.0.16.6, 2015-05-02
Fixed: Separately staged fairing mass jettisons are now calculated in the editor. Fixed: Separately staged fairing mass jettisons are now calculated in the editor.
   
1.0.16.5, 2015-05-02 1.0.16.5, 2015-05-02
Fixed: Delta-V not being correctly calculated. Fixed: Delta-V not being correctly calculated.
Changed: Editor locking now uses the InputLockManager. Changed: Editor locking now uses the InputLockManager.
   
1.0.16.4, 01-05-2015 1.0.16.4, 01-05-2015
Fixed: Physically insignificant part mass is now accounted for. 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). Changed: Module mass accounted for as it now makes its way onto the launch pad (e.g. fairings).
   
Various optimisations: Various optimisations:
Object pooling. Object pooling.
Removed LINQ expressions. Removed LINQ expressions.
Converted foreach to for loops. Converted foreach to for loops.
   
1.0.16.3, 2015-04-27 1.0.16.3, 2015-04-27
Fixed issue with the toolbar icons not being created. Fixed issue with the toolbar icons not being created.
Removed superfluous 'm/s' on the mach slider in the build engineer. Removed superfluous 'm/s' on the mach slider in the build engineer.
   
1.0.16.2, 2015-04-27 1.0.16.2, 2015-04-27
Changed the atmospheric slider on the build engineer to default to 0km when changing bodies. Changed the atmospheric slider on the build engineer to default to 0km when changing bodies.
   
1.0.16.1, 2015-04-26, KSP Build #828 1.0.16.1, 2015-04-26, KSP Build #828
Merged Sarbian's mach adjustments. Merged Sarbian's mach adjustments.
Fixed bugs relating to thrust and atmosphere/velocity curves. 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 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 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. Changed the velocity slider to clamp to the maximum usable mach value for the current vessel.
   
1.0.16.0, 2015-04-25, KSP Build #821 1.0.16.0, 2015-04-25, KSP Build #821
Fixed errors relating to KSP 1.0 update. Fixed errors relating to KSP 1.0 update.
Fixed fuel simulation to account for new thrust system. Fixed fuel simulation to account for new thrust system.
Fixed atmospheric engines to use the new velocity curve. Fixed atmospheric engines to use the new velocity curve.
Fixed atmospheric readouts to work with the new atmospheric model. Fixed atmospheric readouts to work with the new atmospheric model.
   
1.0.15.2, 2015-02-13 1.0.15.2, 2015-02-13
Padishar's Fixes: Padishar's Fixes:
Fixed: Calculation of per-stage resource mass. Fixed: Calculation of per-stage resource mass.
   
1.0.15.1, 2015-02-13 1.0.15.1, 2015-02-13
Rebuild Rebuild
   
1.0.15.0, 2015-02-08 1.0.15.0, 2015-02-08
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, 2014-12-28 1.0.14.1, 2014-12-28
Fixed: Missing texture on the ER-7500 model. Fixed: Missing texture on the ER-7500 model.
   
1.0.14.0, 2014-12-28 1.0.14.0, 2014-12-28
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, 2014-12-16 1.0.13.1, 2014-12-16
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, 2014-12-16 1.0.13.0, 2014-12-16
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, 2014-12-01 1.0.12.0, 2014-12-01
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, 2014-11-11 1.0.11.3, 2014-11-11
Changed: Gravity measurements for Isp to 9.82. Changed: Gravity measurements for Isp to 9.82.
   
1.0.11.2, 2014-11-10 1.0.11.2, 2014-11-10
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, 2014-11-07 1.0.11.1, 2014-11-07
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, 201-11-06 1.0.11.0, 201-11-06
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, 2014-10-19 1.0.10.0, 2014-10-19
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, 2014-10-08 1.0.9.3, 2014-10-08
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, 2014-10-07 1.0.9.2, 2014-10-07
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, 2014-09-17 1.0.9.1, 2014-09-17
Fixed: Part size bug caused by TweakScale's cost calculator. Fixed: Part size bug caused by TweakScale's cost calculator.
   
1.0.9.0, 2014-09-15 1.0.9.0, 2014-09-15
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, 2014-09-06 1.0.8.1, 2014-09-06
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, 2014-09-06 1.0.8.0, 2014-09-06
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, 2014-09-02 1.0.7.1, 2014-09-02
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, 2014-09-01 1.0.7.0, 2014-09-01
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, 2014-08-23 1.0.6.0, 2014-08-23
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, 2014-08-13 1.0.5.0, 2014-08-13
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, 2014-08-12 1.0.4.0, 2014-08-12
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, 2014-07-30 1.0.3.0, 2014-07-30
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, 2014-07-27 1.0.2.0, 2014-07-27
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, 2014-07-26 1.0.1.0, 2014-07-26
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, 2014-06-24 1.0.0.1, 2014-06-24
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, 2014-07-24 1.0.0.0, 2014-07-24
Initial release for public testing. Initial release for public testing.
   
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2016 CYBUTEK // Copyright (C) 2016 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.Unity namespace KerbalEngineer.Unity
{ {
using System; using System;
using System.Collections; using System.Collections;
using UnityEngine; using UnityEngine;
   
[RequireComponent(typeof(CanvasGroup))] [RequireComponent(typeof(CanvasGroup))]
public class CanvasGroupFader : MonoBehaviour public class CanvasGroupFader : MonoBehaviour
{ {
private CanvasGroup m_CanvasGroup; private CanvasGroup m_CanvasGroup;
private IEnumerator m_FadeCoroutine; private IEnumerator m_FadeCoroutine;
   
public bool IsFading public bool IsFading
{ {
get get
{ {
return m_FadeCoroutine != null; return m_FadeCoroutine != null;
} }
} }
   
/// <summary> /// <summary>
/// Fades the canvas group to a specified alpha using the supplied blocking state during fade with optional callback. /// Fades the canvas group to a specified alpha using the supplied blocking state during fade with optional callback.
/// </summary> /// </summary>
public void FadeTo(float alpha, float duration, Action callback = null) public void FadeTo(float alpha, float duration, Action callback = null)
{ {
if (m_CanvasGroup == null) if (m_CanvasGroup == null)
{ {
return; return;
} }
   
Fade(m_CanvasGroup.alpha, alpha, duration, callback); Fade(m_CanvasGroup.alpha, alpha, duration, callback);
} }
   
/// <summary> /// <summary>
/// Sets the alpha value of the canvas group. /// Sets the alpha value of the canvas group.
/// </summary> /// </summary>
public void SetAlpha(float alpha) public void SetAlpha(float alpha)
{ {
if (m_CanvasGroup == null) if (m_CanvasGroup == null)
{ {
return; return;
} }
   
alpha = Mathf.Clamp01(alpha); alpha = Mathf.Clamp01(alpha);
m_CanvasGroup.alpha = alpha; m_CanvasGroup.alpha = alpha;
} }
   
protected virtual void Awake() protected virtual void Awake()
{ {
// cache components // cache components
m_CanvasGroup = GetComponent<CanvasGroup>(); m_CanvasGroup = GetComponent<CanvasGroup>();
} }
   
/// <summary> /// <summary>
/// Starts a fade from one alpha value to another with callback. /// Starts a fade from one alpha value to another with callback.
/// </summary> /// </summary>
private void Fade(float from, float to, float duration, Action callback) private void Fade(float from, float to, float duration, Action callback)
{ {
if (m_FadeCoroutine != null) if (m_FadeCoroutine != null)
{ {
StopCoroutine(m_FadeCoroutine); StopCoroutine(m_FadeCoroutine);
} }
   
m_FadeCoroutine = FadeCoroutine(from, to, duration, callback); m_FadeCoroutine = FadeCoroutine(from, to, duration, callback);
StartCoroutine(m_FadeCoroutine); StartCoroutine(m_FadeCoroutine);
} }
   
/// <summary> /// <summary>
/// Coroutine that handles the fading. /// Coroutine that handles the fading.
/// </summary> /// </summary>
private IEnumerator FadeCoroutine(float from, float to, float duration, Action callback) private IEnumerator FadeCoroutine(float from, float to, float duration, Action callback)
{ {
// wait for end of frame so that only the last call to fade that frame is honoured. // wait for end of frame so that only the last call to fade that frame is honoured.
yield return new WaitForEndOfFrame(); yield return new WaitForEndOfFrame();
   
float progress = 0.0f; float progress = 0.0f;
   
while (progress <= 1.0f) while (progress <= 1.0f)
{ {
progress += Time.deltaTime / duration; progress += Time.deltaTime / duration;
SetAlpha(Mathf.Lerp(from, to, progress)); SetAlpha(Mathf.Lerp(from, to, progress));
yield return null; yield return null;
} }
   
  //print(m_CanvasGroup.alpha);
callback?.Invoke(); callback?.Invoke();
   
m_FadeCoroutine = null; m_FadeCoroutine = null;
} }
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2016 CYBUTEK // Copyright (C) 2016 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 namespace KerbalEngineer
{ {
using KSP.UI; using KSP.UI;
using KSP.UI.Screens; using KSP.UI.Screens;
using UnityEngine; using UnityEngine;
   
public class AppLauncherButton : MonoBehaviour public class AppLauncherButton : MonoBehaviour
{ {
private static Texture s_IconTexture; private static Texture s_IconTexture;
private ApplicationLauncherButton m_Button; private ApplicationLauncherButton m_Button;
   
/// <summary> /// <summary>
  /// Gets the wrapped application launcher button object.
  /// </summary>
  public ApplicationLauncherButton Button
  {
  get
  {
  return m_Button;
  }
  }
   
  /// <summary>
/// Gets or sets the toggle button state. /// Gets or sets the toggle button state.
/// </summary> /// </summary>
public bool IsOn public bool IsOn
{ {
get get
{ {
return m_Button != null && return m_Button != null &&
m_Button.toggleButton.Button.interactable && m_Button.IsEnabled &&
m_Button.toggleButton.CurrentState == UIRadioButton.State.True; m_Button.toggleButton.CurrentState == UIRadioButton.State.True;
} }
set set
{ {
if (m_Button == null) if (m_Button == null)
{ {
return; return;
} }
   
if (value) if (value)
{ {
SetOn(); SetOn();
} }
else else
{ {
SetOff(); SetOff();
} }
} }
} }
   
/// <summary> /// <summary>
/// Disables the button if not already disabled. /// Disables the button if not already disabled.
/// </summary> /// </summary>
public void Disable() public void Disable()
{ {
if (m_Button != null && m_Button.toggleButton.Button.interactable) if (m_Button != null && m_Button.IsEnabled)
{ {
m_Button.Disable(); m_Button.Disable();
} }
} }
   
/// <summary> /// <summary>
/// Enables the button if not already enabled. /// Enables the button if not already enabled.
/// </summary> /// </summary>
public void Enable() public void Enable()
{ {
if (m_Button != null && m_Button.toggleButton.Button.interactable == false) if (m_Button != null && !m_Button.IsEnabled)
{ {
m_Button.Enable(); m_Button.Enable();
} }
} }
   
/// <summary> /// <summary>
/// Gets the anchor position for pop-up content. /// Gets the anchor position for pop-up content.
/// </summary> /// </summary>
public Vector3 GetAnchor() public Vector3 GetAnchor()
{ {
if (m_Button == null) if (m_Button == null)
{ {
return Vector3.zero; return Vector3.zero;
} }
   
Vector3 anchor = m_Button.GetAnchor(); Vector3 anchor = m_Button.GetAnchor();
   
anchor.x -= 3.0f; anchor.x -= 3.0f;
   
return anchor; return anchor;
} }
   
/// <summary> /// <summary>
/// Enables and sets the button to off. /// Enables and sets the button to off.
/// </summary> /// </summary>
public void SetOff() public void SetOff()
{ {
Enable(); Enable();
   
if (m_Button != null && m_Button.toggleButton.CurrentState != UIRadioButton.State.False) if (m_Button != null && m_Button.toggleButton.CurrentState != UIRadioButton.State.False)
{ {
m_Button.SetFalse(); m_Button.SetFalse();
} }
} }
   
/// <summary> /// <summary>
/// Enables and sets the button to on. /// Enables and sets the button to on.
/// </summary> /// </summary>
public void SetOn() public void SetOn()
{ {
Enable(); Enable();
   
if (m_Button != null && m_Button.toggleButton.CurrentState != UIRadioButton.State.True) if (m_Button != null && m_Button.toggleButton.CurrentState != UIRadioButton.State.True)
{ {
m_Button.SetTrue(); m_Button.SetTrue();
} }
} }
   
protected virtual void Awake() protected virtual void Awake()
{ {
// cache icon texture // cache icon texture
if (s_IconTexture == null && AssetBundleLoader.Images != null) if (s_IconTexture == null && AssetBundleLoader.Images != null)
{ {
s_IconTexture = AssetBundleLoader.Images.LoadAsset<Texture2D>("app-launcher-icon"); s_IconTexture = AssetBundleLoader.Images.LoadAsset<Texture2D>("app-launcher-icon");
} }
   
// subscribe event listeners // subscribe event listeners
GameEvents.onGUIApplicationLauncherReady.Add(OnGUIApplicationLauncherReady); GameEvents.onGUIApplicationLauncherReady.Add(OnGUIApplicationLauncherReady);
GameEvents.onGUIApplicationLauncherUnreadifying.Add(OnGUIApplicationLauncherUnreadifying); GameEvents.onGUIApplicationLauncherUnreadifying.Add(OnGUIApplicationLauncherUnreadifying);
} }
   
protected virtual void OnDestroy() protected virtual void OnDestroy()
{ {
// unsubscribe event listeners // unsubscribe event listeners
GameEvents.onGUIApplicationLauncherReady.Remove(OnGUIApplicationLauncherReady); GameEvents.onGUIApplicationLauncherReady.Remove(OnGUIApplicationLauncherReady);
GameEvents.onGUIApplicationLauncherUnreadifying.Remove(OnGUIApplicationLauncherUnreadifying); GameEvents.onGUIApplicationLauncherUnreadifying.Remove(OnGUIApplicationLauncherUnreadifying);
} }
   
/// <summary> /// <summary>
/// Called on button being disabled. /// Called on button being disabled.
/// </summary> /// </summary>
protected virtual void OnDisable() { } protected virtual void OnDisable() { }
   
/// <summary> /// <summary>
/// Called on button being enabled. /// Called on button being enabled.
/// </summary> /// </summary>
protected virtual void OnEnable() { } protected virtual void OnEnable() { }
   
/// <summary> /// <summary>
/// Called on button being toggled off. /// Called on button being toggled off.
/// </summary> /// </summary>
protected virtual void OnFalse() { } protected virtual void OnFalse() { }
   
/// <summary> /// <summary>
/// Called on mouse hovering. /// Called on mouse hovering.
/// </summary> /// </summary>
protected virtual void OnHover() { } protected virtual void OnHover() { }
   
/// <summary> /// <summary>
/// Called on mouse exiting hover. /// Called on mouse exiting hover.
/// </summary> /// </summary>
protected virtual void OnHoverOut() { } protected virtual void OnHoverOut() { }
   
/// <summary> /// <summary>
/// Called on button being ready. /// Called on button being ready.
/// </summary> /// </summary>
protected virtual void OnReady() { } protected virtual void OnReady() { }
   
/// <summary> /// <summary>
/// Called after the application launcher is ready and the button created. /// Called after the application launcher is ready and the button created.
/// </summary> /// </summary>
protected virtual void OnTrue() { } protected virtual void OnTrue() { }
   
/// <summary> /// <summary>
/// Called after the application launcher is unreadified and the button removed. /// Called after the application launcher is unreadified and the button removed.
/// </summary> /// </summary>
protected virtual void OnUnreadifying() { } protected virtual void OnUnreadifying() { }
   
private void OnGUIApplicationLauncherReady() private void OnGUIApplicationLauncherReady()
{ {
// create button // create button
if (ApplicationLauncher.Instance != null) if (ApplicationLauncher.Instance != null)
{ {
m_Button = ApplicationLauncher.Instance.AddModApplication(OnTrue, OnFalse, OnHover, OnHoverOut, OnEnable, OnDisable, ApplicationLauncher.AppScenes.ALWAYS, s_IconTexture); m_Button = ApplicationLauncher.Instance.AddModApplication(OnTrue, OnFalse, OnHover, OnHoverOut, OnEnable, OnDisable, ApplicationLauncher.AppScenes.ALWAYS, s_IconTexture);
} }
   
OnReady(); OnReady();
} }
   
private void OnGUIApplicationLauncherUnreadifying(GameScenes scene) private void OnGUIApplicationLauncherUnreadifying(GameScenes scene)
{ {
// remove button // remove button
if (ApplicationLauncher.Instance != null && m_Button != null) if (ApplicationLauncher.Instance != null && m_Button != null)
{ {
ApplicationLauncher.Instance.RemoveModApplication(m_Button); ApplicationLauncher.Instance.RemoveModApplication(m_Button);
} }
   
OnUnreadifying(); OnUnreadifying();
} }
} }
} }
// //
// Copyright (C) 2015 CYBUTEK // Copyright (C) 2015 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 namespace KerbalEngineer
{ {
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
   
public static class EngineerGlobals public static class EngineerGlobals
{ {
/// <summary> /// <summary>
/// Current version of the Kerbal Engineer assembly. /// Current version of the Kerbal Engineer assembly.
/// </summary> /// </summary>
public const string ASSEMBLY_VERSION = "1.1.0.1"; public const string ASSEMBLY_VERSION = "1.1.0.2";
   
private static string assemblyFile; private static string assemblyFile;
private static string assemblyName; private static string assemblyName;
private static string assemblyPath; private static string assemblyPath;
private static string settingsPath; private static string settingsPath;
   
/// <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 get
{ {
return assemblyFile ?? (assemblyFile = Assembly.GetExecutingAssembly().Location); 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 get
{ {
return assemblyName ?? (assemblyName = new FileInfo(AssemblyFile).Name); 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 get
{ {
return assemblyPath ?? (assemblyPath = AssemblyFile.Replace(new FileInfo(AssemblyFile).Name, "")); return assemblyPath ?? (assemblyPath = AssemblyFile.Replace(new FileInfo(AssemblyFile).Name, ""));
} }
} }
   
/// <summary> /// <summary>
/// Gets the settings directory path. /// Gets the settings directory path.
/// </summary> /// </summary>
public static string SettingsPath public static string SettingsPath
{ {
get get
{ {
if (string.IsNullOrEmpty(settingsPath)) if (string.IsNullOrEmpty(settingsPath))
{ {
settingsPath = Path.Combine(AssemblyPath, "Settings"); settingsPath = Path.Combine(AssemblyPath, "Settings");
} }
return settingsPath; return settingsPath;
} }
} }
} }
} }
// //
// 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.Extensions namespace KerbalEngineer.Extensions
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using CompoundParts; using CompoundParts;
   
public static class PartExtensions public static class PartExtensions
{ {
//private static Part cachePart; //private static Part cachePart;
//private static PartModule cachePartModule; //private static PartModule cachePartModule;
//private static PartResource cachePartResource; //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)
{ {
for (int i = 0; i < part.Resources.list.Count; ++i) for (int i = 0; i < part.Resources.list.Count; ++i)
{ {
if (part.Resources.list[i].amount > 0.0) if (part.Resources.list[i].amount > 0.0)
{ {
return true; return true;
} }
} }
return false; return false;
} }
   
/// <summary> /// <summary>
/// Gets whether the part has fuel. /// Gets whether the part has fuel.
/// </summary> /// </summary>
/* not used /* not used
public static bool EngineHasFuel(this Part part) public static bool EngineHasFuel(this Part part)
{ {
PartModule cachePartModule = GetModule<ModuleEngines>(part); PartModule cachePartModule = GetModule<ModuleEngines>(part);
if (cachePartModule != null) if (cachePartModule != null)
{ {
return (cachePartModule as ModuleEngines).getFlameoutState; return (cachePartModule as ModuleEngines).getFlameoutState;
} }
   
cachePartModule = GetModuleMultiModeEngine(part); cachePartModule = GetModuleMultiModeEngine(part);
if (cachePartModule != null) if (cachePartModule != null)
{ {
return (cachePartModule as ModuleEnginesFX).getFlameoutState; 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 /// Gets the cost of the part modules
/// Same as stock but without mem allocation /// Same as stock but without mem allocation
/// </summary> /// </summary>
public static double GetModuleCostsNoAlloc(this Part part, float defaultCost) public static double GetModuleCostsNoAlloc(this Part part, float defaultCost)
{ {
float cost = 0f; float cost = 0f;
for (int i = 0; i < part.Modules.Count; i++) for (int i = 0; i < part.Modules.Count; i++)
{ {
PartModule pm = part.Modules[i]; PartModule pm = part.Modules[i];
if (pm is IPartCostModifier) if (pm is IPartCostModifier)
cost += (pm as IPartCostModifier).GetModuleCost(defaultCost); cost += (pm as IPartCostModifier).GetModuleCost(defaultCost, ModifierStagingSituation.CURRENT);
} }
return cost; return cost;
} }
   
/// <summary> /// <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.GetModuleCostsNoAlloc(0.0f); // part.GetModuleCosts allocate 44B per call. 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>
/* not used /* not used
public static double GetMaxThrust(this Part part) public static double GetMaxThrust(this Part part)
{ {
PartModule cachePartModule = GetModule<ModuleEngines>(part); PartModule cachePartModule = GetModule<ModuleEngines>(part);
if (cachePartModule != null) if (cachePartModule != null)
{ {
return (cachePartModule as ModuleEngines).maxThrust; return (cachePartModule as ModuleEngines).maxThrust;
} }
   
cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part); cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part);
if (cachePartModule != null) if (cachePartModule != null)
{ {
return (cachePartModule as ModuleEnginesFX).maxThrust; return (cachePartModule as ModuleEnginesFX).maxThrust;
} }
   
return 0.0; return 0.0;
} }
*/ */
   
/// <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
{ {
for (int i = 0; i < part.Modules.Count; i++) for (int i = 0; i < part.Modules.Count; i++)
{ {
PartModule pm = part.Modules[i]; PartModule pm = part.Modules[i];
if (pm is T) if (pm is T)
return (T)pm; return (T)pm;
} }
return null; 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 part.Modules[className] as 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 part.Modules[classId] as 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 GetModule<ModuleAlternator>(part); 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 GetModule<ModuleDeployableSolarPanel>(part); 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 GetModule<ModuleEngines>(part); return GetModule<ModuleEngines>(part);
} }
   
/* public static ModuleEnginesFX GetModuleEnginesFx(this Part part) /* public static ModuleEnginesFX GetModuleEnginesFx(this Part part)
{ {
return GetModule<ModuleEnginesFX>(part); 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 GetModule<ModuleGenerator>(part); 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 GetModule<ModuleGimbal>(part); return GetModule<ModuleGimbal>(part);
} }
   
/// <summary> /// <summary>
/// Gets the current selected ModuleEnginesFX. /// Gets the current selected ModuleEnginesFX.
/// </summary> /// </summary>
public static ModuleEngines GetModuleMultiModeEngine(this Part part) public static ModuleEngines GetModuleMultiModeEngine(this Part part)
{ {
ModuleEngines moduleEngines; ModuleEngines moduleEngines;
MultiModeEngine multiMod = GetModule<MultiModeEngine>(part); MultiModeEngine multiMod = GetModule<MultiModeEngine>(part);
if (multiMod != null) if (multiMod != null)
{ {
string mode = multiMod.mode; string mode = multiMod.mode;
for (int i = 0; i < part.Modules.Count; ++i) for (int i = 0; i < part.Modules.Count; ++i)
{ {
moduleEngines = part.Modules[i] as ModuleEngines; moduleEngines = part.Modules[i] as ModuleEngines;
if (moduleEngines != null && moduleEngines.engineID == mode) if (moduleEngines != null && moduleEngines.engineID == mode)
{ {
return moduleEngines; return moduleEngines;
} }
} }
} }
return null; 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 GetModule<ModuleParachute>(part); return GetModule<ModuleParachute>(part);
} }
   
public static ModuleRCS GetModuleRcs(this Part part) public static ModuleRCS GetModuleRcs(this Part part)
{ {
return GetModule<ModuleRCS>(part); 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
{ {
List<T> list = new List<T>(); List<T> list = new List<T>();
for (int i = 0; i < part.Modules.Count; ++i) for (int i = 0; i < part.Modules.Count; ++i)
{ {
T module = part.Modules[i] as T; T module = part.Modules[i] as T;
if (module != null) if (module != null)
{ {
list.Add(module); list.Add(module);
} }
} }
return list; return list;
} }
   
public static ProtoModuleDecoupler GetProtoModuleDecoupler(this Part part) public static ProtoModuleDecoupler GetProtoModuleDecoupler(this Part part)
{ {
PartModule cachePartModule = GetModule<ModuleDecouple>(part); PartModule cachePartModule = GetModule<ModuleDecouple>(part);
if (cachePartModule == null) if (cachePartModule == null)
{ {
cachePartModule = GetModule<ModuleAnchoredDecoupler>(part); cachePartModule = GetModule<ModuleAnchoredDecoupler>(part);
} }
if (cachePartModule != null) if (cachePartModule != null)
{ {
return new ProtoModuleDecoupler(cachePartModule); 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)
{ {
PartModule cachePartModule = GetModule<ModuleEngines>(part); PartModule cachePartModule = GetModule<ModuleEngines>(part);
if (cachePartModule != null) if (cachePartModule != null)
{ {
return new ProtoModuleEngine(cachePartModule); return new ProtoModuleEngine(cachePartModule);
} }
   
cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part); cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part);
if (cachePartModule != null) if (cachePartModule != null)
{ {
return new ProtoModuleEngine(cachePartModule); return new ProtoModuleEngine(cachePartModule);
} }
   
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)
{ {
double cost = 0.0; double cost = 0.0;
for (int i = 0; i < part.Resources.list.Count; ++i) for (int i = 0; i < part.Resources.list.Count; ++i)
{ {
PartResource cachePartResource = part.Resources.list[i]; PartResource cachePartResource = part.Resources.list[i];
cost = cost + (cachePartResource.amount * cachePartResource.info.unitCost); cost = cost + (cachePartResource.amount * cachePartResource.info.unitCost);
} }
return cost; 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)
{ {
double sum = 0; double sum = 0;
for (int i = 0; i < part.Resources.list.Count; i++) for (int i = 0; i < part.Resources.list.Count; i++)
{ {
PartResource r = part.Resources.list[i]; PartResource r = part.Resources.list[i];
sum += (r.maxAmount - r.amount) * r.info.unitCost; sum += (r.maxAmount - r.amount) * r.info.unitCost;
} }
return sum; 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)
{ {
double cost = 0.0; double cost = 0.0;
for (int i = 0; i < part.Resources.list.Count; ++i) for (int i = 0; i < part.Resources.list.Count; ++i)
{ {
PartResource cachePartResource = part.Resources.list[i]; PartResource cachePartResource = part.Resources.list[i];
cost = cost + (cachePartResource.maxAmount * cachePartResource.info.unitCost); cost = cost + (cachePartResource.maxAmount * cachePartResource.info.unitCost);
} }
return cost; return cost;
} }
   
/// <summary> /// <summary>
/// Gets the current specific impulse for the engine. /// Gets the current specific impulse for the engine.
/// </summary> /// </summary>
/* not used /* not used
public static double GetSpecificImpulse(this Part part, float atmosphere) public static double GetSpecificImpulse(this Part part, float atmosphere)
{ {
PartModule cachePartModule = GetModule<ModuleEngines>(part); PartModule cachePartModule = GetModule<ModuleEngines>(part);
if (cachePartModule != null) if (cachePartModule != null)
{ {
return (cachePartModule as ModuleEngines).atmosphereCurve.Evaluate(atmosphere); return (cachePartModule as ModuleEngines).atmosphereCurve.Evaluate(atmosphere);
} }
   
cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part); cachePartModule = GetModuleMultiModeEngine(part) ?? GetModule<ModuleEnginesFX>(part);
if (cachePartModule != null) if (cachePartModule != null)
{ {
return (cachePartModule as ModuleEnginesFX).atmosphereCurve.Evaluate(atmosphere); return (cachePartModule as ModuleEnginesFX).atmosphereCurve.Evaluate(atmosphere);
} }
   
return 0.0; return 0.0;
} }
*/ */
   
/// <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
{ {
for (int i = 0; i < part.Modules.Count; i++) for (int i = 0; i < part.Modules.Count; i++)
{ {
if (part.Modules[i] is T) if (part.Modules[i] is T)
return true; return true;
} }
return false; 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
{ {
for (int i = 0; i < part.Modules.Count; i++) for (int i = 0; i < part.Modules.Count; i++)
{ {
PartModule pm = part.Modules[i]; PartModule pm = part.Modules[i];
if (pm is T && predicate(pm as T)) if (pm is T && predicate(pm as T))
return true; return true;
} }
return false; 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)
{ {
PartModule cachePartModule = GetModule<ModuleAnimateGeneric>(part); PartModule cachePartModule = GetModule<ModuleAnimateGeneric>(part);
return cachePartModule != null && (cachePartModule as ModuleAnimateGeneric).isOneShot; 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 HasModule<ModuleCommand>(part); 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 ((IsDecoupler(part) || IsLaunchClamp(part)) && 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 IsDecoupledInStage(part.parent, 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 HasModule<ModuleDecouple>(part) || HasModule<ModuleAnchoredDecoupler>(part); 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 HasModule<ModuleEngines>(part); return HasModule<ModuleEngines>(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 HasModule<ModuleGenerator>(part); 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 HasModule<LaunchClamp>(part); 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 HasModule<ModuleParachute>(part); 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)
{ {
for (int i = 0; i < partsList.Count; i++) for (int i = 0; i < partsList.Count; i++)
{ {
var vesselPart = partsList[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 HasModule<ModuleRCS>(part); 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 IsSolidRocket(part) && part.ActivatesEvenIfDisconnected && IsDecoupledInStage(part, 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 HasModule<ModuleDeployableSolarPanel>(part); 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);
} }
   
public class ProtoModuleDecoupler public class ProtoModuleDecoupler
{ {
private readonly PartModule module; private readonly PartModule module;
   
public ProtoModuleDecoupler(PartModule module) public ProtoModuleDecoupler(PartModule module)
{ {
this.module = module; this.module = module;
   
if (this.module is ModuleDecouple) if (this.module is ModuleDecouple)
{ {
SetModuleDecouple(); SetModuleDecouple();
} }
else if (this.module is ModuleAnchoredDecoupler) else if (this.module is ModuleAnchoredDecoupler)
{ {
SetModuleAnchoredDecoupler(); SetModuleAnchoredDecoupler();
} }
} }
   
public double EjectionForce { get; private set; } public double EjectionForce { get; private set; }
public bool IsOmniDecoupler { get; private set; } public bool IsOmniDecoupler { get; private set; }
public bool IsStageEnabled { get; private set; } public bool IsStageEnabled { get; private set; }
   
private void SetModuleAnchoredDecoupler() private void SetModuleAnchoredDecoupler()
{ {
ModuleAnchoredDecoupler decoupler = module as ModuleAnchoredDecoupler; ModuleAnchoredDecoupler decoupler = module as ModuleAnchoredDecoupler;
if (decoupler == null) if (decoupler == null)
{ {
return; return;
} }
   
EjectionForce = decoupler.ejectionForce; EjectionForce = decoupler.ejectionForce;
IsStageEnabled = decoupler.stagingEnabled; IsStageEnabled = decoupler.stagingEnabled;
} }
   
private void SetModuleDecouple() private void SetModuleDecouple()
{ {
ModuleDecouple decoupler = module as ModuleDecouple; ModuleDecouple decoupler = module as ModuleDecouple;
if (decoupler == null) if (decoupler == null)
{ {
return; return;
} }
   
EjectionForce = decoupler.ejectionForce; EjectionForce = decoupler.ejectionForce;
IsOmniDecoupler = decoupler.isOmniDecoupler; IsOmniDecoupler = decoupler.isOmniDecoupler;
IsStageEnabled = decoupler.stagingEnabled; IsStageEnabled = decoupler.stagingEnabled;
} }
} }
   
// This needs updating to handle multi-mode engines and engines with multiple ModuleEngines correctly. // This needs updating to handle multi-mode engines and engines with multiple ModuleEngines correctly.
// It currently just shows the stats of the currently active module for multi-mode engines and just // It currently just shows the stats of the currently active module for multi-mode engines and just
// the first ModuleEngines for engines with multiple modules. // the first ModuleEngines for engines with multiple modules.
// It should really show all the modes for multi-mode engines as separate sections. // It should really show all the modes for multi-mode engines as separate sections.
// For other engines with multiple ModuleEngines it should combine the separate modules into a single set of data // For other engines with multiple ModuleEngines it should combine the separate modules into a single set of data
// The constructor should be changed to take the Part itself. It can be called if HasModule<ModuleEngines>() is true. // The constructor should be changed to take the Part itself. It can be called if HasModule<ModuleEngines>() is true.
public class ProtoModuleEngine public class ProtoModuleEngine
{ {
private readonly PartModule module; private readonly PartModule module;
   
public ProtoModuleEngine(PartModule module) public ProtoModuleEngine(PartModule module)
{ {
this.module = module; this.module = module;
   
if (module is ModuleEngines) if (module is ModuleEngines)
{ {
SetModuleEngines(); SetModuleEngines();
} }
} }
   
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; }
   
public float GetSpecificImpulse(float atmosphere) public float GetSpecificImpulse(float atmosphere)
{ {
if (module is ModuleEngines) if (module is ModuleEngines)
{ {
return (module as ModuleEngines).atmosphereCurve.Evaluate(atmosphere); return (module as ModuleEngines).atmosphereCurve.Evaluate(atmosphere);
} }
return 0.0f; return 0.0f;
} }
   
private void SetModuleEngines() private void SetModuleEngines()
{ {
ModuleEngines engine = module as ModuleEngines; ModuleEngines engine = module as ModuleEngines;
if (engine == null) if (engine == null)
{ {
return; return;
} }
   
MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01); MaximumThrust = engine.maxThrust * (engine.thrustPercentage * 0.01);
MinimumThrust = engine.minThrust; MinimumThrust = engine.minThrust;
Propellants = engine.propellants; Propellants = engine.propellants;
} }
} }
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2016 CYBUTEK // Copyright (C) 2016 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 namespace KerbalEngineer.Flight
{ {
using System.Collections.Generic; using System.Collections.Generic;
using KSP.UI; using KSP.UI;
using Sections; using Sections;
using Unity.Flight; using Unity.Flight;
using UnityEngine; using UnityEngine;
   
[KSPAddon(KSPAddon.Startup.Flight, false)] [KSPAddon(KSPAddon.Startup.Flight, false)]
public class FlightAppLauncher : AppLauncherButton, IFlightAppLauncher public class FlightAppLauncher : AppLauncherButton, IFlightAppLauncher
{ {
private static FlightAppLauncher m_Instance; private static FlightAppLauncher s_Instance;
private FlightMenu m_FlightMenu; private FlightMenu m_FlightMenu;
private GameObject m_MenuObject; private GameObject m_MenuObject;
private GameObject m_MenuPrefab; private GameObject m_MenuPrefab;
   
/// <summary> /// <summary>
/// Gets the current instance of the FlightAppLauncher object. /// Gets the current instance of the FlightAppLauncher object.
/// </summary> /// </summary>
public static FlightAppLauncher Instance public static FlightAppLauncher Instance
{ {
get get
{ {
return m_Instance; return s_Instance;
} }
} }
   
/// <summary> /// <summary>
/// Applies the KSP theme to a game object and its children. /// Applies the KSP theme to a game object and its children.
/// </summary> /// </summary>
public void ApplyTheme(GameObject gameObject) public void ApplyTheme(GameObject gameObject)
{ {
StyleManager.Process(gameObject); StyleManager.Process(gameObject);
} }
   
/// <summary> /// <summary>
/// Clamps the given rect transform within the screen bounds. /// Clamps the given rect transform within the screen bounds.
/// </summary> /// </summary>
public void ClampToScreen(RectTransform rectTransform) public void ClampToScreen(RectTransform rectTransform)
{ {
UIMasterController.ClampToScreen(rectTransform, Vector2.zero); UIMasterController.ClampToScreen(rectTransform, Vector2.zero);
} }
   
/// <summary> /// <summary>
/// Gets a list of custom sections. /// Gets a list of custom sections.
/// </summary> /// </summary>
IList<ISectionModule> IFlightAppLauncher.GetCustomSections() IList<ISectionModule> IFlightAppLauncher.GetCustomSections()
{ {
return new List<ISectionModule>(SectionLibrary.CustomSections.ToArray()); return new List<ISectionModule>(SectionLibrary.CustomSections.ToArray());
} }
   
/// <summary> /// <summary>
/// Gets a list of stock sections. /// Gets a list of stock sections.
/// </summary> /// </summary>
IList<ISectionModule> IFlightAppLauncher.GetStockSections() IList<ISectionModule> IFlightAppLauncher.GetStockSections()
{ {
return new List<ISectionModule>(SectionLibrary.StockSections.ToArray()); return new List<ISectionModule>(SectionLibrary.StockSections.ToArray());
} }
   
/// <summary> /// <summary>
/// Gets or sets the control bar's visibility. /// Gets or sets the control bar's visibility.
/// </summary> /// </summary>
public bool IsControlBarVisible public bool IsControlBarVisible
{ {
get get
{ {
if (DisplayStack.Instance != null) if (DisplayStack.Instance != null)
{ {
return DisplayStack.Instance.ShowControlBar; return DisplayStack.Instance.ShowControlBar;
} }
   
return false; return false;
} }
set set
{ {
if (DisplayStack.Instance != null) if (DisplayStack.Instance != null)
{ {
DisplayStack.Instance.ShowControlBar = value; DisplayStack.Instance.ShowControlBar = value;
} }
} }
} }
   
/// <summary> /// <summary>
/// Gets or sets the display stack's visibility. /// Gets or sets the display stack's visibility.
/// </summary> /// </summary>
public bool IsDisplayStackVisible public bool IsDisplayStackVisible
{ {
get get
{ {
if (DisplayStack.Instance != null) if (DisplayStack.Instance != null)
{ {
return DisplayStack.Instance.Hidden == false; return DisplayStack.Instance.Hidden == false;
} }
   
return false; return false;
} }
set set
{ {
if (DisplayStack.Instance != null) if (DisplayStack.Instance != null)
{ {
DisplayStack.Instance.Hidden = !value; DisplayStack.Instance.Hidden = !value;
} }
} }
} }
   
/// <summary> /// <summary>
/// Creates and initialises a new custom section. /// Creates and initialises a new custom section.
/// </summary> /// </summary>
public ISectionModule NewCustomSection() public ISectionModule NewCustomSection()
{ {
SectionModule section = new SectionModule SectionModule section = new SectionModule
{ {
Name = "Custom " + (SectionLibrary.CustomSections.Count + 1), Name = "Custom " + (SectionLibrary.CustomSections.Count + 1),
Abbreviation = "CUST " + (SectionLibrary.CustomSections.Count + 1), Abbreviation = "CUST " + (SectionLibrary.CustomSections.Count + 1),
IsVisible = true, IsVisible = true,
IsCustom = true, IsCustom = true,
IsEditorVisible = true IsEditorVisible = true
}; };
   
SectionLibrary.CustomSections.Add(section); SectionLibrary.CustomSections.Add(section);
   
return section; return section;
} }
   
protected override void Awake() protected override void Awake()
{ {
base.Awake(); base.Awake();
   
// set singleton instance // set singleton instance
m_Instance = this; s_Instance = this;
   
// cache menu prefab // cache menu prefab
if (m_MenuPrefab == null && AssetBundleLoader.Prefabs != null) if (m_MenuPrefab == null && AssetBundleLoader.Prefabs != null)
{ {
m_MenuPrefab = AssetBundleLoader.Prefabs.LoadAsset<GameObject>("FlightMenu"); m_MenuPrefab = AssetBundleLoader.Prefabs.LoadAsset<GameObject>("FlightMenu");
} }
} }
   
protected override void OnFalse() protected override void OnFalse()
{ {
Close(); Close();
} }
   
protected override void OnHover() protected override void OnHover()
{ {
Open(); Open();
} }
   
protected override void OnHoverOut() protected override void OnHoverOut()
{ {
if (IsOn == false) if (IsOn == false)
{ {
Close(); Close();
} }
} }
   
protected override void OnTrue() protected override void OnTrue()
{ {
Open(); Open();
  }
   
  protected virtual void Update()
  {
  if (Button == null)
  return;
   
  if (FlightEngineerCore.IsDisplayable && Button.IsEnabled == false)
  {
  Enable();
  }
  else if (FlightEngineerCore.IsDisplayable == false && Button.IsEnabled)
  {
  Disable();
  }
} }
   
/// <summary> /// <summary>
/// Closes the menu. /// Closes the menu.
/// </summary> /// </summary>
private void Close() private void Close()
{ {
if (m_FlightMenu != null) if (m_FlightMenu != null)
{ {
m_FlightMenu.Close(); m_FlightMenu.Close();
} }
else if (m_MenuObject != null) else if (m_MenuObject != null)
{ {
Destroy(m_MenuObject); Destroy(m_MenuObject);
} }
} }
   
/// <summary> /// <summary>
/// Opens the menu. /// Opens the menu.
/// </summary> /// </summary>
private void Open() private void Open()
{ {
// fade menu in if already open // fade menu in if already open
if (m_FlightMenu != null) if (m_FlightMenu != null)
{ {
m_FlightMenu.FadeIn(); m_FlightMenu.FadeIn();
return; return;
} }
   
if (m_MenuPrefab == null || m_MenuObject != null) if (m_MenuPrefab == null || m_MenuObject != null)
{ {
return; return;
} }
   
// create object // create object
m_MenuObject = Instantiate(m_MenuPrefab, GetAnchor(), Quaternion.identity) as GameObject; m_MenuObject = Instantiate(m_MenuPrefab, GetAnchor(), Quaternion.identity) as GameObject;
if (m_MenuObject == null) if (m_MenuObject == null)
{ {
return; return;
} }
   
StyleManager.Process(m_MenuObject); StyleManager.Process(m_MenuObject);
   
// set object as a child of the main canvas // set object as a child of the main canvas
m_MenuObject.transform.SetParent(MainCanvasUtil.MainCanvas.transform); m_MenuObject.transform.SetParent(MainCanvasUtil.MainCanvas.transform);
   
// set menu's reference to this object for cross-communication // set menu's reference to this object for cross-communication
m_FlightMenu = m_MenuObject.GetComponent<FlightMenu>(); m_FlightMenu = m_MenuObject.GetComponent<FlightMenu>();
if (m_FlightMenu != null) if (m_FlightMenu != null)
{ {
m_FlightMenu.SetFlightAppLauncher(this); m_FlightMenu.SetFlightAppLauncher(this);
} }
} }
} }
} }
// //
// 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 namespace KerbalEngineer.Flight
{ {
#region Using Directives #region Using Directives
   
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Extensions; using Extensions;
using Readouts; using Readouts;
using Sections; using Sections;
using Settings; using Settings;
using UnityEngine; using UnityEngine;
using VesselSimulator; using VesselSimulator;
   
#endregion #endregion
   
/// <summary> /// <summary>
/// Core management system for the Flight Engineer. /// Core management system for the Flight Engineer.
/// </summary> /// </summary>
[KSPAddon(KSPAddon.Startup.Flight, false)] [KSPAddon(KSPAddon.Startup.Flight, false)]
public sealed class FlightEngineerCore : MonoBehaviour public sealed class FlightEngineerCore : MonoBehaviour
{ {
#region Instance #region Instance
   
/// <summary> /// <summary>
/// Gets the current instance of FlightEngineerCore. /// Gets the current instance of FlightEngineerCore.
/// </summary> /// </summary>
public static FlightEngineerCore Instance { get; private set; } public static FlightEngineerCore Instance { get; private set; }
   
#endregion #endregion
   
#region Fields #region Fields
   
private static bool isCareerMode = true; private static bool isCareerMode = true;
private static bool isKerbalLimited = true; private static bool isKerbalLimited = true;
private static bool isTrackingStationLimited = true; private static bool isTrackingStationLimited = true;
   
#endregion #endregion
   
#region Constructors #region Constructors
   
static FlightEngineerCore() static FlightEngineerCore()
{ {
try try
{ {
var handler = SettingHandler.Load("FlightEngineerCore.xml"); var handler = SettingHandler.Load("FlightEngineerCore.xml");
handler.Get("isCareerMode", ref isCareerMode); handler.Get("isCareerMode", ref isCareerMode);
handler.Get("isKerbalLimited", ref isKerbalLimited); handler.Get("isKerbalLimited", ref isKerbalLimited);
handler.Get("isTrackingStationLimited", ref isTrackingStationLimited); handler.Get("isTrackingStationLimited", ref isTrackingStationLimited);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
   
#region Properties #region Properties
   
/// <summary> /// <summary>
/// Gets and sets whether to the Flight Engineer should be run using career limitations. /// Gets and sets whether to the Flight Engineer should be run using career limitations.
/// </summary> /// </summary>
public static bool IsCareerMode public static bool IsCareerMode
{ {
get { return isCareerMode; } get { return isCareerMode; }
set set
{ {
try try
{ {
if (isCareerMode != value) if (isCareerMode != value)
{ {
var handler = SettingHandler.Load("FlightEngineerCore.xml"); var handler = SettingHandler.Load("FlightEngineerCore.xml");
handler.Set("isCareerMode", value); handler.Set("isCareerMode", value);
handler.Save("FlightEngineerCore.xml"); handler.Save("FlightEngineerCore.xml");
} }
isCareerMode = value; isCareerMode = value;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
} }
   
/// <summary> /// <summary>
/// Gets whether the FlightEngineer should be displayed. /// Gets whether the FlightEngineer should be displayed.
/// </summary> /// </summary>
public static bool IsDisplayable public static bool IsDisplayable
{ {
get get
{ {
if (MainCanvasUtil.MainCanvas.enabled == false) if (MainCanvasUtil.MainCanvas.enabled == false)
{ {
return false; return false;
} }
   
if (isCareerMode) if (isCareerMode)
{ {
if (isKerbalLimited && FlightGlobals.ActiveVessel.GetVesselCrew().Exists(c => c.experienceTrait.TypeName == "Engineer")) if (isKerbalLimited && FlightGlobals.ActiveVessel.GetVesselCrew().Exists(c => c.experienceTrait.TypeName == "Engineer"))
{ {
return true; return true;
} }
if (isTrackingStationLimited && ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) == 1.0f) if (isTrackingStationLimited && ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) == 1.0f)
{ {
return true; return true;
} }
return FlightGlobals.ActiveVessel.parts.Any(p => p.HasModule<FlightEngineerModule>()); return FlightGlobals.ActiveVessel.parts.Any(p => p.HasModule<FlightEngineerModule>());
} }
   
return true; return true;
} }
} }
   
/// <summary> /// <summary>
/// Gets and sets whether to the Flight Engineer should be kerbal limited. /// Gets and sets whether to the Flight Engineer should be kerbal limited.
/// </summary> /// </summary>
public static bool IsKerbalLimited public static bool IsKerbalLimited
{ {
get { return isKerbalLimited; } get { return isKerbalLimited; }
set set
{ {
try try
{ {
if (isKerbalLimited != value) if (isKerbalLimited != value)
{ {
var handler = SettingHandler.Load("FlightEngineerCore.xml"); var handler = SettingHandler.Load("FlightEngineerCore.xml");
handler.Set("isKerbalLimited", value); handler.Set("isKerbalLimited", value);
handler.Save("FlightEngineerCore.xml"); handler.Save("FlightEngineerCore.xml");
} }
isKerbalLimited = value; isKerbalLimited = value;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
} }
   
/// <summary> /// <summary>
/// Gets and sets whether to the Flight Engineer should be tracking station limited. /// Gets and sets whether to the Flight Engineer should be tracking station limited.
/// </summary> /// </summary>
public static bool IsTrackingStationLimited public static bool IsTrackingStationLimited
{ {
get { return isTrackingStationLimited; } get { return isTrackingStationLimited; }
set set
{ {
try try
{ {
if (isTrackingStationLimited != value) if (isTrackingStationLimited != value)
{ {
var handler = SettingHandler.Load("FlightEngineerCore.xml"); var handler = SettingHandler.Load("FlightEngineerCore.xml");
handler.Set("isTrackingStationLimited", value); handler.Set("isTrackingStationLimited", value);
handler.Save("FlightEngineerCore.xml"); handler.Save("FlightEngineerCore.xml");
} }
isTrackingStationLimited = value; isTrackingStationLimited = value;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
} }
   
/// <summary> /// <summary>
/// Gets the editor windows for sections with open editors. /// Gets the editor windows for sections with open editors.
/// </summary> /// </summary>
public List<SectionEditor> SectionEditors { get; private set; } public List<SectionEditor> SectionEditors { get; private set; }
   
/// <summary> /// <summary>
/// Gets the section windows for floating sections. /// Gets the section windows for floating sections.
/// </summary> /// </summary>
public List<SectionWindow> SectionWindows { get; private set; } public List<SectionWindow> SectionWindows { get; private set; }
   
/// <summary> /// <summary>
/// Gets the list of currently running updatable modules. /// Gets the list of currently running updatable modules.
/// </summary> /// </summary>
public List<IUpdatable> UpdatableModules { get; private set; } public List<IUpdatable> UpdatableModules { get; private set; }
   
#endregion #endregion
   
#region Methods #region Methods
   
/// <summary> /// <summary>
/// Creates a section editor, adds it to the FlightEngineerCore and returns a reference to it. /// Creates a section editor, adds it to the FlightEngineerCore and returns a reference to it.
/// </summary> /// </summary>
public SectionEditor AddSectionEditor(SectionModule section) public SectionEditor AddSectionEditor(SectionModule section)
{ {
try try
{ {
var editor = this.gameObject.AddComponent<SectionEditor>(); var editor = this.gameObject.AddComponent<SectionEditor>();
editor.ParentSection = section; editor.ParentSection = section;
editor.Position = new Rect(section.EditorPositionX, section.EditorPositionY, SectionEditor.Width, SectionEditor.Height); editor.Position = new Rect(section.EditorPositionX, section.EditorPositionY, SectionEditor.Width, SectionEditor.Height);
this.SectionEditors.Add(editor); this.SectionEditors.Add(editor);
return editor; return editor;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
return null; return null;
} }
} }
   
/// <summary> /// <summary>
/// Creates a section window, adds it to the FlightEngineerCore and returns a reference to it. /// Creates a section window, adds it to the FlightEngineerCore and returns a reference to it.
/// </summary> /// </summary>
public SectionWindow AddSectionWindow(SectionModule section) public SectionWindow AddSectionWindow(SectionModule section)
{ {
try try
{ {
var window = this.gameObject.AddComponent<SectionWindow>(); var window = this.gameObject.AddComponent<SectionWindow>();
window.ParentSection = section; window.ParentSection = section;
window.WindowPosition = new Rect(section.FloatingPositionX, section.FloatingPositionY, 0, 0); window.WindowPosition = new Rect(section.FloatingPositionX, section.FloatingPositionY, 0, 0);
this.SectionWindows.Add(window); this.SectionWindows.Add(window);
return window; return window;
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
return null; return null;
} }
} }
   
/// <summary> /// <summary>
/// Adds an updatable object to be automatically updated every frame and will ignore duplicate objects. /// Adds an updatable object to be automatically updated every frame and will ignore duplicate objects.
/// </summary> /// </summary>
public void AddUpdatable(IUpdatable updatable) public void AddUpdatable(IUpdatable updatable)
{ {
try try
{ {
if (!this.UpdatableModules.Contains(updatable)) if (!this.UpdatableModules.Contains(updatable))
{ {
this.UpdatableModules.Add(updatable); this.UpdatableModules.Add(updatable);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Create base Flight Engineer child objects. /// Create base Flight Engineer child objects.
/// </summary> /// </summary>
private void Awake() private void Awake()
{ {
try try
{ {
Instance = this; Instance = this;
   
this.SectionWindows = new List<SectionWindow>(); this.SectionWindows = new List<SectionWindow>();
this.SectionEditors = new List<SectionEditor>(); this.SectionEditors = new List<SectionEditor>();
this.UpdatableModules = new List<IUpdatable>(); this.UpdatableModules = new List<IUpdatable>();
   
SimManager.UpdateModSettings(); SimManager.UpdateModSettings();
   
Logger.Log("FlightEngineerCore->Awake"); Logger.Log("FlightEngineerCore->Awake");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Fixed update all required Flight Engineer objects. /// Fixed update all required Flight Engineer objects.
/// </summary> /// </summary>
private void FixedUpdate() private void FixedUpdate()
{ {
  if (FlightGlobals.ActiveVessel == null)
  return;
   
try try
{ {
SectionLibrary.FixedUpdate(); SectionLibrary.FixedUpdate();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Force the destruction of child objects on core destruction. /// Force the destruction of child objects on core destruction.
/// </summary> /// </summary>
private void OnDestroy() private void OnDestroy()
{ {
try try
{ {
SectionLibrary.Save(); SectionLibrary.Save();
   
foreach (var window in this.SectionWindows) foreach (var window in this.SectionWindows)
{ {
print("[FlightEngineer]: Destroying Floating Window for " + window.ParentSection.Name); print("[FlightEngineer]: Destroying Floating Window for " + window.ParentSection.Name);
Destroy(window); Destroy(window);
} }
   
foreach (var editor in this.SectionEditors) foreach (var editor in this.SectionEditors)
{ {
print("[FlightEngineer]: Destroying Editor Window for " + editor.ParentSection.Name); print("[FlightEngineer]: Destroying Editor Window for " + editor.ParentSection.Name);
Destroy(editor); Destroy(editor);
} }
   
Logger.Log("FlightEngineerCore->OnDestroy"); Logger.Log("FlightEngineerCore->OnDestroy");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Initialises the object's state on creation. /// Initialises the object's state on creation.
/// </summary> /// </summary>
private void Start() private void Start()
{ {
try try
{ {
SectionLibrary.Load(); SectionLibrary.Load();
ReadoutLibrary.Reset(); ReadoutLibrary.Reset();
Logger.Log("FlightEngineerCore->Start"); Logger.Log("FlightEngineerCore->Start");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Update all required Flight Engineer objects. /// Update all required Flight Engineer objects.
/// </summary> /// </summary>
private void Update() private void Update()
{ {
  if (FlightGlobals.ActiveVessel == null)
  return;
   
try try
{ {
SectionLibrary.Update(); SectionLibrary.Update();
this.UpdateModules(); this.UpdateModules();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Update all updatable modules. /// Update all updatable modules.
/// </summary> /// </summary>
private void UpdateModules() private void UpdateModules()
{ {
try try
{ {
foreach (var updatable in this.UpdatableModules) foreach (var updatable in this.UpdatableModules)
{ {
if (updatable is IUpdateRequest) if (updatable is IUpdateRequest)
{ {
var request = updatable as IUpdateRequest; var request = updatable as IUpdateRequest;
if (request.UpdateRequested) if (request.UpdateRequested)
{ {
updatable.Update(); updatable.Update();
request.UpdateRequested = false; request.UpdateRequested = false;
} }
} }
else else
{ {
updatable.Update(); updatable.Update();
} }
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
#endregion #endregion
} }
} }
  //
  // Kerbal Engineer Redux
  //
  // Copyright (C) 2014 CYBUTEK
  //
  // This program is free software: you can redistribute it and/or modify
  // it under the terms of the GNU General Public License as published by
  // the Free Software Foundation, either version 3 of the License, or
  // (at your option) any later version.
  //
  // This program is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  // GNU General Public License for more details.
  //
  // You should have received a copy of the GNU General Public License
  // along with this program. If not, see <http://www.gnu.org/licenses/>.
  //
 
  namespace KerbalEngineer.Flight.Readouts.Miscellaneous
  {
  #region Using Directives
 
  using Sections;
  using UnityEngine;
  using VesselSimulator;
 
  #endregion
 
  public class LogSimToggle : ReadoutModule
  {
  #region Constructors
 
  public LogSimToggle()
  {
  this.Name = "Log Simulation";
  this.Category = ReadoutCategory.GetCategory("Miscellaneous");
  this.HelpString = "Shows a button that allows you to make the next run of the simulation code dump extra debugging output.";
  this.IsDefault = false;
  }
 
  #endregion
 
  #region Methods
 
  public override void Draw(SectionModule section)
  {
  GUILayout.BeginHorizontal();
  GUILayout.Label("Log Simulation: ", this.NameStyle);
  SimManager.logOutput = GUILayout.Toggle(SimManager.logOutput, "ENABLED", this.ButtonStyle);
  GUILayout.EndHorizontal();
  }
 
  #endregion
  }
  }
// //
// Copyright (C) 2015 CYBUTEK // Copyright (C) 2015 CYBUTEK
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
   
namespace KerbalEngineer.Flight.Readouts namespace KerbalEngineer.Flight.Readouts
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Miscellaneous; using Miscellaneous;
using Orbital; using Orbital;
using Orbital.ManoeuvreNode; using Orbital.ManoeuvreNode;
using Rendezvous; using Rendezvous;
using Settings; using Settings;
using Surface; using Surface;
using Thermal; using Thermal;
using Vessel; using Vessel;
using AltitudeSeaLevel = Surface.AltitudeSeaLevel; using AltitudeSeaLevel = Surface.AltitudeSeaLevel;
using ApoapsisHeight = Orbital.ApoapsisHeight; using ApoapsisHeight = Orbital.ApoapsisHeight;
using OrbitalPeriod = Orbital.OrbitalPeriod; using OrbitalPeriod = Orbital.OrbitalPeriod;
using PeriapsisHeight = Orbital.PeriapsisHeight; using PeriapsisHeight = Orbital.PeriapsisHeight;
using SemiMajorAxis = Orbital.SemiMajorAxis; using SemiMajorAxis = Orbital.SemiMajorAxis;
using SemiMinorAxis = Orbital.SemiMinorAxis; using SemiMinorAxis = Orbital.SemiMinorAxis;
using TimeToApoapsis = Orbital.TimeToApoapsis; using TimeToApoapsis = Orbital.TimeToApoapsis;
using TimeToPeriapsis = Orbital.TimeToPeriapsis; using TimeToPeriapsis = Orbital.TimeToPeriapsis;
   
public static class ReadoutLibrary public static class ReadoutLibrary
{ {
private static List<ReadoutModule> readouts = new List<ReadoutModule>(); private static List<ReadoutModule> readouts = new List<ReadoutModule>();
   
/// <summary> /// <summary>
/// Sets up and populates the readout library with the stock readouts. /// Sets up and populates the readout library with the stock readouts.
/// </summary> /// </summary>
static ReadoutLibrary() static ReadoutLibrary()
{ {
try try
{ {
ReadoutCategory.SetCategory("Orbital", "Readout for orbital manovoeures."); ReadoutCategory.SetCategory("Orbital", "Readout for orbital manovoeures.");
ReadoutCategory.SetCategory("Surface", "Surface and atmospheric readouts."); ReadoutCategory.SetCategory("Surface", "Surface and atmospheric readouts.");
ReadoutCategory.SetCategory("Vessel", "Vessel performance statistics."); ReadoutCategory.SetCategory("Vessel", "Vessel performance statistics.");
ReadoutCategory.SetCategory("Rendezvous", "Readouts for rendezvous manovoeures."); ReadoutCategory.SetCategory("Rendezvous", "Readouts for rendezvous manovoeures.");
ReadoutCategory.SetCategory("Thermal", "Thermal characteristics readouts."); ReadoutCategory.SetCategory("Thermal", "Thermal characteristics readouts.");
ReadoutCategory.SetCategory("Miscellaneous", "Miscellaneous readouts."); ReadoutCategory.SetCategory("Miscellaneous", "Miscellaneous readouts.");
ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital"); ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital");
   
// Orbital // Orbital
readouts.Add(new ApoapsisHeight()); readouts.Add(new ApoapsisHeight());
readouts.Add(new PeriapsisHeight()); readouts.Add(new PeriapsisHeight());
readouts.Add(new TimeToApoapsis()); readouts.Add(new TimeToApoapsis());
readouts.Add(new TimeToPeriapsis()); readouts.Add(new TimeToPeriapsis());
readouts.Add(new Inclination()); readouts.Add(new Inclination());
readouts.Add(new TimeToEquatorialAscendingNode()); readouts.Add(new TimeToEquatorialAscendingNode());
readouts.Add(new TimeToEquatorialDescendingNode()); readouts.Add(new TimeToEquatorialDescendingNode());
readouts.Add(new AngleToEquatorialAscendingNode()); readouts.Add(new AngleToEquatorialAscendingNode());
readouts.Add(new AngleToEquatorialDescendingNode()); readouts.Add(new AngleToEquatorialDescendingNode());
readouts.Add(new Eccentricity()); readouts.Add(new Eccentricity());
readouts.Add(new OrbitalSpeed()); readouts.Add(new OrbitalSpeed());
readouts.Add(new OrbitalPeriod()); readouts.Add(new OrbitalPeriod());
readouts.Add(new CurrentSoi()); readouts.Add(new CurrentSoi());
readouts.Add(new LongitudeOfAscendingNode()); readouts.Add(new LongitudeOfAscendingNode());
readouts.Add(new LongitudeOfPeriapsis()); readouts.Add(new LongitudeOfPeriapsis());
readouts.Add(new ArgumentOfPeriapsis()); readouts.Add(new ArgumentOfPeriapsis());
readouts.Add(new TrueAnomaly()); readouts.Add(new TrueAnomaly());
readouts.Add(new MeanAnomaly()); readouts.Add(new MeanAnomaly());
readouts.Add(new MeanAnomalyAtEpoc()); readouts.Add(new MeanAnomalyAtEpoc());
readouts.Add(new EccentricAnomaly()); readouts.Add(new EccentricAnomaly());
readouts.Add(new SemiMajorAxis()); readouts.Add(new SemiMajorAxis());
readouts.Add(new SemiMinorAxis()); readouts.Add(new SemiMinorAxis());
readouts.Add(new AngleToPrograde()); readouts.Add(new AngleToPrograde());
readouts.Add(new AngleToRetrograde()); readouts.Add(new AngleToRetrograde());
readouts.Add(new NodeProgradeDeltaV()); readouts.Add(new NodeProgradeDeltaV());
readouts.Add(new NodeNormalDeltaV()); readouts.Add(new NodeNormalDeltaV());
readouts.Add(new NodeRadialDeltaV()); readouts.Add(new NodeRadialDeltaV());
readouts.Add(new NodeTotalDeltaV()); readouts.Add(new NodeTotalDeltaV());
readouts.Add(new NodeBurnTime()); readouts.Add(new NodeBurnTime());
readouts.Add(new NodeHalfBurnTime()); readouts.Add(new NodeHalfBurnTime());
readouts.Add(new NodeTimeToManoeuvre()); readouts.Add(new NodeTimeToManoeuvre());
readouts.Add(new NodeTimeToHalfBurn()); readouts.Add(new NodeTimeToHalfBurn());
readouts.Add(new NodeAngleToPrograde()); readouts.Add(new NodeAngleToPrograde());
readouts.Add(new NodeAngleToRetrograde()); readouts.Add(new NodeAngleToRetrograde());
readouts.Add(new PostBurnApoapsis()); readouts.Add(new PostBurnApoapsis());
readouts.Add(new PostBurnPeriapsis()); readouts.Add(new PostBurnPeriapsis());
readouts.Add(new SpeedAtApoapsis()); readouts.Add(new SpeedAtApoapsis());
readouts.Add(new SpeedAtPeriapsis()); readouts.Add(new SpeedAtPeriapsis());
readouts.Add(new TimeToAtmosphere()); readouts.Add(new TimeToAtmosphere());
   
// Surface // Surface
readouts.Add(new AltitudeSeaLevel()); readouts.Add(new AltitudeSeaLevel());
readouts.Add(new AltitudeTerrain()); readouts.Add(new AltitudeTerrain());
readouts.Add(new AltitudeUnderWater());  
readouts.Add(new VerticalSpeed()); readouts.Add(new VerticalSpeed());
readouts.Add(new VerticalAcceleration()); readouts.Add(new VerticalAcceleration());
readouts.Add(new HorizontalSpeed()); readouts.Add(new HorizontalSpeed());
readouts.Add(new HorizontalAcceleration()); readouts.Add(new HorizontalAcceleration());
readouts.Add(new MachNumber()); readouts.Add(new MachNumber());
readouts.Add(new Latitude()); readouts.Add(new Latitude());
readouts.Add(new Longitude()); readouts.Add(new Longitude());
readouts.Add(new GeeForce()); readouts.Add(new GeeForce());
readouts.Add(new TerminalVelocity()); readouts.Add(new TerminalVelocity());
readouts.Add(new AtmosphericEfficiency()); readouts.Add(new AtmosphericEfficiency());
readouts.Add(new Biome()); readouts.Add(new Biome());
readouts.Add(new Situation()); readouts.Add(new Situation());
readouts.Add(new Slope()); readouts.Add(new Slope());
readouts.Add(new ImpactTime()); readouts.Add(new ImpactTime());
readouts.Add(new ImpactLongitude()); readouts.Add(new ImpactLongitude());
readouts.Add(new ImpactLatitude()); readouts.Add(new ImpactLatitude());
readouts.Add(new ImpactAltitude()); readouts.Add(new ImpactAltitude());
readouts.Add(new ImpactBiome()); readouts.Add(new ImpactBiome());
   
// Vessel // Vessel
readouts.Add(new Name()); readouts.Add(new Name());
readouts.Add(new DeltaVStaged()); readouts.Add(new DeltaVStaged());
readouts.Add(new DeltaVCurrent()); readouts.Add(new DeltaVCurrent());
readouts.Add(new DeltaVTotal()); readouts.Add(new DeltaVTotal());
readouts.Add(new DeltaVCurrentTotal()); readouts.Add(new DeltaVCurrentTotal());
readouts.Add(new SpecificImpulse()); readouts.Add(new SpecificImpulse());
readouts.Add(new Mass()); readouts.Add(new Mass());
readouts.Add(new Thrust()); readouts.Add(new Thrust());
readouts.Add(new ThrustToWeight()); readouts.Add(new ThrustToWeight());
readouts.Add(new ThrustOffsetAngle()); readouts.Add(new ThrustOffsetAngle());
readouts.Add(new ThrustTorque()); readouts.Add(new ThrustTorque());
readouts.Add(new SurfaceThrustToWeight()); readouts.Add(new SurfaceThrustToWeight());
readouts.Add(new Acceleration()); readouts.Add(new Acceleration());
readouts.Add(new SuicideBurnAltitude()); readouts.Add(new SuicideBurnAltitude());
readouts.Add(new SuicideBurnDistance()); readouts.Add(new SuicideBurnDistance());
readouts.Add(new SuicideBurnDeltaV()); readouts.Add(new SuicideBurnDeltaV());
readouts.Add(new IntakeAirUsage()); readouts.Add(new IntakeAirUsage());
readouts.Add(new IntakeAirDemand()); readouts.Add(new IntakeAirDemand());
readouts.Add(new IntakeAirSupply()); readouts.Add(new IntakeAirSupply());
readouts.Add(new IntakeAirDemandSupply()); readouts.Add(new IntakeAirDemandSupply());
readouts.Add(new PartCount()); readouts.Add(new PartCount());
readouts.Add(new Heading()); readouts.Add(new Heading());
readouts.Add(new Pitch()); readouts.Add(new Pitch());
readouts.Add(new Roll()); readouts.Add(new Roll());
readouts.Add(new HeadingRate()); readouts.Add(new HeadingRate());
readouts.Add(new PitchRate()); readouts.Add(new PitchRate());
readouts.Add(new RollRate()); readouts.Add(new RollRate());
   
// Rendezvous // Rendezvous
readouts.Add(new TargetSelector()); readouts.Add(new TargetSelector());
readouts.Add(new PhaseAngle()); readouts.Add(new PhaseAngle());
readouts.Add(new InterceptAngle()); readouts.Add(new InterceptAngle());
readouts.Add(new RelativeVelocity()); readouts.Add(new RelativeVelocity());
readouts.Add(new RelativeSpeed()); readouts.Add(new RelativeSpeed());
readouts.Add(new RelativeInclination()); readouts.Add(new RelativeInclination());
readouts.Add(new TimeToRelativeAscendingNode()); readouts.Add(new TimeToRelativeAscendingNode());
readouts.Add(new TimeToRelativeDescendingNode()); readouts.Add(new TimeToRelativeDescendingNode());
readouts.Add(new AngleToRelativeAscendingNode()); readouts.Add(new AngleToRelativeAscendingNode());
readouts.Add(new AngleToRelativeDescendingNode()); readouts.Add(new AngleToRelativeDescendingNode());
readouts.Add(new Rendezvous.AltitudeSeaLevel()); readouts.Add(new Rendezvous.AltitudeSeaLevel());
readouts.Add(new Rendezvous.ApoapsisHeight()); readouts.Add(new Rendezvous.ApoapsisHeight());
readouts.Add(new Rendezvous.PeriapsisHeight()); readouts.Add(new Rendezvous.PeriapsisHeight());
readouts.Add(new Rendezvous.TimeToApoapsis()); readouts.Add(new Rendezvous.TimeToApoapsis());
readouts.Add(new Rendezvous.TimeToPeriapsis()); readouts.Add(new Rendezvous.TimeToPeriapsis());
readouts.Add(new Distance()); readouts.Add(new Distance());
readouts.Add(new Rendezvous.OrbitalPeriod()); readouts.Add(new Rendezvous.OrbitalPeriod());
readouts.Add(new Rendezvous.SemiMajorAxis()); readouts.Add(new Rendezvous.SemiMajorAxis());
readouts.Add(new Rendezvous.SemiMinorAxis()); readouts.Add(new Rendezvous.SemiMinorAxis());
readouts.Add(new Rendezvous.RelativeRadialVelocity()); readouts.Add(new Rendezvous.RelativeRadialVelocity());
readouts.Add(new Rendezvous.TimeToRendezvous()); readouts.Add(new Rendezvous.TimeToRendezvous());
   
// Thermal // Thermal
readouts.Add(new InternalFlux()); readouts.Add(new InternalFlux());
readouts.Add(new ConvectionFlux()); readouts.Add(new ConvectionFlux());
readouts.Add(new RadiationFlux()); readouts.Add(new RadiationFlux());
readouts.Add(new CriticalPart()); readouts.Add(new CriticalPart());
readouts.Add(new CriticalTemperature()); readouts.Add(new CriticalTemperature());
readouts.Add(new CriticalSkinTemperature()); readouts.Add(new CriticalSkinTemperature());
readouts.Add(new CriticalThermalPercentage()); readouts.Add(new CriticalThermalPercentage());
readouts.Add(new HottestPart()); readouts.Add(new HottestPart());
readouts.Add(new HottestTemperature()); readouts.Add(new HottestTemperature());
readouts.Add(new HottestSkinTemperature()); readouts.Add(new HottestSkinTemperature());
readouts.Add(new CoolestPart()); readouts.Add(new CoolestPart());
readouts.Add(new CoolestTemperature()); readouts.Add(new CoolestTemperature());
readouts.Add(new CoolestSkinTemperature()); readouts.Add(new CoolestSkinTemperature());
   
// Misc // Misc
readouts.Add(new Separator()); readouts.Add(new Separator());
readouts.Add(new GuiSizeAdjustor()); readouts.Add(new GuiSizeAdjustor());
readouts.Add(new SimulationDelay()); readouts.Add(new SimulationDelay());
readouts.Add(new VectoredThrustToggle()); readouts.Add(new VectoredThrustToggle());
readouts.Add(new SystemTime()); readouts.Add(new SystemTime());
  readouts.Add(new LogSimToggle());
   
LoadHelpStrings(); LoadHelpStrings();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
   
/// <summary> /// <summary>
/// Gets and sets the available readout modules. /// Gets and sets the available readout modules.
/// </summary> /// </summary>
public static List<ReadoutModule> Readouts public static List<ReadoutModule> Readouts
{ {
get get
{ {
return readouts; return readouts;
} }
set set
{ {
readouts = value; readouts = value;
} }
} }
   
/// <summary> /// <summary>
/// Gets a list of readout modules which are associated with the specified category. /// Gets a list of readout modules which are associated with the specified category.
/// </summary> /// </summary>
public static List<ReadoutModule> GetCategory(ReadoutCategory category) public static List<ReadoutModule> GetCategory(ReadoutCategory category)
{ {
return readouts.Where(r => r.Category == category).ToList(); return readouts.Where(r => r.Category == category).ToList();
} }
   
/// <summary> /// <summary>
/// Gets a readout module with the specified name or class name. (Returns null if not found.) /// Gets a readout module with the specified name or class name. (Returns null if not found.)
/// </summary> /// </summary>
public static ReadoutModule GetReadout(string name) public static ReadoutModule GetReadout(string name)
{ {
return readouts.FirstOrDefault(r => r.Name == name || r.GetType().Name == name || r.Category + "." + r.GetType().Name == name); return readouts.FirstOrDefault(r => r.Name == name || r.GetType().Name == name || r.Category + "." + r.GetType().Name == name);
} }
   
/// <summary> /// <summary>
/// Resets all the readout modules. /// Resets all the readout modules.
/// </summary> /// </summary>
public static void Reset() public static void Reset()
{ {
foreach (ReadoutModule readout in readouts) foreach (ReadoutModule readout in readouts)
{ {
readout.Reset(); readout.Reset();
} }
} }
   
/// <summary> /// <summary>
/// Loads the help strings from file. /// Loads the help strings from file.
/// </summary> /// </summary>
private static void LoadHelpStrings() private static void LoadHelpStrings()
{ {
try try
{ {
SettingHandler handler = SettingHandler.Load("HelpStrings.xml"); SettingHandler handler = SettingHandler.Load("HelpStrings.xml");
foreach (ReadoutModule readout in readouts) foreach (ReadoutModule readout in readouts)
{ {
readout.HelpString = handler.GetSet(readout.Category + "." + readout.GetType().Name, readout.HelpString); readout.HelpString = handler.GetSet(readout.Category + "." + readout.GetType().Name, readout.HelpString);
} }
handler.Save("HelpStrings.xml"); handler.Save("HelpStrings.xml");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Exception(ex); Logger.Exception(ex);
} }
} }
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2016 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  
   
#endregion  
   
namespace KerbalEngineer.Flight.Readouts.Surface namespace KerbalEngineer.Flight.Readouts.Surface
{ {
#region Using Directives  
   
using Extensions; using Extensions;
using Sections; using Sections;
  using Vessel = global::Vessel;
#endregion  
   
public class AltitudeTerrain : ReadoutModule public class AltitudeTerrain : ReadoutModule
{ {
#region Constructors  
   
public AltitudeTerrain() public AltitudeTerrain()
{ {
this.Name = "Altitude (Terrain)"; Name = "Altitude (Terrain)";
this.Category = ReadoutCategory.GetCategory("Surface"); Category = ReadoutCategory.GetCategory("Surface");
this.HelpString = "Shows the vessel's altitude above the terrain. Turns off if splashed."; HelpString = "Shows the vessel's altitude above the terrain and water's surface, or altitude above underwater terrain whilst splashed down.";
this.IsDefault = true; IsDefault = true;
} }
   
#endregion  
   
#region Methods  
   
public override void Draw(SectionModule section) public override void Draw(SectionModule section)
{ {
if (ScienceUtil.GetExperimentSituation (FlightGlobals.ActiveVessel) != ExperimentSituations.SrfSplashed) if (FlightGlobals.ActiveVessel.terrainAltitude > 0.0 || FlightGlobals.ActiveVessel.situation == Vessel.Situations.SPLASHED)
{ {
if (FlightGlobals.ActiveVessel.terrainAltitude > 0.0) DrawLine((FlightGlobals.ship_altitude - FlightGlobals.ActiveVessel.terrainAltitude).ToDistance(), section.IsHud);
{ }
this.DrawLine ((FlightGlobals.ship_altitude - FlightGlobals.ActiveVessel.terrainAltitude).ToDistance (), section.IsHud); else
} {
else DrawLine((FlightGlobals.ship_altitude).ToDistance(), section.IsHud);
{ }
this.DrawLine ((FlightGlobals.ship_altitude).ToDistance (), section.IsHud);  
}  
}  
} }
   
#endregion  
} }
} }
//  
// Kerbal Engineer Redux  
//  
// Copyright (C) 2014 CYBUTEK  
//  
// This program is free software: you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation, either version 3 of the License, or  
// (at your option) any later version.  
//  
// This program is distributed in the hope that it will be useful,  
// but WITHOUT ANY WARRANTY; without even the implied warranty of  
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
// GNU General Public License for more details.  
//  
// You should have received a copy of the GNU General Public License  
// along with this program. If not, see <http://www.gnu.org/licenses/>.  
//  
 
#region Using Directives  
 
using KerbalEngineer.Extensions;  
using KerbalEngineer.Flight.Sections;  
 
#endregion  
 
namespace KerbalEngineer.Flight.Readouts.Surface  
{  
public class AltitudeUnderWater : ReadoutModule  
{  
#region Constructors  
 
public AltitudeUnderWater()  
{  
this.Name = "Altitude (Terrain Under Water)";  
this.Category = ReadoutCategory.GetCategory("Surface");  
this.HelpString = "While splashed shows the vessel's altitude to the under water Terrain.";  
this.IsDefault = false;  
}  
 
#endregion  
 
#region Methods: public  
 
public override void Draw(SectionModule section)  
{  
if (ScienceUtil.GetExperimentSituation (FlightGlobals.ActiveVessel) == ExperimentSituations.SrfSplashed)  
{  
this.DrawLine ((-(FlightGlobals.ActiveVessel.terrainAltitude - FlightGlobals.ship_altitude)).ToDistance (), section.IsHud);  
}  
}  
 
#endregion  
}  
}  
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
   
#region Using Directives #region Using Directives
   
using KerbalEngineer.Extensions; using KerbalEngineer.Extensions;
using KerbalEngineer.Flight.Sections; using KerbalEngineer.Flight.Sections;
using System; using System;
   
#endregion #endregion
   
namespace KerbalEngineer.Flight.Readouts.Surface namespace KerbalEngineer.Flight.Readouts.Surface
{ {
public class HorizontalSpeed : ReadoutModule public class HorizontalSpeed : ReadoutModule
{ {
#region Constructors #region Constructors
   
public HorizontalSpeed() public HorizontalSpeed()
{ {
this.Name = "Horizontal Speed"; this.Name = "Horizontal Speed";
this.Category = ReadoutCategory.GetCategory("Surface"); this.Category = ReadoutCategory.GetCategory("Surface");
this.HelpString = "Shows the vessel's horizontal speed across a celestial body's surface."; this.HelpString = "Shows the vessel's horizontal speed across a celestial body's surface.";
this.IsDefault = true; this.IsDefault = true;
} }
   
#endregion #endregion
   
#region Methods: public #region Methods: public
   
public override void Draw(SectionModule section) public override void Draw(SectionModule section)
{ {
// Used to do this but the bug-fix to horizontalSrfSpeed in KSP 1.0.3 actually made it worse so workaround this.DrawLine(FlightGlobals.ActiveVessel.horizontalSrfSpeed.ToSpeed(), section.IsHud);
//this.DrawLine(FlightGlobals.ActiveVessel.horizontalSrfSpeed.ToSpeed(), section.IsHud);  
var ves = FlightGlobals.ActiveVessel; // This workaround was used for KSP 1.0.3 and 1.0.4 where horizontalSrfSpeed was really badly broken
double horizSpeed = Math.Sqrt(ves.srfSpeed * ves.srfSpeed - ves.verticalSpeed * ves.verticalSpeed); //var ves = FlightGlobals.ActiveVessel;
this.DrawLine(horizSpeed.ToSpeed(), section.IsHud); //double horizSpeed = Math.Sqrt(ves.srfSpeed * ves.srfSpeed - ves.verticalSpeed * ves.verticalSpeed);
  //this.DrawLine(horizSpeed.ToSpeed(), section.IsHud);
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
   
#region Using Directives #region Using Directives
   
using KerbalEngineer.Extensions; using KerbalEngineer.Extensions;
using KerbalEngineer.Flight.Sections; using KerbalEngineer.Flight.Sections;
  using KerbalEngineer.Helpers;
   
#endregion #endregion
   
namespace KerbalEngineer.Flight.Readouts.Surface namespace KerbalEngineer.Flight.Readouts.Surface
{ {
public class ImpactLatitude : ReadoutModule public class ImpactLatitude : ReadoutModule
{ {
#region Constructors #region Constructors
   
public ImpactLatitude() public ImpactLatitude()
{ {
this.Name = "Impact Latitude"; this.Name = "Impact Latitude";
this.Category = ReadoutCategory.GetCategory("Surface"); this.Category = ReadoutCategory.GetCategory("Surface");
this.HelpString = "Latitude of the impact position."; this.HelpString = "Latitude of the impact position.";
this.IsDefault = false; this.IsDefault = false;
} }
   
#endregion #endregion
   
#region Methods: public #region Methods: public
   
public override void Draw(SectionModule section) public override void Draw(SectionModule section)
{ {
if (ImpactProcessor.ShowDetails) if (ImpactProcessor.ShowDetails)
{ {
this.DrawLine(ImpactProcessor.Latitude.ToAngle(), section.IsHud); this.DrawLine(Units.ToAngleDMS(ImpactProcessor.Latitude) + (ImpactProcessor.Latitude < 0 ? " S" : " N"), section.IsHud);
} }
} }
   
public override void Reset() public override void Reset()
{ {
FlightEngineerCore.Instance.AddUpdatable(ImpactProcessor.Instance); FlightEngineerCore.Instance.AddUpdatable(ImpactProcessor.Instance);
} }
   
public override void Update() public override void Update()
{ {
ImpactProcessor.RequestUpdate(); ImpactProcessor.RequestUpdate();
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
   
#region Using Directives #region Using Directives
   
using KerbalEngineer.Extensions; using KerbalEngineer.Extensions;
using KerbalEngineer.Flight.Sections; using KerbalEngineer.Flight.Sections;
  using KerbalEngineer.Helpers;
   
#endregion #endregion
   
namespace KerbalEngineer.Flight.Readouts.Surface namespace KerbalEngineer.Flight.Readouts.Surface
{ {
public class ImpactLongitude : ReadoutModule public class ImpactLongitude : ReadoutModule
{ {
#region Constructors #region Constructors
   
public ImpactLongitude() public ImpactLongitude()
{ {
this.Name = "Impact Longitude"; this.Name = "Impact Longitude";
this.Category = ReadoutCategory.GetCategory("Surface"); this.Category = ReadoutCategory.GetCategory("Surface");
this.HelpString = "Longditude of the impact position."; this.HelpString = "Longditude of the impact position.";
this.IsDefault = false; this.IsDefault = false;
} }
   
#endregion #endregion
   
#region Methods: public #region Methods: public
   
public override void Draw(SectionModule section) public override void Draw(SectionModule section)
{ {
if (ImpactProcessor.ShowDetails) if (ImpactProcessor.ShowDetails)
{ {
this.DrawLine(ImpactProcessor.Longitude.ToAngle(), section.IsHud); this.DrawLine(Units.ToAngleDMS(ImpactProcessor.Longitude) + (ImpactProcessor.Longitude < 0.0 ? "W" : " E"), section.IsHud);
} }
} }
   
public override void Reset() public override void Reset()
{ {
FlightEngineerCore.Instance.AddUpdatable(ImpactProcessor.Instance); FlightEngineerCore.Instance.AddUpdatable(ImpactProcessor.Instance);
} }
   
public override void Update() public override void Update()
{ {
ImpactProcessor.RequestUpdate(); ImpactProcessor.RequestUpdate();
} }
   
#endregion #endregion
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
   
#region Using Directives #region Using Directives
   
using System; using System;
   
using UnityEngine; using UnityEngine;
   
#endregion #endregion
   
// The calculations and functional code in this processor were generously developed by mic_e. // The calculations and functional code in this processor were generously developed by mic_e.
   
namespace KerbalEngineer.Flight.Readouts.Surface namespace KerbalEngineer.Flight.Readouts.Surface
{ {
public class ImpactProcessor : IUpdatable, IUpdateRequest public class ImpactProcessor : IUpdatable, IUpdateRequest
{ {
#region Instance #region Instance
   
#region Fields #region Fields
   
private static readonly ImpactProcessor instance = new ImpactProcessor(); private static readonly ImpactProcessor instance = new ImpactProcessor();
   
#endregion #endregion
   
#region Properties #region Properties
   
/// <summary> /// <summary>
/// Gets the current instance of the impact processor. /// Gets the current instance of the impact processor.
/// </summary> /// </summary>
public static ImpactProcessor Instance public static ImpactProcessor Instance
{ {
get { return instance; } get { return instance; }
} }
   
#endregion #endregion
   
#endregion #endregion
   
#region Fields #region Fields
   
private double impactAltitude; private double impactAltitude;
private bool impactHappening; private bool impactHappening;
private double impactLatitude; private double impactLatitude;
private double impactLongitude; private double impactLongitude;
private double impactTime; private double impactTime;
   
#endregion #endregion
   
#region Properties #region Properties
   
/// <summary> /// <summary>
/// Gets the altitude of the impact coordinates. /// Gets the altitude of the impact coordinates.
/// </summary> /// </summary>
public static double Altitude { get; private set; } public static double Altitude { get; private set; }
   
/// <summary> /// <summary>
/// Gets the biome of the impact coordinates. /// Gets the biome of the impact coordinates.
/// </summary> /// </summary>
public static string Biome { get; private set; } public static string Biome { get; private set; }
   
/// <summary> /// <summary>
/// Gets the latitude of the impact coordinates. /// Gets the latitude of the impact coordinates.
/// </summary> /// </summary>
public static double Latitude { get; private set; } public static double Latitude { get; private set; }
   
/// <summary> /// <summary>
/// Gets the longitude of the impact coordinates. /// Gets the longitude of the impact coordinates.
/// </summary> /// </summary>
public static double Longitude { get; private set; } public static double Longitude { 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 time to impact. /// Gets the time to impact.
/// </summary> /// </summary>
public static double Time { get; private set; } public static double Time { get; private set; }
   
#endregion #endregion
   
#region IUpdatable Members #region IUpdatable Members
   
public void Update() public void Update()
{ {
this.impactHappening = false; this.impactHappening = false;
   
if (FlightGlobals.ActiveVessel.mainBody.pqsController != null) if (FlightGlobals.ActiveVessel.mainBody.pqsController != null)
{ {
//do impact site calculations //do impact site calculations
this.impactHappening = true; this.impactHappening = true;
this.impactTime = 0; this.impactTime = 0;
this.impactLongitude = 0; this.impactLongitude = 0;
this.impactLatitude = 0; this.impactLatitude = 0;
this.impactAltitude = 0; this.impactAltitude = 0;
var e = FlightGlobals.ActiveVessel.orbit.eccentricity; var e = FlightGlobals.ActiveVessel.orbit.eccentricity;
//get current position direction vector //get current position direction vector
var currentpos = this.RadiusDirection(FlightGlobals.ActiveVessel.orbit.trueAnomaly); var currentpos = this.RadiusDirection(FlightGlobals.ActiveVessel.orbit.trueAnomaly * 180.0 / Math.PI);
//calculate longitude in inertial reference frame from that //calculate longitude in inertial reference frame from that
var currentirflong = 180 * Math.Atan2(currentpos.x, currentpos.y) / Math.PI; var currentirflong = 180 * Math.Atan2(currentpos.x, currentpos.y) / Math.PI;
   
//experimentally determined; even for very flat trajectories, the errors go into the sub-millimeter area after 5 iterations or so //experimentally determined; even for very flat trajectories, the errors go into the sub-millimeter area after 5 iterations or so
const int impactiterations = 6; const int impactiterations = 6;
   
//do a few iterations of impact site calculations //do a few iterations of impact site calculations
for (var i = 0; i < impactiterations; i++) for (var i = 0; i < impactiterations; i++)
{ {
if (FlightGlobals.ActiveVessel.orbit.PeA >= this.impactAltitude) if (FlightGlobals.ActiveVessel.orbit.PeA >= this.impactAltitude)
{ {
//periapsis must be lower than impact alt //periapsis must be lower than impact alt
this.impactHappening = false; this.impactHappening = false;
} }
if ((FlightGlobals.ActiveVessel.orbit.eccentricity < 1) && (FlightGlobals.ActiveVessel.orbit.ApA <= this.impactAltitude)) if ((FlightGlobals.ActiveVessel.orbit.eccentricity < 1) && (FlightGlobals.ActiveVessel.orbit.ApA <= this.impactAltitude))
{ {
//apoapsis must be higher than impact alt //apoapsis must be higher than impact alt
this.impactHappening = false; this.impactHappening = false;
} }
if ((FlightGlobals.ActiveVessel.orbit.eccentricity >= 1) && (FlightGlobals.ActiveVessel.orbit.timeToPe <= 0)) if ((FlightGlobals.ActiveVessel.orbit.eccentricity >= 1) && (FlightGlobals.ActiveVessel.orbit.timeToPe <= 0))
{ {
//if currently escaping, we still need to be before periapsis //if currently escaping, we still need to be before periapsis
this.impactHappening = false; this.impactHappening = false;
} }
if (!this.impactHappening) if (!this.impactHappening)
{ {
this.impactTime = 0; this.impactTime = 0;
this.impactLongitude = 0; this.impactLongitude = 0;
this.impactLatitude = 0; this.impactLatitude = 0;
this.impactAltitude = 0; this.impactAltitude = 0;
break; break;
} }
   
double impacttheta = 0; double impacttheta = 0;
if (e > 0) if (e > 0)
{ {
//in this step, we are using the calculated impact altitude of the last step, to refine the impact site position //in this step, we are using the calculated impact altitude of the last step, to refine the impact site position
impacttheta = -180 * Math.Acos((FlightGlobals.ActiveVessel.orbit.PeR * (1 + e) / (FlightGlobals.ActiveVessel.mainBody.Radius + this.impactAltitude) - 1) / e) / Math.PI; impacttheta = -180 * Math.Acos((FlightGlobals.ActiveVessel.orbit.PeR * (1 + e) / (FlightGlobals.ActiveVessel.mainBody.Radius + this.impactAltitude) - 1) / e) / Math.PI;
} }
   
//calculate time to impact //calculate time to impact
this.impactTime = FlightGlobals.ActiveVessel.orbit.timeToPe - this.TimeToPeriapsis(impacttheta); this.impactTime = FlightGlobals.ActiveVessel.orbit.timeToPe - this.TimeToPeriapsis(impacttheta);
//calculate position vector of impact site //calculate position vector of impact site
var impactpos = this.RadiusDirection(impacttheta); var impactpos = this.RadiusDirection(impacttheta);
//calculate longitude of impact site in inertial reference frame //calculate longitude of impact site in inertial reference frame
var impactirflong = 180 * Math.Atan2(impactpos.x, impactpos.y) / Math.PI; var impactirflong = 180 * Math.Atan2(impactpos.x, impactpos.y) / Math.PI;
var deltairflong = impactirflong - currentirflong; var deltairflong = impactirflong - currentirflong;
//get body rotation until impact //get body rotation until impact
var bodyrot = 360 * this.impactTime / FlightGlobals.ActiveVessel.mainBody.rotationPeriod; var bodyrot = 360 * this.impactTime / FlightGlobals.ActiveVessel.mainBody.rotationPeriod;
//get current longitude in body coordinates //get current longitude in body coordinates
var currentlong = FlightGlobals.ActiveVessel.longitude; var currentlong = FlightGlobals.ActiveVessel.longitude;
//finally, calculate the impact longitude in body coordinates //finally, calculate the impact longitude in body coordinates
this.impactLongitude = this.NormAngle(currentlong - deltairflong - bodyrot); this.impactLongitude = this.NormAngle(currentlong - deltairflong - bodyrot);
//calculate impact latitude from impact position //calculate impact latitude from impact position
this.impactLatitude = 180 * Math.Asin(impactpos.z / impactpos.magnitude) / Math.PI; this.impactLatitude = 180 * Math.Asin(impactpos.z / impactpos.magnitude) / Math.PI;
//calculate the actual altitude of the impact site //calculate the actual altitude of the impact site
//altitude for long/lat code stolen from some ISA MapSat forum post; who knows why this works, but it seems to. //altitude for long/lat code stolen from some ISA MapSat forum post; who knows why this works, but it seems to.
var rad = QuaternionD.AngleAxis(this.impactLongitude, Vector3d.down) * QuaternionD.AngleAxis(this.impactLatitude, Vector3d.forward) * Vector3d.right; var rad = QuaternionD.AngleAxis(this.impactLongitude, Vector3d.down) * QuaternionD.AngleAxis(this.impactLatitude, Vector3d.forward) * Vector3d.right;
this.impactAltitude = FlightGlobals.ActiveVessel.mainBody.pqsController.GetSurfaceHeight(rad) - FlightGlobals.ActiveVessel.mainBody.pqsController.radius; this.impactAltitude = FlightGlobals.ActiveVessel.mainBody.pqsController.GetSurfaceHeight(rad) - FlightGlobals.ActiveVessel.mainBody.pqsController.radius;
if ((this.impactAltitude < 0) && FlightGlobals.ActiveVessel.mainBody.ocean) if ((this.impactAltitude < 0) && FlightGlobals.ActiveVessel.mainBody.ocean)
{ {
this.impactAltitude = 0; this.impactAltitude = 0;
} }
} }
} }
   
// Set accessable properties. // Set accessable properties.
if (this.impactHappening) if (this.impactHappening)
{ {
ShowDetails = true; ShowDetails = true;
Time = this.impactTime; Time = this.impactTime;
Longitude = this.impactLongitude; Longitude = this.impactLongitude;
Latitude = this.impactLatitude; Latitude = this.impactLatitude;
Altitude = this.impactAltitude; Altitude = this.impactAltitude;
Biome = ScienceUtil.GetExperimentBiome(FlightGlobals.ActiveVessel.mainBody, this.impactLatitude, this.impactLongitude); Biome = ScienceUtil.GetExperimentBiome(FlightGlobals.ActiveVessel.mainBody, this.impactLatitude, this.impactLongitude);
} }
else else
{ {
ShowDetails = false; ShowDetails = false;
} }
} }
   
#endregion #endregion
   
#region IUpdateRequest Members #region IUpdateRequest Members
   
public bool UpdateRequested { get; set; } public bool UpdateRequested { get; set; }
   
#endregion #endregion
   
#region Methods: public #region Methods: public
   
public static void RequestUpdate() public static void RequestUpdate()
{ {
instance.UpdateRequested = true; instance.UpdateRequested = true;
} }
   
#endregion #endregion
   
#region Calculations #region Calculations
   
#region Methods: public #region Methods: public
   
public static double ACosh(double x) public static double ACosh(double x)
{ {
return (Math.Log(x + Math.Sqrt((x * x) - 1.0))); return (Math.Log(x + Math.Sqrt((x * x) - 1.0)));
} }
   
#endregion #endregion
   
#region Methods: private #region Methods: private
   
private double NormAngle(double ang) private double NormAngle(double ang)
{ {
if (ang > 180) if (ang > 180)
{ {
ang -= 360 * Math.Ceiling((ang - 180) / 360); ang -= 360 * Math.Ceiling((ang - 180) / 360);
} }
if (ang <= -180) if (ang <= -180)
{ {
ang -= 360 * Math.Floor((ang + 180) / 360); ang -= 360 * Math.Floor((ang + 180) / 360);
} }
   
return ang; return ang;
} }
   
private Vector3d RadiusDirection(double theta) private Vector3d RadiusDirection(double theta)
{ {
theta = Math.PI * theta / 180; theta = Math.PI * theta / 180;
var omega = Math.PI * FlightGlobals.ActiveVessel.orbit.argumentOfPeriapsis / 180; var omega = Math.PI * FlightGlobals.ActiveVessel.orbit.argumentOfPeriapsis / 180;
var incl = Math.PI * FlightGlobals.ActiveVessel.orbit.inclination / 180; var incl = Math.PI * FlightGlobals.ActiveVessel.orbit.inclination / 180;
   
var costheta = Math.Cos(theta); var costheta = Math.Cos(theta);
var sintheta = Math.Sin(theta); var sintheta = Math.Sin(theta);
var cosomega = Math.Cos(omega); var cosomega = Math.Cos(omega);
var sinomega = Math.Sin(omega); var sinomega = Math.Sin(omega);
var cosincl = Math.Cos(incl); var cosincl = Math.Cos(incl);
var sinincl = Math.Sin(incl); var sinincl = Math.Sin(incl);
   
Vector3d result; Vector3d result;
   
result.x = cosomega * costheta - sinomega * sintheta; result.x = cosomega * costheta - sinomega * sintheta;
result.y = cosincl * (sinomega * costheta + cosomega * sintheta); result.y = cosincl * (sinomega * costheta + cosomega * sintheta);
result.z = sinincl * (sinomega * costheta + cosomega * sintheta); result.z = sinincl * (sinomega * costheta + cosomega * sintheta);
   
return result; return result;
} }
   
private double TimeToPeriapsis(double theta) private double TimeToPeriapsis(double theta)
{ {
var e = FlightGlobals.ActiveVessel.orbit.eccentricity; var e = FlightGlobals.ActiveVessel.orbit.eccentricity;
var a = FlightGlobals.ActiveVessel.orbit.semiMajorAxis; var a = FlightGlobals.ActiveVessel.orbit.semiMajorAxis;
var rp = FlightGlobals.ActiveVessel.orbit.PeR; var rp = FlightGlobals.ActiveVessel.orbit.PeR;
var mu = FlightGlobals.ActiveVessel.mainBody.gravParameter; var mu = FlightGlobals.ActiveVessel.mainBody.gravParameter;
   
if (e == 1.0) if (e == 1.0)
{ {
var D = Math.Tan(Math.PI * theta / 360.0); var D = Math.Tan(Math.PI * theta / 360.0);
var M = D + D * D * D / 3.0; var M = D + D * D * D / 3.0;
return (Math.Sqrt(2.0 * rp * rp * rp / mu) * M); return (Math.Sqrt(2.0 * rp * rp * rp / mu) * M);
} }
if (a > 0) if (a > 0)
{ {
var cosTheta = Math.Cos(Math.PI * theta / 180.0); var cosTheta = Math.Cos(Math.PI * theta / 180.0);
var cosE = (e + cosTheta) / (1.0 + e * cosTheta); var cosE = (e + cosTheta) / (1.0 + e * cosTheta);
var radE = Math.Acos(cosE); var radE = Math.Acos(cosE);
var M = radE - e * Math.Sin(radE); var M = radE - e * Math.Sin(radE);
return (Math.Sqrt(a * a * a / mu) * M); return (Math.Sqrt(a * a * a / mu) * M);
} }
if (a < 0) if (a < 0)
{ {
var cosTheta = Math.Cos(Math.PI * theta / 180.0); var cosTheta = Math.Cos(Math.PI * theta / 180.0);
var coshF = (e + cosTheta) / (1.0 + e * cosTheta); var coshF = (e + cosTheta) / (1.0 + e * cosTheta);
var radF = ACosh(coshF); var radF = ACosh(coshF);
var M = e * Math.Sinh(radF) - radF; var M = e * Math.Sinh(radF) - radF;
return (Math.Sqrt(-a * a * a / mu) * M); return (Math.Sqrt(-a * a * a / mu) * M);
} }
   
return 0; return 0;
} }
   
#endregion #endregion
   
#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="AppLauncherButton.cs" /> <Compile Include="AppLauncherButton.cs" />
<Compile Include="AssetBundleLoader.cs" /> <Compile Include="AssetBundleLoader.cs" />
<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\BuildAppLauncher.cs" /> <Compile Include="Editor\BuildAppLauncher.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\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="Extensions\StringExtensions.cs" /> <Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Flight\ActionMenuGui.cs" /> <Compile Include="Flight\ActionMenuGui.cs" />
<Compile Include="Flight\FlightAppLauncher.cs" /> <Compile Include="Flight\FlightAppLauncher.cs" />
<Compile Include="Flight\Presets\Preset.cs" /> <Compile Include="Flight\Presets\Preset.cs" />
  <Compile Include="Flight\Readouts\Miscellaneous\LogSimToggle.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\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\ManoeuvreNode\PostBurnApoapsis.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\PostBurnApoapsis.cs" />
<Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\PostBurnPeriapsis.cs" /> <Compile Include="Flight\Readouts\Orbital\ManoeuvreNode\PostBurnPeriapsis.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\SemiMajorAxis.cs"> <Compile Include="Flight\Readouts\Orbital\SemiMajorAxis.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Flight\Readouts\Orbital\SpeedAtApoapsis.cs" /> <Compile Include="Flight\Readouts\Orbital\SpeedAtApoapsis.cs" />
<Compile Include="Flight\Readouts\Orbital\SpeedAtPeriapsis.cs"> <Compile Include="Flight\Readouts\Orbital\SpeedAtPeriapsis.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Flight\Readouts\Orbital\TimeToAtmosphere.cs" /> <Compile Include="Flight\Readouts\Orbital\TimeToAtmosphere.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\Surface\MachNumber.cs" /> <Compile Include="Flight\Readouts\Surface\MachNumber.cs" />
<Compile Include="Flight\Readouts\Thermal\CoolestSkinTemperature.cs" /> <Compile Include="Flight\Readouts\Thermal\CoolestSkinTemperature.cs" />
<Compile Include="Flight\Readouts\Thermal\CriticalPart.cs" /> <Compile Include="Flight\Readouts\Thermal\CriticalPart.cs" />
<Compile Include="Flight\Readouts\Thermal\CoolestPart.cs" /> <Compile Include="Flight\Readouts\Thermal\CoolestPart.cs" />
<Compile Include="Flight\Readouts\Thermal\CoolestTemperature.cs" /> <Compile Include="Flight\Readouts\Thermal\CoolestTemperature.cs" />
<Compile Include="Flight\Readouts\Thermal\CriticalThermalPercentage.cs" /> <Compile Include="Flight\Readouts\Thermal\CriticalThermalPercentage.cs" />
<Compile Include="Flight\Readouts\Thermal\CriticalSkinTemperature.cs" /> <Compile Include="Flight\Readouts\Thermal\CriticalSkinTemperature.cs" />
<Compile Include="Flight\Readouts\Thermal\CriticalTemperature.cs" /> <Compile Include="Flight\Readouts\Thermal\CriticalTemperature.cs" />
<Compile Include="Flight\Readouts\Thermal\HottestSkinTemperature.cs" /> <Compile Include="Flight\Readouts\Thermal\HottestSkinTemperature.cs" />
<Compile Include="Flight\Readouts\Thermal\InternalFlux.cs" /> <Compile Include="Flight\Readouts\Thermal\InternalFlux.cs" />
<Compile Include="Flight\Readouts\Thermal\RadiationFlux.cs" /> <Compile Include="Flight\Readouts\Thermal\RadiationFlux.cs" />
<Compile Include="Flight\Readouts\Thermal\ConvectionFlux.cs" /> <Compile Include="Flight\Readouts\Thermal\ConvectionFlux.cs" />
<Compile Include="Flight\Readouts\Thermal\HottestTemperature.cs" /> <Compile Include="Flight\Readouts\Thermal\HottestTemperature.cs" />
<Compile Include="Flight\Readouts\Thermal\HottestPart.cs" /> <Compile Include="Flight\Readouts\Thermal\HottestPart.cs" />
<Compile Include="Flight\Readouts\Thermal\ThermalProcessor.cs" /> <Compile Include="Flight\Readouts\Thermal\ThermalProcessor.cs" />
<Compile Include="Flight\Readouts\Vessel\Name.cs" /> <Compile Include="Flight\Readouts\Vessel\Name.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="Helpers\XmlHelper.cs" /> <Compile Include="Helpers\XmlHelper.cs" />
<Compile Include="KeyBinding\KeyBinder.cs" /> <Compile Include="KeyBinding\KeyBinder.cs" />
<Compile Include="Control\ControlCentre.cs" /> <Compile Include="Control\ControlCentre.cs" />
<Compile Include="KeyBinding\KeyBindingsObject.cs" /> <Compile Include="KeyBinding\KeyBindingsObject.cs" />
<Compile Include="Settings\SettingsWindow.cs" /> <Compile Include="Settings\SettingsWindow.cs" />
<Compile Include="StyleManager.cs" /> <Compile Include="StyleManager.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\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="KeyBinding\KeyBindPopup.cs" /> <Compile Include="KeyBinding\KeyBindPopup.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="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" />
<Compile Include="Flight\Readouts\Rendezvous\RelativeRadialVelocity.cs" /> <Compile Include="Flight\Readouts\Rendezvous\RelativeRadialVelocity.cs" />
<Compile Include="Flight\Readouts\Rendezvous\TimeToRendezvous.cs" /> <Compile Include="Flight\Readouts\Rendezvous\TimeToRendezvous.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Assembly-CSharp"> <Reference Include="Assembly-CSharp">
<HintPath>..\..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath> <HintPath>..\..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="Assembly-CSharp-firstpass"> <Reference Include="Assembly-CSharp-firstpass">
<HintPath>..\..\game\KSP_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath> <HintPath>..\..\game\KSP_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="KSPAssets"> <Reference Include="KSPAssets">
<HintPath>..\..\game\KSP_Data\Managed\KSPAssets.dll</HintPath> <HintPath>..\..\game\KSP_Data\Managed\KSPAssets.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="KSPCore"> <Reference Include="KSPCore">
<HintPath>..\..\game\KSP_Data\Managed\KSPCore.dll</HintPath> <HintPath>..\..\game\KSP_Data\Managed\KSPCore.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="KSPUtil"> <Reference Include="KSPUtil">
<HintPath>..\..\game\KSP_Data\Managed\KSPUtil.dll</HintPath> <HintPath>..\..\game\KSP_Data\Managed\KSPUtil.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System"> <Reference Include="System">
<HintPath>..\Game\KSP_Data\Managed\System.dll</HintPath> <HintPath>..\Game\KSP_Data\Managed\System.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="System.Xml"> <Reference Include="System.Xml">
<HintPath>..\Game\KSP_Data\Managed\System.Xml.dll</HintPath> <HintPath>..\Game\KSP_Data\Managed\System.Xml.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="UnityEngine"> <Reference Include="UnityEngine">
<HintPath>..\..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath> <HintPath>..\..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="UnityEngine.UI"> <Reference Include="UnityEngine.UI">
<HintPath>..\..\game\KSP_Data\Managed\UnityEngine.UI.dll</HintPath> <HintPath>..\..\game\KSP_Data\Managed\UnityEngine.UI.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\KerbalEngineer.Unity\KerbalEngineer.Unity.csproj"> <ProjectReference Include="..\KerbalEngineer.Unity\KerbalEngineer.Unity.csproj">
<Project>{5387bb1e-32b1-4bac-b03f-100570b9554c}</Project> <Project>{5387bb1e-32b1-4bac-b03f-100570b9554c}</Project>
<Name>KerbalEngineer.Unity</Name> <Name>KerbalEngineer.Unity</Name>
<Private>False</Private> <Private>False</Private>
</ProjectReference> </ProjectReference>
</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
   
#endregion #endregion
   
namespace KerbalEngineer.VesselSimulator namespace KerbalEngineer.VesselSimulator
{ {
using System; using System;
using System.Text; using System.Text;
   
internal class AttachNodeSim internal class AttachNodeSim
{ {
   
private static readonly Pool<AttachNodeSim> pool = new Pool<AttachNodeSim>(Create, Reset); 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;
   
private static AttachNodeSim Create() private static AttachNodeSim Create()
{ {
return new AttachNodeSim(); return new AttachNodeSim();
} }
   
public static AttachNodeSim New(PartSim partSim, String newId, AttachNode.NodeType newNodeType) public static AttachNodeSim New(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
{ {
AttachNodeSim nodeSim = pool.Borrow(); AttachNodeSim nodeSim = pool.Borrow();
   
nodeSim.attachedPartSim = partSim; nodeSim.attachedPartSim = partSim;
nodeSim.nodeType = newNodeType; nodeSim.nodeType = newNodeType;
nodeSim.id = newId; nodeSim.id = newId;
   
return nodeSim; return nodeSim;
} }
   
static private void Reset(AttachNodeSim attachNodeSim) { } static private void Reset(AttachNodeSim attachNodeSim)
  {
  attachNodeSim.attachedPartSim = null;
  }
   
   
public void Release() public void Release()
{ {
pool.Release(this); pool.Release(this);
} }
   
public void DumpToBuffer(StringBuilder buffer) public void DumpToBuffer(StringBuilder buffer)
{ {
if (attachedPartSim == null) if (attachedPartSim == null)
{ {
buffer.Append("<staged>:<n>"); buffer.Append("<staged>:<n>");
} }
else else
{ {
buffer.Append(attachedPartSim.name); buffer.Append(attachedPartSim.name);
buffer.Append(":"); buffer.Append(":");
buffer.Append(attachedPartSim.partId); buffer.Append(attachedPartSim.partId);
} }
buffer.Append("#"); buffer.Append("#");
buffer.Append(nodeType); buffer.Append(nodeType);
buffer.Append(":"); buffer.Append(":");
buffer.Append(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/>.
// //
   
namespace KerbalEngineer.VesselSimulator namespace KerbalEngineer.VesselSimulator
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using Editor; using Editor;
using Helpers; using Helpers;
using UnityEngine; using UnityEngine;
   
public class EngineSim public class EngineSim
{ {
private static readonly Pool<EngineSim> pool = new Pool<EngineSim>(Create, Reset); private static readonly Pool<EngineSim> pool = new Pool<EngineSim>(Create, Reset);
   
private readonly ResourceContainer resourceConsumptions = new ResourceContainer(); private readonly ResourceContainer resourceConsumptions = new ResourceContainer();
private readonly ResourceContainer resourceFlowModes = new ResourceContainer(); private readonly ResourceContainer resourceFlowModes = 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 = new List<AppliedForce>(); public List<AppliedForce> appliedForces = new List<AppliedForce>();
public float maxMach; 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;
   
private static EngineSim Create() private static EngineSim Create()
{ {
return new EngineSim(); return new EngineSim();
} }
   
private static void Reset(EngineSim engineSim) private static void Reset(EngineSim engineSim)
{ {
engineSim.resourceConsumptions.Reset(); engineSim.resourceConsumptions.Reset();
engineSim.resourceFlowModes.Reset(); engineSim.resourceFlowModes.Reset();
  engineSim.partSim = null;
engineSim.actualThrust = 0; engineSim.actualThrust = 0;
engineSim.isActive = false; engineSim.isActive = false;
engineSim.isp = 0; engineSim.isp = 0;
for (int i = 0; i < engineSim.appliedForces.Count; i++) for (int i = 0; i < engineSim.appliedForces.Count; i++)
{ {
engineSim.appliedForces[i].Release(); engineSim.appliedForces[i].Release();
} }
engineSim.appliedForces.Clear(); engineSim.appliedForces.Clear();
engineSim.thrust = 0; engineSim.thrust = 0;
engineSim.maxMach = 0f; engineSim.maxMach = 0f;
} }
   
public void Release() public void Release()
{ {
pool.Release(this); pool.Release(this);
} }
   
public static EngineSim New(PartSim theEngine, public static EngineSim New(PartSim theEngine,
double atmosphere, ModuleEngines engineMod,
float machNumber, double atmosphere,
float maxFuelFlow, float machNumber,
float minFuelFlow, bool vectoredThrust,
float thrustPercentage, bool fullThrust,
Vector3 vecThrust, LogMsg log)
FloatCurve atmosphereCurve, {
bool atmChangeFlow, float maxFuelFlow = engineMod.maxFuelFlow;
FloatCurve atmCurve, float minFuelFlow = engineMod.minFuelFlow;
FloatCurve velCurve, float thrustPercentage = engineMod.thrustPercentage;
float currentThrottle, List<Transform> thrustTransforms = engineMod.thrustTransforms;
float IspG, List<float> thrustTransformMultipliers = engineMod.thrustTransformMultipliers;
bool throttleLocked, Vector3 vecThrust = CalculateThrustVector(vectoredThrust ? thrustTransforms : null,
List<Propellant> propellants, vectoredThrust ? thrustTransformMultipliers : null,
bool active, log);
float resultingThrust, FloatCurve atmosphereCurve = engineMod.atmosphereCurve;
List<Transform> thrustTransforms, bool atmChangeFlow = engineMod.atmChangeFlow;
LogMsg log) FloatCurve atmCurve = engineMod.useAtmCurve ? engineMod.atmCurve : null;
{ FloatCurve velCurve = engineMod.useVelCurve ? engineMod.velCurve : null;
EngineSim engineSim = pool.Borrow(); float currentThrottle = engineMod.currentThrottle;
  float IspG = engineMod.g;
  bool throttleLocked = engineMod.throttleLocked || fullThrust;
  List<Propellant> propellants = engineMod.propellants;
  bool active = engineMod.isOperational;
  float resultingThrust = engineMod.resultingThrust;
   
  EngineSim engineSim = pool.Borrow();
   
engineSim.isp = 0.0; engineSim.isp = 0.0;
engineSim.maxMach = 0.0f; engineSim.maxMach = 0.0f;
engineSim.actualThrust = 0.0; engineSim.actualThrust = 0.0;
engineSim.partSim = theEngine; engineSim.partSim = theEngine;
engineSim.isActive = active; engineSim.isActive = active;
engineSim.thrustVec = vecThrust; engineSim.thrustVec = vecThrust;
engineSim.resourceConsumptions.Reset(); engineSim.resourceConsumptions.Reset();
engineSim.resourceFlowModes.Reset(); engineSim.resourceFlowModes.Reset();
engineSim.appliedForces.Clear(); engineSim.appliedForces.Clear();
   
double flowRate = 0.0; double flowRate = 0.0;
if (engineSim.partSim.hasVessel) if (engineSim.partSim.hasVessel)
{ {
if (log != null) log.buf.AppendLine("hasVessel is true"); if (log != null) log.buf.AppendLine("hasVessel is true");
   
float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, ref engineSim.maxMach); float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, ref engineSim.maxMach);
engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0; engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0;
if (log != null) if (log != null)
{ {
log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier); log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier);
log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp);
log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust);
log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust);
} }
   
if (throttleLocked) if (throttleLocked)
{ {
if (log != null) log.buf.AppendLine("throttleLocked is true, using thrust for flowRate"); if (log != null) log.buf.AppendLine("throttleLocked is true, using thrust for flowRate");
flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
} }
else else
{ {
if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false) if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false)
{ {
if (log != null) log.buf.AppendLine("throttled up and not landed, using actualThrust for flowRate"); // TODO: This bit doesn't work for RF engines
  if (log != null) log.buf.AppendLine("throttled up and not landed, using actualThrust for flowRate");
flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp); flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp);
} }
else else
{ {
if (log != null) log.buf.AppendLine("throttled down or landed, using thrust for flowRate"); if (log != null) log.buf.AppendLine("throttled down or landed, using thrust for flowRate");
flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
} }
} }
} }
else else
{ {
if (log != null) log.buf.AppendLine("hasVessel is false"); if (log != null) log.buf.AppendLine("hasVessel is false");
float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, CelestialBodies.SelectedBody.GetDensity(BuildAdvanced.Altitude), velCurve, machNumber, ref engineSim.maxMach); float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, CelestialBodies.SelectedBody.GetDensity(BuildAdvanced.Altitude), velCurve, machNumber, ref engineSim.maxMach);
engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere);
engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp);
engineSim.actualThrust = 0d; engineSim.actualThrust = 0d;
if (log != null) if (log != null)
{ {
log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier); log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier);
log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp);
log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust);
log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust);
} }
   
if (log != null) log.buf.AppendLine("no vessel, using thrust for flowRate"); if (log != null) log.buf.AppendLine("no vessel, using thrust for flowRate");
flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
} }
   
if (log != null) log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate); if (log != null) log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate);
   
float flowMass = 0f; float flowMass = 0f;
for (int i = 0; i < propellants.Count; ++i) for (int i = 0; i < propellants.Count; ++i)
{ {
Propellant propellant = propellants[i]; Propellant propellant = propellants[i];
if (!propellant.ignoreForIsp) if (!propellant.ignoreForIsp)
flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id); flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
} }
   
if (log != null) log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass); if (log != null) log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass);
   
for (int i = 0; i < propellants.Count; ++i) for (int i = 0; i < propellants.Count; ++i)
{ {
Propellant propellant = propellants[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 (log != null) log.buf.AppendFormat( if (log != null) log.buf.AppendFormat(
"Add consumption({0}, {1}:{2:d}) = {3:g6}\n", "Add consumption({0}, {1}:{2:d}) = {3:g6}\n",
ResourceContainer.GetResourceName(propellant.id), ResourceContainer.GetResourceName(propellant.id),
theEngine.name, theEngine.name,
theEngine.partId, theEngine.partId,
consumptionRate); consumptionRate);
engineSim.resourceConsumptions.Add(propellant.id, consumptionRate); engineSim.resourceConsumptions.Add(propellant.id, consumptionRate);
engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode()); engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode());
} }
   
double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;  
for (int i = 0; i < thrustTransforms.Count; i++) for (int i = 0; i < thrustTransforms.Count; i++)
{ {
Transform thrustTransform = thrustTransforms[i]; Transform thrustTransform = thrustTransforms[i];
Vector3d direction = thrustTransform.forward.normalized; Vector3d direction = thrustTransform.forward.normalized;
Vector3d position = thrustTransform.position; Vector3d position = thrustTransform.position;
   
AppliedForce appliedForce = AppliedForce.New(direction * thrustPerThrustTransform, position); AppliedForce appliedForce = AppliedForce.New(direction * engineSim.thrust * thrustTransformMultipliers[i], position);
engineSim.appliedForces.Add(appliedForce); engineSim.appliedForces.Add(appliedForce);
} }
   
return engineSim; return engineSim;
} }
   
  private static Vector3 CalculateThrustVector(List<Transform> thrustTransforms, List<float> thrustTransformMultipliers, LogMsg log)
  {
  if (thrustTransforms == null)
  {
  return Vector3.forward;
  }
   
  Vector3 thrustvec = Vector3.zero;
  for (int i = 0; i < thrustTransforms.Count; ++i)
  {
  Transform trans = thrustTransforms[i];
   
  if (log != null) 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);
   
  thrustvec -= (trans.forward * thrustTransformMultipliers[i]);
  }
   
  if (log != null) log.buf.AppendFormat("ThrustVec = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
   
  thrustvec.Normalize();
   
  if (log != null) log.buf.AppendFormat("ThrustVecN = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
   
  return thrustvec;
  }
   
public ResourceContainer ResourceConsumptions public ResourceContainer ResourceConsumptions
{ {
get get
{ {
return resourceConsumptions; return resourceConsumptions;
} }
} }
   
public static double GetExhaustVelocity(double isp) public static double GetExhaustVelocity(double isp)
{ {
return isp * Units.GRAVITY; return isp * Units.GRAVITY;
} }
   
public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, ref float maxMach) public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, ref float maxMach)
{ {
float flowModifier = 1.0f; float flowModifier = 1.0f;
if (atmChangeFlow) if (atmChangeFlow)
{ {
flowModifier = (float)(atmDensity / 1.225); flowModifier = (float)(atmDensity / 1.225);
if (atmCurve != null) if (atmCurve != null)
{ {
flowModifier = atmCurve.Evaluate(flowModifier); flowModifier = atmCurve.Evaluate(flowModifier);
} }
} }
if (velCurve != null) if (velCurve != null)
{ {
flowModifier = flowModifier * velCurve.Evaluate(machNumber); flowModifier = flowModifier * velCurve.Evaluate(machNumber);
maxMach = velCurve.maxTime; maxMach = velCurve.maxTime;
} }
if (flowModifier < float.Epsilon) if (flowModifier < float.Epsilon)
{ {
flowModifier = float.Epsilon; flowModifier = float.Epsilon;
} }
return flowModifier; return flowModifier;
} }
   
public static double GetFlowRate(double thrust, double isp) public static double GetFlowRate(double thrust, double isp)
{ {
return thrust / GetExhaustVelocity(isp); return thrust / GetExhaustVelocity(isp);
} }
   
public static float GetThrottlePercent(float currentThrottle, float thrustPercentage) public static float GetThrottlePercent(float currentThrottle, float thrustPercentage)
{ {
return currentThrottle * GetThrustPercent(thrustPercentage); return currentThrottle * GetThrustPercent(thrustPercentage);
} }
   
public static double GetThrust(double flowRate, double isp) public static double GetThrust(double flowRate, double isp)
{ {
return flowRate * GetExhaustVelocity(isp); return flowRate * GetExhaustVelocity(isp);
} }
   
public static float GetThrustPercent(float thrustPercentage) public static float GetThrustPercent(float thrustPercentage)
{ {
return thrustPercentage * 0.01f; return thrustPercentage * 0.01f;
} }
   
public void DumpEngineToBuffer(StringBuilder buffer, String prefix) public void DumpEngineToBuffer(StringBuilder buffer, String prefix)
{ {
buffer.Append(prefix); buffer.Append(prefix);
buffer.AppendFormat("[thrust = {0:g6}, actual = {1:g6}, isp = {2:g6}\n", thrust, actualThrust, isp); 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 // A dictionary to hold a set of parts for each resource
Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>(); Dictionary<int, HashSet<PartSim>> sourcePartSets = new Dictionary<int, HashSet<PartSim>>();
   
Dictionary<int, HashSet<PartSim>> stagePartSets = new Dictionary<int, HashSet<PartSim>>(); Dictionary<int, HashSet<PartSim>> stagePartSets = new Dictionary<int, HashSet<PartSim>>();
   
HashSet<PartSim> visited = new HashSet<PartSim>(); HashSet<PartSim> visited = new HashSet<PartSim>();
   
public void DumpSourcePartSets(String msg) public void DumpSourcePartSets(String msg)
{ {
MonoBehaviour.print("DumpSourcePartSets " + msg); MonoBehaviour.print("DumpSourcePartSets " + msg);
foreach (int type in sourcePartSets.Keys) foreach (int type in sourcePartSets.Keys)
{ {
MonoBehaviour.print("SourcePartSet for " + ResourceContainer.GetResourceName(type)); MonoBehaviour.print("SourcePartSet for " + ResourceContainer.GetResourceName(type));
HashSet<PartSim> sourcePartSet = sourcePartSets[type]; HashSet<PartSim> sourcePartSet = sourcePartSets[type];
if (sourcePartSet.Count > 0) if (sourcePartSet.Count > 0)
{ {
foreach (PartSim partSim in sourcePartSet) foreach (PartSim partSim in sourcePartSet)
{ {
MonoBehaviour.print("Part " + partSim.name + ":" + partSim.partId); MonoBehaviour.print("Part " + partSim.name + ":" + partSim.partId);
} }
} }
else else
{ {
MonoBehaviour.print("No parts"); MonoBehaviour.print("No parts");
} }
} }
} }
   
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;
//DumpSourcePartSets("before clear"); //DumpSourcePartSets("before clear");
foreach (HashSet<PartSim> sourcePartSet in sourcePartSets.Values) foreach (HashSet<PartSim> sourcePartSet in sourcePartSets.Values)
{ {
sourcePartSet.Clear(); sourcePartSet.Clear();
} }
//DumpSourcePartSets("after clear"); //DumpSourcePartSets("after clear");
   
for (int index = 0; index < this.resourceConsumptions.Types.Count; index++) for (int index = 0; index < this.resourceConsumptions.Types.Count; index++)
{ {
int type = this.resourceConsumptions.Types[index]; int type = this.resourceConsumptions.Types[index];
   
HashSet<PartSim> sourcePartSet; HashSet<PartSim> sourcePartSet;
if (!sourcePartSets.TryGetValue(type, out sourcePartSet)) if (!sourcePartSets.TryGetValue(type, out sourcePartSet))
{ {
sourcePartSet = new HashSet<PartSim>(); sourcePartSet = new HashSet<PartSim>();
sourcePartSets.Add(type, sourcePartSet); sourcePartSets.Add(type, sourcePartSet);
} }
   
switch ((ResourceFlowMode)this.resourceFlowModes[type]) switch ((ResourceFlowMode)this.resourceFlowModes[type])
{ {
case ResourceFlowMode.NO_FLOW: case ResourceFlowMode.NO_FLOW:
if (partSim.resources[type] > SimManager.RESOURCE_MIN && 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(partSim); sourcePartSet.Add(partSim);
} }
break; break;
   
case ResourceFlowMode.ALL_VESSEL: case ResourceFlowMode.ALL_VESSEL:
case ResourceFlowMode.ALL_VESSEL_BALANCE: case ResourceFlowMode.ALL_VESSEL_BALANCE:
for (int i = 0; i < allParts.Count; i++) for (int i = 0; i < allParts.Count; i++)
{ {
PartSim aPartSim = allParts[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)
{ {
sourcePartSet.Add(aPartSim); sourcePartSet.Add(aPartSim);
} }
} }
break; break;
   
case ResourceFlowMode.STAGE_PRIORITY_FLOW: case ResourceFlowMode.STAGE_PRIORITY_FLOW:
case ResourceFlowMode.STAGE_PRIORITY_FLOW_BALANCE: case ResourceFlowMode.STAGE_PRIORITY_FLOW_BALANCE:
   
foreach (HashSet<PartSim> stagePartSet in stagePartSets.Values) foreach (HashSet<PartSim> stagePartSet in stagePartSets.Values)
{ {
stagePartSet.Clear(); stagePartSet.Clear();
} }
var maxStage = -1; var maxStage = -1;
   
//Logger.Log(type); //Logger.Log(type);
for (int i = 0; i < allParts.Count; i++) for (int i = 0; i < allParts.Count; i++)
{ {
var aPartSim = allParts[i]; var 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)
{ {
continue; continue;
} }
   
int stage = aPartSim.DecouplerCount(); int stage = aPartSim.DecouplerCount();
if (stage > maxStage) if (stage > maxStage)
{ {
maxStage = stage; maxStage = stage;
} }
   
HashSet<PartSim> tempPartSet; HashSet<PartSim> tempPartSet;
if (!stagePartSets.TryGetValue(stage, out tempPartSet)) if (!stagePartSets.TryGetValue(stage, out tempPartSet))
{ {
tempPartSet = new HashSet<PartSim>(); tempPartSet = new HashSet<PartSim>();
stagePartSets.Add(stage, tempPartSet); stagePartSets.Add(stage, tempPartSet);
} }
tempPartSet.Add(aPartSim); tempPartSet.Add(aPartSim);
} }
   
for (int j = maxStage; j >= 0; j--) for (int j = maxStage; j >= 0; j--)
{ {
HashSet<PartSim> stagePartSet; HashSet<PartSim> stagePartSet;
if (stagePartSets.TryGetValue(j, out stagePartSet) && stagePartSet.Count > 0) if (stagePartSets.TryGetValue(j, out stagePartSet) && stagePartSet.Count > 0)
{ {
// We have to copy the contents of the set here rather than copying the set reference or // We have to copy the contents of the set here rather than copying the set reference or
// bad things (tm) happen // bad things (tm) happen
foreach (PartSim aPartSim in stagePartSet) foreach (PartSim aPartSim in stagePartSet)
{ {
sourcePartSet.Add(aPartSim); sourcePartSet.Add(aPartSim);
} }
break; break;
} }
} }
break; break;
   
case ResourceFlowMode.STACK_PRIORITY_SEARCH: case ResourceFlowMode.STACK_PRIORITY_SEARCH:
visited.Clear(); visited.Clear();
   
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
log = new LogMsg(); log = new LogMsg();
log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + partSim.name + ":" + partSim.partId); log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + partSim.name + ":" + partSim.partId);
} }
partSim.GetSourceSet(type, PhysicsGlobals.Stack_PriUsesSurf, allParts, visited, sourcePartSet, log, ""); partSim.GetSourceSet(type, PhysicsGlobals.Stack_PriUsesSurf, allParts, visited, sourcePartSet, log, "");
if (SimManager.logOutput && log != null) if (SimManager.logOutput && log != null)
{ {
MonoBehaviour.print(log.buf); MonoBehaviour.print(log.buf);
} }
break; break;
   
case ResourceFlowMode.STAGE_STACK_FLOW: case ResourceFlowMode.STAGE_STACK_FLOW:
case ResourceFlowMode.STAGE_STACK_FLOW_BALANCE: case ResourceFlowMode.STAGE_STACK_FLOW_BALANCE:
visited.Clear(); visited.Clear();
   
if (SimManager.logOutput) if (SimManager.logOutput)
{ {
log = new LogMsg(); log = new LogMsg();
log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + partSim.name + ":" + partSim.partId); log.buf.AppendLine("Find " + ResourceContainer.GetResourceName(type) + " sources for " + partSim.name + ":" + partSim.partId);
} }
partSim.GetSourceSet(type, true, allParts, visited, sourcePartSet, log, ""); partSim.GetSourceSet(type, true, allParts, visited, sourcePartSet, log, "");
if (SimManager.logOutput && log != null) if (SimManager.logOutput && log != null)
{ {
MonoBehaviour.print(log.buf); MonoBehaviour.print(log.buf);
} }
break; break;
   
default: default:
MonoBehaviour.print("SetResourceDrains(" + partSim.name + ":" + 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 (SimManager.logOutput) if (SimManager.logOutput)
{ {
if (sourcePartSet.Count > 0) if (sourcePartSet.Count > 0)
{ {
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);
} }
} }
   
//DumpSourcePartSets("after " + ResourceContainer.GetResourceName(type)); //DumpSourcePartSets("after " + ResourceContainer.GetResourceName(type));
} }
// 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
for (int i = 0; i < this.resourceConsumptions.Types.Count; i++) for (int i = 0; i < this.resourceConsumptions.Types.Count; i++)
{ {
int type = this.resourceConsumptions.Types[i]; int type = this.resourceConsumptions.Types[i];
HashSet<PartSim> sourcePartSet; HashSet<PartSim> sourcePartSet;
if (!sourcePartSets.TryGetValue(type, out sourcePartSet) || sourcePartSet.Count == 0) 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));
} }
   
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
for (int i = 0; i < this.resourceConsumptions.Types.Count; i++) for (int i = 0; i < this.resourceConsumptions.Types.Count; i++)
{ {
int type = this.resourceConsumptions.Types[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 = 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( MonoBehaviour.print(
"Adding drain of " + amount + " " + ResourceContainer.GetResourceName(type) + " to " + partSim.name + ":" + "Adding drain of " + amount + " " + ResourceContainer.GetResourceName(type) + " to " + partSim.name + ":" +
partSim.partId); partSim.partId);
} }
   
partSim.resourceDrains.Add(type, amount); partSim.resourceDrains.Add(type, amount);
drainingParts.Add(partSim); drainingParts.Add(partSim);
} }
} }
return true; return true;
} }
} }
} }
// //
// Kerbal Engineer Redux // Kerbal Engineer Redux
// //
// Copyright (C) 2014 CYBUTEK // Copyright (C) 2014 CYBUTEK
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// //
   
   
namespace KerbalEngineer.VesselSimulator namespace KerbalEngineer.VesselSimulator
{ {
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using CompoundParts; using CompoundParts;
using Extensions; using Extensions;
using UnityEngine; using UnityEngine;
   
public class PartSim public class PartSim
{ {
private static readonly Pool<PartSim> pool = new Pool<PartSim>(Create, Reset); 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 realMass; public double realMass;
public double baseMass; public double baseMass;
public double baseMassForCoM; public double baseMassForCoM;
public Vector3d centerOfMass; public Vector3d centerOfMass;
public double baseCost; public double baseCost;
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 List<PartSim> surfaceMountFuelTargets = new List<PartSim>(); public List<PartSim> surfaceMountFuelTargets = new List<PartSim>();
public bool hasModuleEngines; public bool hasModuleEngines;
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 isFairing;
public float fairingMass; public float postStageMassAdjust;
public int stageIndex; 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;
   
private static PartSim Create() private static PartSim Create()
{ {
return new PartSim(); return new PartSim();
} }
   
private static void Reset(PartSim partSim) private static void Reset(PartSim partSim)
{ {
for (int i = 0; i < partSim.attachNodes.Count; i++) for (int i = 0; i < partSim.attachNodes.Count; i++)
{ {
partSim.attachNodes[i].Release(); partSim.attachNodes[i].Release();
} }
partSim.attachNodes.Clear(); partSim.attachNodes.Clear();
partSim.fuelTargets.Clear(); partSim.fuelTargets.Clear();
  partSim.surfaceMountFuelTargets.Clear();
partSim.resourceDrains.Reset(); partSim.resourceDrains.Reset();
partSim.resourceFlowStates.Reset(); partSim.resourceFlowStates.Reset();
partSim.resources.Reset(); partSim.resources.Reset();
  partSim.parent = null;
partSim.baseCost = 0d; partSim.baseCost = 0d;
partSim.baseMass = 0d; partSim.baseMass = 0d;
partSim.baseMassForCoM = 0d; partSim.baseMassForCoM = 0d;
partSim.startMass = 0d; partSim.startMass = 0d;
} }
   
public void Release() public void Release()
{ {
pool.Release(this); pool.Release(this);
} }
   
public static PartSim New(Part thePart, int id, double atmosphere, LogMsg log) public static PartSim New(Part p, int id, double atmosphere, LogMsg log)
{ {
PartSim partSim = pool.Borrow(); PartSim partSim = pool.Borrow();
   
partSim.part = thePart; partSim.part = p;
partSim.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset); partSim.centerOfMass = p.transform.TransformPoint(p.CoMOffset);
partSim.partId = id; partSim.partId = id;
partSim.name = partSim.part.partInfo.name; partSim.name = p.partInfo.name;
   
if (log != null) log.buf.AppendLine("Create PartSim for " + partSim.name); if (log != null) log.buf.AppendLine("Create PartSim for " + partSim.name);
   
partSim.parent = null; partSim.parent = null;
partSim.parentAttach = partSim.part.attachMode; partSim.parentAttach = p.attachMode;
partSim.fuelCrossFeed = partSim.part.fuelCrossFeed; partSim.fuelCrossFeed = p.fuelCrossFeed;
partSim.noCrossFeedNodeKey = partSim.part.NoCrossFeedNodeKey; partSim.noCrossFeedNodeKey = p.NoCrossFeedNodeKey;
partSim.decoupledInStage = partSim.DecoupledInStage(partSim.part); partSim.decoupledInStage = partSim.DecoupledInStage(p);
partSim.isFuelLine = partSim.part.HasModule<CModuleFuelLine>(); partSim.isFuelLine = p.HasModule<CModuleFuelLine>();
partSim.isFuelTank = partSim.part is FuelTank; partSim.isFuelTank = p is FuelTank;
partSim.isSepratron = partSim.IsSepratron(); partSim.isSepratron = partSim.IsSepratron();
partSim.isFairing = partSim.IsFairing(partSim.part); partSim.inverseStage = p.inverseStage;
partSim.inverseStage = partSim.part.inverseStage;  
//MonoBehaviour.print("inverseStage = " + inverseStage); //MonoBehaviour.print("inverseStage = " + inverseStage);
   
partSim.baseCost = partSim.part.GetCostDry(); partSim.baseCost = p.GetCostDry();
   
if (log != null) if (log != null)
{ {
log.buf.AppendLine("Parent part = " + (partSim.part.parent == null ? "null" : partSim.part.parent.partInfo.name)); log.buf.AppendLine("Parent part = " + (p.parent == null ? "null" : p.parent.partInfo.name));
log.buf.AppendLine("physicalSignificance = " + partSim.part.physicalSignificance); log.buf.AppendLine("physicalSignificance = " + p.physicalSignificance);
log.buf.AppendLine("PhysicsSignificance = " + partSim.part.PhysicsSignificance); log.buf.AppendLine("PhysicsSignificance = " + p.PhysicsSignificance);
} }
   
// Work out if the part should have no physical significance // Work out if the part should have no physical significance
// The root part is never "no physics" // The root part is never "no physics"
partSim.isNoPhysics = partSim.part.physicalSignificance == Part.PhysicalSignificance.NONE || partSim.isNoPhysics = p.physicalSignificance == Part.PhysicalSignificance.NONE ||
partSim.part.PhysicsSignificance == 1; p.PhysicsSignificance == 1;
   
if (partSim.part.HasModule<LaunchClamp>()) if (p.HasModule<LaunchClamp>())
{ {
partSim.realMass = 0d; partSim.realMass = 0d;
if (log != null) log.buf.AppendLine("Ignoring mass of launch clamp"); if (log != null) log.buf.AppendLine("Ignoring mass of launch clamp");
} }
else else
{ {
partSim.realMass = partSim.part.mass; partSim.realMass = p.mass;
if (log != null) log.buf.AppendLine("Using part.mass of " + partSim.part.mass); if (log != null) log.buf.AppendLine("Using part.mass of " + p.mass);
} }
   
if (partSim.isFairing) partSim.postStageMassAdjust = 0f;
{ if (log != null) log.buf.AppendLine("Calculating postStageMassAdjust, prefabMass = " + p.prefabMass);
partSim.fairingMass = partSim.part.GetModuleMass((float)partSim.realMass); int count = p.Modules.Count;
} for (int i = 0; i < count; i++)
  {
for (int i = 0; i < partSim.part.Resources.Count; i++) if (log != null) log.buf.AppendLine("Module: " + p.Modules[i].moduleName);
{ IPartMassModifier partMassModifier = p.Modules[i] as IPartMassModifier;
PartResource resource = partSim.part.Resources[i]; if (partMassModifier != null)
  {
  if (log != null) log.buf.AppendLine("ChangeWhen = " + partMassModifier.GetModuleMassChangeWhen());
  if (partMassModifier.GetModuleMassChangeWhen() == ModifierChangeWhen.STAGED)
  {
  float preStage = partMassModifier.GetModuleMass(p.prefabMass, ModifierStagingSituation.UNSTAGED);
  float postStage = partMassModifier.GetModuleMass(p.prefabMass, ModifierStagingSituation.STAGED);
  if (log != null) log.buf.AppendLine("preStage = " + preStage + " postStage = " + postStage);
  partSim.postStageMassAdjust += (postStage - preStage);
  }
  }
  }
  if (log != null) log.buf.AppendLine("postStageMassAdjust = " + partSim.postStageMassAdjust);
   
  for (int i = 0; i < p.Resources.Count; i++)
  {
  PartResource resource = p.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 (log != null) if (log != null)
log.buf.AppendLine(resource.resourceName + " = " + resource.amount); log.buf.AppendLine(resource.resourceName + " = " + resource.amount);
   
partSim.resources.Add(resource.info.id, resource.amount); partSim.resources.Add(resource.info.id, resource.amount);
partSim.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0); partSim.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0);
} }
else else
{ {
if (log != null) log.buf.AppendLine(resource.resourceName + " is NaN. Skipping."); if (log != null) log.buf.AppendLine(resource.resourceName + " is NaN. Skipping.");
} }
} }
   
partSim.hasVessel = (partSim.part.vessel != null); partSim.hasVessel = (p.vessel != null);
partSim.isLanded = partSim.hasVessel && partSim.part.vessel.Landed; partSim.isLanded = partSim.hasVessel && p.vessel.Landed;
if (partSim.hasVessel) if (partSim.hasVessel)
{ {
partSim.vesselName = partSim.part.vessel.vesselName; partSim.vesselName = p.vessel.vesselName;
partSim.vesselType = partSim.part.vesselType; partSim.vesselType = p.vesselType;
} }
partSim.initialVesselName = partSim.part.initialVesselName; partSim.initialVesselName = p.initialVesselName;
   
partSim.hasMultiModeEngine = partSim.part.HasModule<MultiModeEngine>(); partSim.hasMultiModeEngine = p.HasModule<MultiModeEngine>();
partSim.hasModuleEngines = partSim.part.HasModule<ModuleEngines>(); partSim.hasModuleEngines = p.HasModule<ModuleEngines>();
   
partSim.isEngine = partSim.hasMultiModeEngine || partSim.hasModuleEngines; partSim.isEngine = partSim.hasMultiModeEngine || partSim.hasModuleEngines;
   
if (log != null) log.buf.AppendLine("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage); if (log != null) log.buf.AppendLine("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage);
   
return partSim; return partSim;
} }
   
public ResourceContainer ResourceDrains public ResourceContainer ResourceDrains
{ {
get get
{ {
return resourceDrains; return resourceDrains;
} }
} }
   
public ResourceContainer Resources public ResourceContainer Resources
{ {
get get
{ {
return resources; return resources;
} }
} }
   
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 mach, bool vectoredThrust, bool fullThrust, LogMsg log)
{ {
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++) for (int i = 0; i < this.part.Modules.Count; i++)
{ {
PartModule partMod = this.part.Modules[i]; PartModule partMod = this.part.Modules[i];
log.buf.AppendLine("Module: " + partMod.moduleName); log.buf.AppendLine("Module: " + partMod.moduleName);
} }
} }
   
if (hasMultiModeEngine) if (hasMultiModeEngine)
{ {
// A multi-mode engine has multiple ModuleEngines but only one is active at any point // A multi-mode engine has multiple ModuleEngines but only one is active at any point
// The mode of the engine is the engineID of the ModuleEngines that is active // The mode of the engine is the engineID of the ModuleEngines that is active
string mode = part.GetModule<MultiModeEngine>().mode; string mode = part.GetModule<MultiModeEngine>().mode;
   
List<ModuleEngines> engines = part.GetModules<ModuleEngines>(); List<ModuleEngines> engines = part.GetModules<ModuleEngines>();
for (int i = 0; i < engines.Count; ++i) for (int i = 0; i < engines.Count; ++i)
{ {
ModuleEngines engine = engines[i]; ModuleEngines engine = engines[i];
if (engine.engineID == mode) if (engine.engineID == mode)
{ {
if (log != null) log.buf.AppendLine("Module: " + engine.moduleName); if (log != null) log.buf.AppendLine("Module: " + engine.moduleName);
   
Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);  
   
EngineSim engineSim = EngineSim.New( EngineSim engineSim = EngineSim.New(
this, this,
atmosphere, engine,
  atmosphere,
(float)mach, (float)mach,
engine.maxFuelFlow, vectoredThrust,
engine.minFuelFlow, fullThrust,
engine.thrustPercentage,  
thrustvec,  
engine.atmosphereCurve,  
engine.atmChangeFlow,  
engine.useAtmCurve ? engine.atmCurve : null,  
engine.useVelCurve ? engine.velCurve : null,  
engine.currentThrottle,  
engine.g,  
engine.throttleLocked || fullThrust,  
engine.propellants,  
engine.isOperational,  
engine.resultingThrust,  
engine.thrustTransforms,  
log); log);
allEngines.Add(engineSim); allEngines.Add(engineSim);
} }
} }
} }
else if (hasModuleEngines) else if (hasModuleEngines)
{ {
List<ModuleEngines> engines = part.GetModules<ModuleEngines>(); List<ModuleEngines> engines = part.GetModules<ModuleEngines>();
for (int i = 0; i < engines.Count; ++i) for (int i = 0; i < engines.Count; ++i)
{ {
ModuleEngines engine = engines[i]; ModuleEngines engine = engines[i];
if (log != null) log.buf.AppendLine("Module: " + engine.moduleName); if (log != null) log.buf.AppendLine("Module: " + engine.moduleName);
   
Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);  
   
EngineSim engineSim = EngineSim.New( EngineSim engineSim = EngineSim.New(
this, this,
  engine,
atmosphere, atmosphere,
(float)mach, (float)mach,
engine.maxFuelFlow, vectoredThrust,
engine.minFuelFlow, fullThrust,
engine.thrustPercentage, log);
thrustvec,  
engine.atmosphereCurve,  
engine.atmChangeFlow,  
engine.useAtmCurve ? engine.atmCurve : null,  
engine.useVelCurve ? engine.velCurve : null,  
engine.currentThrottle,  
engine.g,  
engine.throttleLocked || fullThrust,  
engine.propellants,  
engine.isOperational,  
engine.resultingThrust,  
engine.thrustTransforms,  
log);  
allEngines.Add(engineSim); allEngines.Add(engineSim);
} }
} }
   
if (log != null) if (log != null)
{ {
log.Flush(); log.Flush();
} }
} }
   
public int DecouplerCount() public int DecouplerCount()
{ {
int count = 0; int count = 0;
PartSim partSim = this; PartSim partSim = this;
while (partSim != null) while (partSim != null)
{ {
if (partSim.isDecoupler) if (partSim.isDecoupler)
{ {
count++; count++;
} }
   
partSim = partSim.parent; partSim = partSim.parent;
} }
return count; return count;
} }
   
public void DrainResources(double time) public void DrainResources(double time)
{ {
//MonoBehaviour.print("DrainResources(" + name + ":" + partId + ", " + time + ")"); //MonoBehaviour.print("DrainResources(" + name + ":" + partId + ", " + time + ")");
for (int i = 0; i < resourceDrains.Types.Count; ++i) for (int i = 0; i < resourceDrains.Types.Count; ++i)
{ {
int type = resourceDrains.Types[i]; int type = resourceDrains.Types[i];
   
//MonoBehaviour.print("draining " + (time * resourceDrains[type]) + " " + ResourceContainer.GetResourceName(type)); //MonoBehaviour.print("draining " + (time * resourceDrains[type]) + " " + ResourceContainer.GetResourceName(type));
resources.Add(type, -time * resourceDrains[type]); resources.Add(type, -time * resourceDrains[type]);
//MonoBehaviour.print(ResourceContainer.GetResourceName(type) + " left = " + resources[type]); //MonoBehaviour.print(ResourceContainer.GetResourceName(type) + " left = " + resources[type]);
} }