目的:

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

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

如何实现:

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

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

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

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

代码:

 using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Sprites; public class childImage : Image{ protected override void OnPopulateMesh(VertexHelper toFill)
{
base.OnPopulateMesh(toFill);
if (overrideSprite == null)
{
base.OnPopulateMesh(toFill);
return;
}
if (type == Type.Sliced)
{
GenerateSlicedSprite_(toFill);
}
} Vector4 GetAdjustedBorders(Vector4 border, Rect rect)
{
for (int axis = ; axis <= ; 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 + ];
if (rect.size[axis] < combinedBorders && combinedBorders != )
{
float borderScaleRatio = rect.size[axis] / combinedBorders;
border[axis] *= borderScaleRatio;
border[axis + ] *= 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, ), color, new Vector2(uvMin.x, uvMin.y));
vertexHelper.AddVert(new Vector3(posMin.x, posMax.y, ), color, new Vector2(uvMin.x, uvMax.y));
vertexHelper.AddVert(new Vector3(posMax.x, posMax.y, ), color, new Vector2(uvMax.x, uvMax.y));
vertexHelper.AddVert(new Vector3(posMax.x, posMin.y, ), color, new Vector2(uvMax.x, uvMin.y)); vertexHelper.AddTriangle(startIndex, startIndex + , startIndex + );
vertexHelper.AddTriangle(startIndex + , startIndex + , startIndex);
}
private void GenerateSlicedSprite_(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;
#region 实际显示size
float[] x={,,,}; x[] = ;
if (fillAmount <condition)
{
x[] = fillAmount / * rect.width;
x[] = x[]+ ;
x[] = x[]*;
}
else
{
x[] = border.x;
x[] = rect.width *fillAmount-border.z;
x[] =x[]+border.z;
}
float []y ={+rect.y,rect.height+rect.y}; for (int i = ; i < ; ++i)
{
x[i] += rect.x; }
#endregion #region uv值
float[] x_uv = {,,, }; x_uv[] =;
if (fillAmount <condition)
{
x_uv[] = fillAmount*rect.width//sprite.rect.size.x;
x_uv[] = - x_uv[];
}
else
{
x_uv[] = inner.x;
x_uv[] = inner.z;
}
x_uv[] = outer.z; float y_uv = ;
#endregion toFill.Clear();
for (int i = ; i < ; i++)
{
int i2 = i + ;
AddQuad(toFill,
new Vector2(x[i],y[]),
new Vector2(x[i2],y[]),
color,
new Vector2(x_uv[i],),
new Vector2(x_uv[i2],y_uv));
} } }
 using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.UI;
