Author Topic: [REQUEST]: Ability to choose TRUE Aspect Ratio for UITexture  (Read 4520 times)

helmesjo

  • Full Member
  • ***
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 116
    • View Profile
[REQUEST]: Ability to choose TRUE Aspect Ratio for UITexture
« on: August 18, 2014, 02:14:37 AM »
Got a little surprised when there was no option to set "Aspect Ratio" (eg. Aspect fit & aspect fill) for a UITexture. No need to argue about the numerous times the aspect is not known until runtime (downloaded textures).

Just to be clear, the current "Aspect Ratio"-setting is not what I mean. One should be able to set the UITexture-widget to be of any size, but let the raw texture be rendered within this rect based on a setting that is either "Fill", "Aspect Fit" or "Aspect Fill" (leaving am empty area in the case if aspect fit). That way you can show textures with different resolutions within the same rect. Just a guess is that this should be calculated in the UITexture.drawingDimensions.

Any plans on implementing this with a nice drop-down list in the inspector? Mandatory IMO.

Cheers!

Edit.
Just to save you the trouble, I wrapped up a quick solution (needs minor optimisations, like caching of values etc.).

UITexture.cs:

  1. public enum AspectRatio{
  2.                 Fill,
  3.                 AspectFill,
  4.                 AspectFit
  5.         }
  6.         [SerializeField, HideInInspector] private AspectRatio m_AspectRatioMode = AspectRatio.Fill;
  7.         public AspectRatio AspectRatioMode{
  8.                 get{
  9.                         return m_AspectRatioMode;
  10.                 }
  11.                 set{
  12.                         if(m_AspectRatioMode != value){
  13.                                 m_AspectRatioMode = value;
  14.                                 MarkAsChanged();
  15.                         }
  16.                 }
  17.         }
  18.  
  19. [...]
  20.  
  21. public override Vector4 drawingDimensions
  22.         {
  23. Vector2 size = localSize;
  24.  
  25.                         if(mainTexture != null){
  26.                                 switch (m_AspectRatioMode) {
  27.                                 case AspectRatio.Fill:
  28.                                         break;
  29.                                 case AspectRatio.AspectFill:
  30.                                 {
  31.                                         Vector2 maxSize = size;
  32.                                        
  33.                                         float xRatio = maxSize.x / mainTexture.width;
  34.                                         float yRatio = maxSize.y / mainTexture.height;
  35.                                         float maxRatio = Mathf.Max(xRatio, yRatio);
  36.                                        
  37.                                         size = new Vector2(mainTexture.width * maxRatio, mainTexture.height * maxRatio);
  38.                                 }
  39.                                         break;
  40.                                 case AspectRatio.AspectFit:
  41.                                 {
  42.                                         Vector2 maxSize = size;
  43.  
  44.                                         float xRatio = maxSize.x / mainTexture.width;
  45.                                         float yRatio = maxSize.y / mainTexture.height;
  46.                                         float minRatio = Mathf.Min(xRatio, yRatio);
  47.                                        
  48.                                         size = new Vector2(mainTexture.width * minRatio, mainTexture.height * minRatio);
  49.                                 }
  50.                                         break;
  51.                                 default:
  52.                                         throw new System.ArgumentOutOfRangeException();
  53.                                 }
  54.                         }
  55. [...]
  56.  

UITextureInspector.cs:
  1. mTex.AspectRatioMode = (UITexture.AspectRatio)EditorGUILayout.EnumPopup("Aspect Mode:", mTex.AspectRatioMode);
  2.  
« Last Edit: August 18, 2014, 03:21:20 AM by helmesjo »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: [REQUEST]: Ability to choose TRUE Aspect Ratio for UITexture
« Reply #1 on: August 18, 2014, 11:53:59 AM »
Something like this would be trivial to do with an extra script attached to UITexture.

helmesjo

  • Full Member
  • ***
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 116
    • View Profile
Re: [REQUEST]: Ability to choose TRUE Aspect Ratio for UITexture
« Reply #2 on: August 18, 2014, 12:59:20 PM »
Something like this would be trivial to do with an extra script attached to UITexture.

Not sure which definition of trivial you sought for, but my point was more in the way that this should be part of the implementation already and not something you "mod in, in case you need it" (if that's what you meant).
« Last Edit: August 18, 2014, 01:17:17 PM by helmesjo »

mimminito

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 30
    • View Profile
Re: [REQUEST]: Ability to choose TRUE Aspect Ratio for UITexture
« Reply #3 on: August 19, 2014, 06:08:15 AM »
Would be nice to have this added in, or as an example script we can attach.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: [REQUEST]: Ability to choose TRUE Aspect Ratio for UITexture
« Reply #4 on: August 19, 2014, 12:11:51 PM »
  1. using UnityEngine;
  2.  
  3. [RequireComponent(typeof(UITexture))]
  4. public class SetAspectRatio : MonoBehaviour
  5. {
  6.     void Start ()
  7.     {
  8.         UITexture uitex = GetComponent<UITexture>();
  9.         Texture tex = uitex.mainTexture;
  10.         uitex.aspectRatio = (float)tex.width / tex.height;
  11.         uitex.UpdateAnchors();
  12.     }
  13. }
The fit/fill modes can be done just by anchoring two sides of this texture.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: [REQUEST]: Ability to choose TRUE Aspect Ratio for UITexture
« Reply #5 on: August 19, 2014, 12:22:07 PM »
Here's another more complicated version that will make a UITexture always fit the content image within the widget's bounds:
  1. using UnityEngine;
  2.  
  3. [ExecuteInEditMode]
  4. [RequireComponent(typeof(UITexture))]
  5. public class UIFitTexture : MonoBehaviour
  6. {
  7.         UITexture mTex;
  8.  
  9.         void Awake () { mTex = GetComponent<UITexture>(); }
  10.  
  11.         void Update ()
  12.         {
  13.                 Texture tex = mTex.mainTexture;
  14.  
  15.                 if (tex != null)
  16.                 {
  17.                         float widgetWidth = mTex.width;
  18.                         float widgetHeight = mTex.height;
  19.                         float widgetAspect = widgetWidth / widgetHeight;
  20.                         float textureAspect = (float)tex.width / tex.height;
  21.  
  22.                         if (textureAspect < widgetAspect)
  23.                         {
  24.                                 widgetWidth = widgetHeight * textureAspect;
  25.                                 float x = (mTex.width - widgetWidth) / mTex.width * 0.5f;
  26.                                 mTex.drawRegion = new Vector4(x, 0f, 1f - x, 1f);
  27.                         }
  28.                         else
  29.                         {
  30.                                 widgetHeight = widgetWidth / textureAspect;
  31.                                 float y = (mTex.height - widgetHeight) / mTex.height * 0.5f;
  32.                                 mTex.drawRegion = new Vector4(0f, y, 1f, 1f - y);
  33.                         }
  34.                 }
  35.         }
  36. }

helmesjo

  • Full Member
  • ***
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 116
    • View Profile
Re: [REQUEST]: Ability to choose TRUE Aspect Ratio for UITexture
« Reply #6 on: August 19, 2014, 01:28:34 PM »
Here's another more complicated version that will make a UITexture always fit the content image within the widget's bounds:
  1. using UnityEngine;
  2.  
  3. [ExecuteInEditMode]
  4. [RequireComponent(typeof(UITexture))]
  5. public class UIFitTexture : MonoBehaviour
  6. {
  7.         UITexture mTex;
  8.  
  9.         void Awake () { mTex = GetComponent<UITexture>(); }
  10.  
  11.         void Update ()
  12.         {
  13.                 Texture tex = mTex.mainTexture;
  14.  
  15.                 if (tex != null)
  16.                 {
  17.                         float widgetWidth = mTex.width;
  18.                         float widgetHeight = mTex.height;
  19.                         float widgetAspect = widgetWidth / widgetHeight;
  20.                         float textureAspect = (float)tex.width / tex.height;
  21.  
  22.                         if (textureAspect < widgetAspect)
  23.                         {
  24.                                 widgetWidth = widgetHeight * textureAspect;
  25.                                 float x = (mTex.width - widgetWidth) / mTex.width * 0.5f;
  26.                                 mTex.drawRegion = new Vector4(x, 0f, 1f - x, 1f);
  27.                         }
  28.                         else
  29.                         {
  30.                                 widgetHeight = widgetWidth / textureAspect;
  31.                                 float y = (mTex.height - widgetHeight) / mTex.height * 0.5f;
  32.                                 mTex.drawRegion = new Vector4(0f, y, 1f, 1f - y);
  33.                         }
  34.                 }
  35.         }
  36. }

This latter is more like it, but still missing the AspectFill-mode (also running in update).

This is default behaviour so you should really consider integrate it with UITexture (and UISprite also really).

Cheers!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: [REQUEST]: Ability to choose TRUE Aspect Ratio for UITexture
« Reply #7 on: August 19, 2014, 01:35:21 PM »
Your functionality makes the image no longer correspond to the collider dimensions. My approach does, but  it also makes it not work if you happen to have it constrained and try to use it as a slider's foreground (as that's what drawRegion was originally written for). The way I see it the incompatibility with being a slider's foreground when the option is active is a lesser evil. It's not a fully ideal solution, but better.

Also, what's AspectFill? Image's texture must always remain within the bounds of the widget. It must never exceed it.

helmesjo

  • Full Member
  • ***
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 116
    • View Profile
Re: [REQUEST]: Ability to choose TRUE Aspect Ratio for UITexture
« Reply #8 on: August 19, 2014, 03:01:29 PM »
Your functionality makes the image no longer correspond to the collider dimensions. My approach does, but  it also makes it not work if you happen to have it constrained and try to use it as a slider's foreground (as that's what drawRegion was originally written for). The way I see it the incompatibility with being a slider's foreground when the option is active is a lesser evil. It's not a fully ideal solution, but better.

Also, what's AspectFill? Image's texture must always remain within the bounds of the widget. It must never exceed it.

Well, now you're talking about implementation details for your framework, which much comes down to the split of widgets and panels (ideally every widget AKA "view" should be able to clip it's content).
I'm really just talking about common functionality expected in the components you try to mimic (comparing to long-time developed standards created by for example Google and Apple). Since I come from that background, that is what I mostly compare with.

See contentMode for UIView (also see the available flags): https://developer.apple.com/library/ios/documentation/uikit/reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instp/UIView/contentMode

Aspect Fill is when the content is scaled up to fill up the boundaries completely, still keeping the aspect ratio of the content (image in this case). And again, this is where the widget should be able to clip its own content. Still, even without clip, it is still useful for fullscreen UITextures etc.
« Last Edit: August 19, 2014, 04:09:12 PM by helmesjo »