目的:

游戏中经常会用到进度条,但是美术给的图片用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. Elasticsearch(八)【NEST高级客户端--Mapping映射】

    要使用NEST与Elasticsearch进行交互,我们需要能够将我们的解决方案中的POCO类型映射到存储在Elasticsearch中的反向索引中的JSON文档和字段.本节介绍NEST中可用的所有不 ...

  2. 异步 JavaScript - 事件循环

    简评:如果你对 JavaScript 异步的原理感兴趣,这里有一篇不错的介绍. JavaScript 同步代码是如果工作的 在介绍 JavaScript 异步执行之前先来了解一下, JavaScrip ...

  3. 编程开发之--java多线程学习总结(5)

    4.对继承自Runnable的线程进行锁机制的使用 package com.lfy.ThreadsSynchronize; import java.util.concurrent.locks.Lock ...

  4. docker 限制 容器内存 使用

    转载 : https://www.cnblogs.com/sparkdev/p/8032330.html 默认情况下容器使用的资源是不受限制的.也就是可以使用主机内核调度器所允许的最大资源.但是在容器 ...

  5. 树形DP学习笔记

    树形DP 入门模板题 poj P2342 大意就是一群职员之间有上下级关系,每个职员有一个快乐值,但是只有在他的直接上级不在场的情况下才会快乐.求举行一场聚会的快乐值之和的最大值. 求解 声明一个数组 ...

  6. gerapy的初步使用(管理分布式爬虫)

    一.简介与安装 Gerapy 是一款分布式爬虫管理框架,支持 Python 3,基于 Scrapy.Scrapyd.Scrapyd-Client.Scrapy-Redis.Scrapyd-API.Sc ...

  7. Mac 10.12高级防火墙pfctl教程收集(待实践)

    在Mac 10.10之前使用ipfw.之后升级为pfctl.由于Mac自带的GUI防火墙只能针对软件进行放开,且无法针对特定端口入站及出站进行管理.所以使用pfctl能解决这类问题. 收集教程如下: ...

  8. 高性能web服务器(热死你)Resin Linux的安装、配置、部署,性能远超Nginx支持Java、PHP等

    高性能web服务器(热死你)Resin Linux的安装.配置.部署,性能远超Nginx支持Java.PHP等 一.    安装resin 1.  下载resin: 下载地址:http://cauch ...

  9. Windows里下载并安装phpstudy(图文详解)

    不多说,直接上干货! 帮助站长快速搭建网站服务器平台! phpstudy软件简介 此是基于phpStudy 2016.01.01. 该程序包集成最新的Apache+Nginx+LightTPD+PHP ...

  10. javascript中的function 函数名(){} 和 函数名:function(){}有什么不同

    function functionName(){};这是定义一个函数 functionName:function(){};是设置一个对象的方法. 下面举一个例子: <html> <h ...