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.
804 lines
34 KiB
804 lines
34 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEditor.VFX.Block;
|
|
using UnityEngine;
|
|
|
|
namespace UnityEditor.VFX
|
|
{
|
|
static class SanitizeHelper
|
|
{
|
|
public static void MigrateSGOutputToComposed(VFXShaderGraphParticleOutput shaderGraphOutput)
|
|
{
|
|
var shaderGraph = shaderGraphOutput.GetOrRefreshShaderGraphObject(false);
|
|
if (shaderGraph == null)
|
|
return;
|
|
|
|
if (!shaderGraph.generatesWithShaderGraph)
|
|
return;
|
|
|
|
Type topologyType = null;
|
|
Type composedType = null;
|
|
if (shaderGraphOutput.HasStrips())
|
|
{
|
|
topologyType = typeof(ParticleTopologyQuadStrip);
|
|
composedType = typeof(VFXComposedParticleStripOutput);
|
|
}
|
|
else
|
|
{
|
|
switch (shaderGraphOutput.taskType)
|
|
{
|
|
case VFXTaskType.ParticleMeshOutput:
|
|
topologyType = typeof(ParticleTopologyMesh);
|
|
break;
|
|
case VFXTaskType.ParticleQuadOutput:
|
|
case VFXTaskType.ParticleTriangleOutput:
|
|
case VFXTaskType.ParticleOctagonOutput:
|
|
topologyType = typeof(ParticleTopologyPlanarPrimitive);
|
|
break;
|
|
}
|
|
|
|
composedType = typeof(VFXComposedParticleOutput);
|
|
}
|
|
|
|
if (topologyType == null)
|
|
{
|
|
Debug.LogError("Unexpected output primitive: " + shaderGraphOutput);
|
|
return;
|
|
}
|
|
|
|
var composed = (VFXAbstractComposedParticleOutput)ScriptableObject.CreateInstance(composedType);
|
|
composed.SetSettingValue("m_Topology", Activator.CreateInstance(topologyType));
|
|
composed.label = shaderGraphOutput.label;
|
|
|
|
//Transfer blocks
|
|
var sourceBlocks = new List<VFXBlock>(shaderGraphOutput.children);
|
|
foreach (var block in sourceBlocks)
|
|
composed.AddChild(block, -1, false);
|
|
|
|
//Transfer settings (it should include materialSettings)
|
|
var sourceSettings = new List<KeyValuePair<string, object>>();
|
|
var destSettings = new List<VFXSetting>(composed.GetSettings(true, VFXSettingAttribute.VisibleFlags.Default));
|
|
foreach (var setting in destSettings)
|
|
{
|
|
var sourceSetting = shaderGraphOutput.GetSetting(setting.name);
|
|
if (!sourceSetting.valid)
|
|
continue;
|
|
|
|
if (VFXConverter.TryConvertTo(sourceSetting.value, setting.field.FieldType, out var value))
|
|
sourceSettings.Add(new KeyValuePair<string, object>(setting.field.Name, value));
|
|
}
|
|
composed.SetSettingValues(sourceSettings);
|
|
|
|
//Transfer slots
|
|
foreach (var slot in composed.inputSlots)
|
|
{
|
|
var refSlot = shaderGraphOutput.inputSlots.FirstOrDefault(o => o.name == slot.name);
|
|
VFXSlot.CopyLinksAndValue(slot, refSlot, false);
|
|
}
|
|
|
|
//Transfer flow edges
|
|
foreach (var link in shaderGraphOutput.inputFlowSlot[0].link)
|
|
{
|
|
composed.LinkFrom(link.context, link.slotIndex);
|
|
}
|
|
|
|
//Unlink previous flow before replacing model to avoid being kept in data owners
|
|
shaderGraphOutput.UnlinkAll();
|
|
|
|
VFXModel.ReplaceModel(composed, shaderGraphOutput);
|
|
}
|
|
|
|
public static void MigrateVector3OutputToSpaceableKeepingLegacyBehavior(VFXOperator op, string newTypeInfo)
|
|
{
|
|
Debug.LogFormat("Sanitizing Graph: Automatically replace Vector3 to {0} for {1}. An inline Vector3 operator has been added.", newTypeInfo, op.name);
|
|
|
|
var inlineVector3 = ScriptableObject.CreateInstance<VFXInlineOperator>();
|
|
inlineVector3.SetSettingValue("m_Type", (SerializableType)typeof(Vector3));
|
|
inlineVector3.position = op.position + new Vector2(128.0f, 64.0f);
|
|
VFXSlot.CopyLinksAndValue(inlineVector3.outputSlots[0], op.outputSlots[0], false /* we should avoid ReSyncSlot at this stage*/);
|
|
op.outputSlots[0].Link(inlineVector3.inputSlots[0], true /* notify here to correctly invalidate */);
|
|
op.GetParent().AddChild(inlineVector3);
|
|
}
|
|
|
|
public static void MigrateBlockPositionToComposed(VFXGraph graph, Vector2 position, PositionShape to, VFXBlock from, PositionShapeBase.Type shapeType)
|
|
{
|
|
var fromSettings = from.GetSettings(true);
|
|
var toSettings = to.GetSettings(true);
|
|
|
|
foreach (var fromSetting in fromSettings)
|
|
{
|
|
var toSetting = toSettings.FirstOrDefault(o =>
|
|
o.name.Equals(fromSetting.name, StringComparison.InvariantCultureIgnoreCase));
|
|
|
|
if (toSetting.field == null)
|
|
throw new InvalidOperationException("Unexpected migration, can't find approriate settings: " + fromSetting.name);
|
|
|
|
var fromValue = fromSetting.value;
|
|
to.SetSettingValue(toSetting.name, fromValue);
|
|
}
|
|
|
|
to.SetSettingValue("shape", shapeType);
|
|
VFXSlot.CopyLinksAndValue(to.activationSlot, from.activationSlot);
|
|
|
|
if (from.inputSlots.Count == to.inputSlots.Count)
|
|
{
|
|
// Special case for AABox as it is migrated to OBox with no rotation
|
|
int slotStartOffset = 0;
|
|
if (from.inputSlots[0].property.type == typeof(AABox) && shapeType == PositionShapeBase.Type.OrientedBox)
|
|
{
|
|
CopyLinksAndValueFromAABoxToOBox(to.inputSlots[0], from.inputSlots[0]);
|
|
slotStartOffset = 1;
|
|
}
|
|
|
|
for (int i = slotStartOffset; i < from.inputSlots.Count; ++i)
|
|
{
|
|
var fromInputSlot = from.inputSlots[i];
|
|
var toInputSlot = to.inputSlots.FirstOrDefault(o => o.name == fromInputSlot.name);
|
|
VFXSlot.CopyLinksAndValue(toInputSlot, fromInputSlot, true);
|
|
}
|
|
}
|
|
else // Add height sequencer
|
|
{
|
|
if (shapeType != PositionShapeBase.Type.Torus &&
|
|
shapeType != PositionShapeBase.Type.Sphere &&
|
|
shapeType != PositionShapeBase.Type.Cone)
|
|
throw new InvalidOperationException("Unexpected migration to " + shapeType);
|
|
|
|
if (to.spawnMode != PositionBase.SpawnMode.Custom)
|
|
throw new InvalidOperationException("Unexpected migration using spawn mode " + to.spawnMode);
|
|
|
|
//Copy Matching node by name
|
|
foreach (var fromInputSlot in from.inputSlots)
|
|
{
|
|
var toInputSlot = to.inputSlots.FirstOrDefault(o => o.name == fromInputSlot.name);
|
|
if (toInputSlot == null)
|
|
throw new InvalidOperationException("Unexpected migration, can't find slot named " + fromInputSlot.name);
|
|
|
|
VFXSlot.CopyLinksAndValue(toInputSlot, fromInputSlot, true);
|
|
}
|
|
|
|
var heightSlot = to.inputSlots.FirstOrDefault(o => o.name == "heightSequencer");
|
|
if (heightSlot == null)
|
|
throw new NullReferenceException();
|
|
|
|
var randomNode = ScriptableObject.CreateInstance<Operator.Random>();
|
|
randomNode.SetSettingValue("constant", false);
|
|
if (randomNode.inputSlots.Count != 2)
|
|
throw new InvalidOperationException("Unexpected migration, can't setup property random operator");
|
|
graph.AddChild(randomNode);
|
|
randomNode.position = position - new Vector2(120, 0);
|
|
|
|
if (!heightSlot.Link(randomNode.outputSlots[0]))
|
|
throw new InvalidOperationException("Unexpected migration, can't setup property random operator");
|
|
}
|
|
|
|
//Extra clean up, some blocks are migrated twice, avoid previous migration keeping unwanted references in m_SlotOwners
|
|
VFXModel.UnlinkModel(from);
|
|
}
|
|
|
|
public static void MigrateBlockCollisionShapeToComposed(CollisionShape to, VFXBlock from, CollisionShapeBase.Type shapeType)
|
|
{
|
|
var fromSettings = from.GetSettings(true);
|
|
var toSettings = to.GetSettings(true);
|
|
|
|
foreach (var fromSetting in fromSettings)
|
|
{
|
|
var toSetting = toSettings.FirstOrDefault(o =>
|
|
o.name.Equals(fromSetting.name, StringComparison.InvariantCultureIgnoreCase));
|
|
var fromValue = fromSetting.value;
|
|
to.SetSettingValue(toSetting.name, fromValue);
|
|
}
|
|
|
|
to.SetSettingValue("shape", shapeType);
|
|
|
|
// Special case for AABox as it is migrated to OBox with no rotation
|
|
int slotStartOffset = 0;
|
|
if (from.inputSlots[0].property.type == typeof(AABox) && shapeType == CollisionShapeBase.Type.OrientedBox)
|
|
{
|
|
CopyLinksAndValueFromAABoxToOBox(to.inputSlots[0], from.inputSlots[0]);
|
|
slotStartOffset = 1;
|
|
}
|
|
|
|
if (from.inputSlots.Count != to.inputSlots.Count)
|
|
throw new InvalidOperationException();
|
|
|
|
VFXSlot.CopyLinksAndValue(to.activationSlot, from.activationSlot);
|
|
for (int i = slotStartOffset; i < from.inputSlots.Count; ++i)
|
|
{
|
|
var fromInputSlot = from.inputSlots[i];
|
|
var toInputSlot = to.inputSlots.FirstOrDefault(o => o.name == fromInputSlot.name);
|
|
VFXSlot.CopyLinksAndValue(toInputSlot, fromInputSlot, true);
|
|
}
|
|
|
|
// Override bounce speed limit to 0 for sanitized block to avoid changes in behavior
|
|
if (to.behavior == CollisionBase.Behavior.Collision)
|
|
{
|
|
to.SetSettingValue(nameof(CollisionBase.overrideBounceThreshold), true);
|
|
var slot = to.inputSlots.First(s => s.name == nameof(CollisionBase.CollisionProperties.BounceSpeedThreshold));
|
|
slot.value = 0.0f;
|
|
}
|
|
|
|
//Extra clean up, some blocks are migrated twice, avoid previous migration keeping unwanted references in m_SlotOwners
|
|
VFXModel.UnlinkModel(from);
|
|
}
|
|
|
|
public static void MigrateBlockTShapeFromShape(VFXBlock to, VFXBlock from)
|
|
{
|
|
var fromSettings = from.GetSettings(true);
|
|
var toSettings = to.GetSettings(true);
|
|
|
|
foreach (var fromSetting in fromSettings)
|
|
{
|
|
var toSetting = toSettings.FirstOrDefault(o => o.name.Equals(fromSetting.name, StringComparison.InvariantCultureIgnoreCase));
|
|
if (toSetting.field != null)
|
|
to.SetSettingValue(toSetting.name, fromSetting.value);
|
|
}
|
|
|
|
if (from.inputSlots.Count != to.inputSlots.Count)
|
|
throw new InvalidOperationException();
|
|
|
|
for (int i = 0; i < from.inputSlots.Count; ++i)
|
|
{
|
|
var fromInputSlot = from.inputSlots[i];
|
|
var toInputSlot = to.inputSlots[i];
|
|
|
|
if (toInputSlot.property.type == fromInputSlot.property.type)
|
|
{
|
|
VFXSlot.CopyLinksAndValue(toInputSlot, fromInputSlot, true);
|
|
}
|
|
else if (toInputSlot.property.type == typeof(TArcSphere))
|
|
{
|
|
MigrateTArcSphereFromArcSphere(toInputSlot, fromInputSlot);
|
|
}
|
|
else if (toInputSlot.property.type == typeof(TArcCircle))
|
|
{
|
|
MigrateTArcCircleFromArcCircle(toInputSlot, fromInputSlot);
|
|
}
|
|
else if (toInputSlot.property.type == typeof(TArcTorus))
|
|
{
|
|
MigrateTArcTorusFromArcTorus(toInputSlot, fromInputSlot);
|
|
}
|
|
else if (toInputSlot.property.type == typeof(TArcCone))
|
|
{
|
|
//There wasn't a TArcCylinder type
|
|
MigrateTArcConeFromArcCone(toInputSlot, fromInputSlot);
|
|
}
|
|
else if (toInputSlot.property.type == typeof(TSphere))
|
|
{
|
|
MigrateTSphereFromSphere(toInputSlot, fromInputSlot);
|
|
}
|
|
else if (toInputSlot.property.type == typeof(TCircle))
|
|
{
|
|
MigrateTCircleFromCircle(toInputSlot, fromInputSlot);
|
|
}
|
|
else if (toInputSlot.property.type == typeof(TTorus))
|
|
{
|
|
MigrateTTorusFromTorus(toInputSlot, fromInputSlot);
|
|
}
|
|
else if (toInputSlot.property.type == typeof(TCone) && fromInputSlot.property.type == typeof(Cone))
|
|
{
|
|
//Actually, no reference of this case
|
|
MigrateTConeFromCone(toInputSlot, fromInputSlot);
|
|
}
|
|
else if (toInputSlot.property.type == typeof(TCone) && fromInputSlot.property.type == typeof(Cylinder))
|
|
{
|
|
MigrateTConeFromCylinder(toInputSlot, fromInputSlot);
|
|
}
|
|
else
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void MigrateTArcSphereFromArcSphere(VFXSlot to, VFXSlot from)
|
|
{
|
|
var to_sphere = to[0];
|
|
var to_arc = to[1];
|
|
|
|
var refSlot = from.refSlot;
|
|
var from_sphere = refSlot[0];
|
|
var from_arc = refSlot[1];
|
|
VFXSlot.CopySpace(to, refSlot, true);
|
|
|
|
var hasDirectLink = from.HasLink(false);
|
|
MigrateTSphereFromSphere(to_sphere, from_sphere, hasDirectLink);
|
|
if (hasDirectLink)
|
|
{
|
|
to_arc.Link(from_arc, true);
|
|
}
|
|
else
|
|
{
|
|
to_arc.value = (float)from_arc.value; //The value transfer is only applied on masterslot
|
|
VFXSlot.CopyLinksAndValue(to_arc, from_arc, true);
|
|
}
|
|
}
|
|
|
|
public static void MigrateTSphereFromSphere(VFXSlot to, VFXSlot from, bool forceHasLink = false)
|
|
{
|
|
var to_center = to[0][0];
|
|
var to_radius = to[1];
|
|
|
|
var refSlot = from.refSlot;
|
|
VFXSlot.CopySpace(to, refSlot, true);
|
|
if (from.HasLink(false) || forceHasLink)
|
|
{
|
|
//TODO : This behavior leads to an UX issue with if the parent owner of refslot is VFXParameter
|
|
//This is the same issue than OnCopyLinksMySlot/OnCopyLinksOtherSlot needed in VFXSlot.CopyLinks
|
|
var parentCenter = refSlot[0];
|
|
var parentRadius = refSlot[1];
|
|
|
|
to_center.Link(parentCenter, true);
|
|
to_radius.Link(parentRadius, true);
|
|
}
|
|
else
|
|
{
|
|
var center = from[0];
|
|
var radius = from[1];
|
|
|
|
var value = new TSphere()
|
|
{
|
|
transform = new Transform()
|
|
{
|
|
position = (Vector3)center.value,
|
|
scale = Vector3.one
|
|
},
|
|
radius = (float)radius.value
|
|
};
|
|
|
|
to.value = value;
|
|
VFXSlot.CopyLinksAndValue(to_center, center, true);
|
|
VFXSlot.CopyLinksAndValue(to_radius, radius, true);
|
|
}
|
|
}
|
|
|
|
public static void MigrateTArcCircleFromArcCircle(VFXSlot to, VFXSlot from)
|
|
{
|
|
var to_circle = to[0];
|
|
var to_arc = to[1];
|
|
|
|
var refSlot = from.refSlot;
|
|
var from_circle = refSlot[0];
|
|
var from_arc = refSlot[1];
|
|
VFXSlot.CopySpace(to, refSlot, true);
|
|
|
|
var hasDirectLink = from.HasLink(false);
|
|
MigrateTCircleFromCircle(to_circle, from_circle, hasDirectLink);
|
|
if (hasDirectLink)
|
|
{
|
|
to_arc.Link(from_arc, true);
|
|
}
|
|
else
|
|
{
|
|
to_arc.value = (float)from_arc.value; //The value transfer is only applied on masterslot
|
|
VFXSlot.CopyLinksAndValue(to_arc, from_arc, true);
|
|
}
|
|
}
|
|
|
|
public static void MigrateTCircleFromCircle(VFXSlot to, VFXSlot from, bool forceHasLink = false)
|
|
{
|
|
var to_center = to[0][0];
|
|
var to_radius = to[1];
|
|
|
|
var refslot = from.refSlot;
|
|
VFXSlot.CopySpace(to, refslot, true);
|
|
|
|
if (from.HasLink(false) || forceHasLink)
|
|
{
|
|
var parentCenter = refslot[0];
|
|
var parentRadius = refslot[1];
|
|
|
|
to_center.Link(parentCenter, true);
|
|
to_radius.Link(parentRadius, true);
|
|
}
|
|
else
|
|
{
|
|
var center = from[0];
|
|
var radius = from[1];
|
|
|
|
var value = new TCircle()
|
|
{
|
|
transform = new Transform()
|
|
{
|
|
position = (Vector3)center.value,
|
|
scale = Vector3.one
|
|
},
|
|
radius = (float)radius.value
|
|
};
|
|
to.value = value;
|
|
VFXSlot.CopyLinksAndValue(to_center, center, true);
|
|
VFXSlot.CopyLinksAndValue(to_radius, radius, true);
|
|
}
|
|
}
|
|
|
|
public static void MigrateTArcTorusFromArcTorus(VFXSlot to, VFXSlot from)
|
|
{
|
|
var to_torus = to[0];
|
|
var to_arc = to[1];
|
|
|
|
var refSlot = from.refSlot;
|
|
var from_torus = refSlot; //The torus wasn't a composition
|
|
var from_arc = refSlot[3];
|
|
VFXSlot.CopySpace(to, refSlot, true);
|
|
|
|
var hasDirectLink = from.HasLink(false);
|
|
MigrateTTorusFromTorus(to_torus, from_torus, hasDirectLink);
|
|
if (hasDirectLink)
|
|
{
|
|
to_arc.Link(from_arc, true);
|
|
}
|
|
else
|
|
{
|
|
to_arc.value = (float)from_arc.value; //The value transfer is only applied on masterslot
|
|
VFXSlot.CopyLinksAndValue(to_arc, from_arc, true);
|
|
}
|
|
}
|
|
|
|
public static void MigrateTTorusFromTorus(VFXSlot to, VFXSlot from, bool hasLink = false)
|
|
{
|
|
var to_center = to[0][0];
|
|
var to_majorRadius = to[1];
|
|
var to_minorRadius = to[2];
|
|
var refSlot = from.refSlot;
|
|
VFXSlot.CopySpace(to, refSlot, true);
|
|
|
|
if (from.HasLink(false) || hasLink)
|
|
{
|
|
var parentCenter = refSlot[0];
|
|
var parentMajorRadius = refSlot[1];
|
|
var parentMinorRadius = refSlot[2];
|
|
|
|
to_center.Link(parentCenter, true);
|
|
to_majorRadius.Link(parentMajorRadius, true);
|
|
to_minorRadius.Link(parentMinorRadius, true);
|
|
}
|
|
else
|
|
{
|
|
var center = from[0];
|
|
var majorRadius = from[1];
|
|
var minorRadius = from[2];
|
|
|
|
var value = new TTorus()
|
|
{
|
|
transform = new Transform()
|
|
{
|
|
position = (Vector3)center.value,
|
|
scale = Vector3.one
|
|
},
|
|
|
|
majorRadius = (float)majorRadius.value,
|
|
minorRadius = (float)minorRadius.value
|
|
};
|
|
|
|
to.value = value;
|
|
VFXSlot.CopyLinksAndValue(to_center, center, true);
|
|
VFXSlot.CopyLinksAndValue(to_majorRadius, majorRadius, true);
|
|
VFXSlot.CopyLinksAndValue(to_minorRadius, minorRadius, true);
|
|
}
|
|
}
|
|
|
|
public static void MigrateTArcConeFromArcCone(VFXSlot to, VFXSlot from)
|
|
{
|
|
var to_cone = to[0];
|
|
var to_arc = to[1];
|
|
|
|
var refSlot = from.refSlot;
|
|
var from_cone = refSlot; //The ArcCone wasn't a composition
|
|
var from_arc = refSlot[4];
|
|
VFXSlot.CopySpace(to, refSlot, true);
|
|
|
|
var hasDirectLink = from.HasLink(false);
|
|
MigrateTConeFromCone(to_cone, from_cone, hasDirectLink);
|
|
if (hasDirectLink)
|
|
{
|
|
to_arc.Link(from_arc, true);
|
|
}
|
|
else
|
|
{
|
|
to_arc.value = (float)from_arc.value; //The value transfer is only applied on masterslot
|
|
VFXSlot.CopyLinksAndValue(to_arc, from_arc, true);
|
|
}
|
|
}
|
|
|
|
public static void MigrateTConeFromCone(VFXSlot to, VFXSlot from, bool hasLink = false)
|
|
{
|
|
var to_center = to[0][0];
|
|
var to_baseRadius = to[1];
|
|
var to_topRadius = to[2];
|
|
var to_height = to[3];
|
|
|
|
var refSlot = from.refSlot;
|
|
VFXSlot.CopySpace(to, refSlot, true);
|
|
|
|
if (from.HasLink(false) || hasLink)
|
|
{
|
|
var parentCenter = refSlot[0];
|
|
var parentBaseRadius = refSlot[1];
|
|
var parentTopRadius = refSlot[2];
|
|
var parentHeight = refSlot[3];
|
|
|
|
to_center.Link(parentCenter, true);
|
|
to_baseRadius.Link(parentBaseRadius, true);
|
|
to_topRadius.Link(parentTopRadius, true);
|
|
to_height.Link(parentHeight, true);
|
|
}
|
|
else
|
|
{
|
|
var center = from[0];
|
|
var baseRadius = from[1];
|
|
var topRadius = from[2];
|
|
var height = from[3];
|
|
|
|
var value = new TCone()
|
|
{
|
|
transform = new Transform()
|
|
{
|
|
position = (Vector3)center.value,
|
|
scale = Vector3.one
|
|
},
|
|
|
|
baseRadius = (float)baseRadius.value,
|
|
topRadius = (float)topRadius.value,
|
|
height = (float)height.value
|
|
};
|
|
|
|
to.value = value;
|
|
VFXSlot.CopyLinksAndValue(to_center, center, true);
|
|
VFXSlot.CopyLinksAndValue(to_baseRadius, baseRadius, true);
|
|
VFXSlot.CopyLinksAndValue(to_topRadius, topRadius, true);
|
|
VFXSlot.CopyLinksAndValue(to_height, height, true);
|
|
}
|
|
}
|
|
|
|
private static VFXSlot CorrectPositionFromCylinderToCone(VFXGraph graph, Vector2 basePosition, VFXSlot height, VFXSlot center)
|
|
{
|
|
var inlineHeight = ScriptableObject.CreateInstance<VFXInlineOperator>();
|
|
inlineHeight.SetSettingValue("m_Type", (SerializableType)typeof(float));
|
|
inlineHeight.position = basePosition - new Vector2(700.0f, -151.0f);
|
|
VFXSlot.CopyLinksAndValue(inlineHeight.inputSlots[0], height, true);
|
|
graph.AddChild(inlineHeight);
|
|
|
|
var halfHeight = ScriptableObject.CreateInstance<Operator.Multiply>();
|
|
halfHeight.SetOperandType(0, typeof(float));
|
|
halfHeight.SetOperandType(1, typeof(float));
|
|
halfHeight.inputSlots[0].Link(inlineHeight.outputSlots[0]);
|
|
halfHeight.inputSlots[1].value = 0.5f;
|
|
halfHeight.position = basePosition - new Vector2(480.0f, -111.0f);
|
|
graph.AddChild(halfHeight);
|
|
|
|
var inlinePosition = ScriptableObject.CreateInstance<VFXInlineOperator>();
|
|
inlinePosition.SetSettingValue("m_Type", (SerializableType)typeof(Position));
|
|
inlinePosition.position = basePosition - new Vector2(555.0f, -20.0f);
|
|
VFXSlot.CopyLinksAndValue(inlinePosition.inputSlots[0], center, true);
|
|
graph.AddChild(inlinePosition);
|
|
|
|
var correctedPosition = ScriptableObject.CreateInstance<Operator.Subtract>();
|
|
correctedPosition.SetOperandType(0, typeof(Position));
|
|
correctedPosition.SetOperandType(1, typeof(Position));
|
|
VFXSlot.CopySpace(correctedPosition.inputSlots[0], inlinePosition.outputSlots[0], true);
|
|
VFXSlot.CopySpace(correctedPosition.inputSlots[1], inlinePosition.outputSlots[0], true);
|
|
correctedPosition.inputSlots[0].Link(inlinePosition.outputSlots[0]);
|
|
correctedPosition.inputSlots[1][0][1].Link(halfHeight.outputSlots[0]);
|
|
correctedPosition.position = basePosition - new Vector2(282.0f, -20.0f);
|
|
graph.AddChild(correctedPosition);
|
|
|
|
return correctedPosition.outputSlots[0];
|
|
}
|
|
|
|
public static void MigrateTConeFromCylinder(VFXSlot to, VFXSlot from)
|
|
{
|
|
var lastModel = from.owner as VFXModel;
|
|
while (!(lastModel.GetParent() is VFXGraph))
|
|
{
|
|
lastModel = lastModel.GetParent();
|
|
}
|
|
var basePosition = lastModel.position;
|
|
var graph = lastModel.GetParent() as VFXGraph;
|
|
|
|
var to_center = to[0][0];
|
|
var to_baseRadius = to[1];
|
|
var to_topRadius = to[2];
|
|
var to_height = to[3];
|
|
|
|
var refSlot = from.refSlot;
|
|
VFXSlot.CopySpace(to, refSlot, true);
|
|
|
|
if (from.HasLink(false))
|
|
{
|
|
var parentCenter = refSlot[0];
|
|
var parentRadius = refSlot[1];
|
|
var parentHeight = refSlot[2];
|
|
|
|
var correctedPosition = CorrectPositionFromCylinderToCone(graph, basePosition, parentHeight, parentCenter);
|
|
correctedPosition.Link(to_center);
|
|
|
|
to_baseRadius.Link(parentRadius, true);
|
|
to_topRadius.Link(parentRadius, true);
|
|
to_height.Link(parentHeight, true);
|
|
}
|
|
else
|
|
{
|
|
var center = from[0];
|
|
var radius = from[1];
|
|
var height = from[2];
|
|
|
|
var value = new TCone()
|
|
{
|
|
transform = new Transform()
|
|
{
|
|
position = (Vector3)center.value - new Vector3(0, (float)height.value * 0.5f, 0),
|
|
scale = Vector3.one
|
|
},
|
|
height = (float)height.value,
|
|
baseRadius = (float)radius.value,
|
|
topRadius = (float)radius.value,
|
|
};
|
|
to.value = value;
|
|
|
|
if (from.HasLink(true))
|
|
{
|
|
var correctedPosition = CorrectPositionFromCylinderToCone(graph, basePosition, height, center);
|
|
correctedPosition.Link(to_center);
|
|
}
|
|
|
|
VFXSlot.CopyLinksAndValue(to_baseRadius, radius, true);
|
|
VFXSlot.CopyLinksAndValue(to_topRadius, radius, true);
|
|
VFXSlot.CopyLinksAndValue(to_height, height, true);
|
|
}
|
|
}
|
|
|
|
[Flags]
|
|
enum SampleMesh_VertexAttributeFlag_Before_Version_9
|
|
{
|
|
None = 0,
|
|
Position = 1 << 0,
|
|
Normal = 1 << 1,
|
|
Tangent = 1 << 2,
|
|
Color = 1 << 3,
|
|
TexCoord0 = 1 << 4,
|
|
TexCoord1 = 1 << 5,
|
|
TexCoord2 = 1 << 6,
|
|
TexCoord3 = 1 << 7,
|
|
TexCoord4 = 1 << 8,
|
|
TexCoord5 = 1 << 9,
|
|
TexCoord6 = 1 << 10,
|
|
TexCoord7 = 1 << 11,
|
|
BlendWeight = 1 << 12,
|
|
BlendIndices = 1 << 13,
|
|
}
|
|
|
|
public static void MigrateSampleMeshFrom9To10(Operator.SampleMesh op)
|
|
{
|
|
Debug.Log("Sanitize Graph: Sample Mesh & Skinned Mesh");
|
|
|
|
//Starting copying everything to a new instance
|
|
var newSampleMesh = ScriptableObject.CreateInstance<Operator.SampleMesh>();
|
|
var settings = op.GetSettings(true);
|
|
newSampleMesh.SetSettingValues(settings.Select(o => new KeyValuePair<string, object>(o.name, o.value)));
|
|
|
|
//Migrate newly added settings, SkinnedTransform.None to keep the previous behavior
|
|
newSampleMesh.SetSettingValue(nameof(Operator.SampleMesh.skinnedTransform), Operator.SampleMesh.SkinnedRootTransform.None);
|
|
|
|
var vertexOutputName = "output";
|
|
|
|
//Start with empty output, will migrate output slot one by one
|
|
var currentFlag = Operator.SampleMesh.VertexAttributeFlag.None;
|
|
newSampleMesh.SetSettingValue(vertexOutputName, currentFlag);
|
|
|
|
//Skip newly added transform slot
|
|
var toInputSlots = newSampleMesh.inputSlots.Take(newSampleMesh.inputSlots.Count - 1).ToList();
|
|
var fromInputSlots = op.inputSlots;
|
|
|
|
if (fromInputSlots.Count != toInputSlots.Count)
|
|
throw new InvalidOperationException();
|
|
|
|
for (int i = 0; i < fromInputSlots.Count; ++i)
|
|
{
|
|
var fromInputSlot = fromInputSlots[i];
|
|
var toInputSlot = toInputSlots[i];
|
|
VFXSlot.CopyLinksAndValue(toInputSlot, fromInputSlot, true);
|
|
}
|
|
|
|
var previousFlag = (SampleMesh_VertexAttributeFlag_Before_Version_9)op.GetSettingValue(vertexOutputName);
|
|
var oldVertexAttributes = Enum.GetValues(typeof(SampleMesh_VertexAttributeFlag_Before_Version_9))
|
|
.Cast<SampleMesh_VertexAttributeFlag_Before_Version_9>()
|
|
.Where(o => previousFlag.HasFlag(o) && o != SampleMesh_VertexAttributeFlag_Before_Version_9.None)
|
|
.ToArray();
|
|
|
|
foreach (var oldVertexAttribute in oldVertexAttributes)
|
|
{
|
|
if (oldVertexAttribute == SampleMesh_VertexAttributeFlag_Before_Version_9.Tangent)
|
|
{
|
|
//Special case: The old tangent as vector4 as been split in Vector & independent float
|
|
currentFlag = currentFlag | Operator.SampleMesh.VertexAttributeFlag.Tangent | Operator.SampleMesh.VertexAttributeFlag.BitangentSign;
|
|
}
|
|
else
|
|
{
|
|
var name = Enum.GetName(typeof(SampleMesh_VertexAttributeFlag_Before_Version_9), oldVertexAttribute);
|
|
if (!Enum.TryParse<Operator.SampleMesh.VertexAttributeFlag>(name, out var newVertexAttribute))
|
|
throw new InvalidOperationException();
|
|
|
|
currentFlag = currentFlag | newVertexAttribute;
|
|
}
|
|
}
|
|
newSampleMesh.SetSettingValue(vertexOutputName, currentFlag);
|
|
|
|
foreach (var oldVertexAttribute in oldVertexAttributes)
|
|
{
|
|
var name = Enum.GetName(typeof(SampleMesh_VertexAttributeFlag_Before_Version_9), oldVertexAttribute);
|
|
var fromOutputSlot = op.outputSlots.FirstOrDefault(o => o.name == name);
|
|
var toOutputSlot = newSampleMesh.outputSlots.FirstOrDefault(o => o.name == ObjectNames.NicifyVariableName(name));
|
|
if (fromOutputSlot == null || toOutputSlot == null)
|
|
throw new InvalidOperationException();
|
|
|
|
var invalidate = false; //calling invalidate at the end, prevent event propagation
|
|
if (fromOutputSlot.property.type == toOutputSlot.property.type)
|
|
{
|
|
VFXSlot.CopyLinks(toOutputSlot, fromOutputSlot, invalidate);
|
|
}
|
|
else
|
|
{
|
|
if (oldVertexAttribute == SampleMesh_VertexAttributeFlag_Before_Version_9.Position || oldVertexAttribute == SampleMesh_VertexAttributeFlag_Before_Version_9.Normal)
|
|
{
|
|
//Converting back to not spaceable Vector3 output
|
|
var newVector3 = ScriptableObject.CreateInstance<VFXInlineOperator>();
|
|
newVector3.SetSettingValue("m_Type", (SerializableType)typeof(Vector3));
|
|
toOutputSlot.Link(newVector3.inputSlots[0]);
|
|
newVector3.position = op.position + new Vector2(100, 0);
|
|
VFXSlot.CopyLinks(newVector3.outputSlots[0], fromOutputSlot, invalidate);
|
|
op.GetParent().AddChild(newVector3);
|
|
}
|
|
else if (oldVertexAttribute == SampleMesh_VertexAttributeFlag_Before_Version_9.Tangent)
|
|
{
|
|
var tangent = toOutputSlot;
|
|
var bitangentSign = newSampleMesh.outputSlots.FirstOrDefault(o => o.name == ObjectNames.NicifyVariableName(Operator.SampleMesh.VertexAttributeFlag.BitangentSign.ToString()));
|
|
if (bitangentSign == null)
|
|
throw new InvalidOperationException();
|
|
|
|
var newVector4 = ScriptableObject.CreateInstance<VFXInlineOperator>();
|
|
newVector4.SetSettingValue("m_Type", (SerializableType)typeof(Vector4));
|
|
newVector4.inputSlots[0][0].Link(tangent[0][0]);
|
|
newVector4.inputSlots[0][1].Link(tangent[0][1]);
|
|
newVector4.inputSlots[0][2].Link(tangent[0][2]);
|
|
newVector4.inputSlots[0][3].Link(bitangentSign);
|
|
newVector4.position = op.position + new Vector2(110, 0);
|
|
VFXSlot.CopyLinks(newVector4.outputSlots[0], fromOutputSlot, invalidate);
|
|
op.GetParent().AddChild(newVector4);
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
}
|
|
}
|
|
|
|
newSampleMesh.Invalidate(VFXModel.InvalidationCause.kConnectionChanged);
|
|
VFXModel.ReplaceModel(newSampleMesh, op);
|
|
}
|
|
|
|
public static void CopyLinksAndValueFromAABoxToOBox(VFXSlot to, VFXSlot from)
|
|
{
|
|
if (from.property.type != typeof(AABox) || to.property.type != typeof(OrientedBox))
|
|
throw new ArgumentException("Slots are not of the expected type");
|
|
|
|
if (from.direction != VFXSlot.Direction.kInput || to.direction != VFXSlot.Direction.kInput)
|
|
throw new ArgumentException("Slots are not input slots");
|
|
|
|
to.UnlinkAll(true);
|
|
|
|
// First copy value and space
|
|
var aab = (AABox)from.value;
|
|
var ob = new OrientedBox
|
|
{
|
|
center = aab.center,
|
|
angles = Vector3.zero,
|
|
size = aab.size,
|
|
};
|
|
to.value = ob;
|
|
|
|
VFXSlot.CopyLinks(to, from, true); // Will work as sub-slots names match
|
|
VFXSlot.CopySpace(to, from, true);
|
|
}
|
|
}
|
|
}
|