@@ -17,7 +17,7 @@ namespace FlaxEditor.Surface
|
||||
public class MaterialSurface : VisjectSurface
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public MaterialSurface(IVisjectSurfaceOwner owner, Action onSave, FlaxEditor.Undo undo)
|
||||
public MaterialSurface(IVisjectSurfaceOwner owner, Action onSave = null, FlaxEditor.Undo undo = null)
|
||||
: base(owner, onSave, undo)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -73,9 +73,8 @@ namespace FlaxEditor.Surface
|
||||
|
||||
// By name
|
||||
if (Editor.Instance.Options.Options.General.ScriptMembersOrder == GeneralOptions.MembersOrder.Alphabetical)
|
||||
{
|
||||
return string.Compare(x.DisplayName, y.DisplayName, StringComparison.InvariantCulture);
|
||||
}
|
||||
|
||||
// Keep same order
|
||||
return 0;
|
||||
}
|
||||
@@ -106,6 +105,79 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class DummyMaterialSurfaceOwner : IVisjectSurfaceOwner
|
||||
{
|
||||
public Asset SurfaceAsset => null;
|
||||
public string SurfaceName => null;
|
||||
public FlaxEditor.Undo Undo => null;
|
||||
public byte[] SurfaceData { get; set; }
|
||||
public VisjectSurfaceContext ParentContext => null;
|
||||
|
||||
public void OnContextCreated(VisjectSurfaceContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnSurfaceEditedChanged()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnSurfaceGraphEdited()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnSurfaceClose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static void FindGraphParameters(Material material, List<SurfaceParameter> surfaceParameters)
|
||||
{
|
||||
if (material == null || material.WaitForLoaded())
|
||||
return;
|
||||
var surfaceData = material.LoadSurface(false);
|
||||
if (surfaceData != null && surfaceData.Length > 0)
|
||||
{
|
||||
var surfaceOwner = new DummyMaterialSurfaceOwner { SurfaceData = surfaceData };
|
||||
var surface = new MaterialSurface(surfaceOwner);
|
||||
if (!surface.Load())
|
||||
{
|
||||
surfaceParameters.AddRange(surface.Parameters);
|
||||
|
||||
// Search for any nested parameters (eg. via Sample Layer)
|
||||
foreach (var node in surface.Nodes)
|
||||
{
|
||||
if (node.GroupArchetype.GroupID == 8 && node.Archetype.TypeID == 1) // Sample Layer
|
||||
{
|
||||
if (node.Values != null && node.Values.Length > 0 && node.Values[0] is Guid layerId)
|
||||
{
|
||||
var layer = FlaxEngine.Content.Load<MaterialBase>(layerId);
|
||||
if (layer)
|
||||
{
|
||||
FindGraphParameters(layer, surfaceParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void FindGraphParameters(MaterialBase materialBase, List<SurfaceParameter> surfaceParameters)
|
||||
{
|
||||
while (materialBase != null && !materialBase.WaitForLoaded())
|
||||
{
|
||||
if (materialBase is MaterialInstance materialInstance)
|
||||
{
|
||||
materialBase = materialInstance.BaseMaterial;
|
||||
}
|
||||
else if (materialBase is Material material)
|
||||
{
|
||||
FindGraphParameters(material, surfaceParameters);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static GraphParameterData[] InitGraphParameters(IEnumerable<MaterialParameter> parameters, Material material)
|
||||
{
|
||||
int count = parameters.Count();
|
||||
@@ -113,128 +185,11 @@ namespace FlaxEditor.Surface
|
||||
int i = 0;
|
||||
|
||||
// Load material surface parameters meta to use it for material instance parameters editing
|
||||
SurfaceParameter[] surfaceParameters = null;
|
||||
var surfaceParameters = new List<SurfaceParameter>();
|
||||
try
|
||||
{
|
||||
Profiler.BeginEvent("Init Material Parameters UI Data");
|
||||
|
||||
if (material != null && !material.WaitForLoaded())
|
||||
{
|
||||
var surfaceData = material.LoadSurface(false);
|
||||
if (surfaceData != null && surfaceData.Length > 0)
|
||||
{
|
||||
using (var memoryStream = new MemoryStream(surfaceData))
|
||||
using (var stream = new BinaryReader(memoryStream))
|
||||
{
|
||||
// IMPORTANT! This must match C++ Graph format
|
||||
|
||||
// Magic Code
|
||||
int tmp = stream.ReadInt32();
|
||||
if (tmp != 1963542358)
|
||||
{
|
||||
// Error
|
||||
throw new Exception("Invalid Graph format version");
|
||||
}
|
||||
|
||||
// Version
|
||||
var version = stream.ReadUInt32();
|
||||
var guidBytes = new byte[16];
|
||||
if (version < 7000)
|
||||
{
|
||||
// Time saved (not used anymore to prevent binary diffs after saving unmodified surface)
|
||||
stream.ReadInt64();
|
||||
|
||||
// Nodes count
|
||||
int nodesCount = stream.ReadInt32();
|
||||
|
||||
// Parameters count
|
||||
int parametersCount = stream.ReadInt32();
|
||||
|
||||
// For each node
|
||||
for (int j = 0; j < nodesCount; j++)
|
||||
{
|
||||
// ID
|
||||
stream.ReadUInt32();
|
||||
|
||||
// Type
|
||||
stream.ReadUInt16();
|
||||
stream.ReadUInt16();
|
||||
}
|
||||
|
||||
// For each param
|
||||
surfaceParameters = new SurfaceParameter[parametersCount];
|
||||
for (int j = 0; j < parametersCount; j++)
|
||||
{
|
||||
// Create param
|
||||
var param = new SurfaceParameter();
|
||||
surfaceParameters[j] = param;
|
||||
|
||||
// Properties
|
||||
param.Type = new ScriptType(VisjectSurfaceContext.GetGraphParameterValueType((VisjectSurfaceContext.GraphParamType_Deprecated)stream.ReadByte()));
|
||||
stream.Read(guidBytes, 0, 16);
|
||||
param.ID = new Guid(guidBytes);
|
||||
param.Name = stream.ReadStr(97);
|
||||
param.IsPublic = stream.ReadByte() != 0;
|
||||
var isStatic = stream.ReadByte() != 0;
|
||||
var isUIVisible = stream.ReadByte() != 0;
|
||||
var isUIEditable = stream.ReadByte() != 0;
|
||||
|
||||
// References [Deprecated]
|
||||
int refsCount = stream.ReadInt32();
|
||||
for (int k = 0; k < refsCount; k++)
|
||||
stream.ReadUInt32();
|
||||
|
||||
// Value
|
||||
stream.ReadCommonValue(ref param.Value);
|
||||
|
||||
// Meta
|
||||
param.Meta.Load(stream);
|
||||
}
|
||||
}
|
||||
else if (version == 7000)
|
||||
{
|
||||
// Nodes count
|
||||
int nodesCount = stream.ReadInt32();
|
||||
|
||||
// Parameters count
|
||||
int parametersCount = stream.ReadInt32();
|
||||
|
||||
// For each node
|
||||
for (int j = 0; j < nodesCount; j++)
|
||||
{
|
||||
// ID
|
||||
stream.ReadUInt32();
|
||||
|
||||
// Type
|
||||
stream.ReadUInt16();
|
||||
stream.ReadUInt16();
|
||||
}
|
||||
|
||||
// For each param
|
||||
surfaceParameters = new SurfaceParameter[parametersCount];
|
||||
for (int j = 0; j < parametersCount; j++)
|
||||
{
|
||||
// Create param
|
||||
var param = new SurfaceParameter();
|
||||
surfaceParameters[j] = param;
|
||||
|
||||
// Properties
|
||||
param.Type = stream.ReadVariantScriptType();
|
||||
stream.Read(guidBytes, 0, 16);
|
||||
param.ID = new Guid(guidBytes);
|
||||
param.Name = stream.ReadStr(97);
|
||||
param.IsPublic = stream.ReadByte() != 0;
|
||||
|
||||
// Value
|
||||
param.Value = stream.ReadVariant();
|
||||
|
||||
// Meta
|
||||
param.Meta.Load(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FindGraphParameters(material, surfaceParameters);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -248,7 +203,26 @@ namespace FlaxEditor.Surface
|
||||
|
||||
foreach (var parameter in parameters)
|
||||
{
|
||||
var surfaceParameter = surfaceParameters?.FirstOrDefault(x => x.ID == parameter.ParameterID);
|
||||
var parameterId = parameter.ParameterID;
|
||||
var surfaceParameter = surfaceParameters.FirstOrDefault(x => x.ID == parameterId);
|
||||
if (surfaceParameter == null)
|
||||
{
|
||||
// Permutate original parameter ID to reflect logic in MaterialGenerator::prepareLayer used for nested layers
|
||||
unsafe
|
||||
{
|
||||
var raw = parameterId;
|
||||
var interop = *(FlaxEngine.Json.JsonSerializer.GuidInterop*)&raw;
|
||||
interop.A -= (uint)(i * 17 + 13);
|
||||
parameterId = *(Guid*)&interop;
|
||||
}
|
||||
surfaceParameter = surfaceParameters.FirstOrDefault(x => x.ID == parameterId);
|
||||
}
|
||||
if (surfaceParameter != null)
|
||||
{
|
||||
// Reorder so it won't be picked by other parameter that uses the same ID (eg. params from duplicated materials used as layers in other material)
|
||||
surfaceParameters.Remove(surfaceParameter);
|
||||
surfaceParameters.Add(surfaceParameter);
|
||||
}
|
||||
var attributes = surfaceParameter?.Meta.GetAttributes() ?? FlaxEngine.Utils.GetEmptyArray<Attribute>();
|
||||
data[i] = new GraphParameterData(null, parameter.Name, parameter.IsPublic, ToType(parameter.ParameterType), attributes, parameter);
|
||||
i++;
|
||||
|
||||
@@ -192,15 +192,10 @@ void MaterialGenerator::prepareLayer(MaterialLayer* layer, bool allowVisiblePara
|
||||
|
||||
// For all not root layers (sub-layers) we won't to change theirs ID in order to prevent duplicated ID)
|
||||
m.SrcId = param->Identifier;
|
||||
if (isRooLayer)
|
||||
m.DstId = param->Identifier;
|
||||
if (!isRooLayer)
|
||||
{
|
||||
// Use the same ID (so we can edit it)
|
||||
m.DstId = param->Identifier;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate new ID
|
||||
m.DstId = param->Identifier;
|
||||
// Generate new ID (stable permutation based on the original ID)
|
||||
m.DstId.A += _parameters.Count() * 17 + 13;
|
||||
}
|
||||
layer->ParamIdsMappings.Add(m);
|
||||
|
||||
Reference in New Issue
Block a user