You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
KSP-DepthMask/DepthMask/ModuleDepthMask.cs

134 lines
4.8 KiB
C#

using UnityEngine;
using UnityEngine.Serialization;
using System.Collections.Generic;
using System.Linq;
namespace DepthMask {
public class ModuleDepthMask : PartModule {
// The name of the transform that has your mask mesh. The only strictly required property
[KSPField] public string maskTransform = "";
[KSPField] public string bodyTransform = "";
// The name of the depth mask shader
[KSPField] public string shaderName = "DepthMask";
// The render queue value for the mesh, should be less than maskRenderQueue
[KSPField] public int meshRenderQueue = 1000;
// the render queue value for the mask, should be less than 2000
[KSPField] public int maskRenderQueue = 1999;
// depth mask object transforms
public List<Transform> maskTransformObjects;
// body object transform
public List<Transform> bodyTransformObjects;
// depth mask shader object
public Shader depthShader;
public override void OnStart(StartState state) {
base.OnStart(state);
UpdateAllMaterials();
// the part variant system is implemented extremely stupidly
// so we have to make this whole module more complicated as a result
GameEvents.onVariantApplied.Add(OnVariantApplied);
GameEvents.onPartRepaired.Add(OnPartRepaired);
}
private void OnDestroy() {
GameEvents.onVariantApplied.Remove(OnVariantApplied);
GameEvents.onPartRepaired.Remove(OnPartRepaired);
}
public override void OnLoad(ConfigNode node) {
base.OnLoad(node);
if (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight) return;
this.maskTransformObjects = new List<Transform>();
this.bodyTransformObjects = new List<Transform>();
foreach (string name in maskTransform.Split(',')) {
var trimmed = name.Trim();
var transforms = base.part.FindModelTransforms(trimmed);
if (transforms.Length == 0) {
this.LogError($"Can't find any mask transforms named {trimmed}");
}
this.maskTransformObjects.AddRange(transforms);
}
if (this.maskTransformObjects.Count == 0) {
this.LogError($"Can't find any mask transforms");
return;
}
if (bodyTransform.Length == 0) {
this.bodyTransformObjects.Add(base.part.partTransform);
} else {
foreach (string name in bodyTransform.Split(',')) {
var trimmed = name.Trim();
var transforms = base.part.FindModelTransforms(trimmed);
if (transforms.Length == 0) {
this.LogError($"Can't find any body transforms named {trimmed}");
}
this.bodyTransformObjects.AddRange(transforms);
}
}
if (this.bodyTransformObjects.Count == 0) {
this.LogError($"Can't find any body transforms");
return;
}
this.depthShader = Shader.Find(shaderName);
if (this.depthShader == null) {
this.LogError($"Can't find shader {shaderName}");
return;
}
}
public void OnVariantApplied(Part appliedPart, PartVariant variant) {
// I dont know why changing part variants resets all the materials to their as-loaded state, but it does
if (appliedPart == this.part) UpdateAllMaterials();
}
public void OnPartRepaired(Part repairedPart) {
// Part repair resets part of the mesh from the prefab, so it needs to be reapplied
if (repairedPart == this.part) UpdateAllMaterials();
}
private void UpdateAllMaterials() {
var renderers = new List<Renderer>();
foreach (var body in bodyTransformObjects) {
renderers.AddRange(body.GetComponentsInChildren<Renderer>(true));
}
foreach (var renderer in renderers) {
var queue = renderer.material.renderQueue;
if (queue <= maskRenderQueue) continue;
queue = meshRenderQueue + ((queue - 2000) / 2);
renderer.material.renderQueue = queue;
}
foreach (var maskObject in maskTransformObjects) {
var renderer = maskObject.GetComponent<Renderer>();
renderer.material.shader = depthShader;
renderer.material.renderQueue = maskRenderQueue;
}
}
private void LogError(string message) {
Debug.LogError($"[{part.partInfo?.name ?? part.name} {this.GetType()}] {message}");
}
}
}