目的:

游戏中经常会用到进度条,但是美术给的图片用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. Deepin personalized transplantation of kali platform tools

    首先配置更新源: 把kali的源添加到 Deepin 自带的源后面: 简易换源方法: 1.打开文件管理 -> 地址栏输入路径:/etc/apt/ 然后回车->在目录中右键以管理员身份打开 ...

  2. javascript高逼格代码实现数组去重,JSON深度拷贝,匿名函数自执行,数字取整等

    1.如何装逼用代码骂别人傻逼 (!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]] 2.如何优雅的用代 ...

  3. AngularJS入门讲解3:$http服务和路由讲解

    上一课的例子中,我们的模型数据是硬编码的,也就是说,我们的数据不是从服务器请求回来的. 这里,我们先讲解,如何从服务器获取数据: function PhoneListCtrl($scope, $htt ...

  4. 字符串模式匹配算法2 - AC算法

    上篇文章(http://www.cnblogs.com/zzqcn/p/3508442.html)里提到的BF和KMP算法都是单模式串匹配算法,也就是说,模式串只有一个.当需要在字符串中搜索多个关键字 ...

  5. C++基础知识:成员函数、对象拷贝、私有成员

    一.综述 类是我们自己定义的数据类型(新类型) 设计类时要考虑的角度: (1)站在设计和实现者的角度来考虑 (2)站在使用者的角度来考虑 (3)父类,子类 二.类基础 (1)一个类就是一个用户自己定义 ...

  6. web站点启用https (二)

    接上篇内容 二.实际配置案例 实验案例:为web站点启用https 实验环境:seven公司有一个web站点,域名为www.seven.com,启用的身份验证方式是基本验证方式.随着业务发展想成为网上 ...

  7. 编程开发之--java多线程学习总结(1)问题引入与概念叙述

    1.经典问题,火车站售票,公共票源箱,多个窗口同时取箱中车票销售 package com.lfy.ThreadsSynchronize; /** * 解决办法分析:即我们不能同时让超过两个以上的线程进 ...

  8. [HNOI2019]鱼

    Luogu5286 \(2019.4.14\),新生第一题,改了\(3\)个小时 题解-租酥雨,和出题人给的正解一模一样 枚举\(AD\),分别考虑鱼身\(BC\)和鱼尾\(EF\) 到\(E\),\ ...

  9. Apache Maven的入门使用之项目的基本构建(1)

    前言 最近在研究java框架struts2的相关漏洞,然后就去看了官方给出的文档.在看文档的过程中发现使用到了Apache Maven这个项目管理工具,我在网上搜索了一下,大多数文章都写得不是很系统, ...

  10. SpringSecurity之记住我功能的实现

    Spring security记住我基本原理: 登录的时候,请求发送给过滤器UsernamePasswordAuthenticationFilter,当该过滤器认证成功后,会调用RememberMeS ...