• UGUI——重写Image类实现进度条


    目的:

    游戏中经常会用到进度条,但是美术给的图片用filled一拉伸就很难看,如下图

    第一种模式是九宫格模式,第二种是filled。而我们需要的是两种可结合的。

    如何实现:

    新建一个类,继承image类后,我选择改写sliced模式下的渲染方式,将horizont填充方式的功能添加进去。

    因为大部分进度条只需要切割左右两头,所以为了省事只实现了“三宫格”,并且两头切割的长度要相等。

    然而inspector中的sliced模式下不包括fillmount属性,所以我们还需要改写ImageEditor,也是新建类继承。

    注意继承ImageEditor的文本要放在Asset文件夹下的Editor文件夹里,unity会自动编译添加的。

    代码:

      1 using System.Collections;
      2 using System.Collections.Generic;
      3 using UnityEngine;
      4 using UnityEngine.UI;
      5 using UnityEngine.Sprites;
      6 
      7 public class childImage :  Image{
      8     
      9     protected override void OnPopulateMesh(VertexHelper toFill)
     10     {
     11         base.OnPopulateMesh(toFill);
     12         if (overrideSprite == null)
     13         {
     14             base.OnPopulateMesh(toFill);
     15             return;
     16         }
     17         if (type == Type.Sliced)
     18         {
     19             GenerateSlicedSprite_(toFill);
     20         }
     21     }
     22 
     23     Vector4 GetAdjustedBorders(Vector4 border, Rect rect)
     24     {
     25         for (int axis = 0; axis <= 1; axis++)
     26         {
     27             // If the rect is smaller than the combined borders, then there's not room for the borders at their normal size.
     28             // In order to avoid artefacts with overlapping borders, we scale the borders down to fit.
     29             float combinedBorders = border[axis] + border[axis + 2];
     30             if (rect.size[axis] < combinedBorders && combinedBorders != 0)
     31             {
     32                 float borderScaleRatio = rect.size[axis] / combinedBorders;
     33                 border[axis] *= borderScaleRatio;
     34                 border[axis + 2] *= borderScaleRatio;
     35             }
     36         }
     37         return border;
     38     }
     39 
     40     static void AddQuad(VertexHelper vertexHelper, Vector2 posMin, Vector2 posMax, Color32 color, Vector2 uvMin, Vector2 uvMax)
     41     {
     42         int startIndex = vertexHelper.currentVertCount;
     43 
     44         vertexHelper.AddVert(new Vector3(posMin.x, posMin.y, 0), color, new Vector2(uvMin.x, uvMin.y));
     45         vertexHelper.AddVert(new Vector3(posMin.x, posMax.y, 0), color, new Vector2(uvMin.x, uvMax.y));
     46         vertexHelper.AddVert(new Vector3(posMax.x, posMax.y, 0), color, new Vector2(uvMax.x, uvMax.y));
     47         vertexHelper.AddVert(new Vector3(posMax.x, posMin.y, 0), color, new Vector2(uvMax.x, uvMin.y));
     48 
     49         vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
     50         vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
     51     }
     52     private void GenerateSlicedSprite_(VertexHelper toFill)
     53     {
     54         Vector4 outer, inner, padding, border;
     55 
     56         if (overrideSprite != null)
     57         {
     58             outer = DataUtility.GetOuterUV(overrideSprite);
     59             inner = DataUtility.GetInnerUV(overrideSprite);
     60             padding = DataUtility.GetPadding(overrideSprite);
     61             border = overrideSprite.border;
     62         }
     63         else
     64         {
     65             outer = Vector4.zero;
     66             inner = Vector4.zero;
     67             padding = Vector4.zero;
     68             border = Vector4.zero;
     69         }
     70 
     71         Rect rect = GetPixelAdjustedRect();
     72         border = GetAdjustedBorders(border / pixelsPerUnit, rect);
     73         padding = padding / pixelsPerUnit;
     74         float condition = (border.z + border.x) / rect.width;
     75         #region 实际显示size
     76         float[] x={0,0,0,0};
     77 
     78         x[0] = 0;
     79         if (fillAmount <condition)
     80         {
     81             x[1] = fillAmount / 2 * rect.width;
     82             x[2] = x[1]+ 0;
     83             x[3] = x[1]*2;
     84         }
     85         else
     86         {
     87           x[1] = border.x;
     88           x[2] = rect.width *fillAmount-border.z;
     89           x[3] =x[2]+border.z;
     90         }
     91         float []y ={0+rect.y,rect.height+rect.y};
     92 
     93         for (int i = 0; i < 4; ++i)
     94         {
     95             x[i] += rect.x;
     96 
     97         }
     98         #endregion
     99 
    100         #region uv值
    101         float[] x_uv = {0,0,0,0 };
    102 
    103         x_uv[0] =0;
    104         if (fillAmount <condition)
    105         {
    106             x_uv[1] = fillAmount*rect.width/2/sprite.rect.size.x;
    107             x_uv[2] = 1 - x_uv[1];
    108         }
    109         else
    110         {
    111             x_uv[1] = inner.x;
    112             x_uv[2] = inner.z;
    113         }
    114         x_uv[3] = outer.z;
    115 
    116         float y_uv = 1;
    117         #endregion
    118         
    119         toFill.Clear();
    120         for (int i = 0; i < 3; i++)
    121         {
    122             int i2 = i + 1;
    123             AddQuad(toFill,
    124                     new Vector2(x[i],y[0]),
    125                     new Vector2(x[i2],y[1]),
    126                     color,
    127                     new Vector2(x_uv[i],0),
    128                     new Vector2(x_uv[i2],y_uv));
    129         }
    130          
    131     }
    132 
    133 
    134 }
    View Code
      1 using System.Collections;
      2 using System.Collections.Generic;
      3 using UnityEngine;
      4 using UnityEditor.UI;
      5 using UnityEditor;
      6 using UnityEditor.AnimatedValues;
      7 using System.Linq;
      8 
      9 [CustomEditor(typeof(childImage))]
     10 public class ChildchildImageInspector : ImageEditor
     11 {
     12     SerializedProperty m_FillMethod;
     13     SerializedProperty m_FillOrigin;
     14     SerializedProperty m_FillAmount;
     15     SerializedProperty m_FillClockwise;
     16     SerializedProperty m_Type;
     17     SerializedProperty m_FillCenter;
     18     SerializedProperty m_Sprite;
     19     SerializedProperty m_PreserveAspect;
     20     GUIContent m_SpriteContent;
     21     GUIContent m_SpriteTypeContent;
     22     GUIContent m_ClockwiseContent;
     23     AnimBool m_ShowSlicedOrTiled;
     24     AnimBool m_ShowSliced;
     25     AnimBool m_ShowFilled;
     26     AnimBool m_ShowType;
     27 
     28     void SetShowNativeSize(bool instant)
     29     {
     30         childImage.Type type = (childImage.Type)m_Type.enumValueIndex;
     31         bool showNativeSize = (type == childImage.Type.Simple || type == childImage.Type.Filled);
     32         base.SetShowNativeSize(showNativeSize, instant);
     33     }
     34     protected override void OnEnable()
     35     {
     36         base.OnEnable();
     37         m_SpriteContent = new GUIContent("Source childImage");
     38         m_SpriteTypeContent = new GUIContent("childImage Type");
     39         m_ClockwiseContent = new GUIContent("Clockwise");
     40 
     41         m_Sprite = serializedObject.FindProperty("m_Sprite");
     42         m_Type = serializedObject.FindProperty("m_Type");
     43         m_FillCenter = serializedObject.FindProperty("m_FillCenter");
     44         m_FillMethod = serializedObject.FindProperty("m_FillMethod");
     45         m_FillOrigin = serializedObject.FindProperty("m_FillOrigin");
     46         m_FillClockwise = serializedObject.FindProperty("m_FillClockwise");
     47         m_FillAmount = serializedObject.FindProperty("m_FillAmount");
     48         m_PreserveAspect = serializedObject.FindProperty("m_PreserveAspect");
     49 
     50         m_ShowType = new AnimBool(m_Sprite.objectReferenceValue != null);
     51         m_ShowType.valueChanged.AddListener(Repaint);
     52 
     53         var typeEnum = (childImage.Type)m_Type.enumValueIndex;
     54         m_ShowSlicedOrTiled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Sliced);
     55         m_ShowSliced = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Sliced);
     56         m_ShowFilled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Filled);
     57         m_ShowSlicedOrTiled.valueChanged.AddListener(Repaint);
     58         m_ShowSliced.valueChanged.AddListener(Repaint);
     59         m_ShowFilled.valueChanged.AddListener(Repaint);
     60 
     61         SetShowNativeSize(true);
     62     }
     63     public override void OnInspectorGUI()
     64     {
     65         serializedObject.Update();
     66 
     67         SpriteGUI();
     68         AppearanceControlsGUI();
     69         RaycastControlsGUI();
     70 
     71         m_ShowType.target = m_Sprite.objectReferenceValue != null;
     72         if (EditorGUILayout.BeginFadeGroup(m_ShowType.faded))
     73         {
     74             EditorGUILayout.PropertyField(m_Type, m_SpriteTypeContent);
     75 
     76             ++EditorGUI.indentLevel;
     77             {
     78                 childImage.Type typeEnum = (childImage.Type)m_Type.enumValueIndex;
     79                 bool showSlicedOrTiled = (!m_Type.hasMultipleDifferentValues && (typeEnum ==childImage.Type.Sliced|| typeEnum == childImage.Type.Tiled));
     80                 if (showSlicedOrTiled && targets.Length > 1)
     81                     showSlicedOrTiled = targets.Select(obj => obj as childImage).All(img => img.hasBorder);
     82 
     83                 m_ShowSlicedOrTiled.target = showSlicedOrTiled;
     84                 m_ShowSliced.target = (showSlicedOrTiled && !m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Sliced);
     85                 m_ShowFilled.target = (!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Filled);
     86                
     87                 childImage cImage = target as childImage;
     88                 
     89                 if (EditorGUILayout.BeginFadeGroup(m_ShowSlicedOrTiled.faded))
     90                 {
     91                     if (cImage.hasBorder)
     92                     {
     93                         EditorGUILayout.PropertyField(m_FillCenter);
     94                         EditorGUILayout.PropertyField(m_FillAmount);
     95                     }
     96 
     97                 }
     98                 EditorGUILayout.EndFadeGroup();
     99 
    100                 if (EditorGUILayout.BeginFadeGroup(m_ShowSliced.faded))
    101                 {
    102                     if (cImage.sprite != null && !cImage.hasBorder)
    103                         EditorGUILayout.HelpBox("This childImage doesn't have a border.", MessageType.Warning);
    104                 }
    105                 EditorGUILayout.EndFadeGroup();
    106 
    107                 if (EditorGUILayout.BeginFadeGroup(m_ShowFilled.faded))
    108                 {
    109                     EditorGUI.BeginChangeCheck();
    110                     EditorGUILayout.PropertyField(m_FillMethod);
    111                     if (EditorGUI.EndChangeCheck())
    112                     {
    113                         m_FillOrigin.intValue = 0;
    114                     }
    115                     switch ((childImage.FillMethod)m_FillMethod.enumValueIndex)
    116                     {
    117                         case childImage.FillMethod.Horizontal:
    118                             m_FillOrigin.intValue = (int)(childImage.OriginHorizontal)EditorGUILayout.EnumPopup("Fill Origin", (childImage.OriginHorizontal)m_FillOrigin.intValue);
    119                             break;
    120                         case childImage.FillMethod.Vertical:
    121                             m_FillOrigin.intValue = (int)(childImage.OriginVertical)EditorGUILayout.EnumPopup("Fill Origin", (childImage.OriginVertical)m_FillOrigin.intValue);
    122                             break;
    123                         case childImage.FillMethod.Radial90:
    124                             m_FillOrigin.intValue = (int)(childImage.Origin90)EditorGUILayout.EnumPopup("Fill Origin", (childImage.Origin90)m_FillOrigin.intValue);
    125                             break;
    126                         case childImage.FillMethod.Radial180:
    127                             m_FillOrigin.intValue = (int)(childImage.Origin180)EditorGUILayout.EnumPopup("Fill Origin", (childImage.Origin180)m_FillOrigin.intValue);
    128                             break;
    129                         case childImage.FillMethod.Radial360:
    130                             m_FillOrigin.intValue = (int)(childImage.Origin360)EditorGUILayout.EnumPopup("Fill Origin", (childImage.Origin360)m_FillOrigin.intValue);
    131                             break;
    132                     }
    133                     EditorGUILayout.PropertyField(m_FillAmount);
    134                     if ((childImage.FillMethod)m_FillMethod.enumValueIndex > childImage.FillMethod.Vertical)
    135                     {
    136                         EditorGUILayout.PropertyField(m_FillClockwise, m_ClockwiseContent);
    137                     }
    138                 }
    139                 EditorGUILayout.EndFadeGroup();
    140             }
    141             --EditorGUI.indentLevel;
    142         }
    143 
    144         EditorGUILayout.EndFadeGroup();
    145 
    146         SetShowNativeSize(false);
    147         if (EditorGUILayout.BeginFadeGroup(m_ShowNativeSize.faded))
    148         {
    149             EditorGUI.indentLevel++;
    150             EditorGUILayout.PropertyField(m_PreserveAspect);
    151             EditorGUI.indentLevel--;
    152         }
    153         EditorGUILayout.EndFadeGroup();
    154         NativeSizeButtonGUI();
    155 
    156         serializedObject.ApplyModifiedProperties();
    157     }
    158 }
    View Code
  • 相关阅读:
    集线程池应用、多次HttpWebRequest请求,自动切换账号等等的移动信息查询软件
    PropertyGrid实现文件选择项
    git通过命令忽略指定文件
    【转】一张图解析FastAdmin中的表格列表的功能
    一张图解析FastAdmin中的FormBuilder表单生成器
    1140 In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'football.order.id'; this is incompatible with sql_mode=only_full_group_by
    centeros 安装mysql
    Flask 教程 第二十三章:应用程序编程接口(API)
    Flask 教程 第二十二章:后台作业
    Flask 教程 第二十一章:用户通知
  • 原文地址:https://www.cnblogs.com/ninomiya/p/8134497.html
Copyright © 2020-2023  润新知