Author Topic: Change fill direction of radial fills?  (Read 5628 times)

StridingDragon

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 53
    • View Profile
Change fill direction of radial fills?
« on: April 25, 2013, 10:23:44 PM »
Currently radial fills — such as in progress bars — are filling counter-clockwise. Is there way to switch them to work clockwise? I'd need a Radial 180 degree fill that starts at 6 o'clock and fills clockwise to 12 o'clock but I can't seem to figure it out. Thanks for any ideas or tips you guys may have.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Change fill direction of radial fills?
« Reply #1 on: April 26, 2013, 01:40:16 PM »
Check the "Invert Fill" checkbox, rotate it 180 degrees, and lerp from 1 to 0 instead of 0 to 1.

StridingDragon

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 53
    • View Profile
Re: Change fill direction of radial fills?
« Reply #2 on: April 26, 2013, 03:58:04 PM »
I tried that but it doesn't work in my case because of the shape of my progress bar. It is actually a left half-circle and I need a real clockwise radial fill for follow the contour of the shape. So, I assume from your answer that this is not currently possible?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Change fill direction of radial fills?
« Reply #3 on: April 26, 2013, 09:01:56 PM »
You can also approach it from the opposite side. Instead of filling in the "filled" sprite", fill in the "empty" sprite on top of the filled sprite. Short of that -- you can create your own custom widget, overwriting the OnFill function and creating geometry as you need it.

StridingDragon

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 53
    • View Profile
Re: Change fill direction of radial fills?
« Reply #4 on: April 27, 2013, 12:57:43 AM »
I got it to work - the way you suggested in a way. I flipped the image in Photoshop. In Unity I then applied that radial fill and then rotated the resulting image 180 degrees. That did the trick. :-)

Thanks so much for your help.

Mogaba

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 8
    • View Profile
Re: Change fill direction of radial fills?
« Reply #5 on: April 25, 2014, 05:47:00 PM »
Could you possibly expand on your solution and give steps on how you did it? I am having this same issue and really need to resolve it! I am particularly interested in figuring out how to get it to fill in such a way that it fits with the contour of a circle, so it is not cutting off the end of it at an angle.

Thank you!

Thank you!

Fremium

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 1
    • View Profile
Re: Change fill direction of radial fills?
« Reply #6 on: May 08, 2017, 07:21:56 AM »
I've faced the same issue with change of fill direction for radial fills during updating of UI in one of my old games.

It still uses NGUI v2.7 and I can't switch it to last NGUI version since it will need a lot of refactoring.

I have 2 halfs of donut circles mirrowing each other to imitate radial progress bar constantly rotating.

Right half of the circle grows from 0 to 180 degrees at each fixed frame.

I need left half of the circle to continue to grow from 180 to 360 degrees.

But I have different effect (see screenshot given bellow).



Thus I've decided to make my own implementation of UIFilledSprite.cs and made copy of it.

But now I am stuck with mathematics since I can't understand how to modify the script.

I need to mirrow the effect being shown for left half circle when option FillDirection.Radial180 is selected in my new script.

Please, see copy of original UIFilledSprite.cs given bellow from my NGUI v2.7 used in my project.

Can you help me to find out what modifications should I make to get it work properly?

