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.
279 lines
9.7 KiB
279 lines
9.7 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.VFX;
|
|
|
|
namespace UnityEditor.VFX
|
|
{
|
|
enum VFXSeedMode
|
|
{
|
|
PerParticle,
|
|
PerVFXComponent,
|
|
PerParticleStrip,
|
|
}
|
|
}
|
|
|
|
namespace UnityEditor.VFX.Operator
|
|
{
|
|
class RandomProvider : VariantProvider
|
|
{
|
|
readonly Type[] m_SupportedType;
|
|
|
|
public RandomProvider() : this(false) { }
|
|
|
|
public RandomProvider(bool subVariant)
|
|
{
|
|
if (subVariant)
|
|
{
|
|
m_SupportedType = new[]
|
|
{
|
|
typeof(Vector2),
|
|
typeof(Vector4),
|
|
typeof(Color),
|
|
typeof(uint),
|
|
typeof(bool)
|
|
};
|
|
}
|
|
else
|
|
{
|
|
m_SupportedType = new[]
|
|
{
|
|
typeof(float),
|
|
typeof(Vector3),
|
|
typeof(int)
|
|
};
|
|
}
|
|
}
|
|
|
|
public override IEnumerable<Variant> GetVariants()
|
|
{
|
|
foreach (var type in m_SupportedType)
|
|
{
|
|
yield return new Variant(
|
|
$"Random {((Type)type).UserFriendlyName()}",
|
|
"Random",
|
|
typeof(Random),
|
|
new[]
|
|
{
|
|
new KeyValuePair<string, object>("m_Type", (SerializableType)type)
|
|
}, type == typeof(float) ? () => new RandomProvider(true) : null);
|
|
}
|
|
}
|
|
}
|
|
|
|
[VFXHelpURL("Operator-RandomNumber")]
|
|
[VFXInfo(synonyms = new[] { "Probability", "Aleatory" }, variantProvider = typeof(RandomProvider))]
|
|
sealed class Random : VFXOperatorDynamicType
|
|
{
|
|
public static readonly Type[] kSupportedTypes = new[]
|
|
{
|
|
typeof(float),
|
|
typeof(Vector2),
|
|
typeof(Vector3),
|
|
typeof(Vector4),
|
|
typeof(Color),
|
|
typeof(uint),
|
|
typeof(int),
|
|
typeof(bool)
|
|
};
|
|
|
|
[VFXSetting, Tooltip("Specifies whether the random number is generated for each particle, each particle strip, or is shared by the whole system.")]
|
|
public VFXSeedMode seed = VFXSeedMode.PerParticle;
|
|
[VFXSetting, Tooltip("When enabled, the random number will remain constant. Otherwise, it will change every time it is evaluated.")]
|
|
public bool constant = true;
|
|
|
|
[VFXSetting(VFXSettingAttribute.VisibleFlags.InInspector), Tooltip("When enabled, you can customize Seed per channel, otherwise Seed is randomly generated for each channel.")]
|
|
public bool independentSeed = false;
|
|
|
|
public override string name => $"Random {((Type)m_Type).UserFriendlyName()}";
|
|
|
|
public override IEnumerable<Type> validTypes => kSupportedTypes;
|
|
|
|
protected override Type defaultValueType => typeof(float);
|
|
|
|
public override IEnumerable<int> staticSlotIndex
|
|
{
|
|
get
|
|
{
|
|
yield return 2;
|
|
yield return 3;
|
|
yield return 4;
|
|
yield return 5;
|
|
}
|
|
}
|
|
|
|
protected override IEnumerable<VFXPropertyWithValue> inputProperties
|
|
{
|
|
get
|
|
{
|
|
var type = (Type)m_Type;
|
|
object min, max;
|
|
if (type == typeof(float))
|
|
{
|
|
min = 0.0f;
|
|
max = 1.0f;
|
|
}
|
|
else if (type == typeof(Vector2))
|
|
{
|
|
min = Vector2.zero;
|
|
max = Vector2.one;
|
|
}
|
|
else if (type == typeof(Vector3))
|
|
{
|
|
min = Vector3.zero;
|
|
max = Vector3.one;
|
|
}
|
|
else if (type == typeof(Vector4))
|
|
{
|
|
min = Vector4.zero;
|
|
max = Vector4.one;
|
|
}
|
|
else if (type == typeof(Color))
|
|
{
|
|
min = Color.clear;
|
|
max = Color.white;
|
|
}
|
|
else if (type == typeof(uint))
|
|
{
|
|
min = 0u;
|
|
max = 6u;
|
|
}
|
|
else if (type == typeof(int))
|
|
{
|
|
min = 0;
|
|
max = 6;
|
|
}
|
|
else if (type == typeof(bool))
|
|
{
|
|
min = max = null;
|
|
}
|
|
else
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
if (min != null)
|
|
yield return new VFXPropertyWithValue(new VFXProperty(type, "Min", new TooltipAttribute("Sets the minimum range of the random value.")), min);
|
|
|
|
if (max != null)
|
|
yield return new VFXPropertyWithValue(new VFXProperty(type, "Max", new TooltipAttribute("Sets the maximum range of the random value.")), max);
|
|
|
|
if (constant || seed == VFXSeedMode.PerParticleStrip)
|
|
{
|
|
var randomCount = VFXExpression.TypeToSize(VFXExpression.GetVFXValueTypeFromType(m_Type));
|
|
if (!independentSeed || randomCount == 1)
|
|
yield return new VFXPropertyWithValue(new VFXProperty(typeof(uint), "seed", new TooltipAttribute("Specifies a seed that the Operator uses to generate random values.")), 0u);
|
|
else
|
|
{
|
|
var channelName = new[] { 'X', 'Y', 'Z', 'W' };
|
|
for (uint randIndex = 0u; randIndex < randomCount; ++randIndex)
|
|
{
|
|
yield return new VFXPropertyWithValue(new VFXProperty(typeof(uint), "seed" + channelName[randIndex], new TooltipAttribute("Specifies a seed that the Operator uses to generate random values.")), randIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override IEnumerable<VFXPropertyWithValue> outputProperties
|
|
{
|
|
get
|
|
{
|
|
yield return new VFXPropertyWithValue(new VFXProperty(m_Type, "r", new TooltipAttribute("Outputs a random number between the min and max range.")));
|
|
}
|
|
}
|
|
|
|
protected override IEnumerable<string> filteredOutSettings
|
|
{
|
|
get
|
|
{
|
|
foreach (var s in base.filteredOutSettings)
|
|
yield return s;
|
|
|
|
var valueType = VFXExpression.GetVFXValueTypeFromType(m_Type);
|
|
var randomCount = VFXExpression.TypeToSize(valueType);
|
|
|
|
if (seed == VFXSeedMode.PerParticleStrip)
|
|
yield return nameof(constant);
|
|
else if (!constant || randomCount == 1)
|
|
yield return nameof(independentSeed);
|
|
}
|
|
}
|
|
|
|
protected override VFXExpression[] BuildExpression(VFXExpression[] inputExpression)
|
|
{
|
|
var valueType = VFXExpression.GetVFXValueTypeFromType(m_Type);
|
|
var randomCount = VFXExpression.TypeToSize(valueType);
|
|
|
|
var rands = new VFXExpression[randomCount];
|
|
|
|
var startSeedIndex = valueType == VFXValueType.Boolean ? 0 : 2;
|
|
var currentSeed = inputExpression.Length > startSeedIndex ? inputExpression[startSeedIndex] : null;
|
|
|
|
for (int randIndex = 0; randIndex < randomCount; ++randIndex)
|
|
{
|
|
rands[randIndex] = VFXOperatorUtility.BuildRandom(seed, constant, new RandId(this, randIndex), currentSeed);
|
|
|
|
if (currentSeed != null && randIndex != randomCount - 1)
|
|
{
|
|
startSeedIndex++;
|
|
if (inputExpression.Length > startSeedIndex)
|
|
{
|
|
currentSeed = inputExpression[startSeedIndex];
|
|
}
|
|
else
|
|
{
|
|
//Fallback for single seed mode
|
|
currentSeed = new VFXExpressionMul(currentSeed, VFXValue.Constant<uint>(214013));
|
|
currentSeed = new VFXExpressionAdd(currentSeed, VFXValue.Constant<uint>(2531011));
|
|
}
|
|
}
|
|
}
|
|
|
|
VFXExpression rand;
|
|
if (randomCount == 1)
|
|
{
|
|
rand = rands[0];
|
|
}
|
|
else
|
|
{
|
|
rand = new VFXExpressionCombine(rands);
|
|
}
|
|
|
|
if (valueType == VFXValueType.Boolean)
|
|
{
|
|
VFXExpression cond = new VFXExpressionCondition(VFXValueType.Float, VFXCondition.Greater, rand, VFXOperatorUtility.HalfExpression[VFXValueType.Float]);
|
|
return new[] { cond };
|
|
}
|
|
|
|
var min = inputExpression[0];
|
|
var max = inputExpression[1];
|
|
|
|
if (min.valueType != max.valueType)
|
|
throw new InvalidOperationException();
|
|
|
|
if (valueType == VFXValueType.Uint32)
|
|
{
|
|
var range = max - min;
|
|
range = new VFXExpressionCastUintToFloat(range);
|
|
var randUint = new VFXExpressionCastFloatToUint(range * rand);
|
|
return new[] { min + randUint };
|
|
}
|
|
|
|
if (valueType == VFXValueType.Int32)
|
|
{
|
|
var range = max - min;
|
|
range = new VFXExpressionCastIntToFloat(range);
|
|
var randInt = new VFXExpressionCastFloatToInt(range * rand);
|
|
return new[] { min + randInt };
|
|
}
|
|
|
|
if (VFXExpression.IsFloatValueType(valueType))
|
|
{
|
|
return new[] { VFXOperatorUtility.Lerp(min, max, rand) };
|
|
}
|
|
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|