diff --git a/Editor/UIExtensionsMenuOptions.cs b/Editor/UIExtensionsMenuOptions.cs index 9e9267b..b8acb64 100644 --- a/Editor/UIExtensionsMenuOptions.cs +++ b/Editor/UIExtensionsMenuOptions.cs @@ -1656,7 +1656,7 @@ namespace UnityEditor.UI [MenuItem("GameObject/UI/Extensions/Segmented Control", false)] static public void AddSegmentedControl(MenuCommand menuCommand) { - GameObject go = CreateUIElementRoot("Segmented Control", menuCommand, s_ThinGUIElementSize); + GameObject go = CreateUIElementRoot("Segmented Control", menuCommand, s_ThickGUIElementSize); SegmentedControl control = go.AddComponent(); Color selectedColor = new Color(0f, 0.455f, 0.894f); @@ -1677,12 +1677,12 @@ namespace UnityEditor.UI Selection.activeGameObject = go; } #endregion - + #region Stepper [MenuItem("GameObject/UI/Extensions/Stepper", false)] static public void AddStepper(MenuCommand menuCommand) { - GameObject go = CreateUIElementRoot("Stepper", menuCommand, new Vector2(42, kThinHeight)); + GameObject go = CreateUIElementRoot("Stepper", menuCommand, new Vector2(kWidth / 2, kThickHeight)); Stepper control = go.AddComponent(); var labels = new string[] { "−", "+" }; @@ -1741,7 +1741,7 @@ namespace UnityEditor.UI backgroundImage.fillCenter = false; backgroundImage.color = new Color(1f, 1f, 1f, 0.392f); - RectTransform handleRect = SetAnchorsAndStretch(handle); + RectTransform handleRect = SetAnchorsAndStretch(handle); handleRect.sizeDelta = new Vector2(25, 25); Image handleImage = handle.AddComponent(); handleImage.sprite = AssetDatabase.GetBuiltinExtraResource(kKnobPath); diff --git a/Scripts/Controls/SegmentedControl.cs b/Scripts/Controls/SegmentedControl.cs index 0367847..b3fcfe8 100644 --- a/Scripts/Controls/SegmentedControl.cs +++ b/Scripts/Controls/SegmentedControl.cs @@ -117,8 +117,7 @@ namespace UnityEngine.UI.Extensions { base.OnValidate(); - if (separator) - LayoutSegments(); + LayoutSegments(); if (m_selectedSegmentIndex != -1) selectedSegmentIndex = m_selectedSegmentIndex; @@ -151,16 +150,12 @@ namespace UnityEngine.UI.Extensions segment = buttons[i].gameObject.AddComponent(); } segment.index = i; + segment.segmentedControl = this; } return buttons; } - public void SetAllSegmentsOff() - { - selectedSegment = null; - } - private void RecreateSprites() { for (int i = 0; i < segments.Length; i++) @@ -168,28 +163,34 @@ namespace UnityEngine.UI.Extensions if (segments[i].image == null) continue; - var sprite = segments[i].image.sprite; - if (sprite.border.x == 0 || sprite.border.z == 0) - continue; - - var rect = sprite.rect; - var border = sprite.border; - - if (i > 0) - { - rect.xMin = border.x; - border.x = 0; - } - if (i < segments.Length - 1) - { - rect.xMax = border.z; - border.z = 0; - } - - segments[i].image.sprite = Sprite.Create(sprite.texture, rect, sprite.pivot, sprite.pixelsPerUnit, 0, SpriteMeshType.FullRect, border); + var sprite = CutSprite(segments[i].image.sprite, i == 0, i == segments.Length - 1); + segments[i].GetComponent().cutSprite = sprite; + segments[i].image.overrideSprite = sprite; } } + static internal Sprite CutSprite(Sprite sprite, bool leftmost, bool rightmost) + { + if (sprite.border.x == 0 || sprite.border.z == 0) + return sprite; + + var rect = sprite.rect; + var border = sprite.border; + + if (!leftmost) + { + rect.xMin = border.x; + border.x = 0; + } + if (!rightmost) + { + rect.xMax = border.z; + border.z = 0; + } + + return Sprite.Create(sprite.texture, rect, sprite.pivot, sprite.pixelsPerUnit, 0, SpriteMeshType.FullRect, border); + } + public void LayoutSegments() { RecreateSprites(); @@ -234,6 +235,7 @@ namespace UnityEngine.UI.Extensions ISelectHandler, IDeselectHandler { internal int index; + internal SegmentedControl segmentedControl; internal bool leftmost { @@ -241,20 +243,15 @@ namespace UnityEngine.UI.Extensions } internal bool rightmost { - get { return index == segmentControl.segments.Length - 1; } + get { return index == segmentedControl.segments.Length - 1; } } public bool selected { - get { return segmentControl.selectedSegment == this.button; } + get { return segmentedControl.selectedSegment == this.button; } set { SetSelected(value); } } - internal SegmentedControl segmentControl - { - get { return GetComponentInParent(); } - } - internal Selectable button { get { return GetComponent(); } @@ -262,6 +259,7 @@ namespace UnityEngine.UI.Extensions [SerializeField] Color textColor; + internal Sprite cutSprite; protected Segment() { } @@ -313,9 +311,9 @@ namespace UnityEngine.UI.Extensions { if (value && button.IsActive() && button.IsInteractable()) { - if (segmentControl.selectedSegment == this.button) + if (segmentedControl.selectedSegment == this.button) { - if (segmentControl.allowSwitchingOff) + if (segmentedControl.allowSwitchingOff) { Deselect(); } @@ -326,20 +324,20 @@ namespace UnityEngine.UI.Extensions } else { - if (segmentControl.selectedSegment) + if (segmentedControl.selectedSegment) { - var segment = segmentControl.selectedSegment.GetComponent(); - segmentControl.selectedSegment = null; + var segment = segmentedControl.selectedSegment.GetComponent(); + segmentedControl.selectedSegment = null; segment.TransitionButton(); } - segmentControl.selectedSegment = this.button; + segmentedControl.selectedSegment = this.button; StoreTextColor(); TransitionButton(); - segmentControl.onValueChanged.Invoke(index); + segmentedControl.onValueChanged.Invoke(index); } } - else if (segmentControl.selectedSegment == this.button) + else if (segmentedControl.selectedSegment == this.button) { Deselect(); } @@ -347,14 +345,14 @@ namespace UnityEngine.UI.Extensions private void Deselect() { - segmentControl.selectedSegment = null; + segmentedControl.selectedSegment = null; TransitionButton(); - segmentControl.onValueChanged.Invoke(-1); + segmentedControl.onValueChanged.Invoke(-1); } void MaintainSelection() { - if (button != segmentControl.selectedSegment) + if (button != segmentedControl.selectedSegment) return; TransitionButton(true); @@ -367,9 +365,9 @@ namespace UnityEngine.UI.Extensions internal void TransitionButton(bool instant) { - Color tintColor = selected ? segmentControl.selectedColor : button.colors.normalColor; + Color tintColor = selected ? segmentedControl.selectedColor : button.colors.normalColor; Color textColor = selected ? button.colors.normalColor : this.textColor; - Sprite transitionSprite = selected ? button.spriteState.pressedSprite : null; + Sprite transitionSprite = selected ? button.spriteState.pressedSprite : cutSprite; string triggerName = selected ? button.animationTriggers.pressedTrigger : button.animationTriggers.normalTrigger; switch (button.transition) @@ -379,6 +377,8 @@ namespace UnityEngine.UI.Extensions ChangeTextColor(textColor * button.colors.colorMultiplier); break; case Selectable.Transition.SpriteSwap: + if (transitionSprite != cutSprite) + transitionSprite = SegmentedControl.CutSprite(transitionSprite, leftmost, rightmost); DoSpriteSwap(transitionSprite); break; case Selectable.Transition.Animation: diff --git a/Scripts/Controls/Stepper.cs b/Scripts/Controls/Stepper.cs index 406ef5b..1a86f1f 100644 --- a/Scripts/Controls/Stepper.cs +++ b/Scripts/Controls/Stepper.cs @@ -93,6 +93,7 @@ namespace UnityEngine.UI.Extensions { base.OnValidate(); + RecreateSprites(sides); if (separator) LayoutSides(); @@ -172,28 +173,34 @@ namespace UnityEngine.UI.Extensions if (sides[i].image == null) continue; - var sprite = sides[i].image.sprite; - if (sprite.border.x == 0 || sprite.border.z == 0) - continue; - - var rect = sprite.rect; - var border = sprite.border; - - if (i == 0) - { - rect.xMax = border.z; - border.z = 0; - } - else - { - rect.xMin = border.x; - border.x = 0; - } - - sides[i].image.sprite = Sprite.Create(sprite.texture, rect, sprite.pivot, sprite.pixelsPerUnit, 0, SpriteMeshType.FullRect, border); + var sprite = CutSprite(sides[i].image.sprite, i == 0); + sides[i].GetComponent().cutSprite = sprite; + sides[i].image.overrideSprite = sprite; } } + static internal Sprite CutSprite(Sprite sprite, bool leftmost) + { + if (sprite.border.x == 0 || sprite.border.z == 0) + return sprite; + + var rect = sprite.rect; + var border = sprite.border; + + if (leftmost) + { + rect.xMax = border.z; + border.z = 0; + } + else + { + rect.xMin = border.x; + border.x = 0; + } + + return Sprite.Create(sprite.texture, rect, sprite.pivot, sprite.pixelsPerUnit, 0, SpriteMeshType.FullRect, border); + } + public void LayoutSides(Selectable[] sides = null) { sides = sides ?? this.sides; @@ -232,7 +239,13 @@ namespace UnityEngine.UI.Extensions } [RequireComponent(typeof(Selectable))] - public class StepperSide : UIBehaviour, IPointerClickHandler, ISubmitHandler + public class StepperSide : + UIBehaviour, + IPointerClickHandler, + ISubmitHandler, + IPointerEnterHandler, IPointerExitHandler, + IPointerDownHandler, IPointerUpHandler, + ISelectHandler, IDeselectHandler { Selectable button { get { return GetComponent(); } } @@ -240,6 +253,8 @@ namespace UnityEngine.UI.Extensions bool leftmost { get { return button == stepper.sides[0]; } } + internal Sprite cutSprite; + protected StepperSide() { } @@ -249,11 +264,43 @@ namespace UnityEngine.UI.Extensions return; Press(); + AdjustSprite(false); } public virtual void OnSubmit(BaseEventData eventData) { Press(); + AdjustSprite(true); + } + + public virtual void OnPointerEnter(PointerEventData eventData) + { + AdjustSprite(false); + } + + public virtual void OnPointerExit(PointerEventData eventData) + { + AdjustSprite(true); + } + + public virtual void OnPointerDown(PointerEventData eventData) + { + AdjustSprite(false); + } + + public virtual void OnPointerUp(PointerEventData eventData) + { + AdjustSprite(false); + } + + public virtual void OnSelect(BaseEventData eventData) + { + AdjustSprite(false); + } + + public virtual void OnDeselect(BaseEventData eventData) + { + AdjustSprite(true); } private void Press() @@ -270,5 +317,17 @@ namespace UnityEngine.UI.Extensions stepper.StepUp(); } } + + private void AdjustSprite(bool restore) + { + var image = button.image; + if (!image || image.overrideSprite == cutSprite) + return; + + if (restore) + image.overrideSprite = cutSprite; + else + image.overrideSprite = Stepper.CutSprite(image.overrideSprite, leftmost); + } } } \ No newline at end of file