Thanks.

  1. //----------------------------------------------
  2. //            NGUI: Next-Gen UI kit
  3. // Copyright © 2011-2012 Tasharen Entertainment
  4. //----------------------------------------------
  5.  
  6. using UnityEngine;
  7. using System.Collections.Generic;
  8.  
  9. /// <summary>
  10. /// Similar to a regular UISprite, but lets you only display a part of it. Great for progress bars, sliders, timers, etc.
  11. /// </summary>
  12.  
  13. [ExecuteInEditMode]
  14. [AddComponentMenu("NGUI/UI/Sprite (Filled)")]
  15. public class UIFilledSpriteLeftHalfCircle : UISprite
  16. {
  17.         public enum FillDirection
  18.         {
  19.                 Horizontal,
  20.                 Vertical,
  21.                 Radial90,
  22.                 Radial180,
  23.                 Radial360,
  24.         }
  25.  
  26.         [HideInInspector][SerializeField] FillDirection mFillDirection = FillDirection.Radial360;
  27.         [HideInInspector][SerializeField] float mFillAmount = 1.0f;
  28.         [HideInInspector][SerializeField] bool mInvert = false;
  29.  
  30.         /// <summary>
  31.         /// Direction of the cut procedure.
  32.         /// </summary>
  33.  
  34.         public FillDirection fillDirection
  35.         {
  36.                 get
  37.                 {
  38.                         return mFillDirection;
  39.                 }
  40.                 set
  41.                 {
  42.                         if (mFillDirection != value)
  43.                         {
  44.                                 mFillDirection = value;
  45.                                 mChanged = true;
  46.                         }
  47.                 }
  48.         }
  49.  
  50.         /// <summary>
  51.         /// Amount of the sprite shown. 0-1 range with 0 being nothing shown, and 1 being the full sprite.
  52.         /// </summary>
  53.  
  54.         public float fillAmount
  55.         {
  56.                 get
  57.                 {
  58.                         return mFillAmount;
  59.                 }
  60.                 set
  61.                 {
  62.                         float val = Mathf.Clamp01(value);
  63.  
  64.                         if (mFillAmount != val)
  65.                         {
  66.                                 mFillAmount = val;
  67.                                 mChanged = true;
  68.                         }
  69.                 }
  70.         }
  71.  
  72.         /// <summary>
  73.         /// Whether the sprite should be filled in the opposite direction.
  74.         /// </summary>
  75.  
  76.         public bool invert
  77.         {
  78.                 get
  79.                 {
  80.                         return mInvert;
  81.                 }
  82.                 set
  83.                 {
  84.                         if (mInvert != value)
  85.                         {
  86.                                 mInvert = value;
  87.                                 mChanged = true;
  88.                         }
  89.                 }
  90.         }
  91.  
  92.         /// <summary>
  93.         /// Adjust the specified quad, making it be radially filled instead.
  94.         /// </summary>
  95.  
  96.         bool AdjustRadial (Vector2[] xy, Vector2[] uv, float fill, bool invert)
  97.         {
  98.                 // Nothing to fill
  99.                 if (fill < 0.001f) return false;
  100.  
  101.                 // Nothing to adjust
  102.                 if (!invert && fill > 0.999f) return true;
  103.  
  104.                 // Convert 0-1 value into 0 to 90 degrees angle in radians
  105.                 float angle = Mathf.Clamp01(fill);
  106.                 if (!invert) angle = 1f - angle;
  107.                 angle *= 90f * Mathf.Deg2Rad;
  108.  
  109.                 // Calculate the effective X and Y factors
  110.                 float fx = Mathf.Sin(angle);
  111.                 float fy = Mathf.Cos(angle);
  112.  
  113.                 // Normalize the result, so it's projected onto the side of the rectangle
  114.                 if (fx > fy)
  115.                 {
  116.                         fy *= 1f / fx;
  117.                         fx = 1f;
  118.  
  119.                         if (!invert)
  120.                         {
  121.                                 xy[0].y = Mathf.Lerp(xy[2].y, xy[0].y, fy);
  122.                                 xy[3].y = xy[0].y;
  123.  
  124.                                 uv[0].y = Mathf.Lerp(uv[2].y, uv[0].y, fy);
  125.                                 uv[3].y = uv[0].y;
  126.                         }
  127.                 }
  128.                 else if (fy > fx)
  129.                 {
  130.                         fx *= 1f / fy;
  131.                         fy = 1f;
  132.  
  133.                         if (invert)
  134.                         {
  135.                                 xy[0].x = Mathf.Lerp(xy[2].x, xy[0].x, fx);
  136.                                 xy[1].x = xy[0].x;
  137.  
  138.                                 uv[0].x = Mathf.Lerp(uv[2].x, uv[0].x, fx);
  139.                                 uv[1].x = uv[0].x;
  140.                         }
  141.                 }
  142.                 else
  143.                 {
  144.                         fx = 1f;
  145.                         fy = 1f;
  146.                 }
  147.  
  148.                 if (invert)
  149.                 {
  150.                         xy[1].y = Mathf.Lerp(xy[2].y, xy[0].y, fy);
  151.                         uv[1].y = Mathf.Lerp(uv[2].y, uv[0].y, fy);
  152.                 }
  153.                 else
  154.                 {
  155.                         xy[3].x = Mathf.Lerp(xy[2].x, xy[0].x, fx);
  156.                         uv[3].x = Mathf.Lerp(uv[2].x, uv[0].x, fx);
  157.                 }
  158.                 return true;
  159.         }
  160.  
  161.         /// <summary>
  162.         /// Helper function that copies the contents of the array, rotated by the specified offset.
  163.         /// </summary>
  164.  
  165.         void Rotate (Vector2[] v, int offset)
  166.         {
  167.                 for (int i = 0; i < offset; ++i)
  168.                 {
  169.                         Vector2 v0 = new Vector2(v[3].x, v[3].y);
  170.  
  171.                         v[3].x = v[2].y;
  172.                         v[3].y = v[2].x;
  173.  
  174.                         v[2].x = v[1].y;
  175.                         v[2].y = v[1].x;
  176.  
  177.                         v[1].x = v[0].y;
  178.                         v[1].y = v[0].x;
  179.  
  180.                         v[0].x = v0.y;
  181.                         v[0].y = v0.x;
  182.                 }
  183.         }
  184.  
  185.         /// <summary>
  186.         /// Virtual function called by the UIScreen that fills the buffers.
  187.         /// </summary>
  188.  
  189. #if UNITY_3_5_4
  190.         override public void OnFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color> cols)
  191. #else
  192.         override public void OnFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
  193. #endif
  194.         {
  195.                 float x0 =  0f;
  196.                 float y0 =  0f;
  197.                 float x1 =  1f;
  198.                 float y1 = -1f;
  199.  
  200.                 float u0 = mOuterUV.xMin;
  201.                 float v0 = mOuterUV.yMin;
  202.                 float u1 = mOuterUV.xMax;
  203.                 float v1 = mOuterUV.yMax;
  204.  
  205.                 // Horizontal and vertical filled sprites are simple -- just end the sprite prematurely
  206.                 if (mFillDirection == FillDirection.Horizontal || mFillDirection == FillDirection.Vertical)
  207.                 {
  208.                         float du = (u1 - u0) * mFillAmount;
  209.                         float dv = (v1 - v0) * mFillAmount;
  210.  
  211.                         if (fillDirection == FillDirection.Horizontal)
  212.                         {
  213.                                 if (mInvert)
  214.                                 {
  215.                                         x0 = (1f - mFillAmount);
  216.                                         u0 = u1 - du;
  217.                                 }
  218.                                 else
  219.                                 {
  220.                                         x1 *= mFillAmount;
  221.                                         u1 = u0 + du;
  222.                                 }
  223.                         }
  224.                         else if (fillDirection == FillDirection.Vertical)
  225.                         {
  226.                                 if (mInvert)
  227.                                 {
  228.                                         y1 *= mFillAmount;
  229.                                         v0 = v1 - dv;
  230.                                 }
  231.                                 else
  232.                                 {
  233.                                         y0 = -(1f - mFillAmount);
  234.                                         v1 = v0 + dv;
  235.                                 }
  236.                         }
  237.                 }
  238.  
  239.                 // Starting quad for the sprite
  240.                 Vector2[] xy = new Vector2[4];
  241.                 Vector2[] uv = new Vector2[4];
  242.  
  243.                 xy[0] = new Vector2(x1, y0);
  244.                 xy[1] = new Vector2(x1, y1);
  245.                 xy[2] = new Vector2(x0, y1);
  246.                 xy[3] = new Vector2(x0, y0);
  247.  
  248.                 uv[0] = new Vector2(u1, v1);
  249.                 uv[1] = new Vector2(u1, v0);
  250.                 uv[2] = new Vector2(u0, v0);
  251.                 uv[3] = new Vector2(u0, v1);
  252.  
  253. #if UNITY_3_5_4
  254.                 Color col = color;
  255. #else
  256.                 Color32 col = color;
  257. #endif
  258.  
  259.                 if (fillDirection == FillDirection.Radial90)
  260.                 {
  261.                         // Adjust the quad radially, and if 'false' is returned (it's not visible), just exit
  262.                         if (!AdjustRadial(xy, uv, mFillAmount, mInvert)) return;
  263.                 }
  264.                 else if (fillDirection == FillDirection.Radial180)
  265.                 {
  266.                         // Working in 0-1 coordinates is easier
  267.                         Vector2[] oxy = new Vector2[4];
  268.                         Vector2[] ouv = new Vector2[4];
  269.  
  270.                         for (int i = 0; i < 2; ++i)
  271.                         {
  272.                                 oxy[0] = new Vector2(0f, 0f);
  273.                                 oxy[1] = new Vector2(0f, 1f);
  274.                                 oxy[2] = new Vector2(1f, 1f);
  275.                                 oxy[3] = new Vector2(1f, 0f);
  276.  
  277.                                 ouv[0] = new Vector2(0f, 0f);
  278.                                 ouv[1] = new Vector2(0f, 1f);
  279.                                 ouv[2] = new Vector2(1f, 1f);
  280.                                 ouv[3] = new Vector2(1f, 0f);
  281.  
  282.                                 // Each half must be rotated 90 degrees clockwise in order for it to fill properly
  283.                                 if (mInvert)
  284.                                 {
  285.                                         if (i > 0)
  286.                                         {
  287.                                                 Rotate(oxy, i);
  288.                                                 Rotate(ouv, i);
  289.                                         }
  290.                                 }
  291.                                 else if (i < 1)
  292.                                 {
  293.                                         Rotate(oxy, 1 - i);
  294.                                         Rotate(ouv, 1 - i);
  295.                                 }
  296.  
  297.                                 // Each half must fill in only a part of the space
  298.                                 float x, y;
  299.  
  300.                                 if (i == 1)
  301.                                 {
  302.                                         x = mInvert ? 0.5f : 1f;
  303.                                         y = mInvert ? 1f : 0.5f;
  304.                                 }
  305.                                 else
  306.                                 {
  307.                                         x = mInvert ? 1f : 0.5f;
  308.                                         y = mInvert ? 0.5f : 1f;
  309.                                 }
  310.  
  311.                                 oxy[1].y = Mathf.Lerp(x, y, oxy[1].y);
  312.                                 oxy[2].y = Mathf.Lerp(x, y, oxy[2].y);
  313.                                 ouv[1].y = Mathf.Lerp(x, y, ouv[1].y);
  314.                                 ouv[2].y = Mathf.Lerp(x, y, ouv[2].y);
  315.  
  316.                                 float amount = (mFillAmount) * 2 - i;
  317.                                 bool odd = (i % 2) == 1;
  318.  
  319.                                 if (AdjustRadial(oxy, ouv, amount, !odd))
  320.                                 {
  321.                                         if (mInvert) odd = !odd;
  322.  
  323.                                         // Add every other side in reverse order so they don't come out backface-culled due to rotation
  324.                                         if (odd)
  325.                                         {
  326.                                                 for (int b = 0; b < 4; ++b)
  327.                                                 {
  328.                                                         x = Mathf.Lerp(xy[0].x, xy[2].x, oxy[b].x);
  329.                                                         y = Mathf.Lerp(xy[0].y, xy[2].y, oxy[b].y);
  330.  
  331.                                                         float u = Mathf.Lerp(uv[0].x, uv[2].x, ouv[b].x);
  332.                                                         float v = Mathf.Lerp(uv[0].y, uv[2].y, ouv[b].y);
  333.  
  334.                                                         verts.Add(new Vector3(x, y, 0f));
  335.                                                         uvs.Add(new Vector2(u, v));
  336.                                                         cols.Add(col);
  337.                                                 }
  338.                                         }
  339.                                         else
  340.                                         {
  341.                                                 for (int b = 3; b > -1; --b)
  342.                                                 {
  343.                                                         x = Mathf.Lerp(xy[0].x, xy[2].x, oxy[b].x);
  344.                                                         y = Mathf.Lerp(xy[0].y, xy[2].y, oxy[b].y);
  345.  
  346.                                                         float u = Mathf.Lerp(uv[0].x, uv[2].x, ouv[b].x);
  347.                                                         float v = Mathf.Lerp(uv[0].y, uv[2].y, ouv[b].y);
  348.  
  349.                                                         verts.Add(new Vector3(x, y, 0f));
  350.                                                         uvs.Add(new Vector2(u, v));
  351.                                                         cols.Add(col);
  352.                                                 }
  353.                                         }
  354.                                 }
  355.                         }
  356.                         return;
  357.                 }
  358.                 else if (fillDirection == FillDirection.Radial360)
  359.                 {
  360.                         float[] matrix = new float[]
  361.                         {
  362.                                 // x0 y0  x1   y1
  363.                                 0.5f, 1f, 0f, 0.5f, // quadrant 0
  364.                                 0.5f, 1f, 0.5f, 1f, // quadrant 1
  365.                                 0f, 0.5f, 0.5f, 1f, // quadrant 2
  366.                                 0f, 0.5f, 0f, 0.5f, // quadrant 3
  367.                         };
  368.  
  369.                         Vector2[] oxy = new Vector2[4];
  370.                         Vector2[] ouv = new Vector2[4];
  371.  
  372.                         for (int i = 0; i < 4; ++i)
  373.                         {
  374.                                 oxy[0] = new Vector2(0f, 0f);
  375.                                 oxy[1] = new Vector2(0f, 1f);
  376.                                 oxy[2] = new Vector2(1f, 1f);
  377.                                 oxy[3] = new Vector2(1f, 0f);
  378.  
  379.                                 ouv[0] = new Vector2(0f, 0f);
  380.                                 ouv[1] = new Vector2(0f, 1f);
  381.                                 ouv[2] = new Vector2(1f, 1f);
  382.                                 ouv[3] = new Vector2(1f, 0f);
  383.  
  384.                                 // Each quadrant must be rotated 90 degrees clockwise in order for it to fill properly
  385.                                 if (mInvert)
  386.                                 {
  387.                                         if (i > 0)
  388.                                         {
  389.                                                 Rotate(oxy, i);
  390.                                                 Rotate(ouv, i);
  391.                                         }
  392.                                 }
  393.                                 else if (i < 3)
  394.                                 {
  395.                                         Rotate(oxy, 3 - i);
  396.                                         Rotate(ouv, 3 - i);
  397.                                 }
  398.  
  399.                                 // Each quadrant must fill in only a quarter of the space
  400.                                 for (int b = 0; b < 4; ++b)
  401.                                 {
  402.                                         int index = (mInvert) ? (3 - i) * 4 : i * 4;
  403.  
  404.                                         float fx0 = matrix[index];
  405.                                         float fy0 = matrix[index + 1];
  406.                                         float fx1 = matrix[index + 2];
  407.                                         float fy1 = matrix[index + 3];
  408.  
  409.                                         oxy[b].x = Mathf.Lerp(fx0, fy0, oxy[b].x);
  410.                                         oxy[b].y = Mathf.Lerp(fx1, fy1, oxy[b].y);
  411.                                         ouv[b].x = Mathf.Lerp(fx0, fy0, ouv[b].x);
  412.                                         ouv[b].y = Mathf.Lerp(fx1, fy1, ouv[b].y);
  413.                                 }
  414.  
  415.                                 float amount = (mFillAmount) * 4 - i;
  416.                                 bool odd = (i % 2) == 1;
  417.  
  418.                                 if (AdjustRadial(oxy, ouv, amount, !odd))
  419.                                 {
  420.                                         if (mInvert) odd = !odd;
  421.  
  422.                                         // Add every other side in reverse order so they don't come out backface-culled due to rotation
  423.                                         if (odd)
  424.                                         {
  425.                                                 for (int b = 0; b < 4; ++b)
  426.                                                 {
  427.                                                         float x = Mathf.Lerp(xy[0].x, xy[2].x, oxy[b].x);
  428.                                                         float y = Mathf.Lerp(xy[0].y, xy[2].y, oxy[b].y);
  429.                                                         float u = Mathf.Lerp(uv[0].x, uv[2].x, ouv[b].x);
  430.                                                         float v = Mathf.Lerp(uv[0].y, uv[2].y, ouv[b].y);
  431.  
  432.                                                         verts.Add(new Vector3(x, y, 0f));
  433.                                                         uvs.Add(new Vector2(u, v));
  434.                                                         cols.Add(col);
  435.                                                 }
  436.                                         }
  437.                                         else
  438.                                         {
  439.                                                 for (int b = 3; b > -1; --b)
  440.                                                 {
  441.                                                         float x = Mathf.Lerp(xy[0].x, xy[2].x, oxy[b].x);
  442.                                                         float y = Mathf.Lerp(xy[0].y, xy[2].y, oxy[b].y);
  443.                                                         float u = Mathf.Lerp(uv[0].x, uv[2].x, ouv[b].x);
  444.                                                         float v = Mathf.Lerp(uv[0].y, uv[2].y, ouv[b].y);
  445.  
  446.                                                         verts.Add(new Vector3(x, y, 0f));
  447.                                                         uvs.Add(new Vector2(u, v));
  448.                                                         cols.Add(col);
  449.                                                 }
  450.                                         }
  451.                                 }
  452.                         }
  453.                         return;
  454.                 }
  455.  
  456.                 // Fill the buffer with the quad for the sprite
  457.                 for (int i = 0; i < 4; ++i)
  458.                 {
  459.                         verts.Add(xy[i]);
  460.                         uvs.Add(uv[i]);
  461.                         cols.Add(col);
  462.                 }
  463.         }
  464. }
  465.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Change fill direction of radial fills?
« Reply #7 on: May 13, 2017, 12:02:08 PM »
I'm sorry I can't do anything for NGUI 2.7.