Skip to content

Instantly share code, notes, and snippets.

@gotmachine
Created March 2, 2023 13:12
Show Gist options
  • Save gotmachine/5837444551ed64c0660d3668f9b27fb1 to your computer and use it in GitHub Desktop.
Save gotmachine/5837444551ed64c0660d3668f9b27fb1 to your computer and use it in GitHub Desktop.
KSP PAW refresh
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
namespace Utils
{
public static class PAWUtils
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////// This version require the unity object extensions and a publicized Assembly-Csharp /////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Force a PartActionWindow layout refresh.
/// This can be necessary to avoid overlapping items or blank spaces after toggling KSPField/KSPEvent controls visibility
/// </summary>
/// <param name="part">The part to be refreshed</param>
/// <param name="layoutOnly">true to only rebuild the visual layout, false to trigger a full PAW rebuild</param>
public static void RefreshPartActionWindow(this Part part, bool layoutOnly = true)
{
if (part.PartActionWindow.IsNullOrDestroyed() || !part.PartActionWindow.isActiveAndEnabled)
return;
if (layoutOnly)
part.StartCoroutine(new RebuildPAWLayoutCoroutine(part.PartActionWindow));
else
part.PartActionWindow.displayDirty = true;
}
/// <summary>
/// Zero GC alloc coroutine
/// </summary>
private struct RebuildPAWLayoutCoroutine : IEnumerator
{
private static readonly WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
private UIPartActionWindow _paw;
private bool _mustWait;
public RebuildPAWLayoutCoroutine(UIPartActionWindow paw)
{
_paw = paw;
_mustWait = true;
}
public bool MoveNext()
{
if (_mustWait)
{
_mustWait = false;
return true;
}
if (!_paw.IsDestroyed() && _paw.isActiveAndEnabled)
LayoutRebuilder.MarkLayoutForRebuild(_paw.itemsContentTransform);
return false;
}
public object Current => waitForEndOfFrame;
public void Reset() => throw new NotImplementedException();
}
//////////////////////////////////////////////////
//////////// No dependencies version /////////////
//////////////////////////////////////////////////
/// <summary>
/// Force a PartActionWindow layout refresh.
/// This can be necessary to avoid overlapping items or blank spaces after toggling KSPField/KSPEvent controls visibility
/// </summary>
/// <param name="part">The part to be refreshed</param>
/// <param name="layoutOnly">true to only rebuild the visual layout, false to trigger a full PAW rebuild</param>
public static void RefreshPartActionWindow(this Part part, bool layoutOnly = true)
{
if (part.PartActionWindow == null || !part.PartActionWindow.isActiveAndEnabled)
return;
if (layoutOnly)
part.StartCoroutine(new RebuildPAWLayoutCoroutine(part.PartActionWindow));
else
part.PartActionWindow.displayDirty = true;
}
/// <summary>
/// Zero GC alloc coroutine
/// </summary>
private struct RebuildPAWLayoutCoroutine : IEnumerator
{
private static readonly WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame();
private UIPartActionWindow _paw;
private bool _mustWait;
public RebuildPAWLayoutCoroutine(UIPartActionWindow paw)
{
_paw = paw;
_mustWait = true;
}
public bool MoveNext()
{
if (_mustWait)
{
_mustWait = false;
return true;
}
if (_paw != null && _paw.layoutGroup != null && _paw.isActiveAndEnabled)
LayoutRebuilder.MarkLayoutForRebuild((RectTransform)_paw.layoutGroup.transform);
return false;
}
public object Current => waitForEndOfFrame;
public void Reset() => throw new NotImplementedException();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment