Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
1.0.6
Browse files Browse the repository at this point in the history
- Add optional random spacing and lateral offset functions.
  • Loading branch information
algernon-A committed Dec 4, 2023
1 parent a4ae816 commit 71d175a
Show file tree
Hide file tree
Showing 15 changed files with 316 additions and 125 deletions.
2 changes: 1 addition & 1 deletion BepInEx/Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace LineTool
/// <summary>
/// BepInEx plugin to substitute for IMod support.
/// </summary>
[BepInPlugin(GUID, "Line Tool Lite", "1.0")]
[BepInPlugin(GUID, "Line Tool Lite", "1.0.6")]
[HarmonyPatch]
public class Plugin : BaseUnityPlugin
{
Expand Down
2 changes: 1 addition & 1 deletion BepInEx/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Line_Tool_Lite",
"version_number": "1.0.5",
"version_number": "1.0.6",
"website_url": "https://github.com/algernon-A/LineToolLite",
"description": "Place objects in lines, curves, or circles",
"dependencies": [
Expand Down
3 changes: 3 additions & 0 deletions Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
1.0.6
- Add optional random spacing and lateral offset functions.

1.0.5
- Enforce minimum spacing distance to prevent overlapping of multiple invisible items.

Expand Down
24 changes: 21 additions & 3 deletions Code/LineModes/Circle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ public Circle(LineBase mode)
/// <param name="currentPos">Selection current position.</param>
/// <param name="fenceMode">Set to <c>true</c> if fence mode is active.</param>
/// <param name="spacing">Spacing setting.</param>
/// <param name="randomSpacing">Random spacing offset maximum.</param>
/// <param name="randomOffset">Random lateral offset maximum.</param>
/// <param name="rotation">Rotation setting.</param>
/// <param name="zBounds">Prefab zBounds.</param>
/// <param name="pointList">List of points to populate.</param>
/// <param name="heightData">Terrain height data reference.</param>
public override void CalculatePoints(float3 currentPos, bool fenceMode, float spacing, int rotation, Bounds1 zBounds, NativeList<PointData> pointList, ref TerrainHeightData heightData)
public override void CalculatePoints(float3 currentPos, bool fenceMode, float spacing, float randomSpacing, float randomOffset, int rotation, Bounds1 zBounds, NativeList<PointData> pointList, ref TerrainHeightData heightData)
{
// Don't do anything if we don't have valid start.
if (!m_validStart)
Expand All @@ -50,14 +52,30 @@ public override void CalculatePoints(float3 currentPos, bool fenceMode, float sp
float numPoints = math.floor(circumference / spacing);
float increment = (math.PI * 2f) / numPoints;
float startAngle = math.atan2(difference.z, difference.x);
System.Random random = new ((int)circumference * 1000);

// Create points.
for (float i = startAngle; i < startAngle + (math.PI * 2f); i += increment)
{
float xPos = radius * math.cos(i);
float yPos = radius * math.sin(i);
// Apply spacing adjustment.
float adjustedAngle = i;
if (randomSpacing > 0f && !fenceMode)
{
float distanceAdjustment = (float)(random.NextDouble() * randomSpacing * 2f) - randomSpacing;
adjustedAngle += (distanceAdjustment * math.PI * 2f) / circumference;
}

// Calculate point.
float xPos = radius * math.cos(adjustedAngle);
float yPos = radius * math.sin(adjustedAngle);
float3 thisPoint = new (m_startPos.x + xPos, m_startPos.y, m_startPos.z + yPos);

// Apply offset adjustment.
if (randomOffset > 0f && !fenceMode)
{
thisPoint += math.normalize(thisPoint - m_startPos) * ((float)(randomOffset * random.NextDouble() * 2f) - randomOffset);
}

// Calculate terrain height.
thisPoint.y = TerrainUtils.SampleHeight(ref heightData, thisPoint);

Expand Down
25 changes: 21 additions & 4 deletions Code/LineModes/LineBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,13 @@ public virtual void ItemsPlaced(float3 position)
/// <param name="currentPos">Selection current position.</param>
/// <param name="fenceMode">Set to <c>true</c> if fence mode is active.</param>
/// <param name="spacing">Spacing setting.</param>
/// <param name="randomSpacing">Random spacing offset maximum.</param>
/// <param name="randomOffset">Random lateral offset maximum.</param>
/// <param name="rotation">Rotation setting.</param>
/// <param name="zBounds">Prefab zBounds.</param>
/// <param name="pointList">List of points to populate.</param>
/// <param name="heightData">Terrain height data reference.</param>
public virtual void CalculatePoints(float3 currentPos, bool fenceMode, float spacing, int rotation, Bounds1 zBounds, NativeList<PointData> pointList, ref TerrainHeightData heightData)
public virtual void CalculatePoints(float3 currentPos, bool fenceMode, float spacing, float randomSpacing, float randomOffset, int rotation, Bounds1 zBounds, NativeList<PointData> pointList, ref TerrainHeightData heightData)
{
// Don't do anything if we don't have a valid start point.
if (!m_validStart)
Expand All @@ -107,13 +109,14 @@ public virtual void CalculatePoints(float3 currentPos, bool fenceMode, float spa
}

// Calculate length.
float length = math.length(currentPos - m_startPos);
float3 difference = currentPos - m_startPos;
float length = math.length(difference);
System.Random random = new ((int)length * 1000);

// Calculate applied rotation (in radians).
float appliedRotation = math.radians(rotation);
if (fenceMode)
{
float3 difference = currentPos - m_startPos;
appliedRotation = math.atan2(difference.x, difference.z);
}

Expand All @@ -126,7 +129,21 @@ public virtual void CalculatePoints(float3 currentPos, bool fenceMode, float spa
while (currentDistance < endLength)
{
// Calculate interpolated point.
float3 thisPoint = math.lerp(m_startPos, currentPos, currentDistance / length);
float spacingAdjustment = 0f;
if (randomSpacing > 0f && !fenceMode)
{
spacingAdjustment = (float)(random.NextDouble() * randomSpacing * 2f) - randomSpacing;
}

float3 thisPoint = math.lerp(m_startPos, currentPos, (currentDistance + spacingAdjustment) / length);

// Apply offset adjustment.
if (randomOffset > 0f && !fenceMode)
{
float3 left = math.normalize(new float3(-difference.z, 0f, difference.x));
thisPoint += left * ((float)(randomOffset * random.NextDouble() * 2f) - randomOffset);
}

thisPoint.y = TerrainUtils.SampleHeight(ref heightData, thisPoint);

// Add point to list.
Expand Down
37 changes: 29 additions & 8 deletions Code/LineModes/SimpleCurve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@ public override void ItemsPlaced(float3 position)
/// <param name="currentPos">Selection current position.</param>
/// <param name="fenceMode">Set to <c>true</c> if fence mode is active.</param>
/// <param name="spacing">Spacing setting.</param>
/// <param name="randomSpacing">Random spacing offset maximum.</param>
/// <param name="randomOffset">Random lateral offset maximum.</param>
/// <param name="rotation">Rotation setting.</param>
/// <param name="zBounds">Prefab zBounds.</param>
/// <param name="pointList">List of points to populate.</param>
/// <param name="heightData">Terrain height data reference.</param>
public override void CalculatePoints(float3 currentPos, bool fenceMode, float spacing, int rotation, Bounds1 zBounds, NativeList<PointData> pointList, ref TerrainHeightData heightData)
public override void CalculatePoints(float3 currentPos, bool fenceMode, float spacing, float randomSpacing, float randomOffset, int rotation, Bounds1 zBounds, NativeList<PointData> pointList, ref TerrainHeightData heightData)
{
// Don't do anything if we don't have valid start.
if (!m_validStart)
Expand All @@ -98,7 +100,7 @@ public override void CalculatePoints(float3 currentPos, bool fenceMode, float sp
// If we have a valid start but no valid elbow, just draw a straight line.
if (!m_validElbow)
{
base.CalculatePoints(currentPos, fenceMode, spacing, rotation, zBounds, pointList, ref heightData);
base.CalculatePoints(currentPos, fenceMode, spacing, randomSpacing, randomOffset, rotation, zBounds, pointList, ref heightData);
return;
}

Expand All @@ -108,11 +110,29 @@ public override void CalculatePoints(float3 currentPos, bool fenceMode, float sp
// Default rotation quaternion.
quaternion qRotation = quaternion.Euler(0f, math.radians(rotation), 0f);

System.Random random = new ((int)(currentPos.x + currentPos.z) * 1000);

float tFactor = 0f;
while (tFactor < 1.0f)
{
// Apply spacing randomization.
float adjustedT = tFactor;
if (randomSpacing > 0f && !fenceMode)
{
float spacingAdjustment = (float)(random.NextDouble() * randomSpacing * 2f) - randomSpacing;
adjustedT = spacingAdjustment < 0f ? BezierStepReverse(tFactor, spacingAdjustment) : BezierStep(tFactor, spacingAdjustment);
}

// Calculate point.
float3 thisPoint = MathUtils.Position(_thisBezier, tFactor);
float3 thisPoint = MathUtils.Position(_thisBezier, adjustedT);

// Apply offset randomization.
if (randomOffset > 0f && !fenceMode)
{
float3 tangent = MathUtils.Tangent(_thisBezier, adjustedT);
float3 left = math.normalize(new float3(-tangent.z, 0f, tangent.x));
thisPoint += left * ((float)(randomOffset * random.NextDouble() * 2f) - randomOffset);
}

// Get next t factor.
tFactor = BezierStep(tFactor, spacing);
Expand Down Expand Up @@ -213,18 +233,19 @@ private float BezierStep(float tStart, float distance)
}

/// <summary>
/// Steps along a Bezier BACKWARDS from the end point, calculating the target t factor for the given spacing distance.
/// Steps along a Bezier BACKWARDS from the given t factor, calculating the target t factor for the given spacing distance.
/// Code based on Alterran's PropLineTool (StepDistanceCurve, Utilities/PLTMath.cs).
/// </summary>
/// <param name="tStart">Starting t factor.</param>
/// <param name="distance">Distance to travel.</param>
/// <returns>Target t factor.</returns>
private float BezierStepReverse(float distance)
private float BezierStepReverse(float tStart, float distance)
{
const float Tolerance = 0.001f;
const float ToleranceSquared = Tolerance * Tolerance;

float tEnd = Travel(1, -distance);
float usedDistance = CubicBezierArcLengthXZGauss04(tEnd, 1.0f);
float tEnd = Travel(tStart, -distance);
float usedDistance = CubicBezierArcLengthXZGauss04(tEnd, tStart);

// Twelve iteration maximum for performance and to prevent infinite loops.
for (int i = 0; i < 12; ++i)
Expand All @@ -236,7 +257,7 @@ private float BezierStepReverse(float distance)
break;
}

usedDistance = CubicBezierArcLengthXZGauss04(tEnd, 1.0f);
usedDistance = CubicBezierArcLengthXZGauss04(tEnd, tStart);
tEnd -= (distance - usedDistance) / CubicSpeedXZ(tEnd);
}

Expand Down
2 changes: 2 additions & 0 deletions Code/Mod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ public void OnLoad()

// Initialize logger.
Log = LogManager.GetLogger(ModName);
#if DEBUG
Log.Info("setting logging level to Debug");
Log.effectivenessLevel = Level.Debug;
#endif

Log.Info("loading");
}
Expand Down
30 changes: 29 additions & 1 deletion Code/Systems/LineToolSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ public sealed partial class LineToolSystem : ObjectToolBaseSystem
private float _spacing = 20f;
private bool _randomRotation = false;
private int _rotation = 0;
private float _randomSpacing = 0f;
private float _randomOffset = 0f;
private bool _dirty = false;

// Tree Controller integration.
Expand Down Expand Up @@ -141,6 +143,32 @@ internal bool RandomRotation
}
}

/// <summary>
/// Gets or sets the random spacing offset maximum.
/// </summary>
internal float RandomSpacing
{
get => _randomSpacing;
set
{
_randomSpacing = value;
_dirty = true;
}
}

/// <summary>
/// Gets or sets the random lateral offset maximum.
/// </summary>
internal float RandomOffset
{
get => _randomOffset;
set
{
_randomOffset = value;
_dirty = true;
}
}

/// <summary>
/// Gets or sets the rotation setting.
/// </summary>
Expand Down Expand Up @@ -488,7 +516,7 @@ protected override JobHandle OnUpdate(JobHandle inputDeps)

// If we got here we're (re)calculating points.
_points.Clear();
_mode.CalculatePoints(position, _fenceMode, Spacing, _rotation, _zBounds, _points, ref _terrainHeightData);
_mode.CalculatePoints(position, _fenceMode, Spacing, RandomSpacing, RandomOffset, _rotation, _zBounds, _points, ref _terrainHeightData);

// Step along length and place objects.
int count = 0;
Expand Down
Loading

0 comments on commit 71d175a

Please sign in to comment.