diff --git a/Nautilus/Utility/MaterialUtils.cs b/Nautilus/Utility/MaterialUtils.cs
index 44657aefc..7dbd9e8e6 100644
--- a/Nautilus/Utility/MaterialUtils.cs
+++ b/Nautilus/Utility/MaterialUtils.cs
@@ -19,9 +19,8 @@ internal static void Patch()
private static IEnumerator LoadReferences()
{
-#if SUBNAUTICA
yield return PatchInternal();
-#endif
+
IsReady = true;
yield break;
@@ -32,6 +31,26 @@ private static IEnumerator LoadReferences()
///
public static bool IsReady { get; private set; }
+ ///
+ /// Gets the basic glass material
+ ///
+ public static Material GlassMaterial { get; private set; }
+
+ ///
+ /// Gets the material for the outside of glass, such as for base windows
+ ///
+ public static Material ExteriorGlassMaterial { get; private set; }
+
+ ///
+ /// Gets the material for the inside of glass, such as the inside of the Cyclops windshield
+ ///
+ public static Material InteriorGlassMaterial { get; private set; }
+
+ ///
+ /// Gets a shiny glass material
+ ///
+ public static Material ShinyGlassMaterial { get; private set; }
+
///
/// Contains references to various Shaders.
///
diff --git a/Nautilus/Utility/MaterialUtils_BelowZero.cs b/Nautilus/Utility/MaterialUtils_BelowZero.cs
new file mode 100644
index 000000000..a126260a7
--- /dev/null
+++ b/Nautilus/Utility/MaterialUtils_BelowZero.cs
@@ -0,0 +1,47 @@
+using System.Collections;
+using UnityEngine;
+
+#if BELOWZERO
+namespace Nautilus.Utility;
+
+public static partial class MaterialUtils
+{
+ private static IEnumerator PatchInternal()
+ {
+ yield return LoadGlassMaterials();
+ }
+
+ private static IEnumerator LoadGlassMaterials()
+ {
+ var seamothTask = CraftData.GetPrefabForTechTypeAsync(TechType.SeaTruck);
+
+ yield return seamothTask;
+
+ var glassMaterial = seamothTask.GetResult()
+ .transform.Find("model/seatruck_anim/Seatruck_cabin_exterior_glass_geo")
+ .GetComponent().material;
+
+ GlassMaterial = new Material(glassMaterial);
+
+ ExteriorGlassMaterial = new Material(glassMaterial);
+ ExteriorGlassMaterial.SetFloat("_SpecInt", 100);
+ ExteriorGlassMaterial.SetFloat("_Shininess", 6.3f);
+ ExteriorGlassMaterial.SetFloat("_Fresnel", 0.85f);
+ ExteriorGlassMaterial.SetColor("_Color", new Color(0.33f, 0.58f, 0.71f, 0.1f));
+ ExteriorGlassMaterial.SetColor("_SpecColor", new Color(0.5f, 0.76f, 1f, 1f));
+
+ ShinyGlassMaterial = new Material(glassMaterial);
+ ShinyGlassMaterial.SetColor("_Color", new Color(1, 1, 1, 0.2f));
+ ShinyGlassMaterial.SetFloat("_SpecInt", 3);
+ ShinyGlassMaterial.SetFloat("_Shininess", 8);
+ ShinyGlassMaterial.SetFloat("_Fresnel", 0.78f);
+
+ InteriorGlassMaterial = new Material(glassMaterial);
+ InteriorGlassMaterial.SetColor("_Color", new Color(0.67f, 0.71f, 0.76f, 0.56f));
+ InteriorGlassMaterial.SetFloat("_SpecInt", 2);
+ InteriorGlassMaterial.SetFloat("_Shininess", 6f);
+ InteriorGlassMaterial.SetFloat("_Fresnel", 0.88f);
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Nautilus/Utility/MaterialUtils_Subnautica.cs b/Nautilus/Utility/MaterialUtils_Subnautica.cs
index 88636f59f..a39bba9ef 100644
--- a/Nautilus/Utility/MaterialUtils_Subnautica.cs
+++ b/Nautilus/Utility/MaterialUtils_Subnautica.cs
@@ -15,6 +15,8 @@ private static IEnumerator PatchInternal()
yield return LoadAirWaterBarrierMaterial();
yield return LoadForcefieldMaterial();
yield return LoadGhostMaterial();
+ yield return LoadGlassMaterials();
+ yield return LoadUIMaterial();
}
///
@@ -47,6 +49,11 @@ private static IEnumerator PatchInternal()
///
public static Material GhostMaterial { get; private set; }
+ ///
+ /// Gets the material used by the UI in the Cyclops
+ ///
+ public static Material HolographicUIMaterial { get; private set; }
+
private static IEnumerator LoadIonCubeMaterial()
{
if (IonCubeMaterial)
@@ -128,5 +135,57 @@ private static IEnumerator LoadGhostMaterial()
GhostMaterial = wallShelf.GetComponentInChildren().ghostMaterial;
}
}
+
+ private static IEnumerator LoadGlassMaterials()
+ {
+ var seamothTask = CraftData.GetPrefabForTechTypeAsync(TechType.Seamoth);
+
+ yield return seamothTask;
+
+ var glassMaterial = seamothTask.GetResult()
+ .transform.Find("Model/Submersible_SeaMoth/Submersible_seaMoth_geo/Submersible_SeaMoth_glass_geo")
+ .GetComponent().material;
+
+ GlassMaterial = new Material(glassMaterial);
+
+ ExteriorGlassMaterial = new Material(glassMaterial);
+ ExteriorGlassMaterial.SetFloat("_SpecInt", 100);
+ ExteriorGlassMaterial.SetFloat("_Shininess", 6.3f);
+ ExteriorGlassMaterial.SetFloat("_Fresnel", 0.85f);
+ ExteriorGlassMaterial.SetColor("_Color", new Color(0.33f, 0.58f, 0.71f, 0.1f));
+ ExteriorGlassMaterial.SetColor("_SpecColor", new Color(0.5f, 0.76f, 1f, 1f));
+
+ ShinyGlassMaterial = new Material(glassMaterial);
+ ShinyGlassMaterial.SetColor("_Color", new Color(1, 1, 1, 0.2f));
+ ShinyGlassMaterial.SetFloat("_SpecInt", 3);
+ ShinyGlassMaterial.SetFloat("_Shininess", 8);
+ ShinyGlassMaterial.SetFloat("_Fresnel", 0.78f);
+
+ InteriorGlassMaterial = new Material(glassMaterial);
+ InteriorGlassMaterial.SetColor("_Color", new Color(0.67f, 0.71f, 0.76f, 0.56f));
+ InteriorGlassMaterial.SetFloat("_SpecInt", 2);
+ InteriorGlassMaterial.SetFloat("_Shininess", 6f);
+ InteriorGlassMaterial.SetFloat("_Fresnel", 0.88f);
+ }
+
+ private static bool _cyclopsLoaded;
+
+ private static IEnumerator LoadUIMaterial()
+ {
+ yield return new WaitUntil(() => LightmappedPrefabs.main);
+
+ LightmappedPrefabs.main.RequestScenePrefab("Cyclops", new LightmappedPrefabs.OnPrefabLoaded(OnCyclopsLoaded));
+
+ yield return new WaitUntil(() => _cyclopsLoaded);
+ }
+
+ private static void OnCyclopsLoaded(GameObject cyclops)
+ {
+ var holoMat = cyclops.transform.Find("HelmHUD/HelmHUDVisuals/Canvas_LeftHUD/EngineOnUI/EngineOff_Button")
+ .GetComponent().material;
+
+ HolographicUIMaterial = new Material(holoMat);
+ _cyclopsLoaded = true;
+ }
}
#endif
\ No newline at end of file
diff --git a/Nautilus/Utility/ThunderkitUtilities/ApplySNFont.cs b/Nautilus/Utility/ThunderkitUtilities/ApplySNFont.cs
new file mode 100644
index 000000000..881d48996
--- /dev/null
+++ b/Nautilus/Utility/ThunderkitUtilities/ApplySNFont.cs
@@ -0,0 +1,27 @@
+using UnityEngine;
+using TMPro;
+
+namespace Nautilus.Utility.ThunderkitUtilities;
+
+internal class ApplySNFont : MonoBehaviour
+{
+ [Tooltip("How to apply the font")]
+ public GeneralSetMode fontSetMode;
+
+ private void Start()
+ {
+ switch (fontSetMode)
+ {
+ case GeneralSetMode.SingleObject:
+ GetComponent().font = FontUtils.Aller_Rg;
+ break;
+ case GeneralSetMode.AllChildObjects:
+ GetComponentsInChildren().ForEach(t => t.font = FontUtils.Aller_Rg);
+ break;
+ case GeneralSetMode.AllChildObjectsIncludeInactive:
+ GetComponentsInChildren(true).ForEach(t => t.font = FontUtils.Aller_Rg);
+ break;
+ }
+
+ }
+}
diff --git a/Nautilus/Utility/ThunderkitUtilities/ApplySNLayer.cs b/Nautilus/Utility/ThunderkitUtilities/ApplySNLayer.cs
new file mode 100644
index 000000000..4f07755fd
--- /dev/null
+++ b/Nautilus/Utility/ThunderkitUtilities/ApplySNLayer.cs
@@ -0,0 +1,79 @@
+using System.Reflection;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace Nautilus.Utility.ThunderkitUtilities;
+
+internal class ApplySNLayer : MonoBehaviour
+{
+ [Tooltip("The name of the layer you want to apply")]
+ public LayerName layerName;
+
+ [Tooltip("How to apply the layer")]
+ public MaterialSetMode layerSetMode;
+
+ private void Start()
+ {
+ int layer = layerName switch
+ {
+ LayerName.Default => LayerID.Default,
+ LayerName.Useable => LayerID.Useable,
+ LayerName.NotUseable => LayerID.NotUseable,
+ LayerName.Player => LayerID.Player,
+ LayerName.TerrainCollider => LayerID.TerrainCollider,
+ LayerName.UI => LayerID.UI,
+ LayerName.Trigger => LayerID.Trigger,
+ LayerName.BaseClipProxy => LayerID.BaseClipProxy,
+ LayerName.OnlyVehicle => LayerID.OnlyVehicle,
+ LayerName.Vehicle => LayerID.Vehicle,
+#if SUBNAUTICA
+ LayerName.DefaultCollisionMask => LayerID.DefaultCollisionMask,
+ LayerName.SubRigidbodyExclude => LayerID.SubRigidbodyExclude,
+#elif BELOWZERO
+ LayerName.Interior => LayerID.Interior,
+ LayerName.AllowPlayerAndVehicle => LayerID.AllowPlayerAndVehicle,
+#endif
+ _ => 0
+ };
+
+ switch(layerSetMode)
+ {
+ case MaterialSetMode.SingleObject:
+ gameObject.layer = layer;
+ break;
+ case MaterialSetMode.AllChildObjects:
+ GetComponentsInChildren().ForEach(g => g.layer = layer);
+ break;
+ case MaterialSetMode.AllChildObjectsIncludeInactive:
+ GetComponentsInChildren(true).ForEach(g => g.layer = layer);
+ break;
+ case MaterialSetMode.AllChildGraphics:
+ GetComponentsInChildren(true).ForEach(g => g.gameObject.layer = layer);
+ break;
+ }
+ }
+
+ ///
+ /// These are taken from
+ ///
+ public enum LayerName
+ {
+ Default,
+ Useable,
+ NotUseable,
+ Player,
+ TerrainCollider,
+ UI,
+ Trigger,
+ BaseClipProxy,
+ OnlyVehicle,
+ Vehicle,
+#if SUBNAUTICA
+ DefaultCollisionMask,
+ SubRigidbodyExclude,
+#elif BELOWZERO
+ Interior,
+ AllowPlayerAndVehicle
+#endif
+ }
+}
diff --git a/Nautilus/Utility/ThunderkitUtilities/ApplySNMaterial.cs b/Nautilus/Utility/ThunderkitUtilities/ApplySNMaterial.cs
new file mode 100644
index 000000000..adba9e314
--- /dev/null
+++ b/Nautilus/Utility/ThunderkitUtilities/ApplySNMaterial.cs
@@ -0,0 +1,120 @@
+using System.Collections;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace Nautilus.Utility.ThunderkitUtilities;
+
+internal class ApplySNMaterial : MonoBehaviour
+{
+ [Tooltip("How to apply the material")]
+ public MaterialSetMode materialSetMode;
+
+ [Tooltip("What material to apply")]
+ public MaterialType materialType;
+
+ [Tooltip("Run at start, or be manually called?")]
+ public bool runAtStart = true;
+
+ [Header("Single Object Settings:")]
+ public Renderer renderer;
+ public int[] materialIndices = new[] { 0 };
+
+ private void OnValidate()
+ {
+ if (!renderer) TryGetComponent(out renderer);
+ }
+
+ private void Start()
+ {
+ if (!runAtStart) return;
+
+ AssignMaterials();
+ }
+
+ ///
+ /// Applies the set material using the specified
+ ///
+ public void AssignMaterials()
+ {
+ switch(materialSetMode)
+ {
+ case MaterialSetMode.SingleObject:
+ ApplyMaterialsOnSingleRend();
+ break;
+ case MaterialSetMode.AllChildObjects:
+ ApplyMaterialsOnChildren(false);
+ break;
+ case MaterialSetMode.AllChildObjectsIncludeInactive:
+ ApplyMaterialsOnChildren(true);
+ break;
+ case MaterialSetMode.AllChildGraphics:
+ foreach (var graphic in GetComponentsInChildren(true))
+ {
+ graphic.material = GetMaterial(materialType);
+ }
+ break;
+ }
+ }
+
+ private void ApplyMaterialsOnSingleRend()
+ {
+ if (renderer == null) throw new System.Exception($"The renderer is null on {gameObject} when SN materials were trying to be applied");
+
+ var mats = renderer.materials;
+ foreach (var index in materialIndices)
+ {
+ mats[index] = GetMaterial(materialType);
+ }
+
+ renderer.materials = mats;
+ }
+
+ private void ApplyMaterialsOnChildren(bool includeInactive)
+ {
+ var rends = GetComponentsInChildren(includeInactive);
+ foreach (var rend in rends)
+ {
+ var materials = rend.materials;
+ for (int i = 0; i < materials.Length; i++)
+ {
+ materials[i] = GetMaterial(materialType);
+ }
+
+ rend.materials = materials;
+ }
+ }
+
+ private Material GetMaterial(MaterialType type)
+ {
+ Material mat = type switch
+ {
+#if SN_STABLE
+ MaterialType.WaterBarrier => MaterialUtils.AirWaterBarrierMaterial,
+ MaterialType.ForceField => MaterialUtils.ForceFieldMaterial,
+ MaterialType.StasisField => MaterialUtils.StasisFieldMaterial,
+ MaterialType.HolographicUI => MaterialUtils.HolographicUIMaterial,
+#endif
+ MaterialType.Glass => MaterialUtils.GlassMaterial,
+ MaterialType.ExteriorGlass => MaterialUtils.ExteriorGlassMaterial,
+ MaterialType.ShinyGlass => MaterialUtils.ShinyGlassMaterial,
+ MaterialType.InteriorWindowGlass => MaterialUtils.InteriorGlassMaterial,
+ _ => null
+ };
+
+ return mat;
+ }
+
+ internal enum MaterialType
+ {
+ Glass,
+ ExteriorGlass,
+ ShinyGlass,
+ InteriorWindowGlass,
+#if SN_STABLE
+ WaterBarrier,
+ ForceField,
+ StasisField,
+ HolographicUI
+#endif
+ }
+}
diff --git a/Nautilus/Utility/ThunderkitUtilities/ApplySNShaders.cs b/Nautilus/Utility/ThunderkitUtilities/ApplySNShaders.cs
new file mode 100644
index 000000000..743aa428c
--- /dev/null
+++ b/Nautilus/Utility/ThunderkitUtilities/ApplySNShaders.cs
@@ -0,0 +1,19 @@
+using UnityEngine;
+
+namespace Nautilus.Utility.ThunderkitUtilities;
+
+internal class ApplySNShaders : MonoBehaviour
+{
+ [Tooltip("Which GameObject to apply the shaders to (All children will also be affected)")]
+ public GameObject applyTo;
+
+ private void OnValidate()
+ {
+ if (applyTo == null) applyTo = gameObject;
+ }
+
+ private void Start()
+ {
+ MaterialUtils.ApplySNShaders(applyTo);
+ }
+}
diff --git a/Nautilus/Utility/ThunderkitUtilities/SetModes.cs b/Nautilus/Utility/ThunderkitUtilities/SetModes.cs
new file mode 100644
index 000000000..d6f8d3846
--- /dev/null
+++ b/Nautilus/Utility/ThunderkitUtilities/SetModes.cs
@@ -0,0 +1,16 @@
+namespace Nautilus.Utility.ThunderkitUtilities;
+
+internal enum GeneralSetMode
+{
+ SingleObject,
+ AllChildObjects,
+ AllChildObjectsIncludeInactive,
+}
+
+internal enum MaterialSetMode
+{
+ SingleObject,
+ AllChildObjects,
+ AllChildObjectsIncludeInactive,
+ AllChildGraphics
+}