From b6601153bd21f57f28cb25471e3908520fac50f9 Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Fri, 19 Jun 2020 16:35:10 -0700 Subject: [PATCH 1/9] Rename MaterialModifiers namespace --- Source/ConformalDecals/ConformalDecals.csproj | 10 +++++----- .../MaterialColorProperty.cs | 2 +- .../MaterialFloatProperty.cs | 2 +- .../MaterialProperty.cs | 2 +- .../MaterialPropertyCollection.cs | 2 +- .../MaterialTextureProperty.cs | 2 +- Source/ConformalDecals/ModuleConformalDecal.cs | 4 +++- 7 files changed, 13 insertions(+), 11 deletions(-) rename Source/ConformalDecals/{MaterialModifiers => MaterialProperties}/MaterialColorProperty.cs (91%) rename Source/ConformalDecals/{MaterialModifiers => MaterialProperties}/MaterialFloatProperty.cs (91%) rename Source/ConformalDecals/{MaterialModifiers => MaterialProperties}/MaterialProperty.cs (98%) rename Source/ConformalDecals/{MaterialModifiers => MaterialProperties}/MaterialPropertyCollection.cs (99%) rename Source/ConformalDecals/{MaterialModifiers => MaterialProperties}/MaterialTextureProperty.cs (98%) diff --git a/Source/ConformalDecals/ConformalDecals.csproj b/Source/ConformalDecals/ConformalDecals.csproj index 19d5ed4..b748385 100644 --- a/Source/ConformalDecals/ConformalDecals.csproj +++ b/Source/ConformalDecals/ConformalDecals.csproj @@ -54,11 +54,11 @@ - - - - - + + + + + diff --git a/Source/ConformalDecals/MaterialModifiers/MaterialColorProperty.cs b/Source/ConformalDecals/MaterialProperties/MaterialColorProperty.cs similarity index 91% rename from Source/ConformalDecals/MaterialModifiers/MaterialColorProperty.cs rename to Source/ConformalDecals/MaterialProperties/MaterialColorProperty.cs index f60d388..7a665e3 100644 --- a/Source/ConformalDecals/MaterialModifiers/MaterialColorProperty.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialColorProperty.cs @@ -1,7 +1,7 @@ using System; using UnityEngine; -namespace ConformalDecals.MaterialModifiers { +namespace ConformalDecals.MaterialProperties { public class MaterialColorProperty : MaterialProperty { [SerializeField] public Color color; diff --git a/Source/ConformalDecals/MaterialModifiers/MaterialFloatProperty.cs b/Source/ConformalDecals/MaterialProperties/MaterialFloatProperty.cs similarity index 91% rename from Source/ConformalDecals/MaterialModifiers/MaterialFloatProperty.cs rename to Source/ConformalDecals/MaterialProperties/MaterialFloatProperty.cs index 1dad8df..db5c987 100644 --- a/Source/ConformalDecals/MaterialModifiers/MaterialFloatProperty.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialFloatProperty.cs @@ -1,7 +1,7 @@ using System; using UnityEngine; -namespace ConformalDecals.MaterialModifiers { +namespace ConformalDecals.MaterialProperties { public class MaterialFloatProperty : MaterialProperty { [SerializeField] public float value; diff --git a/Source/ConformalDecals/MaterialModifiers/MaterialProperty.cs b/Source/ConformalDecals/MaterialProperties/MaterialProperty.cs similarity index 98% rename from Source/ConformalDecals/MaterialModifiers/MaterialProperty.cs rename to Source/ConformalDecals/MaterialProperties/MaterialProperty.cs index 0bce511..6416d22 100644 --- a/Source/ConformalDecals/MaterialModifiers/MaterialProperty.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialProperty.cs @@ -1,7 +1,7 @@ using System; using UnityEngine; -namespace ConformalDecals.MaterialModifiers { +namespace ConformalDecals.MaterialProperties { public abstract class MaterialProperty : ScriptableObject { public string PropertyName { get => _propertyName; diff --git a/Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs b/Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs similarity index 99% rename from Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs rename to Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs index 8698f88..ce464eb 100644 --- a/Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs @@ -5,7 +5,7 @@ using UniLinq; using UnityEngine; using UnityEngine.Rendering; -namespace ConformalDecals.MaterialModifiers { +namespace ConformalDecals.MaterialProperties { public class MaterialPropertyCollection : ScriptableObject, ISerializationCallbackReceiver { public int RenderQueue { get => _renderQueue; diff --git a/Source/ConformalDecals/MaterialModifiers/MaterialTextureProperty.cs b/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs similarity index 98% rename from Source/ConformalDecals/MaterialModifiers/MaterialTextureProperty.cs rename to Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs index e6004bb..e1b229c 100644 --- a/Source/ConformalDecals/MaterialModifiers/MaterialTextureProperty.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs @@ -1,7 +1,7 @@ using System; using UnityEngine; -namespace ConformalDecals.MaterialModifiers { +namespace ConformalDecals.MaterialProperties { public class MaterialTextureProperty : MaterialProperty { [SerializeField] public bool isNormal; [SerializeField] public bool isMain; diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecal.cs index 863eea7..6eee5e2 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecal.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using ConformalDecals.MaterialModifiers; +using ConformalDecals.MaterialProperties; using ConformalDecals.Util; using UnityEngine; @@ -48,6 +48,8 @@ namespace ConformalDecals { /// [KSPField] public string decalProjector = "Decal-Projector"; + [KSPField] public string decalCollider = "Decal-Collider"; + // Parameters [KSPField] public bool scaleAdjustable = true; From d9e0bbefda0086638c08cf58524e55842350be1e Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Fri, 19 Jun 2020 16:37:35 -0700 Subject: [PATCH 2/9] Layer Test module idk man --- Source/ConformalDecals/ConformalDecals.csproj | 1 + Source/ConformalDecals/Test/TestLayers.cs | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 Source/ConformalDecals/Test/TestLayers.cs diff --git a/Source/ConformalDecals/ConformalDecals.csproj b/Source/ConformalDecals/ConformalDecals.csproj index b748385..b6b940e 100644 --- a/Source/ConformalDecals/ConformalDecals.csproj +++ b/Source/ConformalDecals/ConformalDecals.csproj @@ -63,6 +63,7 @@ + diff --git a/Source/ConformalDecals/Test/TestLayers.cs b/Source/ConformalDecals/Test/TestLayers.cs new file mode 100644 index 0000000..50e413a --- /dev/null +++ b/Source/ConformalDecals/Test/TestLayers.cs @@ -0,0 +1,34 @@ +using System; +using UnityEngine; + +namespace ConformalDecals.Test { + public class TestLayers : PartModule { + + [KSPField(guiActive = true)] + public int layer = 2; + + public override void OnStart(StartState state) { + base.OnStart(state); + + + Part.layerMask.value |= (1 << 3); + } + + public void Update() { + foreach (var collider in GameObject.FindObjectsOfType()) { + if (collider.gameObject.layer == 3) { + Debug.Log($"Has layer 3: {collider.gameObject.name}"); + } + } + } + + [KSPEvent(guiActive = true, guiActiveEditor = true, guiName = "switch layers")] + public void Switch() { + Debug.Log(Part.layerMask.value); + + var cube = part.FindModelTransform("test"); + layer = (layer + 1) % 32; + cube.gameObject.layer = layer; + } + } +} \ No newline at end of file From 63b98a9a9aa23789a6c4c38509c89cbd66b4942b Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Fri, 19 Jun 2020 17:03:17 -0700 Subject: [PATCH 3/9] Fix infinitely scaled decals with zero scale and depth --- Source/ConformalDecals/ModuleConformalDecal.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecal.cs index 6eee5e2..48bfa23 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecal.cs @@ -425,6 +425,8 @@ namespace ConformalDecals { } protected void UpdateScale() { + scale = Mathf.Max(0.01f, scale); + depth = Mathf.Max(0.01f, depth); var aspectRatio = materialProperties.AspectRatio; Vector2 size; From f053fcc6675354e04eabe7ab9fb1caec9308035d Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Fri, 19 Jun 2020 21:44:43 -0700 Subject: [PATCH 4/9] Consolidate config parsing and parse layer value --- .../Plugins/ConformalDecals.dll | 4 +- Source/ConformalDecals/ConformalDecals.csproj | 1 + Source/ConformalDecals/DecalConfig.cs | 22 +- .../MaterialColorProperty.cs | 7 +- .../MaterialFloatProperty.cs | 5 +- .../MaterialProperties/MaterialProperty.cs | 53 ----- .../MaterialPropertyCollection.cs | 5 +- .../MaterialTextureProperty.cs | 26 +-- Source/ConformalDecals/Util/ParseUtil.cs | 216 ++++++++++++++++++ 9 files changed, 257 insertions(+), 82 deletions(-) create mode 100644 Source/ConformalDecals/Util/ParseUtil.cs diff --git a/GameData/ConformalDecals/Plugins/ConformalDecals.dll b/GameData/ConformalDecals/Plugins/ConformalDecals.dll index 1f5442e..b0e1664 100644 --- a/GameData/ConformalDecals/Plugins/ConformalDecals.dll +++ b/GameData/ConformalDecals/Plugins/ConformalDecals.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f667cfa986e09296c083693e3a95294b277abe19099a760881d2bd85fecc7c9c -size 37888 +oid sha256:8a16a71e1a1ac5fcef3e5ef89660ddf4c3a04f78c86fc91a19d6bfee8c7f2c82 +size 41472 diff --git a/Source/ConformalDecals/ConformalDecals.csproj b/Source/ConformalDecals/ConformalDecals.csproj index b6b940e..fd1d246 100644 --- a/Source/ConformalDecals/ConformalDecals.csproj +++ b/Source/ConformalDecals/ConformalDecals.csproj @@ -66,6 +66,7 @@ + diff --git a/Source/ConformalDecals/DecalConfig.cs b/Source/ConformalDecals/DecalConfig.cs index e446b94..b0b8e78 100644 --- a/Source/ConformalDecals/DecalConfig.cs +++ b/Source/ConformalDecals/DecalConfig.cs @@ -1,13 +1,15 @@ using System.Collections.Generic; +using ConformalDecals.Util; using UnityEngine; -using UnityEngine.Experimental.Rendering; namespace ConformalDecals { public static class DecalConfig { - private static Texture2D _blankNormal; + private static Texture2D _blankNormal; private static List _shaderBlacklist; - + private static int _decalLayer = 3; + public static Texture2D BlankNormal => _blankNormal; + public static int DecalLayer => _decalLayer; public static bool IsBlacklisted(Shader shader) { return IsBlacklisted(shader.name); @@ -22,6 +24,8 @@ namespace ConformalDecals { foreach (var shaderName in blacklist.GetValuesList("shader")) { _shaderBlacklist.Add(shaderName); } + + ParseUtil.ParseIntIndirect(ref _decalLayer, node, "decalLayer"); } } @@ -30,7 +34,7 @@ namespace ConformalDecals { var width = 2; var height = 2; var color = new Color32(255, 128, 128, 128); - var colors = new Color32[] { color, color, color, color }; + var colors = new[] {color, color, color, color}; var tex = new Texture2D(width, height, TextureFormat.RGBA32, false); for (var x = 0; x <= width; x++) { @@ -38,11 +42,13 @@ namespace ConformalDecals { tex.SetPixels32(colors); } } + tex.Apply(); return tex; } + // ReSharper disable once UnusedMember.Global public static void ModuleManagerPostLoad() { _shaderBlacklist = new List(); @@ -55,6 +61,14 @@ namespace ConformalDecals { } } + // setup physics for decals, ignore collision with everything + Physics.IgnoreLayerCollision(_decalLayer, 1, true); // default + Physics.IgnoreLayerCollision(_decalLayer, 17, true); // EVA + Physics.IgnoreLayerCollision(_decalLayer, 19, true); // PhysicalObjects + Physics.IgnoreLayerCollision(_decalLayer, 23, true); // AeroFXIgnore + Physics.IgnoreLayerCollision(_decalLayer, 26, true); // wheelCollidersIgnore + Physics.IgnoreLayerCollision(_decalLayer, 27, true); // wheelColliders + _blankNormal = MakeBlankNormal(); } } diff --git a/Source/ConformalDecals/MaterialProperties/MaterialColorProperty.cs b/Source/ConformalDecals/MaterialProperties/MaterialColorProperty.cs index 7a665e3..5b770e6 100644 --- a/Source/ConformalDecals/MaterialProperties/MaterialColorProperty.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialColorProperty.cs @@ -1,18 +1,19 @@ using System; +using ConformalDecals.Util; using UnityEngine; namespace ConformalDecals.MaterialProperties { public class MaterialColorProperty : MaterialProperty { - [SerializeField] public Color color; + [SerializeField] public Color32 color = new Color32(0, 0, 0, byte.MaxValue); public override void ParseNode(ConfigNode node) { base.ParseNode(node); - color = ParsePropertyColor(node, "color", true, color); + ParseUtil.ParseColor32Indirect(ref color, node, "color"); } public override void Modify(Material material) { - if (material == null) throw new ArgumentNullException("material cannot be null"); + if (material == null) throw new ArgumentNullException(nameof(material)); material.SetColor(_propertyID, color); } diff --git a/Source/ConformalDecals/MaterialProperties/MaterialFloatProperty.cs b/Source/ConformalDecals/MaterialProperties/MaterialFloatProperty.cs index db5c987..6745dfc 100644 --- a/Source/ConformalDecals/MaterialProperties/MaterialFloatProperty.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialFloatProperty.cs @@ -1,4 +1,5 @@ using System; +using ConformalDecals.Util; using UnityEngine; namespace ConformalDecals.MaterialProperties { @@ -8,11 +9,11 @@ namespace ConformalDecals.MaterialProperties { public override void ParseNode(ConfigNode node) { base.ParseNode(node); - value = ParsePropertyFloat(node, "value", true, value); + ParseUtil.ParseFloatIndirect(ref value, node, "value"); } public override void Modify(Material material) { - if (material == null) throw new ArgumentNullException("material cannot be null"); + if (material == null) throw new ArgumentNullException(nameof(material)); material.SetFloat(_propertyID, value); } diff --git a/Source/ConformalDecals/MaterialProperties/MaterialProperty.cs b/Source/ConformalDecals/MaterialProperties/MaterialProperty.cs index 6416d22..6d792ab 100644 --- a/Source/ConformalDecals/MaterialProperties/MaterialProperty.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialProperty.cs @@ -22,58 +22,5 @@ namespace ConformalDecals.MaterialProperties { } public abstract void Modify(Material material); - - private delegate bool TryParseDelegate(string valueString, out T value); - - protected bool ParsePropertyBool(ConfigNode node, string valueName, bool isOptional = false, bool defaultValue = false) { - return ParsePropertyValue(node, valueName, bool.TryParse, isOptional, defaultValue); - } - - protected float ParsePropertyFloat(ConfigNode node, string valueName, bool isOptional = false, float defaultValue = 0.0f) { - return ParsePropertyValue(node, valueName, float.TryParse, isOptional, defaultValue); - } - - protected int ParsePropertyInt(ConfigNode node, string valueName, bool isOptional = false, int defaultValue = 0) { - return ParsePropertyValue(node, valueName, int.TryParse, isOptional, defaultValue); - } - - protected Color ParsePropertyColor(ConfigNode node, string valueName, bool isOptional = false, Color defaultValue = default) { - return ParsePropertyValue(node, valueName, ParseExtensions.TryParseColor, isOptional, defaultValue); - } - - protected Rect ParsePropertyRect(ConfigNode node, string valueName, bool isOptional = false, Rect defaultValue = default) { - return ParsePropertyValue(node, valueName, ParseExtensions.TryParseRect, isOptional, defaultValue); - } - - protected Vector2 ParsePropertyVector2(ConfigNode node, string valueName, bool isOptional = false, Vector2 defaultValue = default) { - return ParsePropertyValue(node, valueName, ParseExtensions.TryParseVector2, isOptional, defaultValue); - } - - private T ParsePropertyValue(ConfigNode node, string valueName, TryParseDelegate tryParse, bool isOptional = false, T defaultValue = default) { - string valueString = node.GetValue(valueName); - - if (isOptional) { - if (string.IsNullOrEmpty(valueString)) return defaultValue; - } - else { - if (valueString == null) - throw new FormatException($"Missing {typeof(T)} value for {valueName} in property '{PropertyName}'"); - - if (valueString == string.Empty) - throw new FormatException($"Empty {typeof(T)} value for {valueName} in property '{PropertyName}'"); - } - - if (tryParse(valueString, out var value)) { - return value; - } - - if (isOptional) { - return defaultValue; - } - - else { - throw new FormatException($"Improperly formatted {typeof(T)} value for {valueName} in property '{PropertyName}' : '{valueString}"); - } - } } } \ No newline at end of file diff --git a/Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs b/Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs index ce464eb..b61912b 100644 --- a/Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialPropertyCollection.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Runtime.Serialization; +using ConformalDecals.Util; using UniLinq; using UnityEngine; using UnityEngine.Rendering; @@ -163,8 +164,8 @@ namespace ConformalDecals.MaterialProperties { } public T ParseProperty(ConfigNode node) where T : MaterialProperty { - var propertyName = node.GetValue("name"); - if (string.IsNullOrEmpty(propertyName)) throw new ArgumentException("node has no name"); + string propertyName = ""; + if (!ParseUtil.ParseStringIndirect(ref propertyName, node, "name")) throw new ArgumentException("node has no name"); var newProperty = AddOrGetProperty(propertyName); newProperty.ParseNode(node); diff --git a/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs b/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs index e1b229c..fbbeacf 100644 --- a/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs +++ b/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs @@ -1,4 +1,5 @@ using System; +using ConformalDecals.Util; using UnityEngine; namespace ConformalDecals.MaterialProperties { @@ -9,7 +10,7 @@ namespace ConformalDecals.MaterialProperties { [SerializeField] public bool autoTile; [SerializeField] private string _textureUrl; - [SerializeField] private Texture2D _texture; + [SerializeField] private Texture2D _texture = Texture2D.whiteTexture; [SerializeField] private bool _hasTile; [SerializeField] private Rect _tileRect; @@ -42,24 +43,17 @@ namespace ConformalDecals.MaterialProperties { public override void ParseNode(ConfigNode node) { base.ParseNode(node); - isNormal = ParsePropertyBool(node, "isNormalMap", true, (PropertyName == "_BumpMap") || (PropertyName == "_DecalBumpMap") || isNormal); - isMain = ParsePropertyBool(node, "isMain", true, isMain); - autoScale = ParsePropertyBool(node, "autoScale", true, autoScale); - autoTile = ParsePropertyBool(node, "autoTile", true, autoTile); + ParseUtil.ParseBoolIndirect(ref isMain, node, "isMain"); + ParseUtil.ParseBoolIndirect(ref isNormal, node, "isNormalMap"); + ParseUtil.ParseBoolIndirect(ref autoScale, node, "autoScale"); + ParseUtil.ParseBoolIndirect(ref autoTile, node, "autoTile"); - var textureUrl = node.GetValue("textureUrl"); - - if (string.IsNullOrEmpty(textureUrl)) { - if (string.IsNullOrEmpty(_textureUrl)) { - TextureUrl = ""; - } - } - else { - TextureUrl = node.GetValue("textureUrl"); + if (!autoTile) { + ParseUtil.ParseRectIndirect(ref _tileRect, node, "tile"); } - if (node.HasValue("tile") && !autoTile) { - SetTile(ParsePropertyRect(node, "tile", true, _tileRect)); + if (ParseUtil.ParseStringIndirect(ref _textureUrl, node, "textureUrl")) { + _texture = LoadTexture(_textureUrl, isNormal); } } diff --git a/Source/ConformalDecals/Util/ParseUtil.cs b/Source/ConformalDecals/Util/ParseUtil.cs new file mode 100644 index 0000000..4cbddd3 --- /dev/null +++ b/Source/ConformalDecals/Util/ParseUtil.cs @@ -0,0 +1,216 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; + +namespace ConformalDecals.Util { + public static class ParseUtil { + private static readonly Dictionary NamedColors = new Dictionary(); + private static readonly char[] Separator = {',', ' ', '\t'}; + + public delegate bool TryParseDelegate(string valueString, out T value); + + static ParseUtil() { + // setup named colors + foreach (var propertyInfo in typeof(Color).GetProperties(BindingFlags.Static | BindingFlags.Public)) { + if (!propertyInfo.CanRead) continue; + if (propertyInfo.PropertyType != typeof(Color)) continue; + + NamedColors.Add(propertyInfo.Name, (Color) propertyInfo.GetValue(null, null)); + } + + foreach (var propertyInfo in typeof(XKCDColors).GetProperties(BindingFlags.Static | BindingFlags.Public)) { + if (!propertyInfo.CanRead) continue; + if (propertyInfo.PropertyType != typeof(Color)) continue; + + if (NamedColors.ContainsKey(propertyInfo.Name)) throw new Exception("duplicate key " + propertyInfo.Name); + + NamedColors.Add(propertyInfo.Name, (Color) propertyInfo.GetValue(null, null)); + } + } + + public static string ParseString(ConfigNode node, string valueName, bool isOptional = false, string defaultValue = "") { + if (!node.HasValue(valueName)) throw new FormatException($"Missing value for {valueName}"); + + return node.GetValue(valueName); + } + + public static bool ParseStringIndirect(ref string value, ConfigNode node, string valueName) { + if (node.HasValue(valueName)) { + value = node.GetValue(valueName); + return true; + } + + return false; + } + + public static bool ParseBool(ConfigNode node, string valueName, bool isOptional = false, bool defaultValue = false) { + return ParseValue(node, valueName, bool.TryParse, isOptional, defaultValue); + } + + public static bool ParseBoolIndirect(ref bool value, ConfigNode node, string valueName) { + return ParseValueIndirect(ref value, node, valueName, bool.TryParse); + } + + public static float ParseFloat(ConfigNode node, string valueName, bool isOptional = false, float defaultValue = 0.0f) { + return ParseValue(node, valueName, float.TryParse, isOptional, defaultValue); + } + + public static bool ParseFloatIndirect(ref float value, ConfigNode node, string valueName) { + return ParseValueIndirect(ref value, node, valueName, float.TryParse); + } + + public static int ParseInt(ConfigNode node, string valueName, bool isOptional = false, int defaultValue = 0) { + return ParseValue(node, valueName, int.TryParse, isOptional, defaultValue); + } + + public static bool ParseIntIndirect(ref int value, ConfigNode node, string valueName) { + return ParseValueIndirect(ref value, node, valueName, int.TryParse); + } + + public static Color32 ParseColor32(ConfigNode node, string valueName, bool isOptional = false, Color32 defaultValue = default) { + return ParseValue(node, valueName, TryParseColor32, isOptional, defaultValue); + } + + public static bool ParseColor32Indirect(ref Color32 value, ConfigNode node, string valueName) { + return ParseValueIndirect(ref value, node, valueName, TryParseColor32); + } + + public static Rect ParseRect(ConfigNode node, string valueName, bool isOptional = false, Rect defaultValue = default) { + return ParseValue(node, valueName, ParseExtensions.TryParseRect, isOptional, defaultValue); + } + + public static bool ParseRectIndirect(ref Rect value, ConfigNode node, string valueName) { + return ParseValueIndirect(ref value, node, valueName, ParseExtensions.TryParseRect); + } + + public static Vector2 ParseVector2(ConfigNode node, string valueName, bool isOptional = false, Vector2 defaultValue = default) { + return ParseValue(node, valueName, ParseExtensions.TryParseVector2, isOptional, defaultValue); + } + + public static bool ParseVector2Indirect(ref Vector2 value, ConfigNode node, string valueName) { + return ParseValueIndirect(ref value, node, valueName, ParseExtensions.TryParseVector2); + } + + public static Vector3 ParseVector3(ConfigNode node, string valueName, bool isOptional = false, Vector3 defaultValue = default) { + return ParseValue(node, valueName, ParseExtensions.TryParseVector3, isOptional, defaultValue); + } + + public static bool ParseVector3Indirect(ref Vector3 value, ConfigNode node, string valueName) { + return ParseValueIndirect(ref value, node, valueName, ParseExtensions.TryParseVector3); + } + + public static T ParseValue(ConfigNode node, string valueName, TryParseDelegate tryParse, bool isOptional = false, T defaultValue = default) { + string valueString = node.GetValue(valueName); + + if (isOptional) { + if (string.IsNullOrEmpty(valueString)) return defaultValue; + } + else { + if (valueString == null) + throw new FormatException($"Missing {typeof(T)} value for {valueName}"); + + if (valueString == string.Empty) + throw new FormatException($"Empty {typeof(T)} value for {valueName}"); + } + + if (tryParse(valueString, out var value)) { + return value; + } + + if (isOptional) { + return defaultValue; + } + + else { + throw new FormatException($"Improperly formatted {typeof(T)} value for {valueName} : '{valueString}"); + } + } + + public static bool ParseValueIndirect(ref T value, ConfigNode node, string valueName, TryParseDelegate tryParse) { + if (!node.HasValue(valueName)) return false; + + var valueString = node.GetValue(valueName); + if (tryParse(valueString, out var newValue)) { + value = newValue; + return true; + } + + throw new FormatException($"Improperly formatted {typeof(T)} value for {valueName} : '{valueString}"); + } + + public static bool TryParseColor32(string valueString, out Color32 value) { + value = new Color32(0, 0, 0, byte.MaxValue); + + // HTML-style hex color + if (valueString[0] == '#') { + var hexColorString = valueString.Substring(1); + + if (!int.TryParse(hexColorString, System.Globalization.NumberStyles.HexNumber, null, out var hexColor)) return false; + + switch (hexColorString.Length) { + case 8: // RRGGBBAA + value.a = (byte) (hexColor & 0xFF); + hexColor >>= 8; + goto case 6; + + case 6: // RRGGBB + value.b = (byte) (hexColor & 0xFF); + hexColor >>= 8; + value.g = (byte) (hexColor & 0xFF); + hexColor >>= 8; + value.r = (byte) (hexColor & 0xFF); + return true; + + case 4: // RGBA + value.a = (byte) ((hexColor & 0xF) << 4); + hexColor >>= 4; + goto case 3; + + case 3: // RGB + value.b = (byte) (hexColor & 0xF << 4); + hexColor >>= 4; + value.g = (byte) (hexColor & 0xF << 4); + hexColor >>= 4; + value.r = (byte) (hexColor & 0xF << 4); + return true; + + default: + return false; + } + } + + // named color + if (NamedColors.TryGetValue(valueString, out var namedColor)) { + value = namedColor; + return true; + } + + // float color + var split = valueString.Split(Separator, StringSplitOptions.RemoveEmptyEntries); + for (int i = 0; i < split.Length; i++) { + split[i] = split[i].Trim(); + } + + switch (split.Length) { + case 4: + if (!float.TryParse(split[4], out var alpha)) return false; + value.a = (byte) (alpha * 0xFF); + goto case 3; + + case 3: + if (!float.TryParse(split[0], out var red)) return false; + if (!float.TryParse(split[0], out var green)) return false; + if (!float.TryParse(split[0], out var blue)) return false; + + value.r = (byte) (red * 0xFF); + value.g = (byte) (green * 0xFF); + value.b = (byte) (blue * 0xFF); + return true; + + default: + return false; + } + } + } +} \ No newline at end of file From e1a027d3122d34f6012e4605462044773add249e Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Fri, 19 Jun 2020 21:55:05 -0700 Subject: [PATCH 5/9] Fix color parsing --- Source/ConformalDecals/Util/ParseUtil.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/ConformalDecals/Util/ParseUtil.cs b/Source/ConformalDecals/Util/ParseUtil.cs index 4cbddd3..fcb1ecd 100644 --- a/Source/ConformalDecals/Util/ParseUtil.cs +++ b/Source/ConformalDecals/Util/ParseUtil.cs @@ -200,8 +200,8 @@ namespace ConformalDecals.Util { case 3: if (!float.TryParse(split[0], out var red)) return false; - if (!float.TryParse(split[0], out var green)) return false; - if (!float.TryParse(split[0], out var blue)) return false; + if (!float.TryParse(split[1], out var green)) return false; + if (!float.TryParse(split[2], out var blue)) return false; value.r = (byte) (red * 0xFF); value.g = (byte) (green * 0xFF); From b74ee61dd997901ba157fe09b0c0497f67236e4f Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Fri, 19 Jun 2020 22:09:25 -0700 Subject: [PATCH 6/9] Disable collision in flight scene --- .../ConformalDecals/Assets/decal-blank.mu | 4 +- .../Plugins/ConformalDecals.dll | 2 +- .../ConformalDecals/ModuleConformalDecal.cs | 117 +++++------------- 3 files changed, 33 insertions(+), 90 deletions(-) diff --git a/GameData/ConformalDecals/Assets/decal-blank.mu b/GameData/ConformalDecals/Assets/decal-blank.mu index d06471c..d35fc4c 100644 --- a/GameData/ConformalDecals/Assets/decal-blank.mu +++ b/GameData/ConformalDecals/Assets/decal-blank.mu @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ec3546be98b11c336ddaffb9c4e68c5a27a364922b5fc1f7ac7d909d9272938 -size 4892 +oid sha256:cf169fd66e880660d0f1d1cd7dd255ca6127f8ffaec5228ed00fcb16d7093fbc +size 4972 diff --git a/GameData/ConformalDecals/Plugins/ConformalDecals.dll b/GameData/ConformalDecals/Plugins/ConformalDecals.dll index b0e1664..054bcd3 100644 --- a/GameData/ConformalDecals/Plugins/ConformalDecals.dll +++ b/GameData/ConformalDecals/Plugins/ConformalDecals.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a16a71e1a1ac5fcef3e5ef89660ddf4c3a04f78c86fc91a19d6bfee8c7f2c82 +oid sha256:930a6697e1070339e12e612e0db5c5bb89237960ea941de9c0e1db0d8694dfd1 size 41472 diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecal.cs index 48bfa23..9b67eea 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecal.cs @@ -17,45 +17,21 @@ namespace ConformalDecals { // CONFIGURABLE VALUES - /// - /// Shader name. Should be one that supports decal projection. - /// [KSPField] public string shader = "ConformalDecals/Paint/Diffuse"; - /// - /// Decal front transform name. Required - /// - [KSPField] public string decalFront = "Decal-Front"; - - /// - /// Decal back transform name. Required if is true. - /// - [KSPField] public string decalBack = "Decal-Back"; - - /// - /// Decal model transform name. Is rescaled to preview the decal scale when unattached. - /// - /// - /// If unspecified, the decal front transform is used instead. - /// - [KSPField] public string decalModel = "Decal-Model"; - - /// - /// Decal projector transform name. The decal will project along the +Z axis of this transform. - /// - /// - /// if unspecified, the part "model" transform will be used instead. - /// + [KSPField] public string decalFront = "Decal-Front"; + [KSPField] public string decalBack = "Decal-Back"; + [KSPField] public string decalModel = "Decal-Model"; [KSPField] public string decalProjector = "Decal-Projector"; - - [KSPField] public string decalCollider = "Decal-Collider"; + [KSPField] public string decalCollider = "Decal-Collider"; // Parameters - [KSPField] public bool scaleAdjustable = true; - [KSPField] public float defaultScale = 1; - [KSPField] public Vector2 scaleRange = new Vector2(0, 4); - [KSPField] public DecalScaleMode scaleMode = DecalScaleMode.HEIGHT; + [KSPField] public bool scaleAdjustable = true; + [KSPField] public float defaultScale = 1; + [KSPField] public Vector2 scaleRange = new Vector2(0, 4); + + [KSPField] public DecalScaleMode scaleMode = DecalScaleMode.HEIGHT; [KSPField] public bool depthAdjustable = true; [KSPField] public float defaultDepth = 0.1f; @@ -77,45 +53,28 @@ namespace ConformalDecals { [KSPField] public Vector2 tileSize; [KSPField] public int tileIndex = -1; - /// - /// Should the back material scale be updated automatically? - /// [KSPField] public bool updateBackScale = true; // INTERNAL VALUES - /// - /// Decal scale factor, in meters. - /// + [KSPField(guiName = "#LOC_ConformalDecals_gui-scale", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F2", guiUnits = "m"), UI_FloatRange(stepIncrement = 0.05f)] public float scale = 1.0f; - /// - /// Projection depth value for the decal projector, in meters. - /// [KSPField(guiName = "#LOC_ConformalDecals_gui-depth", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F2", guiUnits = "m"), UI_FloatRange(stepIncrement = 0.02f)] public float depth = 0.2f; - /// - /// Opacity value for the decal shader. - /// [KSPField(guiName = "#LOC_ConformalDecals_gui-opacity", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "P0"), UI_FloatRange(stepIncrement = 0.05f)] public float opacity = 1.0f; - /// - /// Alpha cutoff value for the decal shader. - /// [KSPField(guiName = "#LOC_ConformalDecals_gui-cutoff", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "P0"), UI_FloatRange(stepIncrement = 0.05f)] public float cutoff = 0.5f; - /// - /// Edge wear value for the decal shader. Only relevent when useBaseNormal is true and the shader is a paint shader - /// [KSPField(guiName = "#LOC_ConformalDecals_gui-wear", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F0"), UI_FloatRange()] public float wear = 100; @@ -126,7 +85,8 @@ namespace ConformalDecals { [KSPField] public Transform decalBackTransform; [KSPField] public Transform decalModelTransform; [KSPField] public Transform decalProjectorTransform; - + [KSPField] public Transform decalColliderTransform; + [KSPField] public Material backMaterial; [KSPField] public Vector2 backTextureBaseScale; @@ -139,10 +99,10 @@ namespace ConformalDecals { private bool _isAttached; private Matrix4x4 _orthoMatrix; - private Material _decalMaterial; - private Material _previewMaterial; + private Material _decalMaterial; + private Material _previewMaterial; private BoxCollider _boundsCollider; - + private int DecalQueue { get { _decalQueueCounter++; @@ -171,43 +131,22 @@ namespace ConformalDecals { this.Log("Loading module"); try { // SETUP TRANSFORMS - - // find front transform decalFrontTransform = part.FindModelTransform(decalFront); if (decalFrontTransform == null) throw new FormatException($"Could not find decalFront transform: '{decalFront}'."); - // find back transform - if (string.IsNullOrEmpty(decalBack)) { - if (updateBackScale) { - this.LogWarning("updateBackScale is true but has no specified decalBack transform!"); - this.LogWarning("Setting updateBackScale to false."); - updateBackScale = false; - } - } - else { - decalBackTransform = part.FindModelTransform(decalBack); - if (decalBackTransform == null) throw new FormatException($"Could not find decalBack transform: '{decalBack}'."); - } + decalBackTransform = part.FindModelTransform(decalBack); + if (decalBackTransform == null) throw new FormatException($"Could not find decalBack transform: '{decalBack}'."); - // find model transform - if (string.IsNullOrEmpty(decalModel)) { - decalModelTransform = decalFrontTransform; - } - else { - decalModelTransform = part.FindModelTransform(decalModel); - if (decalModelTransform == null) throw new FormatException($"Could not find decalModel transform: '{decalModel}'."); - } + decalModelTransform = part.FindModelTransform(decalModel); + if (decalModelTransform == null) throw new FormatException($"Could not find decalModel transform: '{decalModel}'."); - // find projector transform - if (string.IsNullOrEmpty(decalProjector)) { - decalProjectorTransform = part.transform; - } - else { - decalProjectorTransform = part.FindModelTransform(decalProjector); - if (decalProjectorTransform == null) throw new FormatException($"Could not find decalProjector transform: '{decalProjector}'."); - } + decalProjectorTransform = part.FindModelTransform(decalProjector); + if (decalProjectorTransform == null) throw new FormatException($"Could not find decalProjector transform: '{decalProjector}'."); + + decalColliderTransform = part.FindModelTransform(decalCollider); + if (decalColliderTransform == null) throw new FormatException($"Could not find decalCollider transform: '{decalCollider}'."); - // get back material if necessary + // SETUP BACK MATERIAL if (updateBackScale) { this.Log("Getting material and base scale for back material"); var backRenderer = decalBackTransform.GetComponent(); @@ -319,6 +258,10 @@ namespace ConformalDecals { OnAttach(); } } + + if (HighLogic.LoadedSceneIsFlight) { + decalColliderTransform.gameObject.layer = DecalConfig.DecalLayer; + } } public virtual void OnDestroy() { @@ -601,7 +544,7 @@ namespace ConformalDecals { public void Render(Camera camera) { if (!_isAttached) return; - + // render on each target object foreach (var target in _targets) { target.Render(_decalMaterial, part.mpb, camera); From e04d5dc39ad1451d2e62000ea773a6292c8679d1 Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Fri, 19 Jun 2020 22:45:29 -0700 Subject: [PATCH 7/9] Enable selection for decal colliders in flight, change layer --- GameData/ConformalDecals/Plugins/ConformalDecals.dll | 2 +- Source/ConformalDecals/DecalConfig.cs | 2 +- Source/ConformalDecals/ModuleConformalDecal.cs | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/GameData/ConformalDecals/Plugins/ConformalDecals.dll b/GameData/ConformalDecals/Plugins/ConformalDecals.dll index 054bcd3..e55b33d 100644 --- a/GameData/ConformalDecals/Plugins/ConformalDecals.dll +++ b/GameData/ConformalDecals/Plugins/ConformalDecals.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:930a6697e1070339e12e612e0db5c5bb89237960ea941de9c0e1db0d8694dfd1 +oid sha256:162fe1f8fe6eb10578271fc3dfb8b69ec9654eee698afb51db935eb45c95643f size 41472 diff --git a/Source/ConformalDecals/DecalConfig.cs b/Source/ConformalDecals/DecalConfig.cs index b0b8e78..9304988 100644 --- a/Source/ConformalDecals/DecalConfig.cs +++ b/Source/ConformalDecals/DecalConfig.cs @@ -6,7 +6,7 @@ namespace ConformalDecals { public static class DecalConfig { private static Texture2D _blankNormal; private static List _shaderBlacklist; - private static int _decalLayer = 3; + private static int _decalLayer = 31; public static Texture2D BlankNormal => _blankNormal; public static int DecalLayer => _decalLayer; diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecal.cs index 9b67eea..466ea57 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecal.cs @@ -57,8 +57,6 @@ namespace ConformalDecals { // INTERNAL VALUES - - [KSPField(guiName = "#LOC_ConformalDecals_gui-scale", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F2", guiUnits = "m"), UI_FloatRange(stepIncrement = 0.05f)] public float scale = 1.0f; @@ -78,6 +76,9 @@ namespace ConformalDecals { [KSPField(guiName = "#LOC_ConformalDecals_gui-wear", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F0"), UI_FloatRange()] public float wear = 100; + + [KSPField(isPersistant = true)] + public bool projectMultiple; // reserved for future features. do not modify [KSPField] public MaterialPropertyCollection materialProperties; @@ -245,7 +246,7 @@ namespace ConformalDecals { materialProperties.RenderQueue = DecalQueue; - _boundsCollider = decalProjectorTransform.GetComponent(); + _boundsCollider = decalColliderTransform.GetComponent(); UpdateMaterials(); @@ -260,6 +261,7 @@ namespace ConformalDecals { } if (HighLogic.LoadedSceneIsFlight) { + Part.layerMask |= 1 << DecalConfig.DecalLayer; decalColliderTransform.gameObject.layer = DecalConfig.DecalLayer; } } From e10ea7af5a0eb1b0faaf7e383e70ef267a353a1a Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Fri, 19 Jun 2020 23:24:01 -0700 Subject: [PATCH 8/9] Allow selectability in flight to be disabled --- .../Plugins/ConformalDecals.dll | 2 +- .../ConformalDecals/ModuleConformalDecal.cs | 22 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/GameData/ConformalDecals/Plugins/ConformalDecals.dll b/GameData/ConformalDecals/Plugins/ConformalDecals.dll index e55b33d..31e40eb 100644 --- a/GameData/ConformalDecals/Plugins/ConformalDecals.dll +++ b/GameData/ConformalDecals/Plugins/ConformalDecals.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:162fe1f8fe6eb10578271fc3dfb8b69ec9654eee698afb51db935eb45c95643f +oid sha256:cb10644075b5b826620fe4cf86eb78d71ad1ae3ab7a30527b5b67b329c3d978b size 41472 diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecal.cs index 466ea57..9a997c0 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecal.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using ConformalDecals.MaterialProperties; using ConformalDecals.Util; using UnityEngine; namespace ConformalDecals { public class ModuleConformalDecal : PartModule { + [SuppressMessage("ReSharper", "InconsistentNaming")] public enum DecalScaleMode { HEIGHT, WIDTH, @@ -54,7 +56,7 @@ namespace ConformalDecals { [KSPField] public int tileIndex = -1; [KSPField] public bool updateBackScale = true; - + [KSPField] public bool selectableInFlight; // INTERNAL VALUES [KSPField(guiName = "#LOC_ConformalDecals_gui-scale", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F2", guiUnits = "m"), @@ -76,9 +78,8 @@ namespace ConformalDecals { [KSPField(guiName = "#LOC_ConformalDecals_gui-wear", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F0"), UI_FloatRange()] public float wear = 100; - - [KSPField(isPersistant = true)] - public bool projectMultiple; // reserved for future features. do not modify + + [KSPField(isPersistant = true)] public bool projectMultiple; // reserved for future features. do not modify [KSPField] public MaterialPropertyCollection materialProperties; @@ -100,9 +101,9 @@ namespace ConformalDecals { private bool _isAttached; private Matrix4x4 _orthoMatrix; - private Material _decalMaterial; - private Material _previewMaterial; - private BoxCollider _boundsCollider; + private Material _decalMaterial; + private Material _previewMaterial; + private MeshRenderer _boundsRenderer; private int DecalQueue { get { @@ -246,7 +247,7 @@ namespace ConformalDecals { materialProperties.RenderQueue = DecalQueue; - _boundsCollider = decalColliderTransform.GetComponent(); + _boundsRenderer = decalProjectorTransform.GetComponent(); UpdateMaterials(); @@ -263,6 +264,9 @@ namespace ConformalDecals { if (HighLogic.LoadedSceneIsFlight) { Part.layerMask |= 1 << DecalConfig.DecalLayer; decalColliderTransform.gameObject.layer = DecalConfig.DecalLayer; + if (!selectableInFlight) { + decalColliderTransform.GetComponent().enabled = false; + } } } @@ -412,7 +416,7 @@ namespace ConformalDecals { // update projection foreach (var target in _targets) { - target.Project(_orthoMatrix, decalProjectorTransform, _boundsCollider.bounds, useBaseNormal); + target.Project(_orthoMatrix, decalProjectorTransform, _boundsRenderer.bounds, useBaseNormal); } } else { From 0bdb7128393c371d598dcc9d988fc352ac302133 Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Fri, 19 Jun 2020 23:54:32 -0700 Subject: [PATCH 9/9] Global override for selectability and kill part on detach --- .../Plugins/ConformalDecals.dll | 4 +- .../Resources/ConformalDecals.cfg | 3 ++ Source/ConformalDecals/DecalConfig.cs | 7 +++- .../ConformalDecals/ModuleConformalDecal.cs | 39 ++++++++++++++----- 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/GameData/ConformalDecals/Plugins/ConformalDecals.dll b/GameData/ConformalDecals/Plugins/ConformalDecals.dll index 31e40eb..d0f41f3 100644 --- a/GameData/ConformalDecals/Plugins/ConformalDecals.dll +++ b/GameData/ConformalDecals/Plugins/ConformalDecals.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb10644075b5b826620fe4cf86eb78d71ad1ae3ab7a30527b5b67b329c3d978b -size 41472 +oid sha256:9b4405eaa6d2efc358a8364e1cc9ea3eba73c42f6a3d50da1433447ca989068a +size 41984 diff --git a/GameData/ConformalDecals/Resources/ConformalDecals.cfg b/GameData/ConformalDecals/Resources/ConformalDecals.cfg index 72c6e59..bed0e9c 100644 --- a/GameData/ConformalDecals/Resources/ConformalDecals.cfg +++ b/GameData/ConformalDecals/Resources/ConformalDecals.cfg @@ -1,4 +1,7 @@ CONFORMALDECALS { + decalLayer = 31 + selectableInFlight = false + SHADERBLACKLIST { shader = DepthMask shader = KSP/Alpha/Cutoff diff --git a/Source/ConformalDecals/DecalConfig.cs b/Source/ConformalDecals/DecalConfig.cs index 9304988..ca35d8d 100644 --- a/Source/ConformalDecals/DecalConfig.cs +++ b/Source/ConformalDecals/DecalConfig.cs @@ -6,11 +6,15 @@ namespace ConformalDecals { public static class DecalConfig { private static Texture2D _blankNormal; private static List _shaderBlacklist; - private static int _decalLayer = 31; + private static int _decalLayer = 31; + private static bool _selectableInFlight = false; public static Texture2D BlankNormal => _blankNormal; + public static int DecalLayer => _decalLayer; + public static bool SelectableInFlight => _selectableInFlight; + public static bool IsBlacklisted(Shader shader) { return IsBlacklisted(shader.name); } @@ -26,6 +30,7 @@ namespace ConformalDecals { } ParseUtil.ParseIntIndirect(ref _decalLayer, node, "decalLayer"); + ParseUtil.ParseBoolIndirect(ref _selectableInFlight, node, "selectableInFlight"); } } diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecal.cs index 9a997c0..c5b06e2 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecal.cs @@ -237,13 +237,7 @@ namespace ConformalDecals { public override void OnStart(StartState state) { this.Log("Starting module"); - // handle tweakables - if (HighLogic.LoadedSceneIsEditor) { - GameEvents.onEditorPartEvent.Add(OnEditorEvent); - GameEvents.onVariantApplied.Add(OnVariantApplied); - UpdateTweakables(); - } materialProperties.RenderQueue = DecalQueue; @@ -261,19 +255,39 @@ namespace ConformalDecals { } } + // handle tweakables + if (HighLogic.LoadedSceneIsEditor) { + GameEvents.onEditorPartEvent.Add(OnEditorEvent); + GameEvents.onVariantApplied.Add(OnVariantApplied); + + UpdateTweakables(); + } + + // handle flight events if (HighLogic.LoadedSceneIsFlight) { + GameEvents.onPartWillDie.Add(OnPartWillDie); + Part.layerMask |= 1 << DecalConfig.DecalLayer; decalColliderTransform.gameObject.layer = DecalConfig.DecalLayer; - if (!selectableInFlight) { + + if (!selectableInFlight || !DecalConfig.SelectableInFlight) { decalColliderTransform.GetComponent().enabled = false; } + + if (part.parent == null) part.explode(); } } public virtual void OnDestroy() { // remove GameEvents - GameEvents.onEditorPartEvent.Remove(OnEditorEvent); - GameEvents.onVariantApplied.Remove(OnVariantApplied); + if (HighLogic.LoadedSceneIsEditor) { + GameEvents.onEditorPartEvent.Remove(OnEditorEvent); + GameEvents.onVariantApplied.Remove(OnVariantApplied); + } + + if (HighLogic.LoadedSceneIsFlight) { + GameEvents.onPartWillDie.Remove(OnPartWillDie); + } // remove from preCull delegate Camera.onPreCull -= Render; @@ -332,6 +346,13 @@ namespace ConformalDecals { } } + protected void OnPartWillDie(Part willDie) { + if (willDie == part.parent) { + this.Log("Parent part about to be destroyed! Killing decal part."); + part.Die(); + } + } + protected void OnAttach() { if (part.parent == null) { this.LogError("Attach function called but part has no parent!");