diff --git a/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll b/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll index cbbccc5..4587fae 100644 --- a/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll +++ b/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a87abea70a75c8e4c1317f25f400276203608a8a6b1ddbeff91014a7986e0f74 -size 27648 +oid sha256:b805b02f176fc212845fd04be41bf49ab22eae5b8a92e6fa404dc05f93ae1ded +size 28160 diff --git a/Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs b/Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs index 09691e2..360262a 100644 --- a/Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs +++ b/Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Smooth.Delegates; using UnityEngine; namespace ConformalDecals.MaterialModifiers { @@ -9,8 +10,6 @@ namespace ConformalDecals.MaterialModifiers { public TextureMaterialProperty MainTextureProperty { get; set; } - public Material parsedMaterial; - public bool UseBaseNormal { get; private set; } private List _materialProperties; @@ -19,6 +18,19 @@ namespace ConformalDecals.MaterialModifiers { public String BaseNormalSrc { get; private set; } public String BaseNormalDest { get; private set; } + public Material DecalMaterial { + get { + if (_protoDecalMaterial == null) { + _protoDecalMaterial = MakeMaterial(_decalShader); + } + + return _protoDecalMaterial; + } + } + + private Shader _decalShader; + private Material _protoDecalMaterial; + private const string _normalTextureName = "_BumpMap"; public void Initialize(ConfigNode node, PartModule module) { @@ -30,15 +42,13 @@ namespace ConformalDecals.MaterialModifiers { // Get shader var shaderString = node.GetValue("shader") ?? throw new FormatException("Missing shader name in material"); - var shaderRef = Shabby.Shabby.FindShader(shaderString); + _decalShader = Shabby.Shabby.FindShader(shaderString); // note to self: null coalescing does not work on UnityEngine classes - if (shaderRef == null) { + if (_decalShader == null) { throw new FormatException($"Shader not found: '{shaderString}'"); } - parsedMaterial = new Material(shaderRef); - // Get useBaseNormal value var useBaseNormalString = node.GetValue("useBaseNormal"); @@ -95,7 +105,6 @@ namespace ConformalDecals.MaterialModifiers { } _materialProperties.Add(property); - property.Modify(parsedMaterial); } catch (Exception e) { @@ -107,19 +116,28 @@ namespace ConformalDecals.MaterialModifiers { module.Log($"Parsed {_materialProperties.Count} properties"); } - - public void SetScale(Vector2 scale) { + + public void SetScale(Material material, Vector2 scale) { foreach (var textureProperty in _textureMaterialProperties) { - textureProperty.UpdateScale(parsedMaterial, scale); + textureProperty.UpdateScale(material, scale); } } + + public void SetOpacity(Material material, float opacity) { + material.SetFloat(_opacityID, opacity); + } - public void SetOpacity(float opacity) { - parsedMaterial.SetFloat(_opacityID, opacity); + public void SetCutoff(Material material, float cutoff) { + material.SetFloat(_cutoffID, cutoff); } - public void SetCutoff(float cutoff) { - parsedMaterial.SetFloat(_cutoffID, cutoff); + private Material MakeMaterial(Shader shader) { + var material = new Material(shader); + foreach (MaterialProperty property in _materialProperties) { + property.Modify(material); + } + + return material; } } } \ No newline at end of file diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecal.cs index d61ca8f..6c48831 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecal.cs @@ -39,24 +39,39 @@ namespace ConformalDecals { [KSPField] public bool opacityAdjustable = true; [KSPField] public bool cutoffAdjustable = true; - [KSPField] public Vector2 scaleRange = new Vector2(0, 4); - [KSPField] public Vector2 depthRange = new Vector2(0, 4); - [KSPField] public Vector2 opacityRange = new Vector2(0, 1); - [KSPField] public Vector2 cutoffRange = new Vector2(0, 1); + [KSPField] public Vector2 scaleRange = new Vector2(0, 4); + [KSPField] public Vector2 depthRange = new Vector2(0, 4); + [KSPField] public Vector2 opacityRange = new Vector2(0, 1); + [KSPField] public Vector2 cutoffRange = new Vector2(0, 1); + [KSPField] public Vector2 decalQueueRange = new Vector2(2100, 2400); [KSPField] public bool updateBackScale = true; [KSPField] public MaterialPropertyCollection materialProperties; + [KSPField] public Material decalMaterial; - private List _targets; + private static int _decalQueueCounter = -1; - private bool _isAttached; + private List _targets; + private bool _isAttached; private Matrix4x4 _orthoMatrix; private Bounds _decalBounds; private Vector2 _backTextureBaseScale; - private Material _backMaterial; + private Material _backMaterial; + + private int DecalQueue { + get { + _decalQueueCounter++; + if (_decalQueueCounter > decalQueueRange.y || _decalQueueCounter < decalQueueRange.x) { + _decalQueueCounter = (int) decalQueueRange.x; + } + + this.Log($"returning decal queue value {_decalQueueCounter}"); + return _decalQueueCounter; + } + } public override void OnLoad(ConfigNode node) { this.Log("Loading module"); @@ -66,6 +81,9 @@ namespace ConformalDecals { materialProperties = ScriptableObject.CreateInstance(); materialProperties.Initialize(materialNode, this); + // get decal material + decalMaterial = materialProperties.DecalMaterial; + // get aspect ratio from main texture, if it exists var mainTexture = materialProperties.MainTextureProperty; if (mainTexture != null) { @@ -134,44 +152,53 @@ namespace ConformalDecals { var opacityField = Fields[nameof(opacity)]; var cutoffField = Fields[nameof(cutoff)]; - if (scaleField.guiActiveEditor = scaleAdjustable) { + scaleField.guiActiveEditor = scaleAdjustable; + depthField.guiActiveEditor = depthAdjustable; + opacityField.guiActiveEditor = opacityAdjustable; + cutoffField.guiActiveEditor = cutoffAdjustable; + + if (scaleAdjustable) { var minValue = Mathf.Max(Mathf.Epsilon, scaleRange.x); var maxValue = Mathf.Max(minValue, scaleRange.y); - (scaleField.uiControlEditor as UI_FloatRange).minValue = minValue; - (scaleField.uiControlEditor as UI_FloatRange).maxValue = maxValue; + ((UI_FloatRange) scaleField.uiControlEditor).minValue = minValue; + ((UI_FloatRange) scaleField.uiControlEditor).maxValue = maxValue; scaleField.uiControlEditor.onFieldChanged = OnSizeTweakEvent; } - if (depthField.guiActiveEditor = depthAdjustable) { + if (depthAdjustable) { var minValue = Mathf.Max(Mathf.Epsilon, depthRange.x); var maxValue = Mathf.Max(minValue, depthRange.y); - (depthField.uiControlEditor as UI_FloatRange).minValue = minValue; - (depthField.uiControlEditor as UI_FloatRange).maxValue = maxValue; + ((UI_FloatRange) depthField.uiControlEditor).minValue = minValue; + ((UI_FloatRange) depthField.uiControlEditor).maxValue = maxValue; depthField.uiControlEditor.onFieldChanged = OnSizeTweakEvent; } - if (opacityField.guiActiveEditor = opacityAdjustable) { + if (opacityAdjustable) { var minValue = Mathf.Max(0, opacityRange.x); var maxValue = Mathf.Max(minValue, opacityRange.y); maxValue = Mathf.Min(1, maxValue); - (opacityField.uiControlEditor as UI_FloatRange).minValue = minValue; - (opacityField.uiControlEditor as UI_FloatRange).maxValue = maxValue; + ((UI_FloatRange) opacityField.uiControlEditor).minValue = minValue; + ((UI_FloatRange) opacityField.uiControlEditor).maxValue = maxValue; opacityField.uiControlEditor.onFieldChanged = OnMaterialTweakEvent; } - if (cutoffField.guiActiveEditor = cutoffAdjustable) { + if (cutoffAdjustable) { var minValue = Mathf.Max(0, cutoffRange.x); var maxValue = Mathf.Max(minValue, cutoffRange.y); maxValue = Mathf.Min(1, maxValue); - (cutoffField.uiControlEditor as UI_FloatRange).minValue = minValue; - (cutoffField.uiControlEditor as UI_FloatRange).maxValue = maxValue; + ((UI_FloatRange) cutoffField.uiControlEditor).minValue = minValue; + ((UI_FloatRange) cutoffField.uiControlEditor).maxValue = maxValue; cutoffField.uiControlEditor.onFieldChanged = OnMaterialTweakEvent; } } + // instantiate decal material and set uniqueish queue + decalMaterial = Material.Instantiate(decalMaterial); + decalMaterial.renderQueue = DecalQueue; + // get back material if necessary if (updateBackScale) { this.Log("Getting material and base scale for back material"); @@ -214,8 +241,8 @@ namespace ConformalDecals { } private void OnMaterialTweakEvent(BaseField field, object obj) { - materialProperties.SetOpacity(opacity); - materialProperties.SetCutoff(cutoff); + materialProperties.SetOpacity(decalMaterial, opacity); + materialProperties.SetCutoff(decalMaterial, cutoff); } private void OnVariantApplied(Part eventPart, PartVariant variant) { @@ -326,11 +353,12 @@ namespace ConformalDecals { } // update material scale - materialProperties.SetScale(size); + materialProperties.SetScale(decalMaterial, size); } private void UpdateProjection() { if (!_isAttached) return; + // project to each target object foreach (var target in _targets) { target.Project(_orthoMatrix, new OrientedBounds(decalProjectorTransform.localToWorldMatrix, _decalBounds), decalProjectorTransform); @@ -342,7 +370,7 @@ namespace ConformalDecals { // render on each target object foreach (var target in _targets) { - target.Render(materialProperties.parsedMaterial, part.mpb, camera); + target.Render(decalMaterial, part.mpb, camera); } } }