Author Topic: Slider - Fill a Sliced Sprite?  (Read 3673 times)

guillopuyol

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 5
    • View Profile
Slider - Fill a Sliced Sprite?
« on: January 27, 2015, 01:05:58 PM »
Hello,

I'm making a progress bar.  It has rounded corners.  I'd like to have it stretch for multiple resolutions like a sliced sprite, but I want the slider to fill rather than stretch.

I saw this question asked before where the person illustrated as follows:

Full Bar:   ((-------------))
Lower:     ((-------------)
Lower:     ((-------------

So the rounded corners look good when it starts, but as the health decreases the slider "unfills".

The only solution I've found so far is to have a BIG sprite that covers the entire length of the bar and set it as filled, but that doesn't allow for my health bar to shrink and expand for multiple resolutions and it uses unnecessary texture space in the atlas.

Any ideas will be very much appreciated.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Slider - Fill a Sliced Sprite?
« Reply #1 on: January 28, 2015, 01:42:49 AM »
You're basically trying to combine two types of sprites here -- sliced and filled. There is no such sprite in NGUI, so if you want this kind of behaviour, you will need to add a custom sprite type and do your own OnFill logic.

Wisteso

  • Full Member
  • ***
  • Thank You
  • -Given: 21
  • -Receive: 3
  • Posts: 103
    • View Profile
Re: Slider - Fill a Sliced Sprite?
« Reply #2 on: June 26, 2015, 09:09:39 PM »
Yes this is a thread necro but since this result comes up on google searching for the topic, it seems like a good place to add my solution.

Since I couldn't find a solution for this anywhere, I decided to figure it out on my own.

It's a little hacky (wont respect Flip, Fill Direction, or Invert Fill), but should be plenty for most people and if they want the fancy stuff it shouldn't be too hard to figure out.

Here's a link to it on gist.github.com and in the thread in case the link becomes broken ever...https://gist.github.com/wisteso/a7bb5bc9178692aa9c2d

  1. using UnityEngine;
  2. using System.Collections;
  3. using System;
  4.  
  5. public class UISpritePlus : UISprite
  6. {
  7.     /*
  8.      * This class doesn't really do all that much more than what the parent does.
  9.      * Only about a 10-15 lines are tweaked, and not tweaked that much.
  10.      */
  11.  
  12.     protected void SlicedFill(BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols, Rect mOuterUV, Rect mInnerUV)
  13.     {
  14.         Vector4 br = border * pixelSize;
  15.  
  16.         Color32 c = drawingColor;
  17.         Vector4 v = drawingDimensions;
  18.  
  19.         float perc = fillAmount; // drawRegion.z - drawRegion.x;
  20.         float percentMaxLeft = br.x / mWidth;
  21.         float percentMaxRight = br.z / mWidth;
  22.         float percentMaxMiddle = 1F - (percentMaxLeft + percentMaxRight);
  23.         float[] percentActual = {
  24.             Mathf.Clamp01(perc / percentMaxLeft),
  25.             Mathf.Clamp01((perc - percentMaxLeft) / percentMaxMiddle),
  26.             Mathf.Clamp01((perc - percentMaxLeft - percentMaxMiddle) / percentMaxRight),
  27.         };
  28.  
  29.         mTempPos[0].x = v.x;
  30.         mTempPos[1].x = v.x + br.x * percentActual[0];
  31.         mTempPos[2].x = mTempPos[1].x + (v.z - v.x - br.x - br.z) * percentActual[1];
  32.         mTempPos[3].x = v.z - br.z * (1F - percentActual[2]);
  33.  
  34.         mTempUVs[0].x = mOuterUV.xMin;
  35.         mTempUVs[1].x = mOuterUV.xMin + (mInnerUV.xMin - mOuterUV.xMin) * percentActual[0];
  36.         mTempUVs[2].x = mInnerUV.xMax;
  37.         mTempUVs[3].x = mInnerUV.xMax + (mOuterUV.xMax - mInnerUV.xMax) * percentActual[2];
  38.  
  39.         mTempPos[0].y = v.y;
  40.         mTempPos[1].y = mTempPos[0].y + br.y;
  41.         mTempPos[2].y = mTempPos[3].y - br.w;
  42.         mTempPos[3].y = v.w;
  43.  
  44.         mTempUVs[0].y = mOuterUV.yMin;
  45.         mTempUVs[1].y = mInnerUV.yMin;
  46.         mTempUVs[2].y = mInnerUV.yMax;
  47.         mTempUVs[3].y = mOuterUV.yMax;
  48.  
  49.         for (int x = 0; x < 3; ++x)
  50.         {
  51.             if (percentActual[x] <= 0) continue;
  52.  
  53.             int x2 = x + 1;
  54.  
  55.             for (int y = 0; y < 3; ++y)
  56.             {
  57.                 if (centerType == AdvancedType.Invisible && x == 1 && y == 1) continue;
  58.  
  59.                 int y2 = y + 1;
  60.  
  61.                 verts.Add(new Vector3(mTempPos[x].x, mTempPos[y].y));
  62.                 verts.Add(new Vector3(mTempPos[x].x, mTempPos[y2].y));
  63.                 verts.Add(new Vector3(mTempPos[x2].x, mTempPos[y2].y));
  64.                 verts.Add(new Vector3(mTempPos[x2].x, mTempPos[y].y));
  65.  
  66.                 uvs.Add(new Vector2(mTempUVs[x].x, mTempUVs[y].y));
  67.                 uvs.Add(new Vector2(mTempUVs[x].x, mTempUVs[y2].y));
  68.                 uvs.Add(new Vector2(mTempUVs[x2].x, mTempUVs[y2].y));
  69.                 uvs.Add(new Vector2(mTempUVs[x2].x, mTempUVs[y].y));
  70.  
  71.                 cols.Add(c);
  72.                 cols.Add(c);
  73.                 cols.Add(c);
  74.                 cols.Add(c);
  75.             }
  76.         }
  77.     }
  78.  
  79.     // below method is MOSTLY a copy/paste from parent class.
  80.     // if SlicedFill was overrideable in the parent class, this could be removed
  81.     public override void OnFill(BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
  82.     {
  83.         if (type == Type.Filled)
  84.         {
  85.             Texture tex = mainTexture;
  86.             if (tex == null) return;
  87.  
  88.             if (mSprite == null) mSprite = atlas.GetSprite(spriteName);
  89.             if (mSprite == null) return;
  90.  
  91.             Rect outer = new Rect(mSprite.x, mSprite.y, mSprite.width, mSprite.height);
  92.             Rect inner = new Rect(mSprite.x + mSprite.borderLeft, mSprite.y + mSprite.borderTop,
  93.                 mSprite.width - mSprite.borderLeft - mSprite.borderRight,
  94.                 mSprite.height - mSprite.borderBottom - mSprite.borderTop);
  95.  
  96.             outer = NGUIMath.ConvertToTexCoords(outer, tex.width, tex.height);
  97.             inner = NGUIMath.ConvertToTexCoords(inner, tex.width, tex.height);
  98.  
  99.             int offset = verts.size;
  100.             SlicedFill(verts, uvs, cols, outer, inner);
  101.  
  102.             if (onPostFill != null)
  103.                 onPostFill(this, offset, verts, uvs, cols);
  104.         }
  105.         else
  106.         {
  107.             base.OnFill(verts, uvs, cols);
  108.         }
  109.     }
  110.  
  111.     // below method is purely a copy/paste from parent class.
  112.     // if drawingColor was "protected" in the parent class, this could be removed
  113.     Color32 drawingColor
  114.     {
  115.         get
  116.         {
  117.             Color colF = color;
  118.             colF.a = finalAlpha;
  119.             if (premultipliedAlpha) colF = NGUITools.ApplyPMA(colF);
  120.  
  121.             if (QualitySettings.activeColorSpace == ColorSpace.Linear)
  122.             {
  123.                 colF.r = Mathf.Pow(colF.r, 2.2f);
  124.                 colF.g = Mathf.Pow(colF.g, 2.2f);
  125.                 colF.b = Mathf.Pow(colF.b, 2.2f);
  126.             }
  127.             return colF;
  128.         }
  129.     }
  130. }
  131.