Skip to content

Commit

Permalink
Fixed bugs with panes and in-flight mod window
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-bures committed Mar 16, 2023
1 parent 2037344 commit c172850
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 49 deletions.
2 changes: 1 addition & 1 deletion KerbonautManagerProject/KerbonautManager.csproj
Expand Up @@ -5,7 +5,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>11</LangVersion>
<ImplicitUsings>true</ImplicitUsings>
<Version>0.2.0</Version>
<Version>0.2.1</Version>
</PropertyGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
Expand Down
137 changes: 97 additions & 40 deletions KerbonautManagerProject/KerbonautManager/KerbonautManagerPlugin.cs
@@ -1,3 +1,4 @@
using System.Collections;
using BepInEx;
using HarmonyLib;
using KSP.Game;
Expand All @@ -16,11 +17,17 @@ namespace KerbonautManager
[BepInDependency(SpaceWarpPlugin.ModGuid, SpaceWarpPlugin.ModVer)]
public class KerbonautManagerPlugin : BaseSpaceWarpPlugin
{
private enum Panel
{
A,
B
}

#region Metadata

public const string ModGuid = "com.munix.KerbonautManager";
public const string ModName = "Kerbonaut Manager";
public const string ModVer = "0.1.0";
public const string ModVer = "0.2.1";

#endregion

Expand All @@ -41,8 +48,8 @@ public class KerbonautManagerPlugin : BaseSpaceWarpPlugin
private static KerbonautManagerPlugin _instance;

private bool _loaded;
private List<GameObject> _kerbalPanels = new();
private readonly List<List<IGGuid>> _kerbals = new();
private Dictionary<Panel, GameObject> _kerbalPanels = new() { { Panel.A, null }, { Panel.B, null } };
private readonly Dictionary<Panel, List<IGGuid>> _kerbals = new();

#endregion

Expand Down Expand Up @@ -89,33 +96,40 @@ public override void OnInitialized()

private void LateUpdate()
{
var isVab = Game?.GlobalGameState?.GetState() == GameState.VehicleAssemblyBuilder;
if (!Input.GetMouseButtonDown(1) || !_kerbalPanels.Any() || !isVab)
if (!Input.GetMouseButtonDown(1) || !IsInVab() || (!_kerbalPanels[Panel.A] && !_kerbalPanels[Panel.B]))
{
return;
}

for (var panelIndex = 0; panelIndex < _kerbalPanels.Count(); panelIndex++)
ProcessPanel(Panel.A);
ProcessPanel(Panel.B);
}

private void ProcessPanel(Panel panel)
{
if (!_kerbalPanels[panel])
{
var kerbalButtons = _kerbalPanels[panelIndex].transform.GetChild(4);
for (var kerbalIndex = 0; kerbalIndex < kerbalButtons.childCount; kerbalIndex++)
return;
}

var kerbalButtons = _kerbalPanels[panel].transform.GetChild(4);
for (var kerbalIndex = 0; kerbalIndex < kerbalButtons.childCount; kerbalIndex++)
{
var rectTransform = kerbalButtons.GetChild(kerbalIndex) as RectTransform;
RectTransformUtility.ScreenPointToLocalPointInRectangle(
rectTransform,
Input.mousePosition,
_mainCamera,
out var localPoint
);
if (!rectTransform!.rect.Contains(localPoint))
{
var rectTransform = kerbalButtons.GetChild(kerbalIndex) as RectTransform;
RectTransformUtility.ScreenPointToLocalPointInRectangle(
rectTransform,
Input.mousePosition,
_mainCamera,
out var localPoint
);
if (!rectTransform!.rect.Contains(localPoint))
{
continue;
}

KerbonautManagerWindow.IsOpen = true;
KerbonautManagerWindow.SetSelectedKerbal(_kerbals[panelIndex][kerbalIndex]);
return;
continue;
}

KerbonautManagerWindow.IsOpen = true;
KerbonautManagerWindow.SetSelectedKerbal(_kerbals[panel][kerbalIndex]);
return;
}
}

Expand All @@ -124,6 +138,11 @@ private void OnGUI()
KerbonautManagerWindow.UpdateGUI();
}

private static bool IsInVab()
{
return Game && Game.GlobalGameState?.GetState() == GameState.VehicleAssemblyBuilder;
}

#endregion

#region Harmony patches
Expand All @@ -132,60 +151,98 @@ private void OnGUI()
[HarmonyPostfix]
public static void KerbalManager_OnShowWindow()
{
RefreshPanels();
if (!IsInVab())
{
return;
}

RefreshPanel(Panel.A);
RefreshPanel(Panel.B);
KerbonautManagerWindow.IsOpen = true;
}

[HarmonyPatch(typeof(KerbalManager), "OnHideWindow")]
[HarmonyPrefix]
public static void KerbalManager_OnHideWindow()
{
RefreshPanels();
if (!IsInVab())
{
return;
}

RefreshPanel(Panel.A);
RefreshPanel(Panel.B);
KerbonautManagerWindow.IsOpen = false;
}

[HarmonyPatch(typeof(KerbalManager), "ReloadLocations")]
[HarmonyPostfix]
public static void DropDownUpdate()
public static void KerbalManager_ReloadLocations()
{
if (!IsInVab())
{
return;
}

RefreshPanel(Panel.A);
RefreshPanel(Panel.B);
}

[HarmonyPatch(typeof(KerbalManager), "OnDropdownASelection")]
[HarmonyPostfix]
public static void KerbalManager_OnDropdownASelection()
{
if (!IsInVab())
{
return;
}

RefreshPanel(Panel.A);
}

[HarmonyPatch(typeof(KerbalManager), "OnDropdownBSelection")]
[HarmonyPostfix]
public static void KerbalManager_OnDropdownBSelection()
{
RefreshPanels();
if (!IsInVab())
{
return;
}

RefreshPanel(Panel.B);
}

#endregion

#region State update methods

private static void RefreshPanels()
private static void RefreshPanel(Panel panel)
{
_instance._kerbalPanels.Clear();
_instance._kerbals.Clear();

var locationA = GameObject.Find(LocationAPath);
var locationB = GameObject.Find(LocationBPath);
_instance._kerbalPanels[panel] = null;
_instance._kerbals[panel] = null;

AddPanelKerbals(locationA);
AddPanelKerbals(locationB);
AddPanelKerbals(panel, GameObject.Find(panel == Panel.A ? LocationAPath : LocationBPath));
}

private static void AddPanelKerbals(GameObject location)
private static void AddPanelKerbals(Panel panel, GameObject location)
{
if (location.transform.childCount <= 1)
{
return;
}

var panel = location.transform.GetChild(1).gameObject;
_instance._kerbalPanels.Add(panel);
var panelObject = location.transform.GetChild(1).gameObject;
_instance._kerbalPanels[panel] = panelObject;

var kerbalList = panel.GetComponent<ContextBindRoot>().BoundParentContext
var kerbalList = panelObject.GetComponent<ContextBindRoot>().BoundParentContext
.Lists["kerbalSlotList"].Data;
var guids = (
from kerbal in kerbalList
where !(bool)kerbal.Properties["isEmpty"].GetObject()
select (IGGuid)kerbal.Properties["kerbalId"].GetObject()
).ToList();

_instance._kerbals.Add(guids);
_instance._kerbals[panel] = guids;
}

#endregion
Expand Down
Expand Up @@ -28,7 +28,7 @@ public static class KerbonautManagerWindow

private const float CloseButtonSize = 16;
private const float CloseButtonOffset = 3;

private static Rect CloseButtonRect => new(
_windowRect.width - CloseButtonSize - CloseButtonOffset,
CloseButtonOffset,
Expand Down Expand Up @@ -152,7 +152,7 @@ private static void FillWindow(int windowID)

private static void OnSaveKerbal()
{
if (!IsKerbalInvalid(_kerbalName, _kerbalSurname))
if (!IsKerbalValid(_kerbalName, _kerbalSurname))
{
return;
}
Expand All @@ -172,7 +172,7 @@ private static void OnCreateKerbal()
return;
}

if (!IsKerbalInvalid(_kerbalName, _kerbalSurname))
if (!IsKerbalValid(_kerbalName, _kerbalSurname))
{
return;
}
Expand Down Expand Up @@ -204,7 +204,7 @@ private static void UpdateKerbal(KerbalInfo kerbalInfo, string name, string surn
}
}

private static bool IsKerbalInvalid(string name, string surname)
private static bool IsKerbalValid(string name, string surname)
{
if (string.IsNullOrEmpty(name))
{
Expand Down
22 changes: 19 additions & 3 deletions README.md
@@ -1,18 +1,34 @@
# Kerbonaut Manager

A mod that adds a window to the VAB where you can create new kerbonauts or rename/remove your existing ones. It also prevents your kerbals from disappearing when you recover their vessel, and it stops the VAB from generating random kerbals whenever their count drops below a certain number.
A mod that adds a window to the VAB where you can create new kerbonauts or rename/remove your existing ones.
It also prevents your kerbals from disappearing when you recover their vessel, and it stops the VAB from generating
random kerbals whenever their count drops below a certain number.

![Kerbonaut Manager](https://i.imgur.com/biqK3Y2.png)

## How to use
When you open the VAB Kerbal Manager, the mod window will open automatically next to it. By default you will see the option to create a Kerbonaut - either fill in your desired Kerbal name, or leave it empty for a random one to be generated. Right clicking on a kerbal in the Kerbal Manager window will open them in the mod window to allow renaming or deleting.

If you want the mod window to close at any time, you can do so using the "x" button in the top right corner, and if you want to access it again without closing and reopening the Kerbal Manager, you can do so from the main toolbar in the bottom right of the game window.
When you open the VAB Kerbal Manager, the mod window will open automatically next to it. By default you will see
the option to create a Kerbonaut - either fill in your desired Kerbal name, or leave it empty for a random one to be
generated. Right clicking on a kerbal in the Kerbal Manager window will open them in the mod window to allow renaming or
deleting.

If you want the mod window to close at any time, you can do so using the "x" button in the top right corner, and if you
want to access it again without closing and reopening the Kerbal Manager, you can do so from the main toolbar in the
bottom right of the game window.

## Known issues

- Creating a new kerbal with a custom last name will prevent a VAB portrait to be generated for them.
**Workaround**: Create the kerbal with the last name "Kerman" first, and then right-click them and edit their
last name afterwards.

## Compatibility

- Tested with Kerbal Space Program 2 v0.1.0.0.20892
- Requires SpaceWarp 0.4+

## Install

1. Download and install [SpaceWarp](https://spacedock.info/mod/3277/Space%20Warp%20+%20BepInEx)
2. Download and extract this mod into your KSP 2 install folder (usually "Kerbal Space Program 2")
2 changes: 1 addition & 1 deletion kerbonaut_manager/swinfo.json
Expand Up @@ -4,7 +4,7 @@
"name": "Kerbonaut Manager",
"description": "Rename and create kerbals",
"source": "https://github.com/jan-bures/KerbonautManager",
"version": "0.2.0",
"version": "0.2.1",
"dependencies": [],
"ksp2_version": {
"min": "0.1.0",
Expand Down

0 comments on commit c172850

Please sign in to comment.