Here's the new script with no CustomEditor or workaround hacks.
Can I make a small suggestion to have something similar to this added to the official version? It's veeeeeeeeeeeeeery useful.
Code:
using UnityEngine;
using UnityEditor;
using FluffyUnderware.Curvy.Controllers;
using System.Linq;
using System.Collections.Generic;
namespace FluffyUnderware.CurvyEditor.Controllers
{
[InitializeOnLoad]
public static class MoveMultipleControllers
{
static int[] clampStyle;
static bool forceClamp = false;
static bool clamp = false;
static bool endDrag = false;
static bool cancel = false;
static float slider = 0;
static float[] orgPos;
static float[] maxPos;
static float offset = 0;
static float orgPosMax = 0;
static float orgPosMin = 0;
static float maxPosMax = 0;
static Color bgC = new Color(0.6117f, 0.6274f, 0.6356f, 0.75f);
static Rect boxW = new Rect(0, 0, 260, 100);
static Rect boxS = new Rect(10, 20, 240, 10);
static Rect boxC = new Rect(10, 10, 10, 10);
static Rect boxT = new Rect(10, 40, 100, 40);
static int index = 0;
static List<SplineController> selectedItems;
static MoveMultipleControllers()
{
EditorApplication.update += update;
}
public static void update()
{
Selection.selectionChanged = checkSelection;
}
public static void checkSelection()
{
selectedItems = Selection.transforms.Select(t => t.gameObject.GetComponent<SplineController>()).Where(c => c != null).ToList();
if (selectedItems.Count > 1)
{
forceClamp = false;
index = 0;
orgPos = new float[selectedItems.Count];
maxPos = new float[selectedItems.Count];
clampStyle = new int[selectedItems.Count];
selectedItems.ToArray();
foreach (SplineController checkController in selectedItems)
{
if (checkController.Spline == null) //Is controller on a spline?
{
index++;
continue;
}
orgPos[index] = checkController.AbsolutePosition;
maxPos[index] = checkController.Spline.Length;
clampStyle[index] = (int)checkController.Clamping;
index++;
}
if (clampStyle.Contains(0) || clampStyle.Contains(2)) //Forces clamping unless all controllers are Loop.
{
forceClamp = true;
clamp = true;
}
orgPosMax = orgPos.Max();
orgPosMin = orgPos.Min();
maxPosMax = maxPos.Min(); //In case they are on different splines.
SceneView.duringSceneGui += DrawGUI;
}
else
{
SceneView.duringSceneGui -= DrawGUI;
}
}
public static void DrawGUI(SceneView sceneview)
{
if (!EditorApplication.isPlaying)
{
if (cancel)
{
cancel = false;
}
//Events must be before GUI, else inputs will be eaten.
if (Event.current.rawType == EventType.MouseUp && Event.current.button == 1 && !cancel && endDrag) //Cancel move. MouseDown doesn't work, will not reset slider if you click while moving mouse.
{
endDrag = false;
cancel = true;
slider = 0;
index = 0;
foreach (SplineController checkController in selectedItems)
{
if (checkController.Spline == null)
{
index++;
continue;
}
checkController.AbsolutePosition = orgPos[index];
maxPos[index] = checkController.Spline.Length;
index++;
}
orgPosMax = orgPos.Max(); //In case spline has changed.
orgPosMin = orgPos.Min();
maxPosMax = maxPos.Min();
}
else if (Event.current.rawType == EventType.MouseUp && Event.current.button == 0 && !cancel && endDrag) //Confirm move.
{
endDrag = false;
cancel = true;
slider = 0;
index = 0;
foreach (SplineController checkController in selectedItems)
{
if (checkController.Spline == null)
{
index++;
continue;
}
orgPos[index] = checkController.AbsolutePosition;
maxPos[index] = checkController.Spline.Length;
index++;
}
orgPosMax = orgPos.Max();
orgPosMin = orgPos.Min();
maxPosMax = maxPos.Min();
}
GUI.BeginGroup(new Rect(Screen.width - 270, Screen.height - 80, 260, 35), "");
GUI.backgroundColor = bgC;
GUI.contentColor = Color.black;
GUI.Box(boxW, "Offset Selected Controllers Position");
clamp = GUI.Toggle(boxC, clamp, new GUIContent("", "Force Clamping? Always\non unless all controllers\nare set to Loop."));
GUI.Label(boxT, GUI.tooltip);
slider = GUI.HorizontalSlider(boxS, slider, -100, 100);
GUI.Button(boxW, "", GUIStyle.none); //Prevents miss click.
GUI.EndGroup();
if (forceClamp && !clamp)
{
clamp = true;
}
if (GUI.changed && !cancel)
{
endDrag = true;
index = 0;
slider = Mathf.Floor(slider);
if (slider > 0 && slider + orgPosMax > maxPosMax - 1 && clamp)
{
offset = maxPosMax - orgPosMax - 1;
}
else if (slider < 0 && orgPosMin + slider < 1 && clamp)
{
offset = orgPosMin * -1 + 1;
}
else
{
offset = slider;
}
foreach (SplineController checkController in selectedItems)
{
if (checkController.Spline == null)
{
index++;
continue;
}
Undo.RecordObject(checkController, "Offset");
checkController.AbsolutePosition = orgPos[index] + offset;
index++;
}
}
}
}
}
}
Can I make a small suggestion to have something similar to this added to the official version? It's veeeeeeeeeeeeeery useful.