using System; using System.Collections.Generic; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; namespace UnityEditor.U2D.Animation { internal class WeightPainterPanel : VisualElement { public class WeightPainterPanelFactory : UxmlFactory {} public class WeightPainterPanelUxmlTraits : UxmlTraits {} public static readonly string kNone = "None"; private WeightPainterMode m_PaintMode; private EnumField m_ModeField; private Toggle m_NormalizeToggle; private IntegerField m_HardnessField; private IntegerField m_StepField; private IntegerField m_SizeField; private FloatField m_AmountField; private Slider m_AmountSlider; private VisualElement m_BonePopupContainer; private PopupField m_BonePopup; private bool m_SliderActive = false; private WeightInspectorIMGUIPanel m_WeightInspectorPanel; private UnityEngine.UIElements.PopupWindow m_PopupWindow; public event Action bonePopupChanged = (s) => {}; public event Action sliderStarted = () => {}; public event Action sliderChanged = (s) => {}; public event Action sliderEnded = () => {}; public event Action weightsChanged = () => {}; public WeightPainterMode paintMode { get { return m_PaintMode; } set { if (value == m_PaintMode) return; m_PaintMode = value; if (m_PaintMode == WeightPainterMode.Brush) { RemoveFromClassList("SliderMode"); AddToClassList("BrushMode"); } else { RemoveFromClassList("BrushMode"); AddToClassList("SliderMode"); } } } public string title { set { m_PopupWindow.text = value; } } public WeightEditorMode mode { get { return (WeightEditorMode)m_ModeField.value; } set { m_ModeField.value = value; } } public int boneIndex { get { return m_BonePopup.index - 1; } } public int size { get { return m_SizeField.value; } set { m_SizeField.value = value; } } public int hardness { get { return m_HardnessField.value; } set { m_HardnessField.value = value; } } public int step { get { return m_StepField.value; } set { m_StepField.value = value; } } public bool normalize { get { return m_NormalizeToggle.value; } set { m_NormalizeToggle.value = value; } } public float amount { get { return m_AmountField.value; } set { m_AmountField.value = value; } } public WeightPainterPanel() { styleSheets.Add(ResourceLoader.Load("SkinningModule/WeightPainterPanelStyle.uss")); if (EditorGUIUtility.isProSkin) AddToClassList("Dark"); paintMode = WeightPainterMode.Brush; AddToClassList("BrushMode"); RegisterCallback((e) => { e.StopPropagation(); }); RegisterCallback((e) => { e.StopPropagation(); }); } public void BindElements() { m_ModeField = this.Q("ModeField"); m_BonePopupContainer = this.Q("BoneEnumPopup"); m_NormalizeToggle = this.Q("NormalizeToggle"); m_SizeField = this.Q("SizeField"); m_HardnessField = this.Q("HardnessField"); m_StepField = this.Q("StepField"); m_AmountSlider = this.Q("AmountSlider"); m_AmountField = this.Q("AmountField"); m_AmountField.isDelayed = true; m_WeightInspectorPanel = this.Q("WeightsInspector"); m_PopupWindow = this.Q(); LinkSliderToIntegerField(this.Q("HardnessSlider"), m_HardnessField); LinkSliderToIntegerField(this.Q("StepSlider"), m_StepField); m_ModeField.RegisterValueChangedCallback((evt) => { SetupMode(); }); m_AmountSlider.RegisterValueChangedCallback((evt) => { if (!evt.Equals(m_AmountField.value)) m_AmountField.value = (float)Math.Round((double)evt.newValue, 2); if (m_SliderActive) sliderChanged?.Invoke(m_AmountField.value); }); m_AmountSlider.RegisterCallback(evt => { m_SliderActive = true; sliderStarted?.Invoke(); }, TrickleDown.TrickleDown); m_AmountSlider.RegisterCallback(evt => { m_SliderActive = false; sliderEnded?.Invoke(); m_AmountSlider.value = 0; }, TrickleDown.TrickleDown); m_AmountField.RegisterValueChangedCallback((evt) => { var newValue = Mathf.Clamp(evt.newValue, m_AmountSlider.lowValue, m_AmountSlider.highValue); if (focusController.focusedElement == m_AmountField && !newValue.Equals(m_AmountSlider.value)) { sliderStarted(); sliderChanged(newValue); sliderEnded(); Focus(); m_AmountField.value = 0f; m_AmountSlider.value = 0f; } }); m_WeightInspectorPanel.weightsChanged += () => weightsChanged(); } public void SetActive(bool active) { this.Q("Amount").SetEnabled(active); } private void SetupMode() { var boneElement = this.Q("Bone"); boneElement.SetHiddenFromLayout(mode == WeightEditorMode.Smooth); SetupAmountSlider(); } private void SetupAmountSlider() { if (paintMode == WeightPainterMode.Slider) { if (mode == WeightEditorMode.Smooth) { m_AmountSlider.lowValue = 0.0f; m_AmountSlider.highValue = 8.0f; } else { m_AmountSlider.lowValue = -1.0f; m_AmountSlider.highValue = 1.0f; } } } private void LinkSliderToIntegerField(Slider slider, IntegerField field) { slider.RegisterValueChangedCallback((evt) => { if (!evt.newValue.Equals(field.value)) field.value = Mathf.RoundToInt(evt.newValue); }); field.RegisterValueChangedCallback((evt) => { if (!evt.newValue.Equals((int)slider.value)) slider.value = evt.newValue; }); } public void UpdateWeightInspector(ISpriteMeshData spriteMeshData, string[] boneNames, ISelection selection, ICacheUndo cacheUndo) { m_WeightInspectorPanel.weightInspector.spriteMeshData = spriteMeshData; m_WeightInspectorPanel.weightInspector.boneNames = ModuleUtility.ToGUIContentArray(boneNames); m_WeightInspectorPanel.weightInspector.selection = selection; m_WeightInspectorPanel.weightInspector.cacheUndo = cacheUndo; } public void UpdatePanel(string[] boneNames) { SetupMode(); UpdateBonePopup(boneNames); } private void UpdateBonePopup(string[] names) { VisualElement boneElement = null; if (m_ModeField != null && mode == WeightEditorMode.Smooth) { boneElement = this.Q("Bone"); boneElement.SetHiddenFromLayout(false); } if (m_BonePopup != null) { m_BonePopupContainer.Remove(m_BonePopup); } m_BonePopup = new PopupField(new List(names), 0); m_BonePopup.name = "BonePopupField"; m_BonePopup.label = TextContent.bone; m_BonePopup.tooltip = TextContent.boneToolTip; m_BonePopup.RegisterValueChangedCallback((evt) => { bonePopupChanged(boneIndex); }); m_BonePopupContainer.Add(m_BonePopup); if (boneElement != null) { boneElement.SetHiddenFromLayout(true); } } internal void SetBoneSelectionByName(string boneName) { if (m_BonePopup != null) m_BonePopup.value = boneName; } public static WeightPainterPanel GenerateFromUXML() { var visualTree = ResourceLoader.Load("SkinningModule/WeightPainterPanel.uxml"); var clone = visualTree.CloneTree().Q("WeightPainterPanel"); // EnumField can only get type of Enum from the current running assembly when defined through UXML // Manually create the EnumField here var mode = clone.Q("Mode"); var modeField = new EnumField(WeightEditorMode.AddAndSubtract); modeField.name = "ModeField"; modeField.label = TextContent.mode; modeField.tooltip = TextContent.modeTooltip; mode.Add(modeField); clone.BindElements(); return clone; } } }