Skip to content

Instantly share code, notes, and snippets.

@belzecue
Forked from drZool/ObjectSpacing.cs
Created October 29, 2019 16:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save belzecue/387d6e98b91ba1ec5b2ee97727655613 to your computer and use it in GitHub Desktop.
Save belzecue/387d6e98b91ba1ec5b2ee97727655613 to your computer and use it in GitHub Desktop.
Tool for aligning and distribute objects, primarly in 2d space, can be extended to 3d
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
/// <summary>
/// Tool for spacing objects, primarly in 2d space, can be extended to 3d
/// </summary>
public class ObjectSpacing : EditorWindow
{
[MenuItem ("Hello/ObjectSpacing/Open Window")]
static void OpenWindow ()
{
ObjectSpacing window = (ObjectSpacing)EditorWindow.GetWindow (typeof(ObjectSpacing));
window.minSize = new Vector2 (100, 30);
window.Show ();
}
Texture[] _icon_distribute;
Texture[] icon_distribute {
get {
if (_icon_distribute == null) {
_icon_distribute = new Texture[2];
_icon_distribute [0] = AssetDatabase.LoadAssetAtPath<Texture2D> ("Assets/Gists/Tools/Editor/distribute-x.png");
_icon_distribute [1] = AssetDatabase.LoadAssetAtPath<Texture2D> ("Assets/Gists/Tools/Editor/distribute-y.png");
}
return _icon_distribute;
}
}
void OnGUI ()
{
List<GameObject> objects = new List<GameObject> (Selection.gameObjects);
int count = objects.Count;
//GUILayout.Label ("Distribute evenly", EditorStyles.boldLabel);
GUILayout.BeginHorizontal ();
EditorGUI.BeginDisabledGroup (count < 2);
for (int axis = 0; axis < 2; ++axis) {
GUILayout.BeginVertical ();
EditorGUILayout.LabelField (" " + GetInterval(axis, objects), GUILayout.MaxWidth (60));
if (icon_distribute [axis] == null) {
if (GUILayout.Button (axisName [axis].ToString(), GUILayout.MaxWidth (28))) {
DistributeByAxis (axis);
}
} else {
if (GUILayout.Button (icon_distribute [axis], GUILayout.MaxWidth (28))) {
DistributeByAxis (axis);
}
}
GUILayout.EndVertical ();
}
//GUILayout.Label ("Distribute by number", EditorStyles.boldLabel);
GUILayout.BeginHorizontal ();
for (int axis = 0; axis < 2; ++axis) {
GUILayout.BeginVertical ();
//if (axis == 0) {
alignment [axis] = GUILayout.HorizontalSlider (alignment [axis], 0, 1);
// } else {
// alignment [axis] = GUILayout.VerticalSlider (alignment [axis], 1, 0);
// }
distance [axis] = EditorGUILayout.FloatField (distance [axis]);
if (GUILayout.Button ("Spread " + axisName [axis])) {
DistributeByAxis (axis, distance [axis], alignment [axis]);
}
GUILayout.EndVertical ();
}
GUILayout.EndHorizontal ();
EditorGUI.EndDisabledGroup ();
GUILayout.EndHorizontal ();
}
Vector3 alignment = Vector3.zero;
float GetInterval(int axis, List<GameObject> objects){
int count = objects.Count;
if (count < 2)
return 0;
objects.Sort ((a, b) => a.transform.position [axis].CompareTo (b.transform.position [axis]));
float min = objects [0].transform.position [axis];
float max = objects [count - 1].transform.position [axis];
float interval = (max - min) / (float)(count - 1);
return interval;
}
static string axisName = "xyz";
Vector3 distance = Vector3.one * 10;
[MenuItem ("Hello/ObjectSpacing/Vertical")]
static void SpaceVertical ()
{
DistributeByAxis (1);
}
[MenuItem ("Hello/ObjectSpacing/Horizontal")]
static void SpaceHorizontal ()
{
DistributeByAxis (0);
}
[MenuItem ("Hello/ObjectSpacing/Vertical And Horizontal")]
static void SpaceVerticalAndHorizontal ()
{
DistributeByAxis (0);
DistributeByAxis (1);
}
static void DistributeByAxis (int axis)
{
List<GameObject> objects = new List<GameObject> (Selection.gameObjects);
int count = objects.Count;
if (count < 2)
return;
Undo.RecordObjects (Selection.gameObjects, "ObjectSpacing axis " + axis);
objects.Sort ((a, b) => a.transform.position [axis].CompareTo (b.transform.position [axis]));
float min = objects [0].transform.position [axis];
float max = objects [count - 1].transform.position [axis];
float interval = (max - min) / (float)(count - 1);
//Debug.Log ("Count " + count);
for (int i = 0; i < count; ++i) {
var p = objects [i].transform.position;
p [axis] = min + (i * interval);
objects [i].transform.position = p;
}
}
static void DistributeByAxis (int axis, float interval, float align)
{
List<GameObject> objects = new List<GameObject> (Selection.gameObjects);
int count = objects.Count;
if (count < 2)
return;
objects.Sort ((a, b) => a.transform.position [axis].CompareTo (b.transform.position [axis]));
Undo.RecordObjects (Selection.gameObjects, "ObjectSpacing axis " + axis);
float min = objects [0].transform.position [axis];
float max = objects [count-1].transform.position [axis];
float alignCenter = Mathf.Lerp (min, max, align);
float distance = interval * (count - 1);
float start = alignCenter - distance * (align);
for (int i = 0; i < count; ++i) {
var p = objects [i].transform.position;
p [axis] = start + (i * interval);
objects [i].transform.position = p;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment