You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
6.5 KiB
158 lines
6.5 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace UnityEditor.VFX
|
|
{
|
|
interface IVFXSubRenderer
|
|
{
|
|
bool hasShadowCasting { get; }
|
|
bool hasMotionVector { get; }
|
|
// TODO Add other per output rendering settings here
|
|
|
|
bool isRayTraced { get; }
|
|
int vfxSystemSortPriority { get; set; }
|
|
|
|
// Allow to setup material generated during import
|
|
void SetupMaterial(Material material);
|
|
}
|
|
|
|
[Serializable]
|
|
class VFXMaterialSerializedSettings : ISerializationCallbackReceiver
|
|
{
|
|
private Dictionary<string, float> m_PropertyMap = new Dictionary<string, float>();
|
|
|
|
public static VFXMaterialSerializedSettings CreateFromMaterial(Material material)
|
|
{
|
|
VFXMaterialSerializedSettings settings = new VFXMaterialSerializedSettings();
|
|
settings.SyncFromMaterial(material);
|
|
return settings;
|
|
}
|
|
|
|
public void UpgradeToMaterialWorkflowVersion(Material referenceMaterial)
|
|
{
|
|
var serializedReferenceMaterial = new SerializedObject(referenceMaterial);
|
|
var referenceProperties = new Dictionary<string, float>();
|
|
var propertyBase = serializedReferenceMaterial.FindProperty("m_SavedProperties");
|
|
propertyBase = propertyBase.FindPropertyRelative("m_Floats");
|
|
for (int index = 0; index < propertyBase.arraySize; ++index)
|
|
{
|
|
var currentElement = propertyBase.GetArrayElementAtIndex(index);
|
|
var name = currentElement.FindPropertyRelative("first").stringValue;
|
|
var floatValue = currentElement.FindPropertyRelative("second").floatValue;
|
|
referenceProperties.Add(name, floatValue);
|
|
}
|
|
|
|
var toRemove = new List<string>();
|
|
foreach (var entry in m_PropertyMap)
|
|
{
|
|
//If the reference material have the same value than the serialized setting,
|
|
//Admit the value has never been modified and shouldn't be considered as override.
|
|
//Before MaterialVariant, every available properties were serialized
|
|
//N.B.: if entry.Key isn't available in reference material, it can be a setting from another unavailable SRP
|
|
if (referenceProperties.TryGetValue(entry.Key, out var referenceValue)
|
|
&& referenceValue == entry.Value)
|
|
{
|
|
toRemove.Add(entry.Key);
|
|
}
|
|
}
|
|
foreach (var entry in toRemove)
|
|
m_PropertyMap.Remove(entry);
|
|
}
|
|
|
|
public void SyncFromMaterial(Material material)
|
|
{
|
|
m_PropertyMap.Clear();
|
|
|
|
var serializedMaterial = new SerializedObject(material);
|
|
var propertyBase = serializedMaterial.FindProperty("m_SavedProperties");
|
|
propertyBase = propertyBase.FindPropertyRelative("m_Floats");
|
|
for (int index = 0; index < propertyBase.arraySize; ++index)
|
|
{
|
|
var currentElement = propertyBase.GetArrayElementAtIndex(index);
|
|
var name = currentElement.FindPropertyRelative("first").stringValue;
|
|
var floatValue = currentElement.FindPropertyRelative("second").floatValue;
|
|
|
|
//material.IsPropertyOverriden doesn't need to be called, only serialized property are overridden in variant
|
|
//if (!material.IsPropertyOverriden(name)) throw new InvalidOperationException();
|
|
//Some not registered properties can be stored in material which correspond to another SRP (!= GetMaterialProperties)
|
|
m_PropertyMap.Add(name, floatValue);
|
|
}
|
|
|
|
renderQueue = material.renderQueue;
|
|
}
|
|
|
|
public void ApplyToMaterial(Material material)
|
|
{
|
|
//Directly modify serialized properties
|
|
//Using material.SetFloat would automatically skip not existing properties (e.g.: input from another SRP)
|
|
//We are fitting to the default material behavior here
|
|
var serializedMaterial = new SerializedObject(material);
|
|
var propertyBase = serializedMaterial.FindProperty("m_SavedProperties");
|
|
propertyBase = propertyBase.FindPropertyRelative("m_Floats");
|
|
propertyBase.arraySize = m_PropertyMap.Count;
|
|
|
|
int index = 0;
|
|
foreach (var kvp in m_PropertyMap)
|
|
{
|
|
var currentEntry = propertyBase.GetArrayElementAtIndex(index++);
|
|
currentEntry.FindPropertyRelative("first").stringValue = kvp.Key;
|
|
currentEntry.FindPropertyRelative("second").floatValue = kvp.Value;
|
|
}
|
|
|
|
serializedMaterial.ApplyModifiedProperties();
|
|
//N.B.: We can't used serialized properties here because renderQueue changes aren't automatically mark this entry as override
|
|
material.renderQueue = renderQueue;
|
|
}
|
|
|
|
public bool TryGetFloat(string name, Material fallback, out float value)
|
|
{
|
|
if (m_PropertyMap.TryGetValue(name, out var readValue))
|
|
{
|
|
value = readValue;
|
|
return true;
|
|
}
|
|
|
|
//With Material Variant workflow, the actual settings could be in parent material but not saved in properties
|
|
if (fallback != null && fallback.HasFloat(name))
|
|
{
|
|
value = fallback.GetFloat(name);
|
|
return true;
|
|
}
|
|
|
|
value = -1;
|
|
return false;
|
|
}
|
|
|
|
// Helper to serialize the property map dictionary.
|
|
public void OnBeforeSerialize() => StoreProperties();
|
|
public void OnAfterDeserialize() => LoadProperties();
|
|
|
|
[SerializeField]
|
|
private List<string> m_PropertyNames = new List<string>();
|
|
|
|
[SerializeField]
|
|
private List<float> m_PropertyValues = new List<float>();
|
|
|
|
[SerializeField] private int renderQueue = -1;
|
|
|
|
void StoreProperties()
|
|
{
|
|
m_PropertyNames.Clear();
|
|
m_PropertyValues.Clear();
|
|
foreach (var kvp in m_PropertyMap)
|
|
{
|
|
m_PropertyNames.Add(kvp.Key);
|
|
m_PropertyValues.Add(kvp.Value);
|
|
}
|
|
}
|
|
|
|
void LoadProperties()
|
|
{
|
|
m_PropertyMap = new Dictionary<string, float>();
|
|
for (int i = 0; i != Math.Min(m_PropertyNames.Count, m_PropertyValues.Count); i++)
|
|
m_PropertyMap.Add(m_PropertyNames[i], m_PropertyValues[i]);
|
|
}
|
|
}
|
|
}
|