Fix scaling issues when part is created

• KSP rescales the model object back to 1,1,1 on start, so don't use that for the model that gets scaled
• Some refactoring to consolidate property IDs
• rename some classes because I am indecisive
• Add and Get methods for MaterialPropertyCollection
• Make an attempt at a scale culling fix
This commit is contained in:
2020-06-05 21:29:57 -07:00
parent 5560eee368
commit da1fbf0f2a
11 changed files with 151 additions and 89 deletions

View File

@ -3,11 +3,19 @@ using System.Collections.Generic;
using System.Runtime.Serialization;
using UniLinq;
using UnityEngine;
using UnityEngine.Rendering;
namespace ConformalDecals.MaterialModifiers {
public class MaterialPropertyCollection : ScriptableObject, ISerializationCallbackReceiver {
private static readonly int OpacityId = Shader.PropertyToID("_DecalOpacity");
private static readonly int CutoffId = Shader.PropertyToID("_Cutoff");
[SerializeField] private Shader _shader;
[SerializeField] private MaterialTextureProperty _mainTexture;
[SerializeField] private string[] _serializedNames;
[SerializeField] private MaterialProperty[] _serializedProperties;
private Dictionary<string, MaterialProperty> _materialProperties;
private Material _decalMaterial;
private Material _previewMaterial;
public Shader DecalShader => _shader;
@ -16,6 +24,8 @@ namespace ConformalDecals.MaterialModifiers {
if (_decalMaterial == null) {
_decalMaterial = new Material(_shader);
UpdateMaterial(_decalMaterial);
_previewMaterial.SetInt(DecalPropertyIDs._Cull, (int) CullMode.Off);
}
return _decalMaterial;
@ -27,7 +37,9 @@ namespace ConformalDecals.MaterialModifiers {
if (_previewMaterial == null) {
_previewMaterial = new Material(_shader);
UpdateMaterial(_previewMaterial);
_previewMaterial.EnableKeyword("DECAL_PREVIEW");
_previewMaterial.SetInt(DecalPropertyIDs._Cull, (int) CullMode.Back);
}
return _previewMaterial;
@ -50,41 +62,31 @@ namespace ConformalDecals.MaterialModifiers {
Debug.Log("No main texture specified! returning 1 for aspect ratio");
return 1;
}
return MainTexture.AspectRatio;
}
}
[SerializeField] private string[] _serializedIDs;
[SerializeField] private MaterialProperty[] _serializedProperties;
[SerializeField] private Shader _shader;
[SerializeField] private MaterialTextureProperty _mainTexture;
private Dictionary<string, MaterialProperty> _materialProperties;
private Material _decalMaterial;
private Material _previewMaterial;
public void OnBeforeSerialize() {
Debug.Log($"Serializing MaterialPropertyCollection {this.GetInstanceID()}");
if (_materialProperties == null) throw new SerializationException("Tried to serialize an unininitalized MaterialPropertyCollection");
if (_materialProperties == null) throw new SerializationException("Tried to serialize an uninitialized MaterialPropertyCollection");
_serializedIDs = _materialProperties.Keys.ToArray();
_serializedNames = _materialProperties.Keys.ToArray();
_serializedProperties = _materialProperties.Values.ToArray();
}
public void OnAfterDeserialize() {
Debug.Log($"Deserializing MaterialPropertyCollection {this.GetInstanceID()}");
if (_serializedIDs == null) throw new SerializationException("ID array is null");
if (_serializedNames == null) throw new SerializationException("ID array is null");
if (_serializedProperties == null) throw new SerializationException("Property array is null");
if (_serializedProperties.Length != _serializedIDs.Length) throw new SerializationException("Material property arrays are different lengths.");
if (_serializedProperties.Length != _serializedNames.Length) throw new SerializationException("Material property arrays are different lengths.");
_materialProperties ??= new Dictionary<string, MaterialProperty>();
for (var i = 0; i < _serializedIDs.Length; i++) {
for (var i = 0; i < _serializedNames.Length; i++) {
var property = MaterialProperty.Instantiate(_serializedProperties[i]);
Debug.Log($"insantiating {property.GetType().Name} {property.GetInstanceID()}");
_materialProperties.Add(_serializedIDs[i], property);
_materialProperties.Add(_serializedNames[i], property);
if (property is MaterialTextureProperty textureProperty) {
_mainTexture = textureProperty;
@ -98,7 +100,7 @@ namespace ConformalDecals.MaterialModifiers {
}
public void AddProperty(MaterialProperty property) {
if (property == null) throw new ArgumentNullException("Tried to add a null property");
if (property == null) throw new ArgumentNullException(nameof(property));
_materialProperties.Add(property.name, property);
@ -107,16 +109,61 @@ namespace ConformalDecals.MaterialModifiers {
}
}
public void ParseProperty<T>(ConfigNode node) where T : MaterialProperty {
var name = node.GetValue("name");
if (string.IsNullOrEmpty(name)) throw new ArgumentException("node has no name");
public T AddProperty<T>(string propertyName) where T : MaterialProperty {
if (_materialProperties.ContainsKey(propertyName)) throw new ArgumentException("property with that name already exists!");
var newProperty = MaterialProperty.CreateInstance<T>();
newProperty.PropertyName = propertyName;
_materialProperties.Add(propertyName, newProperty);
return newProperty;
}
Debug.Log($"Parsing material property {name}");
public T GetProperty<T>(string propertyName) where T : MaterialProperty {
if (_materialProperties.ContainsKey(propertyName) && _materialProperties[propertyName] is T property) {
return property;
}
else {
return null;
}
}
public T AddOrGetProperty<T>(string propertyName) where T : MaterialProperty {
if (_materialProperties.ContainsKey(propertyName) && _materialProperties[propertyName] is T property) {
return property;
}
else {
return AddProperty<T>(propertyName);
}
}
public MaterialTextureProperty AddTextureProperty(string propertyName, bool isMain = false) {
var newProperty = AddProperty<MaterialTextureProperty>(propertyName);
if (isMain) MainTexture = newProperty;
return newProperty;
}
public MaterialTextureProperty GetTextureProperty(string propertyName) {
return GetProperty<MaterialTextureProperty>(propertyName);
}
public MaterialTextureProperty AddOrGetTextureProperty(string propertyName, bool isMain = false) {
if (_materialProperties.ContainsKey(propertyName) && _materialProperties[propertyName] is MaterialTextureProperty property) {
return property;
}
else {
return AddTextureProperty(propertyName, isMain);
}
}
public void ParseProperty<T>(ConfigNode node) where T : MaterialProperty {
var propertyName = node.GetValue("name");
if (string.IsNullOrEmpty(propertyName)) throw new ArgumentException("node has no name");
Debug.Log($"Parsing material property {propertyName}");
T newProperty;
if (_materialProperties.ContainsKey(name)) {
if (_materialProperties[name] is T property) {
if (_materialProperties.ContainsKey(propertyName)) {
if (_materialProperties[propertyName] is T property) {
newProperty = property;
property.ParseNode(node);
}
@ -128,7 +175,7 @@ namespace ConformalDecals.MaterialModifiers {
newProperty = MaterialProperty.CreateInstance<T>();
Debug.Log($"Adding new material property of type {newProperty.GetType().Name} {newProperty.GetInstanceID()}");
newProperty.ParseNode(node);
_materialProperties.Add(name, newProperty);
_materialProperties.Add(propertyName, newProperty);
}
if (newProperty is MaterialTextureProperty textureProperty && textureProperty.isMain) {
@ -170,11 +217,13 @@ namespace ConformalDecals.MaterialModifiers {
}
public void SetOpacity(float opacity) {
DecalMaterial.SetFloat(OpacityId, opacity);
DecalMaterial.SetFloat(DecalPropertyIDs._DecalOpacity, opacity);
PreviewMaterial.SetFloat(DecalPropertyIDs._DecalOpacity, opacity);
}
public void SetCutoff(float cutoff) {
DecalMaterial.SetFloat(CutoffId, cutoff);
DecalMaterial.SetFloat(DecalPropertyIDs._Cutoff, cutoff);
PreviewMaterial.SetFloat(DecalPropertyIDs._Cutoff, cutoff);
}
public void UpdateMaterials() {
@ -195,8 +244,11 @@ namespace ConformalDecals.MaterialModifiers {
public void UpdateMaterial(Material material) {
if (material == null) throw new ArgumentNullException(nameof(material));
foreach (var entry in _materialProperties) {
Debug.Log($"Applying material property {entry.Key} {entry.Value.PropertyName} {entry.Value.GetInstanceID()}");
entry.Value.Modify(material);
}
}