diff --git a/.gitignore b/.gitignore index d23b451..552883f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,42 +1,163 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +## Unity Project ignores + +# This .gitignore file should be placed at the root of your Unity project directory +# +# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore +# +/UI/[Ll]ibrary/ +/UI/[Tt]emp/ +/UI/[Oo]bj/ +/UI/[Bb]uild/ +/UI/[Bb]uilds/ +/UI/[Ll]ogs/ +/UI/[Uu]ser[Ss]ettings/ + +# MemoryCaptures can get excessive in size. +# They also could contain extremely sensitive data +/UI/[Mm]emoryCaptures/ + +# Recordings can get excessive in size +/UI/[Rr]ecordings/ + +# Uncomment this line if you wish to ignore the asset store tools plugin +/UI/[Aa]ssets/AssetStoreTools* + +# Autogenerated Jetbrains Rider plugin +/UI/[Aa]ssets/Plugins/Editor/JetBrains* + +# Visual Studio cache directory +.vs/ + +# Gradle cache directory +/UI/.gradle/ + +# Autogenerated VS/MD/Consulo solution and project files +/UI/ExportedObj/ +/UI/.consulo/ +/UI/*.csproj +/UI/*.unityproj +/UI/*.sln +/UI/*.suo +/UI/*.tmp +/UI/*.user +/UI/*.userprefs +/UI/*.pidb +/UI/*.booproj +/UI/*.svd +/UI/*.pdb +/UI/*.mdb +/UI/*.opendb +/UI/*.VC.db + +# Unity3D generated meta files +*.pidb.meta +*.pdb.meta +*.mdb.meta + +# Unity3D generated file on crash reports +sysinfo.txt + +# Builds +*.apk +*.aab +*.unitypackage +*.app + +# Crashlytics generated file +crashlytics-build.properties + +# Packed Addressables +/UI/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* + +# Temporary auto-generated Android Assets +/UI/[Aa]ssets/[Ss]treamingAssets/aa.meta +/UI/[Aa]ssets/[Ss]treamingAssets/aa/* # User-specific files +*.rsuser *.suo *.user +*.userosscache *.sln.docstates +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# KSP dlls +external_dlls/ + # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ +[Rr]eleases/ x64/ -build/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* -#NUNIT +# NUnit *.VisualState.xml TestResult.xml +nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio *_i.c *_p.c -*_i.h +*_h.h *.ilk *.meta *.obj +*.iobj *.pch *.pdb +*.ipdb *.pgc *.pgd *.rsp @@ -46,6 +167,7 @@ dlldata.c *.tlh *.tmp *.tmp_proj +*_wpftmp.csproj *.log *.vspscc *.vssscc @@ -61,14 +183,21 @@ _Chutzpah* ipch/ *.aps *.ncb +*.opendb *.opensdf *.sdf *.cachefile +*.VC.db +*.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx +*.sap + +# Visual Studio Trace Files +*.e2e # TFS 2012 Local Workspace $tf/ @@ -81,19 +210,29 @@ _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user -# JustCode is a .NET coding addin-in -.JustCode - # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + # NCrunch -*.ncrunch* _NCrunch_* .*crunch*.local.xml +nCrunchTemp_* # MightyMoose *.mm.* @@ -121,118 +260,182 @@ publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml - -# NuGet Packages Directory -packages/ -## TODO: If the tool you use requires repositories.config uncomment the next line -#!packages/repositories.config - -# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets -# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) -!packages/build/ - -# Windows Azure Build Output +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output csx/ *.build.csdef -# Windows Store app package directory +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ # Others -sql/ -*.Cache ClientBin/ -[Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.dbproj.schemaview +*.jfm *.pfx *.publishsettings -node_modules/ +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ # RIA/Silverlight projects Generated_Code/ -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak # SQL Server files *.mdf *.ldf +*.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ -# ========================= -# Operating System Files -# ========================= +# GhostDoc plugin setting file +*.GhostDoc.xml -# OSX -# ========================= +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ -.DS_Store -.AppleDouble -.LSOverride +# Visual Studio 6 build log +*.plg -# Icon must ends with two \r. -Icon +# Visual Studio 6 workspace options file +*.opt -# Thumbnails -._* +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw -# Files that might appear on external disk -.Spotlight-V100 -.Trashes +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk +# Paket dependency manager +.paket/paket.exe +paket-files/ +# FAKE - F# Make +.fake/ +# CodeRush personal settings +.cr/personal -# Windows -# ========================= +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc -# Windows image file caches -Thumbs.db -ehthumbs.db +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config -# Folder config file -Desktop.ini +# Tabs Studio +*.tss -# Recycle Bin used on file shares -$RECYCLE.BIN/ +# Telerik's JustMock configuration file +*.jmconfig -# Windows Installer files -*.cab -*.msi -*.msm -*.msp +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs -# Windows shortcuts -*.lnk +# OpenCover UI analysis results +OpenCover/ -# -# Vim files -# -*~ -*.swp -*.dll -*.pdb -.vs +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ -*.exe -readme.txt \ No newline at end of file +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/LazyOrbit.sln b/LazyOrbit.sln index ae0c002..c14c939 100644 --- a/LazyOrbit.sln +++ b/LazyOrbit.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.4.33403.182 +VisualStudioVersion = 17.5.33502.453 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LazyOrbit", "LazyOrbit\LazyOrbit.csproj", "{C0BDE81C-46FF-40A1-B3A1-07E40830115C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LazyOrbit", "LazyOrbitProject\LazyOrbit.csproj", "{C0BDE81C-46FF-40A1-B3A1-07E40830115C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -19,7 +19,4 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {1928799A-1D41-4C13-995B-265DF15A63C9} - EndGlobalSection EndGlobal diff --git a/LazyOrbit/LazyOrbit.cs b/LazyOrbit/LazyOrbit.cs deleted file mode 100644 index 78e6e07..0000000 --- a/LazyOrbit/LazyOrbit.cs +++ /dev/null @@ -1,511 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System.Reflection; - -using UnityEngine; -using Newtonsoft.Json; - -using KSP.Sim.impl; -using KSP.Game; -using KSP.Sim.ResourceSystem; -using KSP.UI.Binding; - -using BepInEx; -using SpaceWarp; -using SpaceWarp.API; -using SpaceWarp.API.Mods; -using SpaceWarp.API.Assets; -using SpaceWarp.API.UI; -using SpaceWarp.API.UI.Appbar; - - -namespace LazyOrbit -{ - [BepInDependency(SpaceWarpPlugin.ModGuid,SpaceWarpPlugin.ModVer)] - [BepInPlugin(ModGuid, ModName, ModVer)] - public class LazyOrbit : BaseSpaceWarpPlugin - { - public const string ModGuid = "com.github.halbann.lazyorbit"; - public const string ModName = "Lazy Orbit"; - public const string ModVer = MyPluginInfo.PLUGIN_VERSION; - - #region Fields - - // Main. - public static bool loaded = false; - public static LazyOrbit instance; - - // Paths. - private static string _assemblyFolder; - private static string AssemblyFolder => - _assemblyFolder ?? (_assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); - - private static string _settingsPath; - private static string SettingsPath => - _settingsPath ?? (_settingsPath = Path.Combine(AssemblyFolder, "settings.json")); - - // GUI. - private static bool guiLoaded = false; - private bool drawUI = false; - private Rect windowRect; - private int windowWidth = 500; - private int windowHeight = 700; - private static GUIStyle boxStyle, errorStyle, warnStyle, peStyle, apStyle; - private static Vector2 scrollPositionBodies; - private static Vector2 scrollPositionVessels; - private static Color labelColor; - private static GameState[] validScenes = new[] { GameState.FlightView, GameState.Map3DView }; - - private static bool ValidScene => validScenes.Contains(GameManager.Instance.Game.GlobalGameState.GetState()); - - // Orbit. - private static float altitudeKM = 100; - private static float semiMajorAxisKM = 700; - private static float inclinationDegrees = 0; - private static float eccentricity = 0; - private static float ascendingNode = 0; - private static float argOfPeriapsis = 0; - private static double bodyRadius = 600000; - private static double apKM, peKM; - - private static string altitudeString = altitudeKM.ToString(); - private static string semiMajorAxisString = semiMajorAxisKM.ToString(); - private static string inclinationString = inclinationDegrees.ToString(); - private static string eccentricityString = eccentricity.ToString(); - private static string ascendingNodeString = ascendingNode.ToString(); - private static string argOfPeriapsisString = argOfPeriapsis.ToString(); - - // Body selection. - private string selectedBody = "Kerbin"; - private List bodies; - private bool selectingBody = false; - - // Rendezvous. - private static VesselComponent activeVessel; - private static VesselComponent target; - private static List allVessels; - private static bool selectingVessel = false; - private static float rendezvousDistance = 100f; - private static string rendezvousDistanceString = rendezvousDistance.ToString(); - - // Landing. - private static float latitude = -0.65f; - private static float longitude = 285f; - private static float height = 5f; - private static string latitudeString = latitude.ToString(); - private static string longitudeString = longitude.ToString(); - private static string heightString = height.ToString(); - - // Interface modes. - private static InterfaceMode interfaceMode = InterfaceMode.Simple; - private static string[] interfaceModes = { "Simple", "Advanced", "Landing", "Rendezvous" }; - - private InterfaceMode CurrentInterfaceMode - { - get => interfaceMode; - set - { - if (value == interfaceMode) return; - - interfaceMode = value; - if (new[] { InterfaceMode.Simple, InterfaceMode.Advanced }.Contains(interfaceMode)) - SaveDefaultMode(interfaceMode); - } - } - - #endregion - - #region Main - - public override void OnInitialized() - { - if (loaded) - { - Destroy(this); - } - - loaded = true; - instance = this; - - gameObject.hideFlags = HideFlags.HideAndDontSave; - DontDestroyOnLoad(gameObject); - - interfaceMode = GetDefaultMode(); - - Appbar.RegisterAppButton( - "Lazy Orbit", - "BTN-LazyOrbitButton", - AssetManager.GetAsset($"{SpaceWarpMetadata.ModID}/images/icon.png"), - ToggleButton); - } - - void Awake() - { - windowRect = new Rect((Screen.width * 0.7f) - (windowWidth / 2), (Screen.height / 2) - (windowHeight / 2), 0, 0); - } - - void Update() - { - if (Input.GetKey(KeyCode.LeftAlt) && Input.GetKeyDown(KeyCode.H) && ValidScene) - ToggleButton(!drawUI); - } - - void OnGUI() - { - if (drawUI && ValidScene) - { - if (!guiLoaded) - GetStyles(); - - GUI.skin = Skins.ConsoleSkin; - - windowRect = GUILayout.Window( - GUIUtility.GetControlID(FocusType.Passive), - windowRect, - FillWindow, - "// LAZY ORBIT", - GUILayout.Height(0), - GUILayout.Width(350)); - } - } - - void ToggleButton(bool toggle) - { - drawUI = toggle; - GameObject.Find("BTN-LazyOrbitButton")?.GetComponent()?.SetValue(toggle); - } - - #endregion - - #region GUI - - private void GetStyles() - { - if (boxStyle != null) - return; - - boxStyle = GUI.skin.GetStyle("Box"); - errorStyle = new GUIStyle(GUI.skin.GetStyle("Label")); - warnStyle = new GUIStyle(GUI.skin.GetStyle("Label")); - apStyle = new GUIStyle(GUI.skin.GetStyle("Label")); - peStyle = new GUIStyle(GUI.skin.GetStyle("Label")); - errorStyle.normal.textColor = Color.red; - warnStyle.normal.textColor = Color.yellow; - labelColor = GUI.skin.GetStyle("Label").normal.textColor; - - guiLoaded = true; - } - - private void FillWindow(int windowID) - { - if ((activeVessel = GameManager.Instance.Game.ViewController.GetActiveSimVessel()) == null) - { - GUILayout.FlexibleSpace(); - GUILayout.Label("No active vessel.", errorStyle); - GUILayout.FlexibleSpace(); - return; - } - - if (GUI.Button(new Rect(windowRect.width - 18, 2, 16, 16), "x")) - ToggleButton(false); - - GUILayout.BeginVertical(); - - GUILayout.Label($"Active Vessel: {activeVessel.DisplayName}"); - - // Mode selection. - - GUILayout.BeginHorizontal(); - CurrentInterfaceMode = (InterfaceMode)GUILayout.SelectionGrid((int)CurrentInterfaceMode, interfaceModes, 4); - GUILayout.EndHorizontal(); - - // Draw one of the modes. - switch (CurrentInterfaceMode) - { - case InterfaceMode.Simple: SimpleGUI(); break; - case InterfaceMode.Advanced: AdvancedGUI(); break; - case InterfaceMode.Landing: LandingGUI(); break; - case InterfaceMode.Rendezvous: RendezvousGUI(); break; - default: - break; - } - - GUILayout.EndVertical(); - GUI.DragWindow(new Rect(0, 0, 10000, 500)); - } - - void SimpleGUI() - { - bool success = true; - - TextField("Altitude (km):", ref altitudeString, ref altitudeKM, ref success); - BodySelectionGUI(); - - ConditionalButton("Set Orbit", success, SetOrbit); - } - - - void LandingGUI() - { - bool success = true; - - TextField("Latitude (Degrees):", ref latitudeString, ref latitude, ref success); - TextField("Longitude (Degrees):", ref longitudeString, ref longitude, ref success); - TextField("Height (m):", ref heightString, ref height, ref success); - BodySelectionGUI(); - - ConditionalButton("Land", success, Land); - } - - void AdvancedGUI() - { - bool success = true; - - TextField("Semi-Major Axis (km):", ref semiMajorAxisString, ref semiMajorAxisKM, ref success); - - bodyRadius = GameManager.Instance.Game.CelestialBodies.GetRadius(selectedBody) / 1000f; - apKM = (semiMajorAxisKM * (1 + eccentricity) - bodyRadius); - peKM = (semiMajorAxisKM * (1 - eccentricity) - bodyRadius); - apStyle.normal.textColor = apKM < 1 ? warnStyle.normal.textColor : labelColor; - peStyle.normal.textColor = peKM < 1 ? warnStyle.normal.textColor : labelColor; - - GUILayout.BeginHorizontal(); - GUILayout.Label("AP (km): ", apStyle, GUILayout.Width(windowWidth / 4)); - GUILayout.Label(apKM.ToString("n2"), apStyle, GUILayout.Width(windowWidth / 4)); - GUILayout.Label("PE (km): ", peStyle, GUILayout.Width(windowWidth / 4)); - GUILayout.Label(peKM.ToString("n2"), peStyle, GUILayout.Width(windowWidth / 4)); - GUILayout.EndHorizontal(); - - TextField("Inclination (Degrees):", ref inclinationString, ref inclinationDegrees, ref success); - TextField("Eccentricity:", ref eccentricityString, ref eccentricity, ref success); - - if (eccentricity >= 1 || eccentricity < 0) - { - GUILayout.BeginHorizontal(); - GUILayout.Label("Eccentricity must be between 0 and 1.", errorStyle); - GUILayout.EndHorizontal(); - } - - TextField("Longitude of Ascending Node (Degrees):", ref ascendingNodeString, ref ascendingNode, ref success); - TextField("Argument of Periapsis (Degrees):", ref argOfPeriapsisString, ref argOfPeriapsis, ref success); - - BodySelectionGUI(); - - ConditionalButton("Set Orbit", success, SetOrbit); - } - - void RendezvousGUI() - { - bool success = true; - - allVessels = GameManager.Instance.Game.SpaceSimulation.UniverseModel.GetAllVessels(); - allVessels.Remove(activeVessel); - allVessels.RemoveAll(v => v.IsDebris()); - - if (allVessels.Count < 1) - { - GUILayout.Label("No other vessels."); - return; - } - - if (target == null) - target = allVessels.First(); - - TextField("Distance (m):", ref rendezvousDistanceString, ref rendezvousDistance, ref success); - - GUILayout.BeginHorizontal(); - GUILayout.Label("Target: ", GUILayout.Width(0)); - if (!selectingVessel) - { - if (GUILayout.Button(target.DisplayName)) - selectingVessel = true; - } - else - { - GUILayout.BeginVertical(boxStyle); - scrollPositionVessels = GUILayout.BeginScrollView(scrollPositionVessels, false, true, GUILayout.Height(150)); - foreach (VesselComponent vessel in allVessels) - { - if (GUILayout.Button(vessel.DisplayName)) - { - target = vessel; - selectingVessel = false; - } - } - GUILayout.EndScrollView(); - GUILayout.EndVertical(); - } - GUILayout.EndHorizontal(); - - ConditionalButton("Rendezvous", success, Rendezvous); - } - - // Draws the body selection GUI. - void BodySelectionGUI() - { - bodies = GameManager.Instance.Game.SpaceSimulation.GetBodyNameKeys().ToList(); - - GUILayout.BeginHorizontal(); - GUILayout.Label("Body: ", GUILayout.Width(windowWidth / 2)); - if (!selectingBody) - { - if (GUILayout.Button(selectedBody)) - selectingBody = true; - } - else - { - GUILayout.BeginVertical(boxStyle); - scrollPositionBodies = GUILayout.BeginScrollView(scrollPositionBodies, false, true, GUILayout.Height(150)); - foreach (string body in bodies) - { - if (GUILayout.Button(body)) - { - selectedBody = body; - selectingBody = false; - } - } - GUILayout.EndScrollView(); - GUILayout.EndVertical(); - } - GUILayout.EndHorizontal(); - } - - void TextField(string label, ref string field, ref float number, ref bool success) - { - GUILayout.BeginHorizontal(); - GUILayout.Label(label, GUILayout.Width(windowWidth / 2)); - - bool parsed = float.TryParse(field, out number); - if (!parsed) GUI.color = Color.red; - field = GUILayout.TextField(field); - GUI.color = Color.white; - - if (success && !parsed) - success = false; - - GUILayout.EndHorizontal(); - } - - void ConditionalButton(string text, bool condition, Action pressed) - { - GUI.enabled = condition; - - if (GUILayout.Button(text)) - pressed(); - - GUI.enabled = true; - } - - #endregion - - #region Functions - - // Sets vessel orbit according to the current interfaceMode. - void SetOrbit() - { - GameInstance game = GameManager.Instance.Game; - - if (CurrentInterfaceMode == InterfaceMode.Simple) - { - // Set orbit using just altitude. - game.SpaceSimulation.Lua.TeleportToOrbit( - activeVessel.Guid, - selectedBody, - 0, - 0, - (double)altitudeKM * 1000f + GameManager.Instance.Game.CelestialBodies.GetRadius(selectedBody), - 0, - 0, - 0, - 0); - } - else - { - // Set orbit using semi-major axis and other orbital parameters. - game.SpaceSimulation.Lua.TeleportToOrbit( - activeVessel.Guid, - selectedBody, - inclinationDegrees, - eccentricity, - (double)semiMajorAxisKM * 1000f, - ascendingNode, - argOfPeriapsis, - 0, - 0); - } - } - - void Rendezvous() - { - GameInstance game = GameManager.Instance.Game; - - if (target.Guid == activeVessel.Guid) - return; - - game.SpaceSimulation.Lua.TeleportToRendezvous( - activeVessel.Guid, - target.Guid, - rendezvousDistance, - 0, 0, 0, 0, 0); - } - - void Land() - { - GameInstance game = GameManager.Instance.Game; - - game.SpaceSimulation.Lua.TeleportToSurface( - activeVessel.Guid, - selectedBody, - height, - latitude, - longitude, - 0); - } - - #endregion - - #region Settings - - private void SaveDefaultMode(InterfaceMode mode) - { - LazyOrbitSettings settings = new LazyOrbitSettings() - { - defaultMode = mode - }; - - File.WriteAllText(SettingsPath, JsonConvert.SerializeObject(settings)); - } - - private InterfaceMode GetDefaultMode() - { - LazyOrbitSettings settings; - try - { - settings = JsonConvert.DeserializeObject(File.ReadAllText(SettingsPath)); - } - catch (FileNotFoundException) - { - settings = new LazyOrbitSettings(); - } - - return settings.defaultMode; - } - - #endregion - } - - public class LazyOrbitSettings - { - public InterfaceMode defaultMode = InterfaceMode.Simple; - } - - public enum InterfaceMode - { - Simple, - Advanced, - Landing, - Rendezvous, - } -} \ No newline at end of file diff --git a/LazyOrbit/LazyOrbit.csproj b/LazyOrbit/LazyOrbit.csproj deleted file mode 100644 index fc1f860..0000000 --- a/LazyOrbit/LazyOrbit.csproj +++ /dev/null @@ -1,95 +0,0 @@ - - - - - Debug - AnyCPU - {C0BDE81C-46FF-40A1-B3A1-07E40830115C} - Library - Properties - LazyOrbit - LazyOrbit - v4.8 - 512 - true - 0.4.0 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - G:\Games\Steam Library\steamapps\common\Kerbal Space Program 2\KSP2_x64_Data\Managed\Assembly-CSharp.dll - False - - - G:\Games\Steam Library\steamapps\common\Kerbal Space Program 2\BepInEx\core\BepInEx.dll - False - - - G:\Games\Steam Library\steamapps\common\Kerbal Space Program 2\KSP2_x64_Data\Managed\Newtonsoft.Json.dll - False - - - False - G:\Games\Steam Library\steamapps\common\Kerbal Space Program 2\BepInEx\plugins\SpaceWarp\SpaceWarp.dll - False - - - - - - - - - - - G:\Games\Steam Library\steamapps\common\Kerbal Space Program 2\KSP2_x64_Data\Managed\UnityEngine.dll - False - - - G:\Games\Steam Library\steamapps\common\Kerbal Space Program 2\KSP2_x64_Data\Managed\UnityEngine.CoreModule.dll - False - - - G:\Games\Steam Library\steamapps\common\Kerbal Space Program 2\KSP2_x64_Data\Managed\UnityEngine.IMGUIModule.dll - False - - - G:\Games\Steam Library\steamapps\common\Kerbal Space Program 2\KSP2_x64_Data\Managed\UnityEngine.InputLegacyModule.dll - False - - - - - - - - - -"$(ProjectDir)pdb2mdb\pdb2mdb.exe" "$(TargetPath)" - -SET KSP2=G:\Games\Steam Library\steamapps\common\Kerbal Space Program 2 - -copy /Y "$(TargetDir)$(ProjectName).dll" "%25KSP2%25\BepInEx\plugins\LazyOrbit\$(ProjectName).dll" -copy /Y "$(TargetDir)$(Targetname).pdb" "%25KSP2%25\BepInEx\plugins\LazyOrbit\" -copy /Y "$(TargetDir)$(Targetname).dll.mdb" "%25KSP2%25\BepInEx\plugins\LazyOrbit\" - -copy /Y "$(TargetDir)$(ProjectName).dll" "$(SolutionDir)\LazyOrbitBuild\BepInEx\plugins\LazyOrbit\$(ProjectName).dll" -copy /Y "$(SolutionDir)\README.md" "$(SolutionDir)\LazyOrbitBuild\BepInEx\plugins\LazyOrbit\readme.txt" - - \ No newline at end of file diff --git a/LazyOrbit/Properties/AssemblyInfo.cs b/LazyOrbit/Properties/AssemblyInfo.cs deleted file mode 100644 index 6775fd9..0000000 --- a/LazyOrbit/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("LazyOrbit")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("LazyOrbit")] -[assembly: AssemblyCopyright("Copyright © 2023")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c0bde81c-46ff-40a1-b3a1-07e40830115c")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/LazyOrbitBuild/BepInEx/plugins/LazyOrbit/assets/images/icon.png b/LazyOrbit/assets/images/icon.png similarity index 100% rename from LazyOrbitBuild/BepInEx/plugins/LazyOrbit/assets/images/icon.png rename to LazyOrbit/assets/images/icon.png diff --git a/LazyOrbit/swinfo.json b/LazyOrbit/swinfo.json new file mode 100644 index 0000000..98a664a --- /dev/null +++ b/LazyOrbit/swinfo.json @@ -0,0 +1,22 @@ +{ + "mod_id": "LazyOrbit", + "name": "Lazy Orbit", + "author": "Halban, XYZ3211, schlosrat", + "description": "A GUI for teleporting to orbit, keybind is ALT+H.", + "source": "https://github.com/schlosrat/LazyOrbit", + "version": "0.5.3", + "version_check": "https://raw.githubusercontent.com/schlosrat/LazyOrbit/master/LazyOrbit/swinfo.json", + "dependencies": [ + { + "id": "SpaceWarp", + "version": { + "min": "1.3.0", + "max": "*" + } + } + ], + "ksp2_version": { + "min": "0.1.1", + "max": "0.1.5" + } +} diff --git a/LazyOrbitBuild/BepInEx/plugins/LazyOrbit/swinfo.json b/LazyOrbitBuild/BepInEx/plugins/LazyOrbit/swinfo.json deleted file mode 100644 index 04db382..0000000 --- a/LazyOrbitBuild/BepInEx/plugins/LazyOrbit/swinfo.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "mod_id": "LazyOrbit", - "name": "Lazy Orbit", - "author": "Halban, XYZ3211", - "description": "A GUI for teleporting to orbit, keybind is ALT+H.", - "source": "https://github.com/Halbann/LazyOrbit", - "version": "v0.4.0", - "dependencies": [], - "ksp2_version": { - "min": "0", - "max": "1" - } -} \ No newline at end of file diff --git a/LazyOrbitBuild/LazyOrbit-v0.4.0.zip b/LazyOrbitBuild/LazyOrbit-v0.4.0.zip deleted file mode 100644 index 705c9bb..0000000 Binary files a/LazyOrbitBuild/LazyOrbit-v0.4.0.zip and /dev/null differ diff --git a/LazyOrbitProject/LazyOrbit.cs b/LazyOrbitProject/LazyOrbit.cs new file mode 100644 index 0000000..c24172b --- /dev/null +++ b/LazyOrbitProject/LazyOrbit.cs @@ -0,0 +1,599 @@ +using BepInEx; +using BepInEx.Configuration; +using KSP.Game; +using KSP.Messages.PropertyWatchers; +using KSP.Sim.impl; +using KSP.Sim.ResourceSystem; +using KSP.UI.Binding; +using Newtonsoft.Json; +using SpaceWarp; +using SpaceWarp.API.Assets; +using SpaceWarp.API.Mods; +using SpaceWarp.API.UI; +using SpaceWarp.API.UI.Appbar; +using System.Reflection; +using UnityEngine; + + +namespace LazyOrbit +{ + [BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)] + [BepInDependency(SpaceWarpPlugin.ModGuid, SpaceWarpPlugin.ModVer)] + public class LazyOrbit : BaseSpaceWarpPlugin + { + // public const string ModGuid = "com.github.halbann.lazyorbit"; + // public const string ModName = "Lazy Orbit"; + public const string ModVer = MyPluginInfo.PLUGIN_VERSION; + // These are useful in case some other mod wants to add a dependency to this one + public const string ModGuid = MyPluginInfo.PLUGIN_GUID; + public const string ModName = MyPluginInfo.PLUGIN_NAME; + // public const string ModVer = MyPluginInfo.PLUGIN_VERSION; + + private ConfigEntry _keybind; + private ConfigEntry _keybind2; + + #region Fields + + // Main. + public static bool loaded = false; + public static LazyOrbit instance; + + // Paths. + private static string _assemblyFolder; + private static string AssemblyFolder => + _assemblyFolder ?? (_assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); + + private static string _settingsPath; + private static string SettingsPath => + _settingsPath ?? (_settingsPath = Path.Combine(AssemblyFolder, "settings.json")); + + // GUI. + private static bool guiLoaded = false; + private bool drawUI = false; + private Rect windowRect; + private int windowWidth = 500; + private int windowHeight = 700; + private static GUIStyle boxStyle, errorStyle, warnStyle, peStyle, apStyle, labelStyle; + private static Vector2 scrollPositionBodies; + private static Vector2 scrollPositionVessels; + private static Color labelColor; + private static GameState[] validScenes = new[] { GameState.FlightView, GameState.Map3DView }; + private int spacingAfterEntry = -5; + + // Control click through to the game + private bool gameInputState = true; + public List inputFields = new List(); + + private static bool ValidScene => validScenes.Contains(GameManager.Instance.Game.GlobalGameState.GetState()); + + // Orbit. + private static float altitudeKM = 100; + private static float semiMajorAxisKM = 700; + private static float inclinationDegrees = 0; + private static float eccentricity = 0; + private static float ascendingNode = 0; + private static float argOfPeriapsis = 0; + private static double bodyRadius = 600000; + private static double apKM, peKM; + + private static string altitudeString = altitudeKM.ToString(); + private static string semiMajorAxisString = semiMajorAxisKM.ToString(); + private static string inclinationString = inclinationDegrees.ToString(); + private static string eccentricityString = eccentricity.ToString(); + private static string ascendingNodeString = ascendingNode.ToString(); + private static string argOfPeriapsisString = argOfPeriapsis.ToString(); + + // Body selection. + private string selectedBody = "Kerbin"; + private List bodies; + private bool selectingBody = false; + + // Rendezvous. + private static VesselComponent activeVessel; + private static VesselComponent target; + private static List allVessels; + private static bool selectingVessel = false; + private static float rendezvousDistance = 100f; + private static string rendezvousDistanceString = rendezvousDistance.ToString(); + + // Landing. + private static float latitude = -0.65f; + private static float longitude = 285f; + private static float height = 5f; + private static string latitudeString = latitude.ToString(); + private static string longitudeString = longitude.ToString(); + private static string heightString = height.ToString(); + + // Interface modes. + private static InterfaceMode interfaceMode = InterfaceMode.Simple; + private static string[] interfaceModes = { "Simple", "Advanced", "Landing", "Rendezvous" }; + + private InterfaceMode CurrentInterfaceMode + { + get => interfaceMode; + set + { + if (value == interfaceMode) return; + + interfaceMode = value; + if (new[] { InterfaceMode.Simple, InterfaceMode.Advanced }.Contains(interfaceMode)) + SaveDefaultMode(interfaceMode); + } + } + + #endregion + + #region Main + + public override void OnInitialized() + { + if (loaded) + { + Destroy(this); + } + + loaded = true; + instance = this; + + _keybind = Config.Bind( + new ConfigDefinition("Keybindings", "First Keybind"), + new KeyboardShortcut(KeyCode.H, KeyCode.LeftAlt), + new ConfigDescription("Keybind to open mod window") + ); + + _keybind2 = Config.Bind( + new ConfigDefinition("Keybindings", "Second Keybind"), + new KeyboardShortcut(KeyCode.H, KeyCode.RightAlt, KeyCode.AltGr), + new ConfigDescription("Keybind to open mod window") + ); + + gameObject.hideFlags = HideFlags.HideAndDontSave; + DontDestroyOnLoad(gameObject); + + interfaceMode = GetDefaultMode(); + + Logger.LogInfo($"Lazy Orbit: SpaceWarpMetadata.ModID = {SpaceWarpMetadata.ModID}"); + + Appbar.RegisterAppButton( + "Lazy Orbit", + "BTN-LazyOrbitButton", + AssetManager.GetAsset($"{SpaceWarpMetadata.ModID}/images/icon.png"), + ToggleButton); + } + + void Awake() + { + windowRect = new Rect((Screen.width * 0.7f) - (windowWidth / 2), (Screen.height / 2) - (windowHeight / 2), 0, 0); + if (windowRect.x < 0) windowRect.x = 400; + if (windowRect.y < 0) windowRect.y = 250; + } + + void Update() + { + if ((_keybind != null && _keybind.Value.IsDown()) || (_keybind2 != null && _keybind2.Value.IsDown())) + { + ToggleButton(!drawUI); + if (_keybind != null && _keybind.Value.IsDown()) + Logger.LogDebug($"Update: UI toggled with _keybind, hotkey {_keybind.Value}"); + if (_keybind2 != null && _keybind2.Value.IsDown()) + Logger.LogDebug($"Update: UI toggled with _keybind2, hotkey {_keybind2.Value}"); + } + } + + void OnGUI() + { + //GUIenabled = false; + //var gameState = Game?.GlobalGameState?.GetState(); + //if (gameState == GameState.Map3DView) GUIenabled = true; + //if (gameState == GameState.FlightView) GUIenabled = true; + + if (drawUI && ValidScene) + { + if (!guiLoaded) + GetStyles(); + + GUI.skin = Skins.ConsoleSkin; + + windowRect = GUILayout.Window( + GUIUtility.GetControlID(FocusType.Passive), + windowRect, + FillWindow, + "// LAZY ORBIT", + GUILayout.Height(0), + GUILayout.Width(350)); + + if (gameInputState && inputFields.Contains(GUI.GetNameOfFocusedControl())) + { + // Logger.LogDebug($"OnGUI: Disabling Game Input: Focused Item '{GUI.GetNameOfFocusedControl()}'"); + gameInputState = false; + GameManager.Instance.Game.Input.Disable(); + } + else if (!gameInputState && !inputFields.Contains(GUI.GetNameOfFocusedControl())) + { + // Logger.LogDebug($"OnGUI: Enabling Game Input: FYI, Focused Item '{GUI.GetNameOfFocusedControl()}'"); + gameInputState = true; + GameManager.Instance.Game.Input.Enable(); + } + //if (selectingBody) + //{ + // // Do something here to disable mouse wheel control of zoom in and out. + // // Intent: allow player to scroll in the scroll view without causing the game to zoom in and out + // GameManager.Instance._game.MouseManager.enabled = false; + //} + //else + //{ + // // Do something here to re-enable mouse wheel control of zoom in and out. + // GameManager.Instance._game.MouseManager.enabled = true; + //} + } + else + { + if (!gameInputState) + { + // Logger.LogDebug($"OnGUI: Enabling Game Input due to GUI disabled: FYI, Focused Item '{GUI.GetNameOfFocusedControl()}'"); + gameInputState = true; + GameManager.Instance.Game.Input.Enable(); + } + } + } + + void ToggleButton(bool toggle) + { + drawUI = toggle; + GameObject.Find("BTN-LazyOrbitButton")?.GetComponent()?.SetValue(toggle); + } + + #endregion + + #region GUI + + private void GetStyles() + { + if (boxStyle != null) + return; + + boxStyle = GUI.skin.GetStyle("Box"); + labelStyle = new GUIStyle(GUI.skin.GetStyle("Label")); + errorStyle = new GUIStyle(GUI.skin.GetStyle("Label")); + warnStyle = new GUIStyle(GUI.skin.GetStyle("Label")); + apStyle = new GUIStyle(GUI.skin.GetStyle("Label")); + peStyle = new GUIStyle(GUI.skin.GetStyle("Label")); + errorStyle.normal.textColor = Color.red; + warnStyle.normal.textColor = Color.yellow; + labelColor = GUI.skin.GetStyle("Label").normal.textColor; + + guiLoaded = true; + } + + private void FillWindow(int windowID) + { + if ((activeVessel = GameManager.Instance.Game.ViewController.GetActiveSimVessel()) == null) + { + GUILayout.FlexibleSpace(); + GUILayout.Label("No active vessel.", errorStyle); + GUILayout.FlexibleSpace(); + return; + } + + if (GUI.Button(new Rect(windowRect.width - 18, 2, 16, 16), "x")) + { + Logger.LogDebug("FillWindow: Restoring Game Input on window close."); + GameManager.Instance.Game.Input.Enable(); + ToggleButton(false); + } + + GUILayout.BeginVertical(); + + GUILayout.Label($"Active Vessel: {activeVessel.DisplayName}"); + + // Mode selection. + + GUILayout.BeginHorizontal(); + CurrentInterfaceMode = (InterfaceMode)GUILayout.SelectionGrid((int)CurrentInterfaceMode, interfaceModes, 4); + GUILayout.EndHorizontal(); + + // Draw one of the modes. + switch (CurrentInterfaceMode) + { + case InterfaceMode.Simple: SimpleGUI(); break; + case InterfaceMode.Advanced: AdvancedGUI(); break; + case InterfaceMode.Landing: LandingGUI(); break; + case InterfaceMode.Rendezvous: RendezvousGUI(); break; + default: + break; + } + + // Indication to User that its safe to type, or why vessel controls aren't working + GUILayout.BeginHorizontal(); + string inputStateString = gameInputState ? "Enabled" : "Disabled"; + GUILayout.Label("Game Input: ", labelStyle); + if (gameInputState) + GUILayout.Label(inputStateString, labelStyle); + else + GUILayout.Label(inputStateString, warnStyle); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + GUILayout.Space(spacingAfterEntry); + + GUILayout.EndVertical(); + GUI.DragWindow(new Rect(0, 0, 10000, 500)); + } + + void SimpleGUI() + { + bool success = true; + + TextField("Altitude (km):", ref altitudeString, ref altitudeKM, ref success); + BodySelectionGUI(); + + ConditionalButton("Set Orbit", success, SetOrbit); + } + + + void LandingGUI() + { + bool success = true; + + TextField("Latitude (Degrees):", ref latitudeString, ref latitude, ref success); + TextField("Longitude (Degrees):", ref longitudeString, ref longitude, ref success); + TextField("Height (m):", ref heightString, ref height, ref success); + BodySelectionGUI(); + + ConditionalButton("Land", success, Land); + } + + void AdvancedGUI() + { + bool success = true; + + TextField("Semi-Major Axis (km):", ref semiMajorAxisString, ref semiMajorAxisKM, ref success); + + bodyRadius = GameManager.Instance.Game.CelestialBodies.GetRadius(selectedBody) / 1000f; + apKM = (semiMajorAxisKM * (1 + eccentricity) - bodyRadius); + peKM = (semiMajorAxisKM * (1 - eccentricity) - bodyRadius); + apStyle.normal.textColor = apKM < 1 ? warnStyle.normal.textColor : labelColor; + peStyle.normal.textColor = peKM < 1 ? warnStyle.normal.textColor : labelColor; + + GUILayout.BeginHorizontal(); + GUILayout.Label("AP (km): ", apStyle, GUILayout.Width(windowWidth / 4)); + GUILayout.Label(apKM.ToString("n2"), apStyle, GUILayout.Width(windowWidth / 4)); + GUILayout.Label("PE (km): ", peStyle, GUILayout.Width(windowWidth / 4)); + GUILayout.Label(peKM.ToString("n2"), peStyle, GUILayout.Width(windowWidth / 4)); + GUILayout.EndHorizontal(); + + TextField("Inclination (Degrees):", ref inclinationString, ref inclinationDegrees, ref success); + TextField("Eccentricity:", ref eccentricityString, ref eccentricity, ref success); + + if (eccentricity >= 1 || eccentricity < 0) + { + GUILayout.BeginHorizontal(); + GUILayout.Label("Eccentricity must be between 0 and 1.", errorStyle); + GUILayout.EndHorizontal(); + } + + TextField("Longitude of Ascending Node (Degrees):", ref ascendingNodeString, ref ascendingNode, ref success); + TextField("Argument of Periapsis (Degrees):", ref argOfPeriapsisString, ref argOfPeriapsis, ref success); + + BodySelectionGUI(); + + ConditionalButton("Set Orbit", success, SetOrbit); + } + + void RendezvousGUI() + { + bool success = true; + + allVessels = Game.SpaceSimulation.UniverseModel.GetAllVessels(); + List filteredVessels = new(allVessels.Where(v => !v.IsDebris() && v.GlobalId != activeVessel.GlobalId)); + // allVessels.Remove(activeVessel); + // allVessels.RemoveAll(v => v.IsDebris()); + + if (filteredVessels.Count < 1) + { + GUILayout.Label("No other vessels."); + return; + } + + target ??= filteredVessels.First(); + + TextField("Distance (m):", ref rendezvousDistanceString, ref rendezvousDistance, ref success); + + GUILayout.BeginHorizontal(); + GUILayout.Label("Target: ", GUILayout.Width(0)); + if (!selectingVessel) + { + if (GUILayout.Button(target.DisplayName)) + selectingVessel = true; + } + else + { + GUILayout.BeginVertical(boxStyle); + scrollPositionVessels = GUILayout.BeginScrollView(scrollPositionVessels, false, true, GUILayout.Height(150)); + foreach (VesselComponent vessel in filteredVessels) + { + if (GUILayout.Button(vessel.DisplayName)) + { + target = vessel; + selectingVessel = false; + } + } + GUILayout.EndScrollView(); + GUILayout.EndVertical(); + } + GUILayout.EndHorizontal(); + + ConditionalButton("Rendezvous", success, Rendezvous); + } + + // Draws the body selection GUI. + void BodySelectionGUI() + { + bodies = GameManager.Instance.Game.SpaceSimulation.GetBodyNameKeys().ToList(); + + GUILayout.BeginHorizontal(); + GUILayout.Label("Body: ", GUILayout.Width(windowWidth / 2)); + if (!selectingBody) + { + if (GUILayout.Button(selectedBody)) + selectingBody = true; + } + else + { + GUILayout.BeginVertical(boxStyle); + scrollPositionBodies = GUILayout.BeginScrollView(scrollPositionBodies, false, true, GUILayout.Height(150)); + foreach (string body in bodies) + { + if (GUILayout.Button(body)) + { + selectedBody = body; + selectingBody = false; + } + } + GUILayout.EndScrollView(); + GUILayout.EndVertical(); + } + GUILayout.EndHorizontal(); + } + + void TextField(string label, ref string field, ref float number, ref bool success) + { + // Setup the list of input field names (most are the same as the entry string text displayed in the GUI window) + if (!inputFields.Contains(label)) + inputFields.Add(label); + + GUILayout.BeginHorizontal(); + GUILayout.Label(label, GUILayout.Width(windowWidth / 2)); + + bool parsed = float.TryParse(field, out number); + if (!parsed) GUI.color = Color.red; + GUI.SetNextControlName(label); + field = GUILayout.TextField(field); + GUI.color = Color.white; + + if (success && !parsed) + success = false; + + GUILayout.EndHorizontal(); + } + + void ConditionalButton(string text, bool condition, Action pressed) + { + GUI.enabled = condition; + + if (GUILayout.Button(text)) + pressed(); + + GUI.enabled = true; + } + + #endregion + + #region Functions + + // Sets vessel orbit according to the current interfaceMode. + void SetOrbit() + { + GameInstance game = GameManager.Instance.Game; + + if (CurrentInterfaceMode == InterfaceMode.Simple) + { + // Set orbit using just altitude. + game.SpaceSimulation.Lua.TeleportToOrbit( + activeVessel.Guid, + selectedBody, + 0, + 0, + (double)altitudeKM * 1000f + GameManager.Instance.Game.CelestialBodies.GetRadius(selectedBody), + 0, + 0, + 0, + 0); + } + else + { + // Set orbit using semi-major axis and other orbital parameters. + game.SpaceSimulation.Lua.TeleportToOrbit( + activeVessel.Guid, + selectedBody, + inclinationDegrees, + eccentricity, + (double)semiMajorAxisKM * 1000f, + ascendingNode, + argOfPeriapsis, + 0, + 0); + } + } + + void Rendezvous() + { + GameInstance game = GameManager.Instance.Game; + + if (target.Guid == activeVessel.Guid) + return; + + game.SpaceSimulation.Lua.TeleportToRendezvous( + activeVessel.Guid, + target.Guid, + rendezvousDistance, + 0, 0, 0, 0, 0); + } + + void Land() + { + GameInstance game = GameManager.Instance.Game; + + game.SpaceSimulation.Lua.TeleportToSurface( + activeVessel.Guid, + selectedBody, + height, + latitude, + longitude, + 0); + } + + #endregion + + #region Settings + + private void SaveDefaultMode(InterfaceMode mode) + { + LazyOrbitSettings settings = new LazyOrbitSettings() + { + defaultMode = mode + }; + + File.WriteAllText(SettingsPath, JsonConvert.SerializeObject(settings)); + } + + private InterfaceMode GetDefaultMode() + { + LazyOrbitSettings settings; + try + { + settings = JsonConvert.DeserializeObject(File.ReadAllText(SettingsPath)); + } + catch (FileNotFoundException) + { + settings = new LazyOrbitSettings(); + } + + return settings.defaultMode; + } + + #endregion + } + + public class LazyOrbitSettings + { + public InterfaceMode defaultMode = InterfaceMode.Simple; + } + + public enum InterfaceMode + { + Simple, + Advanced, + Landing, + Rendezvous, + } +} \ No newline at end of file diff --git a/LazyOrbitProject/LazyOrbit.csproj b/LazyOrbitProject/LazyOrbit.csproj new file mode 100644 index 0000000..fbe97a2 --- /dev/null +++ b/LazyOrbitProject/LazyOrbit.csproj @@ -0,0 +1,37 @@ + + + + netstandard2.0 + true + latest + true + com.github.schlosrat.LazyOrbit + Lazy Orbit + A GUI for teleporting to orbit, keybind is ALT+H. + 0.5.3 + + https://nuget.spacewarp.org/v3/index.json + + LazyOrbit + LazyOrbit + + + + + + + + + + + + + ..\external_dlls\Assembly-CSharp.dll + true + false + + + + + + diff --git a/README.md b/README.md index 8b97fa0..c4bfab6 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,44 @@ -# LazyOrbit v0.4.0 +# LazyOrbit + +![Lazy Orbit - Simple Mode](https://i.imgur.com/8INfw3O.png) Lazy Orbit is a simple mod that allows you to set a vessel's orbit, land it on a surface, or teleport it to another vessel. Open the GUI by clicking the button in the APP.BAR (or press ALT+H), select a body and an altitude, and press Set Orbit. Great for testing and modding, don't use it for anything nefarious! +## Installation +1. Install [BepInEx/SpaceWarp](https://spacedock.info/mod/3277/Space%20Warp%20+%20BepInEx). (Skip if you've done this previously) + 1. Download and extract BepInEx/SpaceWarp into your game folder. If you've installed the game via Steam, then this is probably here: *C:\Program Files (x86)\Steam\steamapps\common\Kerbal Space Program 2*. +1. Download and extract [Lazy Orbit Boosted](https://spacedock.info/mod/3410/Lazy%20Orbit%20Boosted) into your game's BepInEx/plugins folder. + 1. The mod's ZIP file contains a single BepInEx folder. You can drag the BepInEx folder from the ZIP right onto your KSP2 folder (e.g., *C:\Program Files (x86)\Steam\steamapps\common\Kerbal Space Program 2*) to install the mod. + 1. Alternatively you may install the mod via CKAN + 1. If done correctly, you should have the following folder structure within your KSP2 game folder: *KSP2GameFolder*/**BepInEx/plugins/LazyOrbit**. -# Installation +## Compatibility +* Tested with Kerbal Space Program 2 v0.1.3.1 & SpaceWarp 1.3.0.3 +* Requires SpaceWarp 1.0.1 -Open the game folder by right-clicking on the game in your Steam library, selecting "Manage," and then clicking "Browse local files." +## Warning! +* Do not use this mod when preparing bug reports for the Early Access game as teleporting craft is incompatible with this purpose. +* It is advisable to perform a Quick Save (F5) prior to teleporting any vessel as teleporting will void the warranty and may damage your craft. Not kidding here, it may do damage to your craft. -Install the BepInEx mod loader: -https://spacedock.info/mod/3255/BepInEx%20for%20KSP%202 +## Features +* **Simple Mode**: Set the **Altitude** you want, pick the **Body** you'd like to be in orbit about, and press the **Set Orbit** button! What could possibly be simpler? +* **Advanced Mode**: Pick the **Body** you want to be in orbit about, then configure specific parameters you want to get the exact orbit you need. Set your **Semi-Major Axis** and see what you'll get for *Ap* and *Pe*. Set your **Inclination**, **Eccentricity**, **Longitude of Ascending Node**, and **Argument of Periapsis**. With these configured, press the **Set Orbit** button and before you know it you'll be in the exact orbit you want! +* **Landing Mode**: Here you can set the **Lattitude**, **Longitude**, and **Height** above ground level for the point you'd like to have your craft dropped at on the **Body** you've selected. Be sure to have landing legs and/or parachutes ready, or this might be a bumpy ride! +* **Rendezvous Mode**: Set the **Distance** (in meters) you'd like to be from a **Target** you can pick from the dropdown menu, then just press the **Rendezvous** button and you'll be there in a flash! -Install the Space Warp plugin. You need both BepInEx AND Space Warp: -https://spacedock.info/mod/3257/Space%20Warp +In all modes, clicking inside a text entry field will automatically disable game input from the keyboard and mouse. This allows you to type what you need to without inadvertently affecting the timewarp or muting the game or music. Your current Game Input state is displayed on the bottom of the GUI and will be bright Yellow when game input is disabled. Game input from your keyboard and mouse is automatically restored when you click anywhere outside a text input field, or if you should close the mod. In the image below note that Game Input is shown as Disabled. -Download Lazy Orbit, open the zip file, and drag the included `BepInEx` folder into the game folder. +![Lazy Orbit - Advanced Mode](https://i.imgur.com/GuGAHds.png) +All the text input fields in this mod's GUI are designed for entering numbers. If you should accidentally type something that can't be converted to a number (e.g., include non-numeric characters or too many decimal points, etc.) the mod will alert you by setting that field to red as shown above. # Contributors - [Halban](https://github.com/Halbann) - [XYZ3211](https://github.com/XYZ3211) - +- [Schlosrat](https://github.com/schlosrat) # License Lazy Orbit is distributed under the CC BY-SA 4.0 license. Read about the license here before redistributing: -https://creativecommons.org/licenses/by-sa/4.0/ \ No newline at end of file +https://creativecommons.org/licenses/by-sa/4.0/ diff --git a/batches/copy_to_ksp.bat b/batches/copy_to_ksp.bat new file mode 100644 index 0000000..d1909aa --- /dev/null +++ b/batches/copy_to_ksp.bat @@ -0,0 +1,24 @@ +echo on +echo "Starting copy_to_ksp.bat" +set ConfigurationName=%1 +set PROJECT_NAME=%2 + +echo ConfigurationName = %ConfigurationName% +echo PROJECT_NAME = %PROJECT_NAME% +set SOURCE_DIR=..\%ConfigurationName%\BepInEx\plugins\%PROJECT_NAME%\ + +@REM call the local_dev_options +call local_dev_options.bat + +echo ####################### Copy to target Ksp dir ####################### +set DEST_PATH="%KSP2_LOCATION%\BepInEx\plugins\%PROJECT_NAME%\" +echo source path is : %SOURCE_DIR% +echo dest path is : %DEST_PATH% + +@REM rd /s/q %DEST_PATH% +if not exist %DEST_PATH% mkdir %DEST_PATH% + +@REM dir %SOURCE_DIR% +@REM dir %DEST_PATH% + +xcopy /Y /s /d %SOURCE_DIR% %DEST_PATH% diff --git a/batches/get_dlls.bat b/batches/get_dlls.bat new file mode 100644 index 0000000..76f5c3a --- /dev/null +++ b/batches/get_dlls.bat @@ -0,0 +1,34 @@ +@REM used to get all dlls from skp 2 and unity. saved to externals_dll directory + +echo "Starting get_dlls.bat" + +@REM call the ksp_location +call local_dev_options.bat + +@REM echo loc:%KSP2_LOCATION% +echo on + +set OUTPUT=output +set DEST_DIR=..\external_dlls + +echo KSP_LOC : %KSP2_LOCATION% +echo Dest_Dir is : %DEST_DIR% + +echo create local dir %DEST_DIR% +if not exist %DEST_DIR% mkdir %DEST_DIR% + +echo ####################### Get assembly dll ####################### +copy %KSP2_LOCATION%\KSP2_x64_Data\Managed\Assembly-CSharp.dll %DEST_DIR% + +copy %KSP2_LOCATION%\BepInEx\core\BepInEx.dll %DEST_DIR% +copy %KSP2_LOCATION%\BepInEx\plugins\SpaceWarp\SpaceWarp.dll %DEST_DIR% + +copy %KSP2_LOCATION%\KSP2_x64_Data\Managed\Newtonsoft.Json.dll %DEST_DIR% + +copy %KSP2_LOCATION%\KSP2_x64_Data\Managed\UnityEngine.TextRenderingModule.dll %DEST_DIR% +copy %KSP2_LOCATION%\KSP2_x64_Data\Managed\UnityEngine.InputLegacyModule.dll %DEST_DIR% +copy %KSP2_LOCATION%\KSP2_x64_Data\Managed\UnityEngine.IMGUIModule.dll %DEST_DIR% +copy %KSP2_LOCATION%\KSP2_x64_Data\Managed\UnityEngine.CoreModule.dll %DEST_DIR% +copy %KSP2_LOCATION%\KSP2_x64_Data\Managed\UnityEngine.dll %DEST_DIR% + + diff --git a/batches/local_dev_options.bat b/batches/local_dev_options.bat new file mode 100644 index 0000000..8948c05 --- /dev/null +++ b/batches/local_dev_options.bat @@ -0,0 +1,20 @@ +@REM this exemple file should be renamed to ksp_location.bat. +@REM ksp_location.bat is git ignored and therefore can contains informations depending on dev local machine + +echo "Starting local_dev_options.bat" + +@REM set your own KSP2_LOCATION and rename me to ksp_location.bat (git ignored) +@REM ps : don't use "" +set KSP2_LOCATION=C:\Kerbal Space Program 2 Debug + +@REM Create Zip package (require 7zip) +set Create_zip=True + +@REM CLOSE KSP before build +set Close_KSP2=True + +@REM Open KSP after build +set Open_KSP2=True + +@REM Copy to Other Mods repos +@REM set PostBuildCopy=..\FlightPlan\FlightPlanProject\external_dlls;..\ManeuverNodeController\ManeuverNodeControllerProject\external_dlls diff --git a/batches/local_dev_options.exemple.bat b/batches/local_dev_options.exemple.bat new file mode 100644 index 0000000..d2f59f1 --- /dev/null +++ b/batches/local_dev_options.exemple.bat @@ -0,0 +1,18 @@ +@REM this exemple file should be renamed to ksp_location.bat. +@REM ksp_location.bat is git ignored and therefore can contains informations depending on dev local machine + +@REM set your own KSP2_LOCATION and rename me to ksp_location.bat (git ignored) +@REM ps : don't use "" +set KSP2_LOCATION=Z:\SteamLibrary\steamapps\common\Kerbal Space Program 2 + +@REM Create Zip package (require 7zip) +set Create_zip=True + +@REM CLOSE KSP before build +set Close_KSP2=True + +@REM Open KSP after build +set Open_KSP2=True + +@REM Copy to Other Mods repos +set PostBuildCopy=..\FlightPlan\FlightPlanProject\external_dlls;..\ManeuverNodeController\ManeuverNodeControllerProject\external_dlls diff --git a/batches/make_zip.bat b/batches/make_zip.bat new file mode 100644 index 0000000..0972430 --- /dev/null +++ b/batches/make_zip.bat @@ -0,0 +1,38 @@ +@REM Create the zip for SpaceDock +echo on + +echo "Starting make_zip.bat" + +set ConfigurationName=%1 +set PROJECT_NAME=%2 + +@REM call the local_dev_options +call local_dev_options.bat + +@REM define the default build mode to Debug + +set swinfo_json=..\%PROJECT_NAME%\swinfo.json + +@echo on +@REM Title Get Version from swinfo_json.json using PowerShell with a batch file +Set PSCMD=Powershell -C "$(GC %swinfo_json% | ConvertFrom-Json).version" +@for /f %%a in ('%PSCMD%') do set "Ver=%%a" +@REM echo Version=%Ver% + +set ZIP_File=%PROJECT_NAME%_v%Ver%.zip +SET OUTPUT=..\%ConfigurationName% + +set CWD=%cd% +cd %OUTPUT% + +echo ###################### Build %ZIP_File% #################### +del %ZIP_File% +"C:\Program Files\7-Zip\7z.exe" a %ZIP_File% BepInEx + +if not exist ..\releases mkdir ..\releases + +move %ZIP_File% ..\releases + +cd %CWD% + +:end \ No newline at end of file diff --git a/batches/post_build.bat b/batches/post_build.bat new file mode 100644 index 0000000..220aa81 --- /dev/null +++ b/batches/post_build.bat @@ -0,0 +1,38 @@ +echo on + +echo "Starting post_build.bat" + + +@REM call the local_dev_options +call local_dev_options.bat + +set ConfigurationName=%1 +set PROJECT_NAME=%2 + +if "%Close_KSP2%"=="True" ( + @REM test if KSP2_x64.exe is running + tasklist /fi "imagename eq KSP2_x64.exe" |find ":" > nul + if errorlevel 1 ( + echo "Kill KSP2 !!!!" + taskkill /f /im "KSP2_x64.exe" + timeout 2 + ) else echo "KSP2 Not running" +) + +if "%Create_zip%"=="True" ( + call make_zip.bat %ConfigurationName% %Project_name% +) + +call copy_to_ksp.bat %ConfigurationName% %Project_name% + +if "%Open_KSP2%"=="True" ( + "%KSP2_LOCATION%\KSP2_x64.exe" +) + +@REM copy to dependencies dll +set SOURCE_DIR=..\%ConfigurationName%\BepInEx\plugins\%PROJECT_NAME%\ +SET Copies=%PostBuildCopy:;= % +FOR %%e in (%Copies%) DO ( + echo copy to ..\%%e + xcopy /Y /s %SOURCE_DIR%\%PROJECT_NAME%.dll ..\%%e +) diff --git a/batches/set_debug_dll.bat b/batches/set_debug_dll.bat new file mode 100644 index 0000000..201e2ff --- /dev/null +++ b/batches/set_debug_dll.bat @@ -0,0 +1,11 @@ +@REM copy debug dll (unity) to ksp, useful for debuging +echo on + +echo "Starting set_debug_dll.bat" + +@REM call the local_dev_options +call local_dev_options.bat +call kill_ksp.bat + +copy "%KSP2_LOCATION%\backup_dll\UnityPlayer_debug.dll" "%KSP2_LOCATION%\UnityPlayer.dll" + diff --git a/batches/set_release_dll.bat b/batches/set_release_dll.bat new file mode 100644 index 0000000..02f4f7e --- /dev/null +++ b/batches/set_release_dll.bat @@ -0,0 +1,10 @@ +@REM copy release dll (unity) to ksp, quick and official version +echo off + +@REM call the local_dev_options +call local_dev_options.bat + +call kill_ksp.bat + +copy "%KSP2_LOCATION%\backup_dll\UnityPlayer_release.dll" "%KSP2_LOCATION%\UnityPlayer.dll" + diff --git a/LazyOrbitBuild/BepInEx/plugins/LazyOrbit/license.txt b/license.txt similarity index 100% rename from LazyOrbitBuild/BepInEx/plugins/LazyOrbit/license.txt rename to license.txt