Skip to content

Instantly share code, notes, and snippets.

@huiliu
Last active May 30, 2018 21:04
Show Gist options
  • Select an option

  • Save huiliu/45d7392146e56b8c7e3d89de13ddb95b to your computer and use it in GitHub Desktop.

Select an option

Save huiliu/45d7392146e56b8c7e3d89de13ddb95b to your computer and use it in GitHub Desktop.

Revisions

  1. huiliu revised this gist May 30, 2018. 1 changed file with 142 additions and 185 deletions.
    327 changes: 142 additions & 185 deletions SlicedImage.cs
    Original file line number Diff line number Diff line change
    @@ -1,14 +1,11 @@
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    using UnityEngine.Sprites;

    /// <summary>
    /// 参照 https://www.cnblogs.com/ninomiya/p/8134497.html 修改
    /// </summary>
    public class SlicedImage : Image
    {
    public SlicedType slicedType;

    public class ChildImage : Image{

    protected override void OnPopulateMesh(VertexHelper toFill)
    {
    base.OnPopulateMesh(toFill);
    @@ -19,18 +16,8 @@ protected override void OnPopulateMesh(VertexHelper toFill)
    }
    if (type == Type.Sliced)
    {
    switch (slicedType)
    {
    case SlicedType.Center:
    GenerateSlicedSpriteCenter(toFill);
    break;
    case SlicedType.Left:
    GenerateSlicedSpriteLeft(toFill);
    break;
    case SlicedType.Right:
    GenerateSlicedSpriteRight(toFill);
    break;
    }
    //GenerateSlicedSprite_(toFill);
    GenerateSprite(toFill);
    }
    }

    @@ -63,8 +50,7 @@ static void AddQuad(VertexHelper vertexHelper, Vector2 posMin, Vector2 posMax, C
    vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
    vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
    }

    private void GenerateSlicedSpriteLeft(VertexHelper toFill)
    private void GenerateSlicedSprite_(VertexHelper toFill)
    {
    Vector4 outer, inner, padding, border;

    @@ -87,43 +73,38 @@ private void GenerateSlicedSpriteLeft(VertexHelper toFill)
    border = GetAdjustedBorders(border / pixelsPerUnit, rect);
    padding = padding / pixelsPerUnit;
    float condition = (border.z + border.x) / rect.width;
    var realFillAmount = fillAmount;
    #region 实际显示size
    float[] x = { 0, 0, 0, 0 };
    float[] x={0,0,0,0};

    x[0] = 0;
    if (fillAmount <condition)
    {
    x[0] = 0;
    if (realFillAmount < condition)
    {
    x[1] = realFillAmount / 2 * rect.width;
    x[2] = x[1] + 0;
    x[3] = x[1] * 2;
    }
    else
    {
    x[1] = border.x;
    x[2] = rect.width * realFillAmount - border.z;
    x[3] = x[2] + border.z;
    }
    x[1] = fillAmount / 2 * rect.width;
    x[2] = x[1]+ 0;
    x[3] = x[1]*2;
    }
    else
    {
    x[1] = border.x;
    x[2] = rect.width *fillAmount-border.z;
    x[3] =x[2]+border.z;
    }
    float []y ={0+rect.y,rect.height+rect.y};

    float[] y = { 0 + rect.y, rect.height + rect.y };

    Debug.Log(string.Format("xo: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    for (int i = 0; i < 4; ++i)
    {
    x[i] += rect.x;
    }

    }
    #endregion

    #region uv值
    float[] x_uv = { 0, 0, 0, 0 };
    float[] x_uv = {0,0,0,0 };

    x_uv[0] = 0;
    if (realFillAmount < condition)
    x_uv[0] =0;
    if (fillAmount <condition)
    {
    x_uv[1] = realFillAmount * rect.width / 2 / sprite.rect.size.x;
    x_uv[1] = fillAmount*rect.width/2/sprite.rect.size.x;
    x_uv[2] = 1 - x_uv[1];
    }
    else
    @@ -135,23 +116,25 @@ private void GenerateSlicedSpriteLeft(VertexHelper toFill)

    float y_uv = 1;
    #endregion
    Debug.Log(string.Format("x: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    Debug.Log(string.Format("x_uv: {0} {1} {2} {3}", x_uv[0], x_uv[1], x_uv[2], x_uv[3]));


    toFill.Clear();
    for (int i = 0; i < 3; i++)
    {
    int i2 = i + 1;
    AddQuad(toFill,
    new Vector2(x[i], y[0]),
    new Vector2(x[i2], y[1]),
    new Vector2(x[i],y[0]),
    new Vector2(x[i2],y[1]),
    color,
    new Vector2(x_uv[i], 0),
    new Vector2(x_uv[i2], y_uv));
    new Vector2(x_uv[i],0),
    new Vector2(x_uv[i2],y_uv));
    }

    }

    private void GenerateSlicedSpriteRight(VertexHelper toFill)
    public SliceFilledType sliceFilledType;
    static readonly Vector2[] s_VertScratch = new Vector2[4];
    static readonly Vector2[] s_UVScratch = new Vector2[4];
    private void GenerateSprite(VertexHelper toFill)
    {
    Vector4 outer, inner, padding, border;

    @@ -171,177 +154,151 @@ private void GenerateSlicedSpriteRight(VertexHelper toFill)
    }

    Rect rect = GetPixelAdjustedRect();
    border = GetAdjustedBorders(border / pixelsPerUnit, rect);
    var adjustedBorders = GetAdjustedBorders(border / pixelsPerUnit, rect);
    padding = padding / pixelsPerUnit;
    float condition = (border.z + border.x) / rect.width;
    var realFillAmount = fillAmount;
    #region 实际显示size
    float[] x = { 0, 0, 0, 0 };

    Debug.Log(string.Format("rect.x: {0} rect.y: {1} rect.width: {2} rect.heigh: {3}", rect.x, rect.y, rect.width, rect.height));
    Debug.Log(string.Format("border.x: {0} border.y: {1} border.z: {2} border.w: {3}", border.x, border.y, border.z, border.w));
    var tx0 = outer.x;
    var ty0 = outer.y;
    var tx1 = outer.z;
    var ty1 = outer.w;

    var v = GetDrawingDimensions(preserveAspect);
    var fill = (tx1 - tx0) * fillAmount;

    v.x = v.z - (v.x - v.z) * fillAmount;
    tx0 = tx1 - fill;

    switch (sliceFilledType)
    {
    x[0] = 0;
    if (realFillAmount < condition)
    {
    x[1] = realFillAmount / 2 * rect.width;
    x[2] = x[1] + 0;
    x[3] = x[1] * 2;
    }
    else
    {
    x[1] = border.x;
    x[2] = rect.width * realFillAmount - border.z;
    x[3] = x[2] + border.z;
    }
    case SliceFilledType.Left:
    {
    s_VertScratch[0] = new Vector2(padding.x, padding.y);
    //s_VertScratch[3] = new Vector2(rect.width - padding.z, rect.height - padding.w);

    var tmp = x[0];
    x[0] = x[3];
    x[3] = tmp;
    s_VertScratch[1].x = adjustedBorders.x;
    s_VertScratch[1].y = adjustedBorders.y;

    tmp = x[1];
    x[1] = x[2];
    x[2] = tmp;
    }
    s_VertScratch[2].x = (rect.width - adjustedBorders.z) * fillAmount;
    s_VertScratch[2].y = rect.height - adjustedBorders.w;

    float[] y = { 0 + rect.y, rect.height + rect.y };
    s_VertScratch[3] = new Vector2(s_VertScratch[2].x + adjustedBorders.z, rect.height - padding.w);
    }
    break;
    case SliceFilledType.Right:
    {
    s_VertScratch[2].x = rect.width - adjustedBorders.z;
    s_VertScratch[2].y = rect.height - adjustedBorders.w;

    Debug.Log(string.Format("xo: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    for (int i = 0; i < 4; ++i)
    {
    x[i] += rect.x;
    x[i] *= (-1);
    }
    s_VertScratch[3] = new Vector2(rect.width - padding.z, rect.height - padding.w);

    #endregion
    s_VertScratch[0].x = rect.width - (rect.width - adjustedBorders.x) * fillAmount - adjustedBorders.x;
    s_VertScratch[0].y = padding.y;

    #region uv值
    float[] x_uv = { 0, 0, 0, 0 };
    s_VertScratch[1].x = s_VertScratch[0].x + adjustedBorders.x;
    s_VertScratch[1].y = adjustedBorders.y;

    x_uv[0] = 0;
    if (realFillAmount < condition)
    {
    x_uv[1] = realFillAmount * rect.width / 2 / sprite.rect.size.x;
    x_uv[2] = 1 - x_uv[1];
    }
    break;
    case SliceFilledType.Center:
    {
    s_VertScratch[0].x = (rect.width - adjustedBorders.x) * fillAmount / 2;
    s_VertScratch[0].y = padding.y;

    s_VertScratch[1].x = s_VertScratch[0].x + adjustedBorders.x;
    s_VertScratch[1].y = adjustedBorders.y;

    s_VertScratch[2].x = rect.width - (rect.width - adjustedBorders.z) * fillAmount/2 - adjustedBorders.z;
    s_VertScratch[2].y = rect.height - adjustedBorders.w;

    s_VertScratch[3] = new Vector2(s_VertScratch[2].x + adjustedBorders.z, rect.height - padding.w);
    }
    break;
    }
    else

    for (int i = 0; i < 4; ++i)
    {
    x_uv[1] = inner.x;
    x_uv[2] = inner.z;
    s_VertScratch[i].x += rect.x;
    s_VertScratch[i].y += rect.y;
    }
    x_uv[3] = outer.z;

    float y_uv = 1;
    #endregion

    Debug.Log(string.Format("x: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    Debug.Log(string.Format("x_uv: {0} {1} {2} {3}", x_uv[0], x_uv[1], x_uv[2], x_uv[3]));
    s_UVScratch[0] = new Vector2(outer.x, outer.y);
    s_UVScratch[1] = new Vector2(inner.x, inner.y);
    s_UVScratch[2] = new Vector2(inner.z, inner.w);
    s_UVScratch[3] = new Vector2(outer.z, outer.w);

    toFill.Clear();
    for (int i = 0; i < 3; i++)

    for (int x = 0; x < 3; ++x)
    {
    int i2 = i + 1;
    AddQuad(toFill,
    new Vector2(x[i], y[0]),
    new Vector2(x[i2], y[1]),
    int x2 = x + 1;

    for (int y = 0; y < 3; ++y)
    {
    if (!fillCenter && x == 1 && y == 1)
    continue;

    int y2 = y + 1;


    AddQuad(toFill,
    new Vector2(s_VertScratch[x].x, s_VertScratch[y].y),
    new Vector2(s_VertScratch[x2].x, s_VertScratch[y2].y),
    color,
    new Vector2(x_uv[i], 0),
    new Vector2(x_uv[i2], y_uv));
    new Vector2(s_UVScratch[x].x, s_UVScratch[y].y),
    new Vector2(s_UVScratch[x2].x, s_UVScratch[y2].y));
    }
    }
    }

    private void GenerateSlicedSpriteCenter(VertexHelper toFill)
    /// Image's dimensions used for drawing. X = left, Y = bottom, Z = right, W = top.
    private Vector4 GetDrawingDimensions(bool shouldPreserveAspect)
    {
    Vector4 outer, inner, padding, border;
    var padding = overrideSprite == null ? Vector4.zero : UnityEngine.Sprites.DataUtility.GetPadding(overrideSprite);
    var size = overrideSprite == null ? Vector2.zero : new Vector2(overrideSprite.rect.width, overrideSprite.rect.height);

    if (overrideSprite != null)
    {
    outer = DataUtility.GetOuterUV(overrideSprite);
    inner = DataUtility.GetInnerUV(overrideSprite);
    padding = DataUtility.GetPadding(overrideSprite);
    border = overrideSprite.border;
    }
    else
    {
    outer = Vector4.zero;
    inner = Vector4.zero;
    padding = Vector4.zero;
    border = Vector4.zero;
    }
    Rect r = GetPixelAdjustedRect();
    // Debug.Log(string.Format("r:{2}, size:{0}, padding:{1}", size, padding, r));

    Rect rect = GetPixelAdjustedRect();
    border = GetAdjustedBorders(border / pixelsPerUnit, rect);
    padding = padding / pixelsPerUnit;
    float condition = (border.z + border.x) / rect.width;
    var realFillAmount = fillAmount / 2;
    #region 实际显示size
    float[] x = { 0, 0, 0, 0 };
    int spriteW = Mathf.RoundToInt(size.x);
    int spriteH = Mathf.RoundToInt(size.y);

    var v = new Vector4(
    padding.x / spriteW,
    padding.y / spriteH,
    (spriteW - padding.z) / spriteW,
    (spriteH - padding.w) / spriteH);

    if (shouldPreserveAspect && size.sqrMagnitude > 0.0f)
    {
    x[0] = 0;
    if (realFillAmount < condition)
    var spriteRatio = size.x / size.y;
    var rectRatio = r.width / r.height;

    if (spriteRatio > rectRatio)
    {
    x[1] = realFillAmount / 2 * rect.width;
    x[2] = x[1] + 0;
    x[3] = x[1] * 2;
    var oldHeight = r.height;
    r.height = r.width * (1.0f / spriteRatio);
    r.y += (oldHeight - r.height) * rectTransform.pivot.y;
    }
    else
    {
    x[1] = border.x;
    x[2] = rect.width * realFillAmount - border.z;
    x[3] = x[2] + border.z;
    var oldWidth = r.width;
    r.width = r.height * spriteRatio;
    r.x += (oldWidth - r.width) * rectTransform.pivot.x;
    }
    }

    float[] y = { 0 + rect.y, rect.height + rect.y };
    v = new Vector4(
    r.x + r.width * v.x,
    r.y + r.height * v.y,
    r.x + r.width * v.z,
    r.y + r.height * v.w
    );

    Debug.Log(string.Format("xo: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    for (int i = 0; i < 4; ++i)
    {
    x[i] += rect.x + rect.width / 2;
    //x[i] += rect.x;
    }

    #endregion

    #region uv值
    float[] x_uv = { 0, 0, 0, 0 };

    x_uv[0] = 0;
    if (realFillAmount < condition)
    {
    x_uv[1] = realFillAmount * rect.width / 2 / sprite.rect.size.x;
    x_uv[2] = 1 - x_uv[1];
    }
    else
    {
    x_uv[1] = inner.x;
    x_uv[2] = inner.z;
    }
    x_uv[3] = outer.z;

    float y_uv = 1;
    #endregion
    x[0] = -x[3];
    x[1] = -x[2];
    Debug.Log(string.Format("x: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    Debug.Log(string.Format("x_uv: {0} {1} {2} {3}", x_uv[0], x_uv[1], x_uv[2], x_uv[3]));

    toFill.Clear();
    for (int i = 0; i < 3; i++)
    {
    int i2 = i + 1;
    AddQuad(toFill,
    new Vector2(x[i], y[0]),
    new Vector2(x[i2], y[1]),
    color,
    new Vector2(x_uv[i], 0),
    new Vector2(x_uv[i2], y_uv));
    }
    return v;
    }

    public enum SlicedType
    public enum SliceFilledType
    {
    Left,
    Right,
  2. huiliu created this gist May 29, 2018.
    350 changes: 350 additions & 0 deletions SlicedImage.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,350 @@
    using UnityEngine;
    using UnityEngine.UI;
    using UnityEngine.Sprites;

    /// <summary>
    /// 参照 https://www.cnblogs.com/ninomiya/p/8134497.html 修改
    /// </summary>
    public class SlicedImage : Image
    {
    public SlicedType slicedType;

    protected override void OnPopulateMesh(VertexHelper toFill)
    {
    base.OnPopulateMesh(toFill);
    if (overrideSprite == null)
    {
    base.OnPopulateMesh(toFill);
    return;
    }
    if (type == Type.Sliced)
    {
    switch (slicedType)
    {
    case SlicedType.Center:
    GenerateSlicedSpriteCenter(toFill);
    break;
    case SlicedType.Left:
    GenerateSlicedSpriteLeft(toFill);
    break;
    case SlicedType.Right:
    GenerateSlicedSpriteRight(toFill);
    break;
    }
    }
    }

    Vector4 GetAdjustedBorders(Vector4 border, Rect rect)
    {
    for (int axis = 0; axis <= 1; axis++)
    {
    // If the rect is smaller than the combined borders, then there's not room for the borders at their normal size.
    // In order to avoid artefacts with overlapping borders, we scale the borders down to fit.
    float combinedBorders = border[axis] + border[axis + 2];
    if (rect.size[axis] < combinedBorders && combinedBorders != 0)
    {
    float borderScaleRatio = rect.size[axis] / combinedBorders;
    border[axis] *= borderScaleRatio;
    border[axis + 2] *= borderScaleRatio;
    }
    }
    return border;
    }

    static void AddQuad(VertexHelper vertexHelper, Vector2 posMin, Vector2 posMax, Color32 color, Vector2 uvMin, Vector2 uvMax)
    {
    int startIndex = vertexHelper.currentVertCount;

    vertexHelper.AddVert(new Vector3(posMin.x, posMin.y, 0), color, new Vector2(uvMin.x, uvMin.y));
    vertexHelper.AddVert(new Vector3(posMin.x, posMax.y, 0), color, new Vector2(uvMin.x, uvMax.y));
    vertexHelper.AddVert(new Vector3(posMax.x, posMax.y, 0), color, new Vector2(uvMax.x, uvMax.y));
    vertexHelper.AddVert(new Vector3(posMax.x, posMin.y, 0), color, new Vector2(uvMax.x, uvMin.y));

    vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
    vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
    }

    private void GenerateSlicedSpriteLeft(VertexHelper toFill)
    {
    Vector4 outer, inner, padding, border;

    if (overrideSprite != null)
    {
    outer = DataUtility.GetOuterUV(overrideSprite);
    inner = DataUtility.GetInnerUV(overrideSprite);
    padding = DataUtility.GetPadding(overrideSprite);
    border = overrideSprite.border;
    }
    else
    {
    outer = Vector4.zero;
    inner = Vector4.zero;
    padding = Vector4.zero;
    border = Vector4.zero;
    }

    Rect rect = GetPixelAdjustedRect();
    border = GetAdjustedBorders(border / pixelsPerUnit, rect);
    padding = padding / pixelsPerUnit;
    float condition = (border.z + border.x) / rect.width;
    var realFillAmount = fillAmount;
    #region 实际显示size
    float[] x = { 0, 0, 0, 0 };

    {
    x[0] = 0;
    if (realFillAmount < condition)
    {
    x[1] = realFillAmount / 2 * rect.width;
    x[2] = x[1] + 0;
    x[3] = x[1] * 2;
    }
    else
    {
    x[1] = border.x;
    x[2] = rect.width * realFillAmount - border.z;
    x[3] = x[2] + border.z;
    }
    }

    float[] y = { 0 + rect.y, rect.height + rect.y };

    Debug.Log(string.Format("xo: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    for (int i = 0; i < 4; ++i)
    {
    x[i] += rect.x;
    }

    #endregion

    #region uv值
    float[] x_uv = { 0, 0, 0, 0 };

    x_uv[0] = 0;
    if (realFillAmount < condition)
    {
    x_uv[1] = realFillAmount * rect.width / 2 / sprite.rect.size.x;
    x_uv[2] = 1 - x_uv[1];
    }
    else
    {
    x_uv[1] = inner.x;
    x_uv[2] = inner.z;
    }
    x_uv[3] = outer.z;

    float y_uv = 1;
    #endregion
    Debug.Log(string.Format("x: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    Debug.Log(string.Format("x_uv: {0} {1} {2} {3}", x_uv[0], x_uv[1], x_uv[2], x_uv[3]));

    toFill.Clear();
    for (int i = 0; i < 3; i++)
    {
    int i2 = i + 1;
    AddQuad(toFill,
    new Vector2(x[i], y[0]),
    new Vector2(x[i2], y[1]),
    color,
    new Vector2(x_uv[i], 0),
    new Vector2(x_uv[i2], y_uv));
    }
    }

    private void GenerateSlicedSpriteRight(VertexHelper toFill)
    {
    Vector4 outer, inner, padding, border;

    if (overrideSprite != null)
    {
    outer = DataUtility.GetOuterUV(overrideSprite);
    inner = DataUtility.GetInnerUV(overrideSprite);
    padding = DataUtility.GetPadding(overrideSprite);
    border = overrideSprite.border;
    }
    else
    {
    outer = Vector4.zero;
    inner = Vector4.zero;
    padding = Vector4.zero;
    border = Vector4.zero;
    }

    Rect rect = GetPixelAdjustedRect();
    border = GetAdjustedBorders(border / pixelsPerUnit, rect);
    padding = padding / pixelsPerUnit;
    float condition = (border.z + border.x) / rect.width;
    var realFillAmount = fillAmount;
    #region 实际显示size
    float[] x = { 0, 0, 0, 0 };

    Debug.Log(string.Format("rect.x: {0} rect.y: {1} rect.width: {2} rect.heigh: {3}", rect.x, rect.y, rect.width, rect.height));
    Debug.Log(string.Format("border.x: {0} border.y: {1} border.z: {2} border.w: {3}", border.x, border.y, border.z, border.w));

    {
    x[0] = 0;
    if (realFillAmount < condition)
    {
    x[1] = realFillAmount / 2 * rect.width;
    x[2] = x[1] + 0;
    x[3] = x[1] * 2;
    }
    else
    {
    x[1] = border.x;
    x[2] = rect.width * realFillAmount - border.z;
    x[3] = x[2] + border.z;
    }

    var tmp = x[0];
    x[0] = x[3];
    x[3] = tmp;

    tmp = x[1];
    x[1] = x[2];
    x[2] = tmp;
    }

    float[] y = { 0 + rect.y, rect.height + rect.y };

    Debug.Log(string.Format("xo: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    for (int i = 0; i < 4; ++i)
    {
    x[i] += rect.x;
    x[i] *= (-1);
    }

    #endregion

    #region uv值
    float[] x_uv = { 0, 0, 0, 0 };

    x_uv[0] = 0;
    if (realFillAmount < condition)
    {
    x_uv[1] = realFillAmount * rect.width / 2 / sprite.rect.size.x;
    x_uv[2] = 1 - x_uv[1];
    }
    else
    {
    x_uv[1] = inner.x;
    x_uv[2] = inner.z;
    }
    x_uv[3] = outer.z;

    float y_uv = 1;
    #endregion

    Debug.Log(string.Format("x: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    Debug.Log(string.Format("x_uv: {0} {1} {2} {3}", x_uv[0], x_uv[1], x_uv[2], x_uv[3]));

    toFill.Clear();
    for (int i = 0; i < 3; i++)
    {
    int i2 = i + 1;
    AddQuad(toFill,
    new Vector2(x[i], y[0]),
    new Vector2(x[i2], y[1]),
    color,
    new Vector2(x_uv[i], 0),
    new Vector2(x_uv[i2], y_uv));
    }
    }

    private void GenerateSlicedSpriteCenter(VertexHelper toFill)
    {
    Vector4 outer, inner, padding, border;

    if (overrideSprite != null)
    {
    outer = DataUtility.GetOuterUV(overrideSprite);
    inner = DataUtility.GetInnerUV(overrideSprite);
    padding = DataUtility.GetPadding(overrideSprite);
    border = overrideSprite.border;
    }
    else
    {
    outer = Vector4.zero;
    inner = Vector4.zero;
    padding = Vector4.zero;
    border = Vector4.zero;
    }

    Rect rect = GetPixelAdjustedRect();
    border = GetAdjustedBorders(border / pixelsPerUnit, rect);
    padding = padding / pixelsPerUnit;
    float condition = (border.z + border.x) / rect.width;
    var realFillAmount = fillAmount / 2;
    #region 实际显示size
    float[] x = { 0, 0, 0, 0 };

    {
    x[0] = 0;
    if (realFillAmount < condition)
    {
    x[1] = realFillAmount / 2 * rect.width;
    x[2] = x[1] + 0;
    x[3] = x[1] * 2;
    }
    else
    {
    x[1] = border.x;
    x[2] = rect.width * realFillAmount - border.z;
    x[3] = x[2] + border.z;
    }
    }

    float[] y = { 0 + rect.y, rect.height + rect.y };

    Debug.Log(string.Format("xo: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    for (int i = 0; i < 4; ++i)
    {
    x[i] += rect.x + rect.width / 2;
    //x[i] += rect.x;
    }

    #endregion

    #region uv值
    float[] x_uv = { 0, 0, 0, 0 };

    x_uv[0] = 0;
    if (realFillAmount < condition)
    {
    x_uv[1] = realFillAmount * rect.width / 2 / sprite.rect.size.x;
    x_uv[2] = 1 - x_uv[1];
    }
    else
    {
    x_uv[1] = inner.x;
    x_uv[2] = inner.z;
    }
    x_uv[3] = outer.z;

    float y_uv = 1;
    #endregion
    x[0] = -x[3];
    x[1] = -x[2];
    Debug.Log(string.Format("x: {0} {1} {2} {3}", x[0], x[1], x[2], x[3]));
    Debug.Log(string.Format("x_uv: {0} {1} {2} {3}", x_uv[0], x_uv[1], x_uv[2], x_uv[3]));

    toFill.Clear();
    for (int i = 0; i < 3; i++)
    {
    int i2 = i + 1;
    AddQuad(toFill,
    new Vector2(x[i], y[0]),
    new Vector2(x[i2], y[1]),
    color,
    new Vector2(x_uv[i], 0),
    new Vector2(x_uv[i2], y_uv));
    }
    }

    public enum SlicedType
    {
    Left,
    Right,
    Center
    }
    }
    160 changes: 160 additions & 0 deletions SlicedImageEditor.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,160 @@
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEditor.UI;
    using UnityEditor;
    using UnityEditor.AnimatedValues;
    using System.Linq;

    [CustomEditor(typeof(SlicedImage))]
    public class SlicedImageInspector : ImageEditor
    {
    SerializedProperty m_FillMethod;
    SerializedProperty m_FillOrigin;
    SerializedProperty m_FillAmount;
    SerializedProperty m_FillClockwise;
    SerializedProperty m_Type;
    SerializedProperty m_FillCenter;
    SerializedProperty m_Sprite;
    SerializedProperty m_PreserveAspect;
    GUIContent m_SpriteContent;
    GUIContent m_SpriteTypeContent;
    GUIContent m_ClockwiseContent;
    AnimBool m_ShowSlicedOrTiled;
    AnimBool m_ShowSliced;
    AnimBool m_ShowFilled;
    AnimBool m_ShowType;

    void SetShowNativeSize(bool instant)
    {
    SlicedImage.Type type = (SlicedImage.Type)m_Type.enumValueIndex;
    bool showNativeSize = (type == SlicedImage.Type.Simple || type == SlicedImage.Type.Filled);
    base.SetShowNativeSize(showNativeSize, instant);
    }
    protected override void OnEnable()
    {
    base.OnEnable();
    m_SpriteContent = new GUIContent("Source childImage");
    m_SpriteTypeContent = new GUIContent("childImage Type");
    m_ClockwiseContent = new GUIContent("Clockwise");

    m_Sprite = serializedObject.FindProperty("m_Sprite");
    m_Type = serializedObject.FindProperty("m_Type");
    m_FillCenter = serializedObject.FindProperty("m_FillCenter");
    m_FillMethod = serializedObject.FindProperty("m_FillMethod");
    m_FillOrigin = serializedObject.FindProperty("m_FillOrigin");
    m_FillClockwise = serializedObject.FindProperty("m_FillClockwise");
    m_FillAmount = serializedObject.FindProperty("m_FillAmount");
    m_PreserveAspect = serializedObject.FindProperty("m_PreserveAspect");

    m_ShowType = new AnimBool(m_Sprite.objectReferenceValue != null);
    m_ShowType.valueChanged.AddListener(Repaint);

    var typeEnum = (SlicedImage.Type)m_Type.enumValueIndex;
    m_ShowSlicedOrTiled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == SlicedImage.Type.Sliced);
    m_ShowSliced = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == SlicedImage.Type.Sliced);
    m_ShowFilled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == SlicedImage.Type.Filled);
    m_ShowSlicedOrTiled.valueChanged.AddListener(Repaint);
    m_ShowSliced.valueChanged.AddListener(Repaint);
    m_ShowFilled.valueChanged.AddListener(Repaint);

    SetShowNativeSize(true);
    }
    public override void OnInspectorGUI()
    {
    serializedObject.Update();

    SpriteGUI();
    AppearanceControlsGUI();
    RaycastControlsGUI();

    m_ShowType.target = m_Sprite.objectReferenceValue != null;
    if (EditorGUILayout.BeginFadeGroup(m_ShowType.faded))
    {
    EditorGUILayout.PropertyField(m_Type, m_SpriteTypeContent);

    ++EditorGUI.indentLevel;
    {
    SlicedImage.Type typeEnum = (SlicedImage.Type)m_Type.enumValueIndex;
    bool showSlicedOrTiled = (!m_Type.hasMultipleDifferentValues && (typeEnum == SlicedImage.Type.Sliced || typeEnum == SlicedImage.Type.Tiled));
    if (showSlicedOrTiled && targets.Length > 1)
    showSlicedOrTiled = targets.Select(obj => obj as SlicedImage).All(img => img.hasBorder);

    m_ShowSlicedOrTiled.target = showSlicedOrTiled;
    m_ShowSliced.target = (showSlicedOrTiled && !m_Type.hasMultipleDifferentValues && typeEnum == SlicedImage.Type.Sliced);
    m_ShowFilled.target = (!m_Type.hasMultipleDifferentValues && (typeEnum == SlicedImage.Type.Filled));

    SlicedImage cImage = target as SlicedImage;

    if (EditorGUILayout.BeginFadeGroup(m_ShowSlicedOrTiled.faded))
    {
    if (cImage.hasBorder)
    {
    EditorGUILayout.PropertyField(m_FillCenter);
    cImage.slicedType = (SlicedImage.SlicedType)EditorGUILayout.EnumPopup("Fill Origin", cImage.slicedType);

    EditorGUILayout.PropertyField(m_FillAmount);
    }

    }
    EditorGUILayout.EndFadeGroup();

    if (EditorGUILayout.BeginFadeGroup(m_ShowSliced.faded))
    {
    if (cImage.sprite != null && !cImage.hasBorder)
    EditorGUILayout.HelpBox("This childImage doesn't have a border.", MessageType.Warning);
    }
    EditorGUILayout.EndFadeGroup();

    if (EditorGUILayout.BeginFadeGroup(m_ShowFilled.faded))
    {
    EditorGUI.BeginChangeCheck();
    EditorGUILayout.PropertyField(m_FillMethod);
    if (EditorGUI.EndChangeCheck())
    {
    m_FillOrigin.intValue = 0;
    }
    switch ((SlicedImage.FillMethod)m_FillMethod.enumValueIndex)
    {
    case SlicedImage.FillMethod.Horizontal:
    m_FillOrigin.intValue = (int)(SlicedImage.OriginHorizontal)EditorGUILayout.EnumPopup("Fill Origin", (SlicedImage.OriginHorizontal)m_FillOrigin.intValue);
    break;
    case SlicedImage.FillMethod.Vertical:
    m_FillOrigin.intValue = (int)(SlicedImage.OriginVertical)EditorGUILayout.EnumPopup("Fill Origin", (SlicedImage.OriginVertical)m_FillOrigin.intValue);
    break;
    case SlicedImage.FillMethod.Radial90:
    m_FillOrigin.intValue = (int)(SlicedImage.Origin90)EditorGUILayout.EnumPopup("Fill Origin", (SlicedImage.Origin90)m_FillOrigin.intValue);
    break;
    case SlicedImage.FillMethod.Radial180:
    m_FillOrigin.intValue = (int)(SlicedImage.Origin180)EditorGUILayout.EnumPopup("Fill Origin", (SlicedImage.Origin180)m_FillOrigin.intValue);
    break;
    case SlicedImage.FillMethod.Radial360:
    m_FillOrigin.intValue = (int)(SlicedImage.Origin360)EditorGUILayout.EnumPopup("Fill Origin", (SlicedImage.Origin360)m_FillOrigin.intValue);
    break;
    }
    EditorGUILayout.PropertyField(m_FillAmount);
    if ((SlicedImage.FillMethod)m_FillMethod.enumValueIndex > SlicedImage.FillMethod.Vertical)
    {
    EditorGUILayout.PropertyField(m_FillClockwise, m_ClockwiseContent);
    }
    }
    EditorGUILayout.EndFadeGroup();
    }
    --EditorGUI.indentLevel;
    }

    EditorGUILayout.EndFadeGroup();

    SetShowNativeSize(false);
    if (EditorGUILayout.BeginFadeGroup(m_ShowNativeSize.faded))
    {
    EditorGUI.indentLevel++;
    EditorGUILayout.PropertyField(m_PreserveAspect);
    EditorGUI.indentLevel--;
    }
    EditorGUILayout.EndFadeGroup();
    NativeSizeButtonGUI();

    serializedObject.ApplyModifiedProperties();
    }
    }