Author Topic: NGUI 2.7.0: Add 'relativeSizeOffset' to UIStretch  (Read 3857 times)

OnlineCop

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 51
    • View Profile
NGUI 2.7.0: Add 'relativeSizeOffset' to UIStretch
« on: September 12, 2013, 12:38:14 PM »
I would like to propose an added effect to UIStretch.cs: a "relative size" offset (in pixels), which works in tandem with relativeSize.

I want to have one sprite always be exactly 10 pixels smaller than another (it's for a "gloss" foreground overlay on a button). When the button background gets resized, the overlay scales to be the same. Using 'relativeSize' by itself doesn't work for me, since a percentage means that it doesn't line up correctly.

I'm not well-versed in creating patches, but wanted to share this in case it is useful:

Add a new variable at the top called 'relativeSizeOffset':
  1.    /// <summary>
  2.    /// When Style is Both, Vertical, or Horizontal, make the scale relativeSize + this amount.
  3.    /// </summary>
  4.  
  5.    public Vector2 relativeSizeOffset = Vector2.zero;
  6.  
Then at the bottom of the Update loop, modify the line:
  1.             if (style == Style.Both || style == Style.Horizontal) localScale.x = relativeSize.x * rectWidth;
  2.             if (style == Style.Both || style == Style.Vertical) localScale.y = relativeSize.y * rectHeight;
  3.  
to be:
  1.             if (style == Style.Both || style == Style.Horizontal)
  2.             {
  3.                localScale.x = Mathf.Max(0f, (relativeSize.x * rectWidth) + relativeSizeOffset.x);
  4.             }
  5.             if (style == Style.Both || style == Style.Vertical)
  6.             {
  7.                localScale.y = Mathf.Max(0f, (relativeSize.y * rectHeight) + relativeSizeOffset.y);
  8.             }
  9.  

To use this, I:
  • Attach the UIStretch component to my button's "gloss" foreground sprite
  • Set "Widget Container" to point to the button's background sprite
  • Set the "Style" to Both
  • Set 'relativeSize.x' to 1.0
  • Set 'relativeSizeOffset.x' value to -10.0

Now any resizing done to the button's background is carried up to the button's foreground.

Comments? Suggestions?

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
Re: NGUI 2.7.0: Add 'relativeSizeOffset' to UIStretch
« Reply #1 on: September 12, 2013, 01:13:03 PM »
I would probably call this a PixelSizeOffset, but I like it.

OnlineCop

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 51
    • View Profile
Re: NGUI 2.7.0: Add 'relativeSizeOffset' to UIStretch
« Reply #2 on: September 22, 2013, 05:59:50 PM »
So re-bumping this, but now (that 3.x is out) with a request that it can be added to NGUI 3.0. Ple-e-e-ease? (Each time I upgrade, I have to go back in and re-add the lines.)

It works amazingly well for stretchable windows (a couple screenshots attached to demonstrate). Everything uses the 'background' UISprite as their reference, using either UIStretch (with the pixel offset) for their scale or UIAnchor (which already has a pixel offset) for their position.

The only changes are:
  1.    /// <summary>
  2.    /// When Style is Both, Vertical, or Horizontal, make the scale relativeSize + this amount.
  3.    /// </summary>
  4.  
  5.    public Vector2 pixelSizeOffset = Vector2.zero;
  6.  
instead of relativeSizeOffset, per Nicki's suggestion, and 'localScale' is changed to simply 'size' to match the rest of the 3.0 changes:
  1.  
  2.                                 if (style == Style.Both || style == Style.Horizontal)
  3.                                 {
  4.                                         size.x = Mathf.Max(0f, (relativeSize.x * rectWidth) + pixelSizeOffset.x);
  5.                                 }
  6.                                 if (style == Style.Both || style == Style.Vertical)
  7.                                 {
  8.                                         size.y = Mathf.Max(0f, (relativeSize.y * rectHeight) + pixelSizeOffset.y);
  9.                                 }
  10.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: NGUI 2.7.0: Add 'relativeSizeOffset' to UIStretch
« Reply #3 on: September 23, 2013, 07:40:45 AM »
Somehow I missed this thread the first time around. Sounds useful, but I'm going to call it "border padding", because that's what this is.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: NGUI 2.7.0: Add 'relativeSizeOffset' to UIStretch
« Reply #4 on: September 23, 2013, 07:56:33 AM »
Try this.
  1. //----------------------------------------------
  2. //            NGUI: Next-Gen UI kit
  3. // Copyright © 2011-2013 Tasharen Entertainment
  4. //----------------------------------------------
  5.  
  6. using UnityEngine;
  7.  
  8. /// <summary>
  9. /// This script can be used to stretch objects relative to the screen's width and height.
  10. /// The most obvious use would be to create a full-screen background by attaching it to a sprite.
  11. /// </summary>
  12.  
  13. [ExecuteInEditMode]
  14. [AddComponentMenu("NGUI/UI/Stretch")]
  15. public class UIStretch : MonoBehaviour
  16. {
  17.         public enum Style
  18.         {
  19.                 None,
  20.                 Horizontal,
  21.                 Vertical,
  22.                 Both,
  23.                 BasedOnHeight,
  24.                 FillKeepingRatio, // Fits the image so that it entirely fills the specified container keeping its ratio
  25.                 FitInternalKeepingRatio // Fits the image/item inside of the specified container keeping its ratio
  26.         }
  27.  
  28.         /// <summary>
  29.         /// Camera used to determine the anchor bounds. Set automatically if none was specified.
  30.         /// </summary>
  31.  
  32.         public Camera uiCamera = null;
  33.  
  34.         /// <summary>
  35.         /// Object used to determine the container's bounds. Overwrites the camera-based anchoring if the value was specified.
  36.         /// </summary>
  37.  
  38.         public GameObject container = null;
  39.  
  40.         /// <summary>
  41.         /// Stretching style.
  42.         /// </summary>
  43.  
  44.         public Style style = Style.None;
  45.  
  46.         /// <summary>
  47.         /// Whether the operation will occur only once and the script will then be disabled.
  48.         /// </summary>
  49.  
  50.         public bool runOnlyOnce = false;
  51.  
  52.         /// <summary>
  53.         /// Relative-to-target size.
  54.         /// </summary>
  55.  
  56.         public Vector2 relativeSize = Vector2.one;
  57.  
  58.         /// <summary>
  59.         /// The size that the item/image should start out initially.
  60.         /// Used for FillKeepingRatio, and FitInternalKeepingRatio.
  61.         /// Contributed by Dylan Ryan.
  62.         /// </summary>
  63.  
  64.         public Vector2 initialSize = Vector2.one;
  65.  
  66.         /// <summary>
  67.         /// Padding applied after the size of the stretched object gets calculated. This value is in pixels.
  68.         /// </summary>
  69.  
  70.         public Vector2 borderPadding = Vector2.zero;
  71.  
  72.         // Deprecated legacy functionality
  73.         [HideInInspector][SerializeField] UIWidget widgetContainer;
  74.  
  75.         Transform mTrans;
  76.         UIWidget mWidget;
  77.         UISprite mSprite;
  78.         UIRoot mRoot;
  79.         Animation mAnim;
  80.         Rect mRect;
  81.  
  82.         void OnEnable ()
  83.         {
  84.                 mAnim = animation;
  85.                 mRect = new Rect();
  86.                 mTrans = transform;
  87.                 mWidget = GetComponent<UIWidget>();
  88.                 mSprite = GetComponent<UISprite>();
  89.         }
  90.  
  91.         void Start ()
  92.         {
  93.                 if (container == null && widgetContainer != null)
  94.                 {
  95.                         container = widgetContainer.gameObject;
  96.                         widgetContainer = null;
  97. #if UNITY_EDITOR
  98.                         UnityEditor.EditorUtility.SetDirty(this);
  99. #endif
  100.                 }
  101.  
  102.                 if (uiCamera == null) uiCamera = NGUITools.FindCameraForLayer(gameObject.layer);
  103.                 mRoot = NGUITools.FindInParents<UIRoot>(gameObject);
  104.                 Update();
  105.         }
  106.  
  107.         void Update ()
  108.         {
  109.                 if (mAnim != null && mAnim.isPlaying) return;
  110.  
  111.                 if (style != Style.None)
  112.                 {
  113.                         UIWidget wc = (container == null) ? null : container.GetComponent<UIWidget>();
  114.                         UIPanel pc = (container == null && wc == null) ? null : container.GetComponent<UIPanel>();
  115.                         float adjustment = 1f;
  116.  
  117.                         if (wc != null)
  118.                         {
  119.                                 Bounds b = wc.CalculateBounds(transform.parent);
  120.  
  121.                                 mRect.x = b.min.x;
  122.                                 mRect.y = b.min.y;
  123.  
  124.                                 mRect.width = b.size.x;
  125.                                 mRect.height = b.size.y;
  126.                         }
  127.                         else if (pc != null)
  128.                         {
  129.                                 if (pc.clipping == UIDrawCall.Clipping.None)
  130.                                 {
  131.                                         // Panel has no clipping -- just use the screen's dimensions
  132.                                         float ratio = (mRoot != null) ? (float)mRoot.activeHeight / Screen.height * 0.5f : 0.5f;
  133.                                         mRect.xMin = -Screen.width * ratio;
  134.                                         mRect.yMin = -Screen.height * ratio;
  135.                                         mRect.xMax = -mRect.xMin;
  136.                                         mRect.yMax = -mRect.yMin;
  137.                                 }
  138.                                 else
  139.                                 {
  140.                                         // Panel has clipping -- use it as the mRect
  141.                                         Vector4 pos = pc.clipRange;
  142.                                         mRect.x = pos.x - (pos.z * 0.5f);
  143.                                         mRect.y = pos.y - (pos.w * 0.5f);
  144.                                         mRect.width = pos.z;
  145.                                         mRect.height = pos.w;
  146.                                 }
  147.                         }
  148.                         else if (container != null)
  149.                         {
  150.                                 Transform root = transform.parent;
  151.                                 Bounds b = (root != null) ? NGUIMath.CalculateRelativeWidgetBounds(root, container.transform) :
  152.                                         NGUIMath.CalculateRelativeWidgetBounds(container.transform);
  153.  
  154.                                 mRect.x = b.min.x;
  155.                                 mRect.y = b.min.y;
  156.  
  157.                                 mRect.width = b.size.x;
  158.                                 mRect.height = b.size.y;
  159.                         }
  160.                         else if (uiCamera != null)
  161.                         {
  162.                                 mRect = uiCamera.pixelRect;
  163.                                 if (mRoot != null) adjustment = mRoot.pixelSizeAdjustment;
  164.                         }
  165.                         else return;
  166.  
  167.                         float rectWidth = mRect.width;
  168.                         float rectHeight = mRect.height;
  169.  
  170.                         if (adjustment != 1f && rectHeight > 1f)
  171.                         {
  172.                                 float scale = mRoot.activeHeight / rectHeight;
  173.                                 rectWidth *= scale;
  174.                                 rectHeight *= scale;
  175.                         }
  176.  
  177.                         Vector3 size = (mWidget != null) ? new Vector3(mWidget.width, mWidget.height) : mTrans.localScale;
  178.  
  179.                         if (style == Style.BasedOnHeight)
  180.                         {
  181.                                 size.x = relativeSize.x * rectHeight;
  182.                                 size.y = relativeSize.y * rectHeight;
  183.                         }
  184.                         else if (style == Style.FillKeepingRatio)
  185.                         {
  186.                                 // Contributed by Dylan Ryan
  187.                                 float screenRatio = rectWidth / rectHeight;
  188.                                 float imageRatio = initialSize.x / initialSize.y;
  189.  
  190.                                 if (imageRatio < screenRatio)
  191.                                 {
  192.                                         // Fit horizontally
  193.                                         float scale = rectWidth / initialSize.x;
  194.                                         size.x = rectWidth;
  195.                                         size.y = initialSize.y * scale;
  196.                                 }
  197.                                 else
  198.                                 {
  199.                                         // Fit vertically
  200.                                         float scale = rectHeight / initialSize.y;
  201.                                         size.x = initialSize.x * scale;
  202.                                         size.y = rectHeight;
  203.                                 }
  204.                         }
  205.                         else if (style == Style.FitInternalKeepingRatio)
  206.                         {
  207.                                 // Contributed by Dylan Ryan
  208.                                 float screenRatio = rectWidth / rectHeight;
  209.                                 float imageRatio = initialSize.x / initialSize.y;
  210.  
  211.                                 if (imageRatio > screenRatio)
  212.                                 {
  213.                                         // Fit horizontally
  214.                                         float scale = rectWidth / initialSize.x;
  215.                                         size.x = rectWidth;
  216.                                         size.y = initialSize.y * scale;
  217.                                 }
  218.                                 else
  219.                                 {
  220.                                         // Fit vertically
  221.                                         float scale = rectHeight / initialSize.y;
  222.                                         size.x = initialSize.x * scale;
  223.                                         size.y = rectHeight;
  224.                                 }
  225.                         }
  226.                         else
  227.                         {
  228.                                 if (style == Style.Both || style == Style.Horizontal) size.x = relativeSize.x * rectWidth;
  229.                                 if (style == Style.Both || style == Style.Vertical) size.y = relativeSize.y * rectHeight;
  230.                         }
  231.  
  232.                         if (mSprite != null)
  233.                         {
  234.                                 float multiplier = (mSprite.atlas != null) ? mSprite.atlas.pixelSize : 1f;
  235.                                 size.x += borderPadding.x * multiplier;
  236.                                 size.y += borderPadding.y * multiplier;
  237.  
  238.                                 mSprite.width = Mathf.RoundToInt(size.x);
  239.                                 mSprite.height = Mathf.RoundToInt(size.y);
  240.                                 size = Vector3.one;
  241.                         }
  242.                         else if (mWidget != null)
  243.                         {
  244.                                 mWidget.width = Mathf.RoundToInt(size.x + borderPadding.x);
  245.                                 mWidget.height = Mathf.RoundToInt(size.y + borderPadding.y);
  246.                                 size = Vector3.one;
  247.                         }
  248.                         else
  249.                         {
  250.                                 size.x += borderPadding.x;
  251.                                 size.y += borderPadding.y;
  252.                         }
  253.                        
  254.                         if (mTrans.localScale != size)
  255.                                 mTrans.localScale = size;
  256.  
  257.                         if (runOnlyOnce && Application.isPlaying) Destroy(this);
  258.                 }
  259.         }
  260. }