using UnityEditor;
using UnityEditor.AnimatedValues;
using System.Linq; [CustomEditor(typeof(childImage))]
public class ChildchildImageInspector : 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)
{
childImage.Type type = (childImage.Type)m_Type.enumValueIndex;
bool showNativeSize = (type == childImage.Type.Simple || type == childImage.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 = (childImage.Type)m_Type.enumValueIndex;
m_ShowSlicedOrTiled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Sliced);
m_ShowSliced = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Sliced);
m_ShowFilled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == childImage.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;
{
childImage.Type typeEnum = (childImage.Type)m_Type.enumValueIndex;
bool showSlicedOrTiled = (!m_Type.hasMultipleDifferentValues && (typeEnum ==childImage.Type.Sliced|| typeEnum == childImage.Type.Tiled));
if (showSlicedOrTiled && targets.Length > )
showSlicedOrTiled = targets.Select(obj => obj as childImage).All(img => img.hasBorder); m_ShowSlicedOrTiled.target = showSlicedOrTiled;
m_ShowSliced.target = (showSlicedOrTiled && !m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Sliced);
m_ShowFilled.target = (!m_Type.hasMultipleDifferentValues && typeEnum == childImage.Type.Filled); childImage cImage = target as childImage; if (EditorGUILayout.BeginFadeGroup(m_ShowSlicedOrTiled.faded))
{
if (cImage.hasBorder)
{
EditorGUILayout.PropertyField(m_FillCenter);
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 = ;
}
switch ((childImage.FillMethod)m_FillMethod.enumValueIndex)
{
case childImage.FillMethod.Horizontal:
m_FillOrigin.intValue = (int)(childImage.OriginHorizontal)EditorGUILayout.EnumPopup("Fill Origin", (childImage.OriginHorizontal)m_FillOrigin.intValue);
break;
case childImage.FillMethod.Vertical:
m_FillOrigin.intValue = (int)(childImage.OriginVertical)EditorGUILayout.EnumPopup("Fill Origin", (childImage.OriginVertical)m_FillOrigin.intValue);
break;
case childImage.FillMethod.Radial90:
m_FillOrigin.intValue = (int)(childImage.Origin90)EditorGUILayout.EnumPopup("Fill Origin", (childImage.Origin90)m_FillOrigin.intValue);
break;
case childImage.FillMethod.Radial180:
m_FillOrigin.intValue = (int)(childImage.Origin180)EditorGUILayout.EnumPopup("Fill Origin", (childImage.Origin180)m_FillOrigin.intValue);
break;
case childImage.FillMethod.Radial360:
m_FillOrigin.intValue = (int)(childImage.Origin360)EditorGUILayout.EnumPopup("Fill Origin", (childImage.Origin360)m_FillOrigin.intValue);
break;
}
EditorGUILayout.PropertyField(m_FillAmount);
if ((childImage.FillMethod)m_FillMethod.enumValueIndex > childImage.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();
}
}

UGUI——重写Image类实现进度条的更多相关文章

  1. [C#] (原创)一步一步教你自定义控件——04,ProgressBar(进度条)

    一.前言 技术没有先进与落后,只有合适与不合适. 本篇的自定义控件是:进度条(ProgressBar). 进度条的实现方式多种多样,主流的方式有:使用多张图片去实现.使用1个或2个Panel放到Use ...

  2. css绘制进度条,持续转动的进度条

    //只有 progress pregress-par bar,进度条不会转, //增加 active 这个类,进度条会转, //html结构 <div class='progress activ ...

  3. progressbar进度条组件

    Progressbar 进度条组件 通过$.fn.progressbar.fn.defaults重写默认的defaults进度条(progressbar)提供了一种显示长时间操作进度的反馈.进度可被更 ...

  4. asp.net 后台多线程异步处理时的 进度条实现一(Ajax+Ashx实现以及封装成控件的实现)

    (更新:有的同学说源代码不想看,说明也不想看,只想要一个demo,这边提供一下:http://url.cn/LPT50k (密码:TPHU)) 工作好长时间了,这期间许多功能也写成了不少的控件来使用, ...

  5. 关于JFace中的进度条对话框(ProgressMonitorDialog类)

    在Windows操作系统中,最常用的进度条对话框就是文件复制时的弹出框,如果想让用户愉快的使用你开发 的软件,那么在执行某个较长时间的操作时候,就应该弹出一个进度条提示框,告诉用户程序正在做什么. 做 ...

  6. Android第三方开源SeekBarCompat:音乐类播放器等APP进度条常用

     Android第三方开源SeekBarCompat:音乐类播放器等APP进度条常用 Android平台原生的SeekBar设计简单,然而,比如现在流行的一些音乐播放器的播放进度控制条,如果直接使 ...

  7. wxpython中列表框(ListBox类)、复选列表框(CheckListBox)、下拉选项(Choice)、进度条(Gauge)、滑块(Slider)使用实例源码分享

    #coding=utf-8 import wx import time class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(s ...

  8. struts2上传文件添加进度条

    给文件上传添加进度条,整了两天终于成功了. 想要添加一个上传的进度条,通过分析,应该是需要不断的去访问服务器,询问上传文件的大小.通过已上传文件的大小, 和上传文件的总长度来评估上传的进度. 实现监听 ...

  9. Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)

      Android 高手进阶(21)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明地址:http://blog.csdn.net/xiaanming/article/detail ...

随机推荐

  1. linux系统无法启动,提示give root password for maintenance错误

    电脑的虚拟机安装的是centos6.2操作系统,今天打开虚拟机时候,提示 give root password for maintenance (or type control-D to contin ...

  2. wamp集成多个版本php (php7.0)

    https://www.cnblogs.com/ypf5208/p/5510274.html

  3. java编码规范_缩进和注释

    1.       缩进排版(Indentation) 4个空格常被作为缩进排版的一个单位.缩进的确切解释并未详细指定(空格 vs. 制表符).一个制表符等于n个空格(视具体的编辑器而定,Eclipse ...

  4. Java_异常处理(Exception)

    异常:Exception try{ //捕获异常 }catch{ //处理异常 } 异常处理机制: 1.在try块中,如果捕获了异常,那么剩余的代码都不会执行,会直接跳到catch中, 2.在try之 ...

  5. 多事实表 SQL实现和SSAS中MDX实现的差异

    如图,资产负债视图是事实表,损益表也是事实表.都包含年.月.组织.账簿信息. SQL如何实现呢? 简单粗暴,事实事实表串事实表,Full Join select 损益视图.年 ,损益视图.年月 ,损益 ...

  6. JDK7,8,JD9的hashmap,hashtable,concurrenthashmap及他们的区别

    1:hashmap简介(如下,数组-链表形式) HashMap的存储结构 图中,紫色部分即代表哈希表,也称为哈希数组(默认数组大小是16,每对key-value键值对其实是存在map的内部类entry ...

  7. Mac安装的PyCharm找不到顶部菜单栏 PyCharm找不到setting PyCharm不能个性化设置和直接导库

    安装的是最新版的PyCharm,打开发现没有顶部菜单栏,不能直接导库..有点方 以前的就是下面这种 找了很久发现原来在右下角!!!眼拙 点击画圈圈的地方就可以直接进去导库这些啦〜

  8. Mac 10.12安装远程桌面工具TeamViewer

    说明:个人使用时免费的,虽然启动时有弹框,但是不影响使用. 下载: https://www.teamviewer.com/zhCN/

  9. (转)drbd详解

    原文:http://blog.csdn.net/u014421556/article/details/52925442

  10. (转)mysql主从切换步骤

    原文:http://6226001001.blog.51cto.com/9243584/1723273 1> 正常切换 1)从服务器检查SHOW PROCESSLIST语句的输出,直到你看到Ha ...