Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Moving multiple controllers at once
#23
Here's the new script with no CustomEditor or workaround hacks.
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.
Reply


Messages In This Thread
Moving multiple controllers at once - by Lupp_ - 01-15-2020, 07:46 PM
RE: Moving multiple controllers at once - by Lupp_ - 02-10-2020, 03:44 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Distance travelled across multiple splines jh092 1 7 02-23-2024, 09:44 AM
Last Post: _Aka_
  Best practice for controllers slowing down/speeding up along the spline Curry 1 5 08-06-2023, 09:47 PM
Last Post: _Aka_
  Moving object down or up the spline using gravity velikizlivuk 6 19 07-26-2023, 10:06 PM
Last Post: _Aka_
  Multiple Splines and Generators Performantly for Road System drock 1 6 07-17-2023, 10:31 AM
Last Post: _Aka_

Forum Jump: