Files
2025-06-09 23:23:13 +08:00

107 lines
3.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace JBooth.MicroVerseCore
{
public class BendRules : MonoBehaviour
{
public enum Mode
{
None = -1,
Bend = 0,
Place,
PlaceRotate,
PlaceRotateNoSlope,
}
[Tooltip("How should objects be affected by the spline\n" +
" (Bend) Bend vertices to follow the spline\n" +
" (PlaceRotate) Follow spline facing\n" +
" (PlaceRotateNoSlope) Do not follow virtical slope\n"
)]
public Mode mode = Mode.Bend;
public enum CapMode
{
Always,
BeginOnly,
Along,
EndOnly
}
public enum CullMode
{
Cull,
Clamp,
Overflow
}
[System.Serializable]
public class SpawnRules
{
[Range(0, 1)]
[Tooltip("Chance that this object appears")]
public float chance = 1.0f;
[Tooltip("Should this object only appear at the begining or end of the spline, or all along it?")]
public CapMode capMode = CapMode.Always;
[Tooltip("How much of the segment needs to be left to place the end object")]
[Range(0, 1.5f)] public float requiredLeft = 0.25f;
[Tooltip("Should the object be culled when out of the range of the segment? Or clamped to the edge? Or allowed to flow over the edge?")]
public CullMode cullingMode = CullMode.Cull;
}
[System.Serializable]
public class PlaceRules
{
public Vector3 positionVariance = Vector3.zero;
[Tooltip("Random Rotation applied to any axis")]
public Vector3 rotationVariance = Vector3.zero;
[Tooltip("Random Scale applied to any axis. Beware when using with colliders!")]
public Vector3 scaleVariant = Vector3.zero;
[Tooltip("Use X scale as Uniform Scale")]
public bool scaleUniform = false;
}
public SpawnRules spawnRules = new SpawnRules();
public PlaceRules placeRules = new PlaceRules();
public static CapMode GetDesiredCapMode(float remainingLength, float meshLength, float totalLength)
{
if (remainingLength == totalLength)
{
return CapMode.BeginOnly;
}
else if (meshLength > remainingLength)
{
return CapMode.EndOnly;
}
return CapMode.Along;
}
public static bool ShouldSpawn(BendRules rules, float curLength, float meshLength, float totalLength, Unity.Mathematics.Random rand)
{
if (rules == null) return true;
if (rand.NextFloat(1.0f) > rules.spawnRules.chance)
return false;
if (rules.spawnRules.capMode != CapMode.Always)
{
var capMode = BendRules.GetDesiredCapMode(curLength, meshLength, totalLength);
if (capMode != rules.spawnRules.capMode)
{
return false;
}
else if (rules.spawnRules.capMode == CapMode.EndOnly)
{
float left = curLength / meshLength;
if (left < rules.spawnRules.requiredLeft)
{
return false;
}
}
}
return true;
}
}
}