private void Unbuild()
        {
            var track = Track;

            if (workDirection > 0)
            {
                if (track.PrevTrack)
                {
                    Selection.activeGameObject = track.PrevTrack.gameObject;
                }
            }
            else
            {
                if (track.NextTrack)
                {
                    Selection.activeGameObject = track.NextTrack.gameObject;
                }
            }

            Undo.RecordObjects(TrackEditor.GetObjectsInvolvedWithTrack(track), "Unbuild");

            if (track.PrevTrack)
            {
                track.PrevTrack.NextTrack = null;
            }
            if (track.NextTrack)
            {
                track.NextTrack.PrevTrack = null;
            }

            Undo.DestroyObjectImmediate(track.gameObject);
        }
        private void Straighten()
        {
            var track = Track;

            Undo.RecordObjects(TrackEditor.GetObjectsInvolvedWithTrack(track), "Straighten");
            var length = track.Length;

            track.curveEndStrength = track.curveStartStrength = Track.DefaultCurveStrength;

            if (workDirection > 0)
            {
                var newEnd = new SimpleTransform(new Vector3(0, 0, length));
                track.TrackEnd = newEnd;
                if (track.NextTrack)
                {
                    track.NextTrack.TrackAbsoluteStart = track.TrackAbsoluteEnd;
                }
            }
            else
            {
                var absEnd = track.TrackAbsoluteEnd;
                track.TrackAbsoluteStart = new SimpleTransform(
                    absEnd.position + absEnd.rotation * new Vector3(0, 0, -length),
                    absEnd.rotation
                    );

                if (track.PrevTrack)
                {
                    track.PrevTrack.TrackAbsoluteEnd = track.TrackAbsoluteStart;
                }
            }

            track.Update();
        }
        protected void CreateNewTrackUnderSelection()
        {
            var parent = Selection.activeGameObject ? Selection.activeGameObject.transform : null;

            var track = TrackEditor.CreateNewTrack();

            if (parent)
            {
                track.transform.parent        = parent;
                track.transform.localRotation = Quaternion.identity;
                track.transform.localPosition = Vector3.zero;
            }

            Undo.RegisterCreatedObjectUndo(track.gameObject, "Create Track");
            Selection.activeGameObject = track.gameObject;
        }
        /** Bends the currently selected track pieces according to the current parameters. */
        protected void Bend()
        {
            ignoreNextChange = true;
            foreach (var obj in Selection.transforms)
            {
                var track = obj.GetComponent <Track>();
                if (!track)
                {
                    continue;
                }

                Undo.RecordObjects(TrackEditor.GetObjectsInvolvedWithTrack(track), "Bend Track");

                if (workDirection > 0)
                {
                    var rot = Quaternion.Euler(bend);
                    var pos = Vector3.Lerp(track.TrackAbsoluteStart.rotation * shim, rot * shim, .5f) + track.TrackAbsoluteStart.position;

                    track.TrackAbsoluteEnd = new SimpleTransform(pos, rot);
                    track.Update();

                    if (track.NextTrack)
                    {
                        track.NextTrack.TrackAbsoluteStart = track.TrackAbsoluteEnd;
                        track.NextTrack.Update();
                    }
                }
                else
                {
                    var rot      = Quaternion.Euler(bend) * Quaternion.AngleAxis(180, Vector3.up);
                    var facedEnd = track.TrackAbsoluteEnd.AboutFaced();
                    var pos      = Vector3.Lerp(facedEnd.rotation * shim, rot * shim, .5f) + facedEnd.position;

                    track.TrackAbsoluteStart = new SimpleTransform(pos, rot).AboutFace();
                    track.Update();

                    if (track.PrevTrack)
                    {
                        track.PrevTrack.TrackAbsoluteEnd = track.TrackAbsoluteStart;
                        track.PrevTrack.Update();
                    }
                }
            }
        }
        private void Flatten()
        {
            var track = Track;

            Undo.RecordObjects(TrackEditor.GetObjectsInvolvedWithTrack(track), "Flatten");
            var endPos = workDirection > 0 ? track.TrackAbsoluteEnd : track.TrackAbsoluteStart;

            //flatten the end and quantize the direction the nearest 45°
            var forward = endPos.rotation * Vector3.forward;

            forward.y = 0;
            if (forward.sqrMagnitude < .001f)
            {
                endPos.rotation = Quaternion.identity;
            }
            else
            {
                var angle = Mathf.Atan2(forward.x, forward.z) * Mathf.Rad2Deg;
                angle           = Mathf.Round(angle / snapAngle) * snapAngle;
                endPos.rotation = Quaternion.AngleAxis(angle, Vector3.up);
            }


            if (workDirection > 0)
            {
                track.TrackAbsoluteEnd = endPos;
                if (track.NextTrack)
                {
                    track.NextTrack.TrackAbsoluteStart = track.TrackAbsoluteEnd;
                }
            }
            else
            {
                track.TrackAbsoluteStart = endPos;
                if (track.PrevTrack)
                {
                    track.PrevTrack.TrackAbsoluteEnd = track.TrackAbsoluteStart;
                }
            }
            track.Update();
        }
        private void Build()
        {
            var track = Track;

            if (workDirection > 0)
            {
                if (track.NextTrack)
                {
                    Selection.activeGameObject = track.NextTrack.gameObject;
                }
                else
                {
                    var newTrack = TrackEditor.AddTrack(track, false);
                    newTrack.TrackEnd          = new SimpleTransform(new Vector3(0, 0, shim.z / track.transform.lossyScale.x));
                    newTrack.curveEndStrength  = newTrack.curveStartStrength = Track.DefaultCurveStrength;
                    Selection.activeGameObject = newTrack.gameObject;
                    Undo.RegisterCreatedObjectUndo(newTrack.gameObject, "Build Track");
                }
            }
            else
            {
                if (track.PrevTrack)
                {
                    Selection.activeGameObject = track.PrevTrack.gameObject;
                }
                else
                {
                    var newTrack = TrackEditor.AddTrack(track, true);
                    newTrack.curveEndStrength = newTrack.curveStartStrength = Track.DefaultCurveStrength;
                    var absEnd = newTrack.TrackAbsoluteEnd;
                    newTrack.TrackAbsoluteStart = new SimpleTransform(
                        absEnd.position + absEnd.rotation * new Vector3(0, 0, -shim.z),
                        absEnd.rotation
                        );
                    Selection.activeGameObject = newTrack.gameObject;
                    Undo.RegisterCreatedObjectUndo(newTrack.gameObject, "Build Track");
                }
            }
        }