Files
BABA_YAGA/Assets/Editor/DistributeTool.cs

131 lines
4.9 KiB
C#
Raw Permalink Normal View History

2026-03-26 20:27:19 +07:00
// ===============================================================================
// DistributeTool - Professional Object Alignment & Distribution
//
// Creator: Scove
// Last Updated: 2024-05-08
// Version: 2.0
//
// Purpose:
// This tool helps organize multiple objects by distributing them evenly along
// the X, Y, or Z axis. It's essential for creating fences, grids, or UI in 3D space.
//
// Key Features:
// 1. Distribute Between Bounds: Keeps the first and last object in place, fills the gap.
// 2. Fixed Spacing: Moves objects based on a specific numerical offset.
// 3. Smart Sorting: Automatically sorts objects by position before distributing.
// 4. Undo Support: Full integration with Unity's Undo system.
//
// How to Use:
// 1. Place this script in an 'Editor' folder.
// 2. Open via: Menu -> Tools -> Distribute Tool.
// 3. Select 3 or more objects in the Hierarchy/Scene.
// 4. Click the desired axis button (X, Y, or Z).
// ===============================================================================
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Editor
{
public class DistributeTool : EditorWindow
{
private float fixedSpacing = 1.0f;
private bool useFixedSpacing = false;
[MenuItem("Tools/Distribute Tool")]
public static void ShowWindow()
{
GetWindow<DistributeTool>("Distribute");
}
private void OnGUI()
{
GUILayout.Label("Distribution Settings", EditorStyles.boldLabel);
EditorGUILayout.Space();
// Mode Selection
useFixedSpacing = EditorGUILayout.Toggle("Use Fixed Spacing", useFixedSpacing);
if (useFixedSpacing)
{
fixedSpacing = EditorGUILayout.FloatField("Distance Offset", fixedSpacing);
}
else
{
EditorGUILayout.HelpBox("Linear Mode: Objects will be distributed evenly between the first and last selected items.", MessageType.Info);
}
EditorGUILayout.Space();
GUILayout.Label("Distribute Along Axis:", EditorStyles.label);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("X Axis", GUILayout.Height(30))) Distribute(0);
if (GUILayout.Button("Y Axis", GUILayout.Height(30))) Distribute(1);
if (GUILayout.Button("Z Axis", GUILayout.Height(30))) Distribute(2);
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
// Helpful Reminder
if (Selection.transforms.Length < 3)
{
EditorGUILayout.HelpBox("Please select at least 3 objects to distribute.", MessageType.Warning);
}
else
{
GUILayout.Label($"Objects Selected: {Selection.transforms.Length}", EditorStyles.miniLabel);
}
}
private void Distribute(int axis) // 0=x, 1=y, 2=z
{
Transform[] selection = Selection.transforms;
if (selection.Length < 3)
{
Debug.LogWarning("[DistributeTool] You need to select at least 3 objects.");
return;
}
// Register Undo for all selected objects
Undo.RecordObjects(selection, "Distribute Objects");
// Sort selection by position on the chosen axis to maintain visual order
var sorted = selection.OrderBy(t => t.position[axis]).ToList();
if (useFixedSpacing)
{
// Fixed Spacing Logic: Move each object relative to the first one
Vector3 startPos = sorted[0].position;
for (int i = 1; i < sorted.Count; i++)
{
Vector3 newPos = sorted[i].position;
newPos[axis] = startPos[axis] + (fixedSpacing * i);
sorted[i].position = newPos;
}
}
else
{
// Linear Distribution Logic: Fill the space between first and last
float start = sorted.First().position[axis];
float end = sorted.Last().position[axis];
float totalDistance = end - start;
// Avoid division by zero if objects are at the same spot
if (Mathf.Abs(totalDistance) < 0.0001f) return;
float step = totalDistance / (sorted.Count - 1);
for (int i = 0; i < sorted.Count; i++)
{
Vector3 newPos = sorted[i].position;
newPos[axis] = start + (step * i);
sorted[i].position = newPos;
}
}
Debug.Log($"<color=#FFCC00><b>[DistributeTool]</b></color> Distributed {sorted.Count} objects along the {(axis == 0 ? "X" : axis == 1 ? "Y" : "Z")} axis.");
}
}
}