first commit
This commit is contained in:
105
NitroxClient/Unity/Helper/AssetBundleLoader.cs
Normal file
105
NitroxClient/Unity/Helper/AssetBundleLoader.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Unity.Helper;
|
||||
|
||||
public static class AssetBundleLoader
|
||||
{
|
||||
private static readonly string assetRootFolder = NitroxUser.AssetBundlePath;
|
||||
|
||||
private static bool loadedSharedAssets;
|
||||
|
||||
private static IEnumerator LoadAssetBundle(NitroxAssetBundle nitroxAssetBundle)
|
||||
{
|
||||
if (IsBundleLoaded(nitroxAssetBundle))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
if (!loadedSharedAssets)
|
||||
{
|
||||
loadedSharedAssets = true;
|
||||
yield return LoadAllAssets(NitroxAssetBundle.SHARED_ASSETS);
|
||||
}
|
||||
|
||||
AssetBundleCreateRequest assetRequest;
|
||||
using (Stream stream = File.Open(Path.Combine(assetRootFolder, nitroxAssetBundle.BundleName), FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
assetRequest = AssetBundle.LoadFromStreamAsync(stream);
|
||||
|
||||
if (assetRequest == null)
|
||||
{
|
||||
Log.Error($"Failed to load AssetBundle: {nitroxAssetBundle.BundleName}");
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return assetRequest;
|
||||
}
|
||||
|
||||
nitroxAssetBundle.AssetBundle = assetRequest.assetBundle;
|
||||
}
|
||||
|
||||
public static IEnumerator LoadAllAssets(NitroxAssetBundle nitroxAssetBundle)
|
||||
{
|
||||
yield return LoadAssetBundle(nitroxAssetBundle);
|
||||
|
||||
AssetBundleRequest loadRequest = nitroxAssetBundle.AssetBundle.LoadAllAssetsAsync();
|
||||
yield return loadRequest;
|
||||
|
||||
|
||||
if (loadRequest.allAssets == null || loadRequest.allAssets.Length == 0)
|
||||
{
|
||||
Log.Error($"Failed to load AssetBundle: {nitroxAssetBundle.BundleName}. It contained no assets");
|
||||
yield break;
|
||||
}
|
||||
|
||||
nitroxAssetBundle.LoadedAssets = loadRequest.allAssets;
|
||||
}
|
||||
|
||||
public static IEnumerator LoadUIAsset(NitroxAssetBundle nitroxAssetBundle, bool hideUI)
|
||||
{
|
||||
yield return LoadAssetBundle(nitroxAssetBundle);
|
||||
|
||||
AssetBundleRequest fetchAssetRequest = nitroxAssetBundle.AssetBundle.LoadAssetAsync<GameObject>(nitroxAssetBundle.BundleName);
|
||||
yield return fetchAssetRequest;
|
||||
|
||||
GameObject asset = UnityEngine.Object.Instantiate(fetchAssetRequest.asset, uGUI.main.screenCanvas.transform, false) as GameObject;
|
||||
|
||||
if (!asset)
|
||||
{
|
||||
Log.Error($"Instantiated assetBundle ({nitroxAssetBundle.BundleName}) but GameObject is null.");
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (hideUI && asset.TryGetComponent(out CanvasGroup canvasGroup))
|
||||
{
|
||||
canvasGroup.alpha = 0;
|
||||
}
|
||||
nitroxAssetBundle.LoadedAssets = new UnityEngine.Object[] { asset };
|
||||
}
|
||||
|
||||
public static bool IsBundleLoaded(NitroxAssetBundle nitroxAssetBundle)
|
||||
{
|
||||
return nitroxAssetBundle.LoadedAssets != null && nitroxAssetBundle.LoadedAssets.Length > 0;
|
||||
}
|
||||
|
||||
// ReSharper disable class StringLiteralTypo, InconsistentNaming
|
||||
public class NitroxAssetBundle
|
||||
{
|
||||
public string BundleName { get; }
|
||||
public AssetBundle AssetBundle { get; set; }
|
||||
public UnityEngine.Object[] LoadedAssets { get; set; }
|
||||
|
||||
private NitroxAssetBundle(string bundleName)
|
||||
{
|
||||
BundleName = bundleName;
|
||||
}
|
||||
|
||||
public static readonly NitroxAssetBundle SHARED_ASSETS = new("sharedassets");
|
||||
public static readonly NitroxAssetBundle PLAYER_LIST_TAB = new("playerlisttab");
|
||||
public static readonly NitroxAssetBundle CHAT_LOG = new("chatlog");
|
||||
public static readonly NitroxAssetBundle CHAT_KEY_HINT = new("chatkeyhint");
|
||||
public static readonly NitroxAssetBundle DISCORD_JOIN_REQUEST = new("discordjoinrequest");
|
||||
}
|
||||
}
|
36
NitroxClient/Unity/Helper/CoroutineHelper.cs
Normal file
36
NitroxClient/Unity/Helper/CoroutineHelper.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace NitroxClient.Unity.Helper;
|
||||
|
||||
public static class CoroutineHelper
|
||||
{
|
||||
public static IEnumerator OnYieldError(this IEnumerator enumerator, Action<Exception> exceptionCallback)
|
||||
{
|
||||
return enumerator.OnYieldError<Exception>(exceptionCallback);
|
||||
}
|
||||
|
||||
public static IEnumerator OnYieldError<T>(this IEnumerator enumerator, Action<T> exceptionCallback = null) where T : Exception
|
||||
{
|
||||
if (enumerator == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
catch (T exception)
|
||||
{
|
||||
exceptionCallback?.Invoke(exception);
|
||||
yield break;
|
||||
}
|
||||
yield return enumerator.Current;
|
||||
}
|
||||
}
|
||||
}
|
70
NitroxClient/Unity/Helper/DebugUtils.cs
Normal file
70
NitroxClient/Unity/Helper/DebugUtils.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using NitroxClient.MonoBehaviours;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Unity.Helper
|
||||
{
|
||||
public static class DebugUtils
|
||||
{
|
||||
public static void PrintHierarchy(GameObject gameObject, bool startAtRoot = false, int parentsUpwards = 1, bool listComponents = false, bool travelDown = true)
|
||||
{
|
||||
GameObject startHierarchy = gameObject;
|
||||
if (startAtRoot)
|
||||
{
|
||||
GameObject rootObject = gameObject.transform.root.gameObject;
|
||||
if (rootObject != null)
|
||||
{
|
||||
startHierarchy = rootObject;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject parentObject = gameObject;
|
||||
int i = 0;
|
||||
while (i < parentsUpwards)
|
||||
{
|
||||
i++;
|
||||
if (parentObject.transform.parent != null)
|
||||
{
|
||||
parentObject = parentObject.transform.parent.gameObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = parentsUpwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TravelDown(startHierarchy, listComponents, "", travelDown);
|
||||
}
|
||||
|
||||
private static void TravelDown(GameObject gameObject, bool listComponents = false, string linePrefix = "", bool travelDown = true)
|
||||
{
|
||||
NitroxEntity entity = gameObject.GetComponent<NitroxEntity>();
|
||||
string guid = (entity) ? entity.Id.ToString() : "None";
|
||||
|
||||
Log.Debug($"{linePrefix}+GameObject GUID={guid} NAME={gameObject.name} POSITION={gameObject.transform.position}");
|
||||
if (listComponents)
|
||||
{
|
||||
ListComponents(gameObject, linePrefix);
|
||||
}
|
||||
|
||||
if (!travelDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (Transform child in gameObject.transform)
|
||||
{
|
||||
TravelDown(child.gameObject, listComponents, $"{linePrefix}| ");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ListComponents(GameObject gameObject, string linePrefix = "")
|
||||
{
|
||||
Component[] allComponents = gameObject.GetComponents<Component>();
|
||||
foreach (Component c in allComponents)
|
||||
{
|
||||
Log.Debug($"{linePrefix}=Component NAME={c.GetType().Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
136
NitroxClient/Unity/Helper/GUISkinUtils.cs
Normal file
136
NitroxClient/Unity/Helper/GUISkinUtils.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Unity.Helper
|
||||
{
|
||||
public static class GUISkinUtils
|
||||
{
|
||||
private static Dictionary<string, GUISkin> guiSkins = new Dictionary<string, GUISkin>();
|
||||
|
||||
public static GUISkin CreateDerived(GUISkin baseSkin = null, string name = null)
|
||||
{
|
||||
if (baseSkin == null)
|
||||
{
|
||||
GUISkin prevSkin = GUI.skin;
|
||||
GUI.skin = null;
|
||||
baseSkin = GUI.skin;
|
||||
GUI.skin = prevSkin;
|
||||
}
|
||||
|
||||
GUISkin copy = ScriptableObject.CreateInstance<GUISkin>();
|
||||
|
||||
copy.name = name ?? Guid.NewGuid().ToString();
|
||||
copy.box = new GUIStyle(baseSkin.box);
|
||||
copy.button = new GUIStyle(baseSkin.button);
|
||||
copy.label = new GUIStyle(baseSkin.label);
|
||||
copy.scrollView = new GUIStyle(baseSkin.scrollView);
|
||||
copy.textArea = new GUIStyle(baseSkin.textArea);
|
||||
copy.textField = new GUIStyle(baseSkin.textField);
|
||||
copy.toggle = new GUIStyle(baseSkin.toggle);
|
||||
copy.window = new GUIStyle(baseSkin.window);
|
||||
copy.horizontalScrollbar = new GUIStyle(baseSkin.horizontalScrollbar);
|
||||
copy.horizontalScrollbarLeftButton = new GUIStyle(baseSkin.horizontalScrollbarLeftButton);
|
||||
copy.horizontalScrollbarRightButton = new GUIStyle(baseSkin.horizontalScrollbarRightButton);
|
||||
copy.horizontalScrollbarThumb = new GUIStyle(baseSkin.horizontalScrollbarThumb);
|
||||
copy.horizontalSlider = new GUIStyle(baseSkin.horizontalSlider);
|
||||
copy.horizontalSliderThumb = new GUIStyle(baseSkin.horizontalSliderThumb);
|
||||
copy.verticalScrollbar = new GUIStyle(baseSkin.verticalScrollbar);
|
||||
copy.verticalScrollbarDownButton = new GUIStyle(baseSkin.verticalScrollbarDownButton);
|
||||
copy.verticalScrollbarThumb = new GUIStyle(baseSkin.verticalScrollbarThumb);
|
||||
copy.verticalScrollbarUpButton = new GUIStyle(baseSkin.verticalScrollbarUpButton);
|
||||
copy.verticalSlider = new GUIStyle(baseSkin.verticalSlider);
|
||||
copy.verticalSliderThumb = new GUIStyle(baseSkin.verticalSliderThumb);
|
||||
copy.customStyles = baseSkin.customStyles.Select(s => new GUIStyle(s)).ToArray();
|
||||
copy.hideFlags = baseSkin.hideFlags;
|
||||
|
||||
copy.settings.cursorColor = baseSkin.settings.cursorColor;
|
||||
copy.settings.cursorFlashSpeed = baseSkin.settings.cursorFlashSpeed;
|
||||
copy.settings.doubleClickSelectsWord = baseSkin.settings.doubleClickSelectsWord;
|
||||
copy.settings.tripleClickSelectsLine = baseSkin.settings.tripleClickSelectsLine;
|
||||
copy.settings.selectionColor = baseSkin.settings.selectionColor;
|
||||
|
||||
// TODO: Create identical copy of font.
|
||||
copy.font = baseSkin.font; // Gives a giberish font: copy.font = UnityEngine.Object.Instantiate(baseSkin.font);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
public static GUISkin RegisterDerived(string name, GUISkin baseSkin = null)
|
||||
{
|
||||
Validate.NotNull(name);
|
||||
Validate.IsFalse(guiSkins.ContainsKey(name), $"Name of new GUISkin already exists.");
|
||||
|
||||
GUISkin newSkin = CreateDerived(baseSkin, name);
|
||||
guiSkins.Add(name, newSkin);
|
||||
return newSkin;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new default Unity skin if there are no existing skins with the given <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">Name for the new skin.</param>
|
||||
/// <param name="skinInitializer">Optional skin initializer.</param>
|
||||
/// <param name="baseSkin">Optional base skin to copy from.</param>
|
||||
/// <returns>New or cached skin.</returns>
|
||||
public static GUISkin RegisterDerivedOnce(string name, Action<GUISkin> skinInitializer = null, GUISkin baseSkin = null)
|
||||
{
|
||||
if (!guiSkins.ContainsKey(name))
|
||||
{
|
||||
GUISkin newSkin = RegisterDerived(name, baseSkin);
|
||||
skinInitializer?.Invoke(newSkin);
|
||||
}
|
||||
|
||||
return guiSkins[name];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Switches the active skin until after the <paramref name="render"/> action.
|
||||
/// </summary>
|
||||
/// <param name="skin">Skin to switch to.</param>
|
||||
/// <param name="render">Render function to run.</param>
|
||||
public static void RenderWithSkin(GUISkin skin, Action render)
|
||||
{
|
||||
Validate.NotNull(render);
|
||||
|
||||
GUISkin prevSkin = GUI.skin;
|
||||
GUI.skin = skin;
|
||||
render();
|
||||
GUI.skin = prevSkin;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or sets a custom style to the skin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Custom skins can be used by passing the "nameofskin" to the <see cref="GUIStyle"/> parameter of <see cref="GUILayout.Label(string, GUIStyle, GUILayoutOption[])"/> and similar.
|
||||
/// </remarks>
|
||||
/// <param name="skin">Skin to add a custom style to.</param>
|
||||
/// <param name="name">Name of the new custom style.</param>
|
||||
/// <param name="baseStyle">Style to base your custom style on.</param>
|
||||
/// <param name="modify">Function that changes the custom style to your liking.</param>
|
||||
public static void SetCustomStyle(this GUISkin skin, string name, GUIStyle baseStyle, Action<GUIStyle> modify)
|
||||
{
|
||||
GUIStyle style = new GUIStyle(baseStyle);
|
||||
style.name = name;
|
||||
modify(style);
|
||||
|
||||
int index = Array.FindIndex(skin.customStyles, item => item.name == style.name);
|
||||
if (index >= 0)
|
||||
{
|
||||
skin.customStyles[index] = style;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Increase array size and add style.
|
||||
List<GUIStyle> styles = new List<GUIStyle>(skin.customStyles)
|
||||
{
|
||||
style
|
||||
};
|
||||
skin.customStyles = styles.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
181
NitroxClient/Unity/Helper/GameObjectHelper.cs
Normal file
181
NitroxClient/Unity/Helper/GameObjectHelper.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using NitroxClient.MonoBehaviours;
|
||||
using NitroxModel.DataStructures;
|
||||
using NitroxModel.Helper;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace NitroxClient.Unity.Helper
|
||||
{
|
||||
public static class GameObjectHelper
|
||||
{
|
||||
public static bool TryGetComponentInChildren<T>(this GameObject go, out T component, bool includeInactive = false) where T : Component
|
||||
{
|
||||
component = go.GetComponentInChildren<T>(includeInactive);
|
||||
return component;
|
||||
}
|
||||
|
||||
public static bool TryGetComponentInParent<T>(this GameObject go, out T component, bool includeInactive = false) where T : Component
|
||||
{
|
||||
component = go.GetComponentInParent<T>(includeInactive);
|
||||
return component;
|
||||
}
|
||||
|
||||
public static bool TryGetComponentInChildren<T>(this Component co, out T component, bool includeInactive = false) where T : Component => TryGetComponentInChildren(co.gameObject, out component, includeInactive);
|
||||
public static bool TryGetComponentInParent<T>(this Component co, out T component, bool includeInactive = false) where T : Component => TryGetComponentInParent(co.gameObject, out component, includeInactive);
|
||||
|
||||
public static T RequireComponent<T>(this GameObject o) where T : Component
|
||||
{
|
||||
T component = o.GetComponent<T>();
|
||||
Validate.IsTrue(component, $"{o.name} did not have a component of type {typeof(T)}");
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
public static T RequireComponentInChildren<T>(this GameObject o, bool includeInactive = false) where T : Component
|
||||
{
|
||||
T component = o.GetComponentInChildren<T>(includeInactive);
|
||||
Validate.IsTrue(component, $"{o.name} did not have a component of type {typeof(T)} in its children");
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
public static T RequireComponentInParent<T>(this GameObject o) where T : Component
|
||||
{
|
||||
T component = o.GetComponentInParent<T>();
|
||||
Validate.IsTrue(component, $"{o.name} did not have a component of type {typeof(T)} in its parent");
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
public static T RequireComponent<T>(this Component co) where T : Component => RequireComponent<T>(co.gameObject);
|
||||
public static T RequireComponentInChildren<T>(this Component co, bool includeInactive = false) where T : Component => RequireComponentInChildren<T>(co.gameObject, includeInactive);
|
||||
public static T RequireComponentInParent<T>(this Component co) where T : Component => RequireComponentInParent<T>(co.gameObject);
|
||||
|
||||
public static Transform RequireTransform(this Transform tf, string name)
|
||||
{
|
||||
Transform child = tf.Find(name);
|
||||
|
||||
if (!child)
|
||||
{
|
||||
throw new ArgumentNullException($@"{tf} does not contain ""{name}""");
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
public static Transform RequireTransform(this GameObject go, string name) => go.transform.RequireTransform(name);
|
||||
public static Transform RequireTransform(this MonoBehaviour mb, string name) => mb.transform.RequireTransform(name);
|
||||
|
||||
public static GameObject RequireGameObject(this Transform tf, string name) => tf.RequireTransform(name).gameObject;
|
||||
public static GameObject RequireGameObject(this GameObject go, string name) => go.transform.RequireGameObject(name);
|
||||
public static GameObject RequireGameObject(this MonoBehaviour mb, string name) => mb.transform.RequireGameObject(name);
|
||||
|
||||
public static GameObject RequireGameObject(string name)
|
||||
{
|
||||
GameObject go = GameObject.Find(name);
|
||||
Validate.IsTrue(go, $"No global GameObject found with {name}!");
|
||||
|
||||
return go;
|
||||
}
|
||||
|
||||
public static string GetFullHierarchyPath(this Component component)
|
||||
{
|
||||
return component ? $"{component.gameObject.GetFullHierarchyPath()} -> {component.GetType().Name}.cs" : "";
|
||||
}
|
||||
|
||||
public static string GetHierarchyPath(this GameObject go, GameObject end)
|
||||
{
|
||||
if (!go || go == end)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!go.transform.parent)
|
||||
{
|
||||
return go.name;
|
||||
}
|
||||
|
||||
StringBuilder sb = new(go.name);
|
||||
for (GameObject gameObject = go.transform.parent.gameObject;
|
||||
gameObject && gameObject != end;
|
||||
gameObject = gameObject.transform.parent ? gameObject.transform.parent.gameObject : null)
|
||||
{
|
||||
sb.Insert(0, $"{gameObject.name}/");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static Transform GetRootParent(this Component co) => co.transform.GetRootParent();
|
||||
public static Transform GetRootParent(this GameObject go) => go.transform.GetRootParent();
|
||||
|
||||
public static Transform GetRootParent(this Transform root)
|
||||
{
|
||||
while (root.parent)
|
||||
{
|
||||
root = root.parent;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static bool TryGetComponentInAscendance<T>(this Transform transform, int degree, out T component)
|
||||
{
|
||||
while (degree > 0)
|
||||
{
|
||||
if (!transform.parent)
|
||||
{
|
||||
component = default;
|
||||
return false;
|
||||
}
|
||||
transform = transform.parent;
|
||||
degree--;
|
||||
}
|
||||
return transform.TryGetComponent(out component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom wrapper for prefab spawning which ensures a NitroxEntity is present
|
||||
/// on the newly created object before its components are enabled (Awake is not fired).
|
||||
/// </summary>
|
||||
public static GameObject InstantiateInactiveWithId(GameObject original, NitroxId nitroxId, Vector3 position = default, Quaternion rotation = default)
|
||||
{
|
||||
GameObject copy = Object.Instantiate(original, position, rotation, false);
|
||||
NitroxEntity.SetNewId(copy, nitroxId);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="InstantiateInactiveWithId(GameObject, NitroxId, Vector3, Quaternion)"/>
|
||||
/// <remarks>
|
||||
/// Sets the GameObject to active after spawning it with a NitroxEntity.
|
||||
/// </remarks>
|
||||
public static GameObject InstantiateWithId(GameObject original, NitroxId nitroxId, Vector3 position = default, Quaternion rotation = default)
|
||||
{
|
||||
GameObject copy = InstantiateInactiveWithId(original, nitroxId, position, rotation);
|
||||
copy.SetActive(true);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override for <see cref="Utils.CreateGenericLoot"/> using our own <see cref="InstantiateWithId"/> wrapper
|
||||
/// </summary>
|
||||
public static GameObject CreateGenericLoot(TechType techType, NitroxId nitroxId)
|
||||
{
|
||||
GameObject gameObject = SpawnFromPrefab(Utils.genericLootPrefab, nitroxId);
|
||||
gameObject.GetComponent<Pickupable>().SetTechTypeOverride(techType, lootCube: true);
|
||||
return gameObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override for <see cref="Utils.SpawnFromPrefab"/> using our own <see cref="InstantiateWithId"/> wrapper
|
||||
/// </summary>
|
||||
public static GameObject SpawnFromPrefab(GameObject prefab, NitroxId nitroxId, Transform parent = null)
|
||||
{
|
||||
GameObject gameObject = InstantiateWithId(prefab, nitroxId);
|
||||
gameObject.transform.parent = parent;
|
||||
return gameObject;
|
||||
}
|
||||
}
|
||||
}
|
22
NitroxClient/Unity/Helper/MathUtil.cs
Normal file
22
NitroxClient/Unity/Helper/MathUtil.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Unity.Helper
|
||||
{
|
||||
public class MathUtil
|
||||
{
|
||||
public static Vector3 ClampMagnitude(Vector3 v, float max, float min)
|
||||
{
|
||||
double sm = v.sqrMagnitude;
|
||||
if (sm > (double)max * max)
|
||||
{
|
||||
return v.normalized * max;
|
||||
}
|
||||
else if (sm < (double)min * min)
|
||||
{
|
||||
return v.normalized * min;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
134
NitroxClient/Unity/Helper/RendererHelpers.cs
Normal file
134
NitroxClient/Unity/Helper/RendererHelpers.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System.Collections;
|
||||
using NitroxClient.GameLogic.PlayerLogic.PlayerModel.ColorSwap;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace NitroxClient.Unity.Helper;
|
||||
|
||||
public static class RendererHelpers
|
||||
{
|
||||
//This entire method is necessary in order to deal with the fact that UWE compiles Subnautica in a mode
|
||||
//that prevents us from accessing the pixel map of the 2D textures they apply to their materials.
|
||||
public static Texture2D Clone(this Texture2D sourceTexture)
|
||||
{
|
||||
// Create a temporary RenderTexture of the same size as the texture
|
||||
RenderTexture tmp = RenderTexture.GetTemporary(
|
||||
sourceTexture.width,
|
||||
sourceTexture.height,
|
||||
0,
|
||||
RenderTextureFormat.Default,
|
||||
RenderTextureReadWrite.Linear);
|
||||
|
||||
// Blit the pixels on texture to the RenderTexture
|
||||
Graphics.Blit(sourceTexture, tmp);
|
||||
// Backup the currently set RenderTexture
|
||||
RenderTexture previous = RenderTexture.active;
|
||||
// Set the current RenderTexture to the temporary one we created
|
||||
RenderTexture.active = tmp;
|
||||
// Create a new readable Texture2D to copy the pixels to it
|
||||
Texture2D clonedTexture = new(sourceTexture.width, sourceTexture.height);
|
||||
// Copy the pixels from the RenderTexture to the new Texture
|
||||
clonedTexture.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0);
|
||||
clonedTexture.Apply();
|
||||
// Reset the active RenderTexture
|
||||
RenderTexture.active = previous;
|
||||
// Release the temporary RenderTexture
|
||||
RenderTexture.ReleaseTemporary(tmp);
|
||||
|
||||
return clonedTexture;
|
||||
// "clonedTexture" now has the same pixels from "texture" and it's readable.
|
||||
}
|
||||
|
||||
//This applies a color filter to a specific region of a 2D texture.
|
||||
public static void SwapTextureColors(
|
||||
this Texture2D texture,
|
||||
HsvSwapper filter,
|
||||
TextureBlock textureBlock)
|
||||
{
|
||||
Color[] pixels = texture.GetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight);
|
||||
|
||||
filter.SwapColors(pixels);
|
||||
|
||||
texture.SetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight, pixels);
|
||||
texture.Apply();
|
||||
}
|
||||
|
||||
public static void UpdateMainTextureColors(this Material material, Color[] pixels)
|
||||
{
|
||||
Texture2D mainTexture = (Texture2D)material.mainTexture;
|
||||
mainTexture.SetPixels(pixels);
|
||||
mainTexture.Apply();
|
||||
}
|
||||
|
||||
//This applies a color filter to a specific region of a 2D texture.
|
||||
public static void UpdateMainTextureColors(
|
||||
this Material material,
|
||||
Color[] pixels,
|
||||
//IColorSwapStrategy colorSwapStrategy,
|
||||
TextureBlock textureBlock)
|
||||
{
|
||||
Texture2D mainTexture = (Texture2D)material.mainTexture;
|
||||
//Color[] pixels = mainTexture.GetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight);
|
||||
//pixelIndexes.ForEach(pixelIndex => pixels[pixelIndex] = colorSwapStrategy.SwapColor(pixels[pixelIndex]));
|
||||
mainTexture.SetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight, pixels);
|
||||
mainTexture.Apply();
|
||||
}
|
||||
|
||||
public static void ApplyClonedTexture(this Material material)
|
||||
{
|
||||
Texture2D mainTexture = (Texture2D)material.mainTexture;
|
||||
Texture2D clonedTexture = mainTexture.Clone();
|
||||
material.mainTexture = clonedTexture;
|
||||
}
|
||||
|
||||
public static SkinnedMeshRenderer GetRenderer(this GameObject playerModel, string equipmentGameObjectName)
|
||||
{
|
||||
return playerModel
|
||||
.transform
|
||||
.Find(equipmentGameObjectName)
|
||||
.gameObject
|
||||
.GetComponent<SkinnedMeshRenderer>();
|
||||
}
|
||||
|
||||
public static Color[] GetMainTexturePixels(this Material material)
|
||||
{
|
||||
Texture2D mainTexture = (Texture2D)material.mainTexture;
|
||||
return mainTexture.GetPixels();
|
||||
}
|
||||
|
||||
public static Color[] GetMainTexturePixelBlock(
|
||||
this Material material,
|
||||
TextureBlock textureBlock)
|
||||
{
|
||||
Texture2D mainTexture = (Texture2D)material.mainTexture;
|
||||
return mainTexture.GetPixels(textureBlock.X, textureBlock.Y, textureBlock.BlockWidth, textureBlock.BlockHeight);
|
||||
}
|
||||
|
||||
/// Copied from MainMenuLoadButton.ShiftAlpha()
|
||||
public static IEnumerator ShiftAlpha(
|
||||
this CanvasGroup cg,
|
||||
float targetAlpha,
|
||||
float animTime,
|
||||
float power,
|
||||
bool toActive,
|
||||
Selectable buttonToSelect = null)
|
||||
{
|
||||
float start = Time.time;
|
||||
while (Time.time - start < animTime)
|
||||
{
|
||||
cg.alpha = Mathf.Lerp(cg.alpha, targetAlpha, Mathf.Pow(Mathf.Clamp01((Time.time - start) / animTime), power));
|
||||
yield return null;
|
||||
}
|
||||
cg.alpha = targetAlpha;
|
||||
if (toActive)
|
||||
{
|
||||
cg.interactable = true;
|
||||
cg.blocksRaycasts = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cg.interactable = false;
|
||||
cg.blocksRaycasts = false;
|
||||
}
|
||||
}
|
||||
}
|
38
NitroxClient/Unity/Helper/StringUtils.cs
Normal file
38
NitroxClient/Unity/Helper/StringUtils.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.Text;
|
||||
using NitroxModel.Helper;
|
||||
|
||||
namespace NitroxClient.Unity.Helper
|
||||
{
|
||||
public static class StringUtils
|
||||
{
|
||||
public static string TruncateRight(this string value, int maxChars, string appendix = "...")
|
||||
{
|
||||
Validate.NotNull(value);
|
||||
Validate.NotNull(appendix);
|
||||
|
||||
return value.Length <= maxChars ? value : value.Substring(0, maxChars) + appendix;
|
||||
}
|
||||
|
||||
public static string TruncateLeft(this string value, int maxChars, string appendix = "...")
|
||||
{
|
||||
Validate.NotNull(value);
|
||||
Validate.NotNull(appendix);
|
||||
|
||||
return value.Length <= maxChars ? value : appendix + value.Substring(value.Length - maxChars, maxChars);
|
||||
}
|
||||
|
||||
public static string ByteArrayToHexString(this byte[] bytes)
|
||||
{
|
||||
StringBuilder hex = new StringBuilder(bytes.Length * 2);
|
||||
|
||||
foreach (byte b in bytes)
|
||||
{
|
||||
hex.Append("0x");
|
||||
hex.Append(b.ToString("X2"));
|
||||
hex.Append(" ");
|
||||
}
|
||||
|
||||
return hex.ToString();
|
||||
}
|
||||
}
|
||||
}
|
18
NitroxClient/Unity/Helper/Yielders.cs
Normal file
18
NitroxClient/Unity/Helper/Yielders.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NitroxClient.Unity.Helper;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for yields in IEnumeration to reduce GC pressure.
|
||||
/// </summary>
|
||||
public static class Yielders
|
||||
{
|
||||
public static readonly WaitForFixedUpdate WaitForFixedUpdate = new();
|
||||
public static readonly WaitForEndOfFrame WaitForEndOfFrame = new();
|
||||
public static readonly WaitForSeconds WaitFor100Milliseconds = new(.1f);
|
||||
public static readonly WaitForSeconds WaitForHalfSecond = new(.5f);
|
||||
public static readonly WaitForSeconds WaitFor1Second = new(1);
|
||||
public static readonly WaitForSeconds WaitFor2Seconds = new(2);
|
||||
public static readonly WaitForSeconds WaitFor3Seconds = new(3);
|
||||
}
|
||||
|
Reference in New Issue
Block a user