diff --git a/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll b/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll index a715ca6..10325b1 100644 Binary files a/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll and b/Distribution/GameData/ConformalDecals/Plugins/ConformalDecals.dll differ diff --git a/Source/ConformalDecals/ConformalDecals.csproj b/Source/ConformalDecals/ConformalDecals.csproj index 5457277..f8c1bdf 100644 --- a/Source/ConformalDecals/ConformalDecals.csproj +++ b/Source/ConformalDecals/ConformalDecals.csproj @@ -55,8 +55,10 @@ + + - + diff --git a/Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs b/Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs index ed9f3ba..8f80426 100644 --- a/Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs +++ b/Source/ConformalDecals/MaterialModifiers/MaterialPropertyCollection.cs @@ -14,16 +14,22 @@ namespace ConformalDecals.MaterialModifiers { public Material DecalMaterial { get { - if (_protoDecalMaterial == null) { - _protoDecalMaterial = MakeMaterial(_decalShader); + if (_decalMaterial == null) { + _decalMaterial = new Material(_decalShader); + UpdateMaterial(_decalMaterial); } - return _protoDecalMaterial; + return _decalMaterial; } } - private Shader _decalShader; - private Material _protoDecalMaterial; + public Shader DecalShader => _decalShader; + + public float AspectRatio => MainMaterialTextureProperty?.AspectRatio ?? 1f; + + [SerializeField] private Shader _decalShader; + + private Material _decalMaterial; public void Initialize() { _materialProperties = new List(); @@ -36,7 +42,7 @@ namespace ConformalDecals.MaterialModifiers { Initialize(); Debug.LogWarning("Tried to add a property to uninitialized property collection! correcting now."); } - + foreach (var p in _materialProperties) { if (p.PropertyName == property.PropertyName) { _materialProperties.Remove(property); @@ -70,33 +76,38 @@ namespace ConformalDecals.MaterialModifiers { } var shader = Shabby.Shabby.FindShader(shaderName); - + if (shader == null) throw new FormatException($"Unable to find specified shader '{shaderName}'"); _decalShader = shader; } - public void SetScale(Material material, Vector2 scale) { + public void SetRenderQueue(int queue) { + DecalMaterial.renderQueue = queue; + } + + public void SetScale(Vector2 scale) { foreach (var textureProperty in _textureMaterialProperties) { - textureProperty.UpdateScale(material, scale); + textureProperty.UpdateScale(DecalMaterial, scale); } } - public void SetOpacity(Material material, float opacity) { - material.SetFloat(OpacityId, opacity); + public void SetOpacity(float opacity) { + DecalMaterial.SetFloat(OpacityId, opacity); + } + + public void SetCutoff(float cutoff) { + DecalMaterial.SetFloat(CutoffId, cutoff); } - public void SetCutoff(Material material, float cutoff) { - material.SetFloat(CutoffId, cutoff); + public void UpdateMaterials() { + UpdateMaterial(_decalMaterial); } - private Material MakeMaterial(Shader shader) { - var material = new Material(shader); - foreach (MaterialProperty property in _materialProperties) { + public void UpdateMaterial(Material material) { + foreach (var property in _materialProperties) { property.Modify(material); } - - return material; } } } \ No newline at end of file diff --git a/Source/ConformalDecals/MaterialModifiers/MaterialTextureProperty.cs b/Source/ConformalDecals/MaterialModifiers/MaterialTextureProperty.cs index c14ab06..03dda7d 100644 --- a/Source/ConformalDecals/MaterialModifiers/MaterialTextureProperty.cs +++ b/Source/ConformalDecals/MaterialModifiers/MaterialTextureProperty.cs @@ -3,7 +3,7 @@ using UnityEngine; namespace ConformalDecals.MaterialModifiers { public class MaterialTextureProperty : MaterialProperty { - public Texture2D TextureRef { get; } + public Texture2D texture; public bool IsNormal { get; } public bool IsMain { get; } @@ -23,53 +23,53 @@ namespace ConformalDecals.MaterialModifiers { var textureUrl = node.GetValue("textureURL"); if ((textureUrl == null && IsNormal) || textureUrl == "Bump") { - TextureRef = Texture2D.normalTexture; + texture = Texture2D.normalTexture; } else if ((textureUrl == null && !IsNormal) || textureUrl == "White") { - TextureRef = Texture2D.whiteTexture; + texture = Texture2D.whiteTexture; } else if (textureUrl == "Black") { - TextureRef = Texture2D.blackTexture; + texture = Texture2D.blackTexture; } else { var textureInfo = GameDatabase.Instance.GetTextureInfo(textureUrl); if (textureInfo == null) throw new Exception($"Cannot find texture: '{textureUrl}'"); - TextureRef = IsNormal ? textureInfo.normalMap : textureInfo.texture; + texture = IsNormal ? textureInfo.normalMap : textureInfo.texture; } - if (TextureRef == null) throw new Exception($"Cannot get texture from texture info '{textureUrl}' isNormalMap = {IsNormal}"); + if (texture == null) throw new Exception($"Cannot get texture from texture info '{textureUrl}' isNormalMap = {IsNormal}"); - _tileRect = ParsePropertyRect(node, "tileRect", true, new Rect(0, 0, TextureRef.width, TextureRef.height)); + _tileRect = ParsePropertyRect(node, "tileRect", true, new Rect(0, 0, texture.width, texture.height)); - _textureScale.x = _tileRect.width / TextureRef.width; - _textureScale.y = _tileRect.height / TextureRef.height; + _textureScale.x = _tileRect.width / texture.width; + _textureScale.y = _tileRect.height / texture.height; - _textureOffset.x = _tileRect.x / TextureRef.width; - _textureOffset.y = _tileRect.y / TextureRef.height; + _textureOffset.x = _tileRect.x / texture.width; + _textureOffset.y = _tileRect.y / texture.height; } public MaterialTextureProperty(string name, Texture2D texture, Rect tileRect = default, bool isNormal = false, bool isMain = false, bool autoScale = false) : base(name) { - TextureRef = texture; + this.texture = texture; - _tileRect = tileRect == default ? new Rect(0, 0, TextureRef.width, TextureRef.height) : tileRect; + _tileRect = tileRect == default ? new Rect(0, 0, this.texture.width, this.texture.height) : tileRect; IsNormal = isNormal; IsMain = isMain; AutoScale = autoScale; - _textureScale.x = _tileRect.width / TextureRef.width; - _textureScale.y = _tileRect.height / TextureRef.height; + _textureScale.x = _tileRect.width / this.texture.width; + _textureScale.y = _tileRect.height / this.texture.height; - _textureOffset.x = _tileRect.x / TextureRef.width; - _textureOffset.y = _tileRect.y / TextureRef.height; + _textureOffset.x = _tileRect.x / this.texture.width; + _textureOffset.y = _tileRect.y / this.texture.height; } - + public override void Modify(Material material) { - material.SetTexture(_propertyID, TextureRef); + material.SetTexture(_propertyID, texture); material.SetTextureOffset(_propertyID, _textureOffset); material.SetTextureScale(_propertyID, _textureScale); } diff --git a/Source/ConformalDecals/ModuleConformalDecal.cs b/Source/ConformalDecals/ModuleConformalDecalBase.cs similarity index 83% rename from Source/ConformalDecals/ModuleConformalDecal.cs rename to Source/ConformalDecals/ModuleConformalDecalBase.cs index 8e2217b..63a4b23 100644 --- a/Source/ConformalDecals/ModuleConformalDecal.cs +++ b/Source/ConformalDecals/ModuleConformalDecalBase.cs @@ -5,7 +5,7 @@ using ConformalDecals.Util; using UnityEngine; namespace ConformalDecals { - public class ModuleConformalDecal : PartModule { + public abstract class ModuleConformalDecalBase : PartModule { [KSPField(guiName = "#LOC_ConformalDecals_gui-scale", guiActive = false, guiActiveEditor = true, isPersistant = true, guiFormat = "F2", guiUnits = "m"), UI_FloatRange(minValue = 0.05f, maxValue = 4f, stepIncrement = 0.05f)] public float scale = 1.0f; @@ -22,9 +22,6 @@ namespace ConformalDecals { UI_FloatRange(minValue = 0.0f, maxValue = 1f, stepIncrement = 0.05f)] public float cutoff = 0.5f; - [KSPField(guiName = "#LOC_ConformalDecals_gui-aspectratio", guiActive = false, guiActiveEditor = true, guiFormat = "F2")] - public float aspectRatio = 1.0f; - [KSPField] public string decalFront = string.Empty; [KSPField] public string decalBack = string.Empty; [KSPField] public string decalModel = string.Empty; @@ -52,7 +49,6 @@ namespace ConformalDecals { [KSPField] public MaterialPropertyCollection materialProperties; - [KSPField] public Material decalMaterial; [KSPField] public Material backMaterial; private static int _decalQueueCounter = -1; @@ -64,7 +60,7 @@ namespace ConformalDecals { private Bounds _decalBounds; private Vector2 _backTextureBaseScale; - public ModuleConformalDecal() { + public ModuleConformalDecalBase() { decalBackTransform = null; decalModelTransform = null; decalProjectorTransform = null; @@ -77,7 +73,6 @@ namespace ConformalDecals { _decalQueueCounter = (int) decalQueueRange.x; } - this.Log($"returning decal queue value {_decalQueueCounter}"); return _decalQueueCounter; } } @@ -88,7 +83,7 @@ namespace ConformalDecals { if (HighLogic.LoadedSceneIsEditor) { UpdateTweakables(); } - + if (materialProperties == null) { // materialProperties is null, so make a new one materialProperties = ScriptableObject.CreateInstance(); @@ -96,38 +91,27 @@ namespace ConformalDecals { } else { // materialProperties already exists, so make a copy - this.Log($"{materialProperties == null}"); materialProperties = ScriptableObject.Instantiate(materialProperties); } - - // add texture nodes - foreach (var textureNode in node.GetNodes("TEXTURE")) { - materialProperties.AddProperty(new MaterialTextureProperty(textureNode)); - } - - // add float nodes - foreach (var floatNode in node.GetNodes("FLOAT")) { - materialProperties.AddProperty(new MaterialFloatProperty(floatNode)); - } - - // add color nodes - foreach (var colorNode in node.GetNodes("COLOR")) { - materialProperties.AddProperty(new MaterialColorProperty(colorNode)); - } - + // set shader materialProperties.SetShader(decalShader); - // get decal material - decalMaterial = materialProperties.DecalMaterial; - - // get aspect ratio from main texture, if it exists - var mainTexture = materialProperties.MainMaterialTextureProperty; - if (mainTexture != null) { - aspectRatio = mainTexture.AspectRatio; - } - else { - aspectRatio = 1; + // get back material if necessary + if (updateBackScale) { + this.Log("Getting material and base scale for back material"); + var backRenderer = decalBackTransform.GetComponent(); + if (backRenderer == null) { + this.LogError($"Specified decalBack transform {decalBack} has no renderer attached! Setting updateBackScale to false."); + updateBackScale = false; + } + else if ((backMaterial = backRenderer.material) == null) { + this.LogError($"Specified decalBack transform {decalBack} has a renderer but no material! Setting updateBackScale to false."); + updateBackScale = false; + } + else { + _backTextureBaseScale = backMaterial.GetTextureScale(PropertyIDs._MainTex); + } } // find front transform @@ -182,35 +166,17 @@ namespace ConformalDecals { if (HighLogic.LoadedSceneIsEditor) { GameEvents.onEditorPartEvent.Add(OnEditorEvent); GameEvents.onVariantApplied.Add(OnVariantApplied); - + UpdateTweakables(); } - + // generate orthogonal projection matrix and offset it by 0.5 on x and y axes _orthoMatrix = Matrix4x4.identity; _orthoMatrix[0, 3] = 0.5f; _orthoMatrix[1, 3] = 0.5f; // 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"); - var backRenderer = decalBackTransform.GetComponent(); - if (backRenderer == null) { - this.LogError($"Specified decalBack transform {decalBack} has no renderer attached! Setting updateBackScale to false."); - updateBackScale = false; - } - else if ((backMaterial = backRenderer.material) == null) { - this.LogError($"Specified decalBack transform {decalBack} has a renderer but no material! Setting updateBackScale to false."); - updateBackScale = false; - } - else { - _backTextureBaseScale = backMaterial.GetTextureScale(PropertyIDs._MainTex); - } - } + materialProperties.SetRenderQueue(DecalQueue); // set initial attachment state if (part.parent == null) { @@ -237,8 +203,8 @@ namespace ConformalDecals { } private void OnMaterialTweakEvent(BaseField field, object obj) { - materialProperties.SetOpacity(decalMaterial, opacity); - materialProperties.SetCutoff(decalMaterial, cutoff); + materialProperties.SetOpacity(opacity); + materialProperties.SetCutoff(cutoff); } private void OnVariantApplied(Part eventPart, PartVariant variant) { @@ -301,7 +267,7 @@ namespace ConformalDecals { } private void UpdateScale() { - var size = new Vector2(scale, scale * aspectRatio); + var size = new Vector2(scale, scale * materialProperties.AspectRatio); // update orthogonal matrix scale _orthoMatrix[0, 0] = 1 / size.x; @@ -321,7 +287,7 @@ namespace ConformalDecals { } // update material scale - materialProperties.SetScale(decalMaterial, size); + materialProperties.SetScale(size); } private void UpdateProjection() { @@ -418,13 +384,13 @@ namespace ConformalDecals { cutoffField.uiControlEditor.onFieldChanged = OnMaterialTweakEvent; } } - + private void Render(Camera camera) { if (!_isAttached) return; // render on each target object foreach (var target in _targets) { - target.Render(decalMaterial, part.mpb, camera); + target.Render(materialProperties.DecalMaterial, part.mpb, camera); } } } diff --git a/Source/ConformalDecals/ModuleConformalDecalFlag.cs b/Source/ConformalDecals/ModuleConformalDecalFlag.cs new file mode 100644 index 0000000..f00bc62 --- /dev/null +++ b/Source/ConformalDecals/ModuleConformalDecalFlag.cs @@ -0,0 +1,32 @@ +using System; +using ConformalDecals.MaterialModifiers; +using ConformalDecals.Util; +using UnityEngine; + +namespace ConformalDecals { + public class ModuleConformalDecalFlag : ModuleConformalDecalBase { + + [KSPField] + private MaterialTextureProperty _flagTextureProperty; + + public override void OnLoad(ConfigNode node) { + base.OnLoad(node); + + _flagTextureProperty = new MaterialTextureProperty("_MainTex", Texture2D.whiteTexture); + materialProperties.AddProperty(_flagTextureProperty); + } + + public override void OnStart(StartState state) { + base.OnStart(state); + + UpdateFlag(EditorLogic.FlagURL != string.Empty ? EditorLogic.FlagURL : HighLogic.CurrentGame.flagURL); + GameEvents.onMissionFlagSelect.Add(UpdateFlag); + } + + private void UpdateFlag(string flagUrl) { + _flagTextureProperty.texture = GameDatabase.Instance.GetTexture(flagUrl, false); + + materialProperties.UpdateMaterials(); + } + } +} \ No newline at end of file diff --git a/Source/ConformalDecals/ModuleConformalDecalGeneric.cs b/Source/ConformalDecals/ModuleConformalDecalGeneric.cs new file mode 100644 index 0000000..4b523fa --- /dev/null +++ b/Source/ConformalDecals/ModuleConformalDecalGeneric.cs @@ -0,0 +1,26 @@ +using ConformalDecals.MaterialModifiers; +using ConformalDecals.Util; +using UnityEngine; + +namespace ConformalDecals { + public class ModuleConformalDecalGeneric : ModuleConformalDecalBase { + public override void OnLoad(ConfigNode node) { + base.OnLoad(node); + + // add texture nodes + foreach (var textureNode in node.GetNodes("TEXTURE")) { + materialProperties.AddProperty(new MaterialTextureProperty(textureNode)); + } + + // add float nodes + foreach (var floatNode in node.GetNodes("FLOAT")) { + materialProperties.AddProperty(new MaterialFloatProperty(floatNode)); + } + + // add color nodes + foreach (var colorNode in node.GetNodes("COLOR")) { + materialProperties.AddProperty(new MaterialColorProperty(colorNode)); + } + } + } +} \ No newline at end of file