OldBlueWater/BlueWater/Assets/Doozy/Editor/UIDesigner/Windows/RotateWindow.cs

485 lines
19 KiB
C#

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System.Collections.Generic;
using Doozy.Editor.EditorUI;
using Doozy.Editor.EditorUI.Components;
using Doozy.Editor.EditorUI.Components.Internal;
using Doozy.Editor.EditorUI.Utils;
using Doozy.Editor.EditorUI.Windows.Internal;
using Doozy.Editor.UIDesigner.Utils;
using Doozy.Editor.UIElements;
using Doozy.Runtime.UIDesigner;
using Doozy.Runtime.UIElements.Extensions;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using Space = Doozy.Runtime.UIDesigner.Space;
// ReSharper disable MemberCanBePrivate.Global
namespace Doozy.Editor.UIDesigner.Windows
{
public class RotateWindow : FluidWindow<RotateWindow>
{
private const string WINDOW_TITLE = "Rotate";
public const string k_WindowMenuPath = "Tools/Doozy/UI Designer/";
[MenuItem(k_WindowMenuPath + WINDOW_TITLE, priority = -800)]
public static void Open() => InternalOpenWindow(WINDOW_TITLE);
private FloatField snapIntervalFloatField { get; set; }
private FluidField optionsFluidField { get; set; }
private FluidField rotation180ToZeroFluidField { get; set; }
private FluidField rotationZeroToNegative180FluidField { get; set; }
private FluidRangeSlider rotation180ToZeroSlider { get; set; }
private FluidRangeSlider rotationZeroToNegative180Slider { get; set; }
private FluidToggleCheckbox relativeChangeCheckbox { get; set; }
private FluidToggleCheckbox snapToIntervalCheckbox { get; set; }
private FluidToggleCheckbox snapToValuesCheckbox { get; set; }
private FluidToggleButtonTab xTabButton { get; set; }
private FluidToggleButtonTab yTabButton { get; set; }
private FluidToggleButtonTab zTabButton { get; set; }
private FluidToggleGroup spaceToggleGroup { get; set; }
private FluidToggleButtonTab localSpaceButton { get; set; }
private FluidToggleButtonTab worldSpaceButton { get; set; }
private Space space
{
get => (Space)EditorPrefs.GetInt(EditorPrefsKey(nameof(space)), (int)Space.Local);
set => EditorPrefs.SetInt(EditorPrefsKey(nameof(space)), (int)value);
}
private bool rotateX
{
get => EditorPrefs.GetBool(EditorPrefsKey(nameof(rotateX)), true);
set => EditorPrefs.SetBool(EditorPrefsKey(nameof(rotateX)), value);
}
private bool rotateY
{
get => EditorPrefs.GetBool(EditorPrefsKey(nameof(rotateY)), true);
set => EditorPrefs.SetBool(EditorPrefsKey(nameof(rotateY)), value);
}
private bool rotateZ
{
get => EditorPrefs.GetBool(EditorPrefsKey(nameof(rotateZ)), true);
set => EditorPrefs.SetBool(EditorPrefsKey(nameof(rotateZ)), value);
}
private float snapInterval
{
get => EditorPrefs.GetFloat(EditorPrefsKey(nameof(snapInterval)), 1f);
set => EditorPrefs.SetFloat(EditorPrefsKey(nameof(snapInterval)), value);
}
private bool snapToInterval
{
get => EditorPrefs.GetBool(EditorPrefsKey(nameof(snapToInterval)), true);
set => EditorPrefs.SetBool(EditorPrefsKey(nameof(snapToInterval)), value);
}
private bool snapToValues
{
get => EditorPrefs.GetBool(EditorPrefsKey(nameof(snapToValues)), true);
set => EditorPrefs.SetBool(EditorPrefsKey(nameof(snapToValues)), value);
}
private bool relativeChange
{
get => EditorPrefs.GetBool(EditorPrefsKey(nameof(relativeChange)), true);
set => EditorPrefs.SetBool(EditorPrefsKey(nameof(relativeChange)), value);
}
protected override void OnEnable()
{
base.OnEnable();
SceneView.duringSceneGui -= OnSceneGUI;
SceneView.duringSceneGui += OnSceneGUI;
OnSelectionChanged();
}
protected override void OnDisable()
{
base.OnDisable();
SceneView.duringSceneGui -= OnSceneGUI;
}
private void OnSceneGUI(SceneView sceneView)
{
if (selected.Count == 0)
return;
Handles.BeginGUI();
Color color = Handles.color;
Handles.color = EditorColors.EditorUI.Amber;
{
//ToDo SceneView visuals
}
Handles.color = color;
Handles.EndGUI();
}
protected override void CreateGUI()
{
Initialize();
Compose();
Selection.selectionChanged -= OnSelectionChanged;
Selection.selectionChanged += OnSelectionChanged;
}
private static HashSet<RectTransform> selected { get; set; } = new HashSet<RectTransform>();
private void OnSelectionChanged() =>
selected = DesignerEditorUtils.selected;
private void Initialize()
{
root
.RecycleAndClear()
.SetStylePadding(DesignUtils.k_Spacing2X)
// .SetStyleBackgroundColor(EditorColors.Default.BoxBackground)
;
#region 0 to -180
rotationZeroToNegative180Slider =
new FluidRangeSlider(0, -180)
.SetTooltip
(
"Rotate the selected objects clockwise by or to the specified value."
)
.SetAccentColor(EditorColors.UIDesigner.Color)
.SetSnapInterval(snapInterval)
.SetSnapValues(-180, -120, -90, -60, -45, -30, -15, 0)
.SetSnapDistanceForSnapValues(4f)
.SetAutoResetValue(0)
.SetSliderValue(0);
rotationZeroToNegative180Slider.onStartValueChange.AddListener(DesignerEditorUtils.StartRotation);
rotationZeroToNegative180Slider.onEndValueChange.AddListener(DesignerEditorUtils.EndRotation);
rotationZeroToNegative180Slider.onValueChanged.AddListener(UpdateRotation);
rotationZeroToNegative180FluidField =
FluidField.Get()
.SetStyleFlexGrow(0)
.SetStyleFlexShrink(0)
// .SetLabelText("Clockwise")
.SetIcon(EditorSpriteSheets.UIDesigner.Icons.RotateRight)
.AddFieldContent(rotationZeroToNegative180Slider);
#endregion
#region 180 to 0
rotation180ToZeroSlider =
new FluidRangeSlider(180, 0)
.SetTooltip
(
"Rotate the selected objects counter-clockwise by or to the specified value."
)
.SetAccentColor(EditorColors.UIDesigner.Color)
.SetSnapInterval(1f)
.SetSnapValues(0, 15, 30, 45, 60, 90, 120, 180)
.SetSnapDistanceForSnapValues(4f)
.SetAutoResetValue(0)
.SetSliderValue(0);
rotation180ToZeroSlider.onStartValueChange.AddListener(DesignerEditorUtils.StartRotation);
rotation180ToZeroSlider.onEndValueChange.AddListener(DesignerEditorUtils.EndRotation);
rotation180ToZeroSlider.onValueChanged.AddListener(UpdateRotation);
rotation180ToZeroFluidField =
FluidField.Get()
.SetStyleFlexGrow(0)
.SetStyleFlexShrink(0)
// .SetLabelText("Counter-Clockwise")
.SetIcon(EditorSpriteSheets.UIDesigner.Icons.RotateLeft)
.AddFieldContent(rotation180ToZeroSlider);
#endregion
#region Options
xTabButton =
GetToggleButton()
.SetLabelText("X")
.SetTooltip("Rotate the selected objects around the X axis by or to the specified value.")
.SetOnValueChanged(evt => rotateX = evt.newValue)
.SetTabPosition(TabPosition.TabOnLeft);
yTabButton =
GetToggleButton()
.SetLabelText("Y")
.SetTooltip("Rotate the selected objects around the Y axis by or to the specified value.")
.SetOnValueChanged(evt => rotateY = evt.newValue)
.SetTabPosition(TabPosition.TabInCenter);
zTabButton =
GetToggleButton()
.SetLabelText("Z")
.SetTooltip("Rotate the selected objects around the Z axis by or to the specified value.")
.SetOnValueChanged(evt => rotateZ = evt.newValue)
.SetTabPosition(TabPosition.TabOnRight);
xTabButton.SetIsOn(rotateX, false);
yTabButton.SetIsOn(rotateY, false);
zTabButton.SetIsOn(rotateZ, false);
if (!xTabButton.isOn & !yTabButton.isOn & !zTabButton.isOn)
zTabButton.SetIsOn(true, false);
localSpaceButton =
GetToggleButton()
.SetLabelText("Local")
.SetTooltip("Rotate the selected objects in local space.")
.SetOnValueChanged(evt =>
{
if (!evt.newValue) return;
space = Space.Local;
})
.SetTabPosition(TabPosition.TabOnLeft);
worldSpaceButton =
GetToggleButton()
.SetLabelText("World")
.SetTooltip("Rotate the selected objects in world space.")
.SetOnValueChanged(evt =>
{
if (!evt.newValue) return;
space = Space.World;
})
.SetTabPosition(TabPosition.TabOnRight);
localSpaceButton.SetIsOn(space == Space.Local, false);
worldSpaceButton.SetIsOn(space == Space.World, false);
if (!localSpaceButton.isOn && !worldSpaceButton.isOn)
localSpaceButton.SetIsOn(true, false);
spaceToggleGroup =
FluidToggleGroup.Get()
.SetControlMode(FluidToggleGroup.ControlMode.OneToggleOnEnforced);
localSpaceButton.AddToToggleGroup(spaceToggleGroup);
worldSpaceButton.AddToToggleGroup(spaceToggleGroup);
relativeChangeCheckbox =
FluidToggleCheckbox.Get()
.SetLabelText("Relative Change")
.SetTooltip
(
"If enabled, the rotation will be relative to the current rotation of the selected objects.\n" +
"If disabled, the rotation will be absolute."
)
.SetToggleAccentColor(EditorSelectableColors.UIDesigner.Color)
.SetIsOn(relativeChange, false)
.SetOnValueChanged(evt => relativeChange = evt.newValue);
snapToIntervalCheckbox =
FluidToggleCheckbox.Get()
.SetLabelText("Snap to Interval")
.SetTooltip
(
"If enabled, the rotation will snap to the nearest interval.\n" +
"If disabled, the rotation will be continuous."
)
.SetToggleAccentColor(EditorSelectableColors.UIDesigner.Color)
.SetIsOn(snapToInterval, false)
.SetOnValueChanged(evt =>
{
snapToInterval = evt.newValue;
rotationZeroToNegative180Slider.SnapToInterval(evt.newValue);
rotation180ToZeroSlider.SnapToInterval(evt.newValue);
snapIntervalFloatField.SetEnabled(evt.newValue);
});
snapIntervalFloatField =
new FloatField()
.ResetLayout()
.SetStyleWidth(60)
.SetTooltip
(
"The interval to snap to.\n" +
"If Snap to Interval is disabled, this value will be ignored."
);
snapIntervalFloatField.value = snapInterval;
snapIntervalFloatField.RegisterValueChangedCallback(evt =>
{
if (evt?.newValue == null) return;
snapInterval = evt.newValue;
rotationZeroToNegative180Slider.SetSnapInterval(evt.newValue);
rotation180ToZeroSlider.SetSnapInterval(evt.newValue);
});
rotationZeroToNegative180Slider.SetSnapInterval(snapIntervalFloatField.value);
rotation180ToZeroSlider.SetSnapInterval(snapIntervalFloatField.value);
snapToValuesCheckbox =
FluidToggleCheckbox.Get()
.SetLabelText("Snap to Values")
.SetTooltip
(
"If enabled, the rotation will snap to the marked predefined values."
)
.SetToggleAccentColor(EditorSelectableColors.UIDesigner.Color)
.SetIsOn(snapToValues, false)
.SetOnValueChanged(evt =>
{
snapToValues = evt.newValue;
rotationZeroToNegative180Slider.SnapToValues(evt.newValue);
rotation180ToZeroSlider.SnapToValues(evt.newValue);
});
rotationZeroToNegative180Slider.SnapToValues(snapToValuesCheckbox.isOn);
rotation180ToZeroSlider.SnapToValues(snapToValuesCheckbox.isOn);
optionsFluidField =
FluidField.Get()
.SetStyleFlexGrow(0)
.SetStyleFlexShrink(0)
.AddFieldContent
(
new VisualElement()
.SetName("XYZ - Space - Relative Change")
.SetStyleFlexShrink(0)
.SetStyleFlexWrap(Wrap.Wrap)
.SetStyleFlexDirection(FlexDirection.Row)
.AddChild
(
new VisualElement()
.SetName("XYZ")
.SetStyleFlexDirection(FlexDirection.Row)
.SetStylePadding(DesignUtils.k_Spacing2X)
.AddChild(xTabButton)
.AddSpace(1, 0)
.AddChild(yTabButton)
.AddSpace(1, 0)
.AddChild(zTabButton)
)
.AddChild
(
new VisualElement()
.SetName("Relative Change")
.SetStyleFlexDirection(FlexDirection.Row)
.SetStylePadding(DesignUtils.k_Spacing2X)
.AddChild(relativeChangeCheckbox)
)
.AddChild
(
new VisualElement()
.SetName("Space")
.SetStyleFlexDirection(FlexDirection.Row)
.SetStylePadding(DesignUtils.k_Spacing2X)
.AddChild(localSpaceButton)
.AddSpace(1, 0)
.AddChild(worldSpaceButton)
)
)
.AddFieldContent
(
new VisualElement()
.SetName("Snap to Interval - Snap Values")
.SetStyleFlexShrink(0)
.SetStyleFlexWrap(Wrap.Wrap)
.SetStyleFlexDirection(FlexDirection.Row)
.AddChild
(
new VisualElement()
.SetName("Snap to Interval")
.SetStyleFlexDirection(FlexDirection.Row)
.SetStylePadding(DesignUtils.k_Spacing2X)
.AddChild(snapToIntervalCheckbox)
.AddSpaceBlock()
.AddChild(snapIntervalFloatField)
)
.AddChild
(
new VisualElement()
.SetName("Snap to Values")
.SetStyleFlexDirection(FlexDirection.Row)
.SetStylePadding(DesignUtils.k_Spacing2X)
.AddChild(snapToValuesCheckbox)
)
);
#endregion
}
private void Compose()
{
root
.AddChild(rotationZeroToNegative180FluidField)
.AddSpaceBlock(2)
.AddChild(rotation180ToZeroFluidField)
.AddSpaceBlock(2)
.AddChild(optionsFluidField);
}
private void UpdateRotation(float value)
{
if (rotateX & rotateY & rotateZ)
{
DesignerEditorUtils.UpdateRotation(space, value, value, value, relativeChange);
return;
}
if (rotateX & rotateY)
{
DesignerEditorUtils.UpdateRotationXY(space, value, value, relativeChange);
return;
}
if (rotateX & rotateZ)
{
DesignerEditorUtils.UpdateRotationXZ(space, value, value, relativeChange);
return;
}
if (rotateY & rotateZ)
{
DesignerEditorUtils.UpdateRotationYZ(space, value, value, relativeChange);
return;
}
if (rotateX)
{
DesignerEditorUtils.UpdateRotation(space, Axis.X, value, relativeChange);
return;
}
if (rotateY)
{
DesignerEditorUtils.UpdateRotation(space, Axis.Y, value, relativeChange);
return;
}
if (rotateZ)
{
DesignerEditorUtils.UpdateRotation(space, Axis.Z, value, relativeChange);
return;
}
Debug.Log("UIDesigner - Unable to rotate - No rotation axis selected");
}
private FluidToggleButtonTab GetToggleButton() =>
FluidToggleButtonTab.Get()
.SetToggleAccentColor(EditorSelectableColors.UIDesigner.Color)
.SetStyleFlexShrink(0)
.SetElementSize(ElementSize.Normal)
.SetContainerColorOff(DesignUtils.tabButtonColorOff);
}
}