初始化

This commit is contained in:
come
2025-07-26 16:56:42 +08:00
parent 8291dbb91c
commit fa81439a8c
2574 changed files with 328492 additions and 2170 deletions

View File

@@ -0,0 +1,28 @@
using Sirenix.OdinInspector;
namespace YIUIFramework
{
/// <summary>
/// 颜色叠加模式
/// </summary>
public enum ColorModeEnum
{
/// <summary>
/// 混合源和覆盖。
/// </summary>
[LabelText("混合源和覆盖")]
Blend = 0,
/// <summary>
/// 添加源颜色和叠加。
/// </summary>
[LabelText("添加源颜色和叠加")]
Additive = 1,
/// <summary>
/// 在叠加之间筛选源颜色。
/// </summary>
[LabelText("在叠加之间筛选源颜色")]
Screen = 2,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6ca73f53dcfd4fc88ace0eaf0b2d924f
timeCreated: 1681377423

View File

@@ -0,0 +1,759 @@
using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 效果控制
/// </summary>
[AddComponentMenu("YIUIBind/Effect/Effect Control 特效控制器")]
public sealed class EffectControl : MonoBehaviour
{
[SerializeField]
[LabelText("循环中")]
private bool looping = false;
[SerializeField]
[LabelText("延迟时间")]
private float delay = 0.0f;
[SerializeField]
[LabelText("效果持续时间")]
private float duration = 5.0f;
[SerializeField]
[LabelText("随着时间的推移而逐渐消失")]
private float fadeout = 1.0f;
private PlayState state = PlayState.Stopping;
private float timer;
private List<ParticleSystem> particleSystems;
private List<Animator> animators;
private List<Animation> animations;
private float playbackSpeed = 1.0f;
private bool releaseAfterFinish = false;
public bool ReleaseAfterFinish
{
get { return releaseAfterFinish; }
set { releaseAfterFinish = value; }
}
/// <summary>
/// 淡出事件
/// </summary>
public event Action FadeoutEvent;
/// <summary>
/// 完成事件
/// </summary>
public event Action FinishEvent;
/// <summary>
/// 效果的播放状态
/// </summary>
private enum PlayState
{
Stopping,
Pending,
Playing,
Pausing,
Fadeouting,
}
/// <summary>
/// 获取一个值,该值指示此效果是否正在循环
/// </summary>
public bool IsLooping
{
get { return this.looping; }
}
/// <summary>
/// 获取一个值,该值指示是否暂停此效果。
/// </summary>
public bool IsPaused
{
get { return PlayState.Pausing == this.state; }
}
/// <summary>
/// 获取一个值,该值指示是否停止此效果。
/// </summary>
public bool IsStopped
{
get { return PlayState.Stopping == this.state; }
}
/// <summary>
/// 获取效果持续时间。
/// </summary>
public float Duration
{
get { return this.duration; }
}
/// <summary>
/// 获取效果淡出时间。
/// </summary>
public float Fadeout
{
get { return this.fadeout; }
}
/// <summary>
/// 获取或设置此效果的播放速度。
/// </summary>
public float PlaybackSpeed
{
get { return this.playbackSpeed; }
set
{
this.playbackSpeed = value;
foreach (var particleSystem in this.ParticleSystems)
{
var main = particleSystem.main;
main.simulationSpeed = this.playbackSpeed;
}
foreach (var animator in this.Animators)
{
animator.speed = this.playbackSpeed;
}
foreach (var animation in this.Animations)
{
var clip = animation.clip;
if (clip != null)
{
animation[clip.name].speed = this.playbackSpeed;
}
}
}
}
/// <summary>
/// 得到粒子系统。
/// </summary>
private List<ParticleSystem> ParticleSystems
{
get
{
if (this.particleSystems == null)
{
this.particleSystems = ListPool<ParticleSystem>.Get();
this.GetComponentsInChildren(true, particleSystems);
foreach (var particleSystem in this.ParticleSystems)
{
var main = particleSystem.main;
main.simulationSpeed = this.playbackSpeed;
}
}
return this.particleSystems;
}
}
/// <summary>
/// 获取动画器
/// </summary>
private List<Animator> Animators
{
get
{
if (this.animators == null)
{
this.animators = ListPool<Animator>.Get();
this.GetComponentsInChildren(true, this.animators);
foreach (var animator in this.animators)
{
animator.speed = this.playbackSpeed;
}
}
return this.animators;
}
}
/// <summary>
/// 获取动画
/// </summary>
private List<Animation> Animations
{
get
{
if (this.animations == null)
{
this.animations = ListPool<Animation>.Get();
this.GetComponentsInChildren(true, this.animations);
foreach (var animation in this.animations)
{
var clip = animation.clip;
if (clip != null)
{
animation[clip.name].speed = this.playbackSpeed;
}
}
}
return this.animations;
}
}
#if UNITY_EDITOR
/// <summary>
/// 估计持续时间。
/// </summary>
public void EstimateDuration()
{
this.looping = false;
this.duration = 0.0f;
this.fadeout = 0.0f;
foreach (var particleSystem in this.ParticleSystems)
{
if (particleSystem == null)
{
continue;
}
if (particleSystem.main.loop)
{
this.looping = true;
}
if (this.duration < particleSystem.main.duration)
{
this.duration = particleSystem.main.duration;
}
if (this.fadeout < particleSystem.main.startLifetimeMultiplier)
{
this.fadeout = particleSystem.main.startLifetimeMultiplier;
}
}
foreach (var animation in this.Animations)
{
if (animation == null)
{
continue;
}
var clip = animation.clip;
if (clip == null)
{
continue;
}
if (clip.isLooping)
{
this.looping = true;
}
if (this.duration < clip.length)
{
this.duration = clip.length;
}
}
foreach (var animator in this.Animators)
{
if (animator == null)
{
continue;
}
var stateInfo = animator.GetCurrentAnimatorStateInfo(0);
if (stateInfo.loop)
{
this.looping = true;
}
if (this.duration < stateInfo.length)
{
this.duration = stateInfo.length;
}
}
}
/// <summary>
/// 刷新此效果。
/// </summary>
public void Refresh()
{
if (this.particleSystems != null)
{
ListPool<ParticleSystem>.Put(this.particleSystems);
this.particleSystems = null;
}
if (this.animations != null)
{
ListPool<Animation>.Put(this.animations);
this.animations = null;
}
if (this.animators != null)
{
ListPool<Animator>.Put(this.animators);
this.animators = null;
}
}
private void OnDestroy()
{
Refresh();
}
/// <summary>
/// 开始模拟。
/// </summary>
public void SimulateInit()
{
// 烘焙所有动画师。
var animators = this.Animators;
foreach (var animator in animators)
{
if (animator == null)
{
continue;
}
if (animator.runtimeAnimatorController == null)
{
continue;
}
const float FrameRate = 30f;
var stateInfo = animator.GetCurrentAnimatorStateInfo(0);
int frameCount = (int)((stateInfo.length * FrameRate) + 2);
animator.Rebind();
animator.StopPlayback();
animator.recorderStartTime = 0;
animator.StartRecording(frameCount);
for (var i = 0; i < frameCount - 1; ++i)
{
animator.Update(i / FrameRate);
}
animator.StopRecording();
animator.StartPlayback();
}
}
/// <summary>
/// 开始模拟效果。
/// </summary>
public void SimulateStart()
{
var particleSystems = this.ParticleSystems;
foreach (var ps in particleSystems)
{
if (ps == null)
{
continue;
}
ps.Simulate(0, false, true);
ps.time = 0;
ps.Play();
}
var animators = this.Animators;
foreach (var animator in animators)
{
if (animator == null)
{
continue;
}
if (animator.runtimeAnimatorController == null)
{
continue;
}
animator.playbackTime = 0.0f;
animator.Update(0.0f);
}
var animations = this.Animations;
foreach (var animation in animations)
{
if (animation == null)
{
continue;
}
var clip = animation.clip;
if (clip == null)
{
continue;
}
clip.SampleAnimation(animation.gameObject, 0.0f);
}
}
/// <summary>
/// 通过增量时间更新模拟的效果。
/// </summary>
public void SimulateDelta(float time, float deltaTime)
{
var particleSystems = this.ParticleSystems;
foreach (var ps in particleSystems)
{
if (ps == null)
{
continue;
}
ps.Simulate(deltaTime, false, false);
}
var animators = this.Animators;
foreach (var animator in animators)
{
if (animator == null)
{
continue;
}
if (animator.runtimeAnimatorController == null)
{
continue;
}
animator.playbackTime = time;
animator.Update(0.0f);
}
var animations = this.Animations;
foreach (var animation in animations)
{
if (animation == null)
{
continue;
}
var clip = animation.clip;
if (clip == null)
{
continue;
}
clip.SampleAnimation(animation.gameObject, time);
}
}
/// <summary>
/// 模拟在编辑器模式下。
/// </summary>
public void Simulate(float time)
{
var randomKeeper = new Dictionary<ParticleSystem, KeyValuePair<bool, uint>>();
var particleSystems = this.ParticleSystems;
foreach (var ps in particleSystems)
{
if (ps == null)
{
continue;
}
ps.Stop(false);
var pair = new KeyValuePair<bool, uint>(
ps.useAutoRandomSeed, ps.randomSeed);
randomKeeper.Add(ps, pair);
if (!ps.isPlaying)
{
ps.useAutoRandomSeed = false;
ps.randomSeed = 0;
}
ps.Simulate(0, false, true);
ps.time = 0;
ps.Play();
}
for (float i = 0.0f; i < time; i += 0.02f)
{
foreach (var ps in particleSystems)
{
if (ps == null)
{
continue;
}
ps.Simulate(0.02f, false, false);
}
}
foreach (var ps in particleSystems)
{
if (ps == null)
{
continue;
}
ps.Stop(false);
var pair = randomKeeper[ps];
ps.randomSeed = pair.Value;
ps.useAutoRandomSeed = pair.Key;
}
var animators = this.Animators;
foreach (var animator in animators)
{
if (animator == null)
{
continue;
}
if (animator.runtimeAnimatorController == null)
{
continue;
}
animator.playbackTime = time;
animator.Update(0.0f);
}
var animations = this.Animations;
foreach (var animation in animations)
{
if (animation == null)
{
continue;
}
var clip = animation.clip;
if (clip == null)
{
continue;
}
clip.SampleAnimation(animation.gameObject, time);
}
}
#endif
/// <summary>
/// 开始
/// </summary>
public void Play()
{
if (PlayState.Playing == this.state)
{
this.Stop();
}
this.state = PlayState.Pending;
}
/// <summary>
/// 暂停
/// </summary>
public void Pause()
{
if (PlayState.Playing == this.state)
{
foreach (var particleSystem in this.ParticleSystems)
{
particleSystem.Pause(false);
}
foreach (var animator in this.Animators)
{
animator.speed = 0.0f;
}
foreach (var animation in this.Animations)
{
var clip = animation.clip;
if (clip != null)
{
animation[clip.name].speed = 0.0f;
}
}
this.state = PlayState.Pausing;
}
}
/// <summary>
/// 重新开始
/// </summary>
public void Resume()
{
if (PlayState.Pausing == this.state)
{
foreach (var particleSystem in this.ParticleSystems)
{
particleSystem.Play(false);
}
foreach (var animator in this.Animators)
{
animator.speed = this.playbackSpeed;
}
foreach (var animation in this.Animations)
{
var clip = animation.clip;
if (clip != null)
{
animation[clip.name].speed = this.playbackSpeed;
}
}
this.state = PlayState.Playing;
}
}
public void ForceCallFinishEvent()
{
if (this.FinishEvent != null)
{
this.FinishEvent();
}
}
public void ClearFinishEvent()
{
this.FinishEvent = null;
this.ReleaseAfterFinish = false;
}
/// <summary>
/// 暂停
/// </summary>
public void Stop()
{
if (this.state != PlayState.Stopping)
{
this.state = PlayState.Fadeouting;
foreach (var particleSystem in this.ParticleSystems)
{
particleSystem.Stop(false);
}
foreach (var animator in this.Animators)
{
animator.gameObject.SetActive(false);
}
foreach (var animation in this.Animations)
{
if (animation.playAutomatically)
{
animation.gameObject.SetActive(false);
}
else
{
animation.Stop();
}
}
if (this.FadeoutEvent != null)
{
this.FadeoutEvent();
this.FadeoutEvent = null;
}
}
}
/// <summary>
/// 重置
/// </summary>
public void Reset()
{
this.timer = 0.0f;
this.state = PlayState.Stopping;
}
private void Awake()
{
if (this.particleSystems == null)
{
this.particleSystems = ListPool<ParticleSystem>.Get();
this.GetComponentsInChildren(true, this.particleSystems);
}
this.Reset();
}
private void LateUpdate()
{
if (PlayState.Stopping == this.state ||
PlayState.Pausing == this.state)
{
return;
}
this.timer += Time.deltaTime * this.playbackSpeed;
if (PlayState.Pending == this.state && this.timer >= this.delay)
{
foreach (var particleSystem in this.ParticleSystems)
{
particleSystem.Play(false);
}
foreach (var animator in this.Animators)
{
animator.gameObject.SetActive(false);
animator.gameObject.SetActive(true);
}
foreach (var animation in this.Animations)
{
if (animation.playAutomatically)
{
animation.gameObject.SetActive(false);
animation.gameObject.SetActive(true);
}
else
{
animation.Stop();
animation.Play();
}
}
this.state = PlayState.Playing;
}
if (!this.looping)
{
if (PlayState.Playing == this.state &&
this.timer >= this.duration)
{
this.Stop();
}
}
if (PlayState.Fadeouting == this.state &&
this.timer >= this.duration + this.fadeout)
{
this.state = PlayState.Stopping;
if (this.FinishEvent != null)
{
this.FinishEvent();
this.FinishEvent = null;
if (ReleaseAfterFinish)
{
ReleaseAfterFinish = false;
//Debug.LogError("TODO GameObjectPool");
//GameObjectPool.Instance.Free(gameObject);
}
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: baa80460a939459984ae4185c1d08399
timeCreated: 1679041703

View File

@@ -0,0 +1,191 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
namespace YIUIFramework
{
/// <summary>
/// 这是一个仅用于编辑器的脚本,用于在编辑模式下显示预览对象
/// </summary>
[ExecuteInEditMode]
public sealed class PreviewObject : MonoBehaviour
{
private GameObject preview;
private bool simulateInEditMode = true; //记录播放时间
private float playingTime = 0.0f;
private double lastTime = -1.0;
/// <summary>
/// 获取或设置一个值,该值指示是否在编辑模式下模拟。
/// </summary>
public bool SimulateInEditMode
{
get { return this.simulateInEditMode; }
set { this.simulateInEditMode = value; }
}
/// <summary>
/// 清除预览对象。
/// </summary>
public void ClearPreview()
{
if (this.preview != null)
{
var deletePreview = this.preview;
this.preview = null;
EditorApplication.delayCall += () => { GameObject.DestroyImmediate(deletePreview); };
}
}
/// <summary>
/// 设置预览对象
/// </summary>
public void SetPreview(GameObject previewObj)
{
// Destroy the pre-preview.
if (this.preview != null)
{
var deletePreview = this.preview;
this.preview = null;
EditorApplication.delayCall += () => { GameObject.DestroyImmediate(deletePreview); };
}
// Attach the preview object.
this.preview = previewObj;
this.preview.tag = "EditorOnly";
this.preview.transform.SetParent(this.transform, false);
// Start the animation.
if (this.simulateInEditMode)
{
var effectControl = this.preview.GetComponent<EffectControl>();
if (effectControl != null)
{
effectControl.SimulateInit();
effectControl.SimulateStart();
}
else
{
var particelSystems = this.preview.GetComponentsInChildren<ParticleSystem>();
foreach (var ps in particelSystems)
{
ps.Simulate(0.0f, false, true);
}
}
}
// Hide this preview.
this.SetHideFlags(this.preview, HideFlags.DontSave);
}
private void Awake()
{
this.hideFlags = HideFlags.DontSave;
EditorApplication.playModeStateChanged += (PlayModeStateChange state) =>
{
if (EditorApplication.isPlaying ||
EditorApplication.isPlayingOrWillChangePlaymode ||
EditorApplication.isCompiling)
{
if (this.preview != null)
{
GameObject.DestroyImmediate(this.preview);
this.preview = null;
}
}
};
}
private void OnDestroy()
{
if (this.preview != null)
{
GameObject.DestroyImmediate(this.preview);
this.preview = null;
}
}
private void OnEnable()
{
if (Application.isPlaying)
{
return;
}
EditorApplication.update += this.UpdatePreview;
this.lastTime = EditorApplication.timeSinceStartup;
if (this.preview != null)
{
this.preview.SetActive(true);
}
}
private void OnDisable()
{
if (Application.isPlaying)
{
return;
}
EditorApplication.update -= this.UpdatePreview;
if (this.preview != null)
{
this.preview.SetActive(false);
}
}
private void UpdatePreview()
{
if (!this.simulateInEditMode)
{
return;
}
var timeSinceStartup = EditorApplication.timeSinceStartup;
var deltaTime = (float)(timeSinceStartup - this.lastTime);
this.lastTime = timeSinceStartup;
this.playingTime += deltaTime;
if (this.preview == null)
{
return;
}
// Start the animation.
var effectControl = this.preview.GetComponent<EffectControl>();
if (effectControl != null)
{
effectControl.SimulateDelta(this.playingTime, deltaTime);
}
else
{
float playTime = 0.0f;
var particelSystems =
this.preview.GetComponentsInChildren<ParticleSystem>();
foreach (var ps in particelSystems)
{
if (playTime < ps.main.duration)
{
playTime = ps.main.duration;
}
}
foreach (var ps in particelSystems)
{
ps.Simulate(deltaTime, false, false);
}
}
}
private void SetHideFlags(GameObject obj, HideFlags flags)
{
obj.hideFlags = flags;
for (int i = 0; i < obj.transform.childCount; ++i)
{
var child = obj.transform.GetChild(i);
this.SetHideFlags(child.gameObject, flags);
}
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7c63b46be60d4b3f990e04cccd7196b1
timeCreated: 1679041382

View File

@@ -0,0 +1,240 @@
Shader "YIUI/UIEffect"
{
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
_Color("Tint", Color) = (1,1,1,1)
_StencilComp("Stencil Comparison", Float) = 8
_Stencil("Stencil ID", Float) = 0
_StencilOp("Stencil Operation", Float) = 0
_StencilWriteMask("Stencil Write Mask", Float) = 255
_StencilReadMask("Stencil Read Mask", Float) = 255
_ColorMask("Color Mask", Float) = 15
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0
_OverlayTex("Overlay Texture", 2D) = "white" {}
_OverlaySpeed("Overlay Texture Speed", Float) = 1
_BlurDistance("Blur Distance", Float) = 0.015
_GrayLerp("Grayscale Lerp", Float) = 1
_LightOffset("Light Offset", Float) = 1
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
"CanUseSpriteAtlas" = "True"
}
Stencil
{
Ref[_Stencil]
Comp[_StencilComp]
Pass[_StencilOp]
ReadMask[_StencilReadMask]
WriteMask[_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile __ UNITY_UI_ALPHACLIP
//#pragma multi_compile __ UIEFFECT_OVERLAY UIEFFECT_OVERLAY_ANIMATION
#pragma multi_compile __ UIEFFECT_GRAYSCALE UIEFFECT_GRAYSCALE_LERP
#pragma multi_compile __ UIEFFECT_WHITEALL
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
#if defined(UIEFFECT_OVERLAY) || defined(UIEFFECT_OVERLAY_ANIMATION) || defined(UIEFFECT_INNER_BEVEL)
float2 texcoord1 : TEXCOORD1;
#endif
#if defined(UIEFFECT_INNER_BEVEL)
float4 tangent : TANGENT;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
#if defined(UIEFFECT_OVERLAY) || defined(UIEFFECT_OVERLAY_ANIMATION) || defined(UIEFFECT_INNER_BEVEL)
half4 texcoord : TEXCOORD0;
#else
half2 texcoord : TEXCOORD0;
#endif
#if defined(UIEFFECT_INNER_BEVEL)
float4 tangent : TEXCOORD1;
#endif
float4 worldPosition : TEXCOORD2;
UNITY_VERTEX_OUTPUT_STEREO
};
fixed4 _Color;
half _IsInUICamera;
v2f vert(appdata_t IN)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = IN.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
#if defined(UIEFFECT_OVERLAY) || defined(UIEFFECT_OVERLAY_ANIMATION) || defined(UIEFFECT_INNER_BEVEL)
OUT.texcoord.xy = IN.texcoord;
OUT.texcoord.zw = IN.texcoord1;
#else
OUT.texcoord = IN.texcoord;
#endif
#if defined(UIEFFECT_INNER_BEVEL)
OUT.tangent = IN.tangent;
#endif
//IN.color.rgb *=
OUT.color = IN.color * _Color;
return OUT;
}
sampler2D _MainTex;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
// Overlay
sampler2D _OverlayTex;
int _OverlayColorMode;
float _OverlaySpeed;
// Inner Bevel
fixed4 _HighlightColor;
int _HighlightColorMode;
fixed4 _ShadowColor;
int _ShadowColorMode;
half2 _HighlightOffset;
// Blur.
float _BlurDistance;
// Grayscale.
float _GrayLerp;
// LightOffset.
float _LightOffset;
fixed4 frag(v2f IN) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord.xy) + _TextureSampleAdd) * IN.color;
#ifdef UIEFFECT_BLUR
color += tex2D(_MainTex, half2(IN.texcoord.x + _BlurDistance, IN.texcoord.y + _BlurDistance)) * IN.color;
color += tex2D(_MainTex, half2(IN.texcoord.x + _BlurDistance, IN.texcoord.y)) * IN.color;
color += tex2D(_MainTex, half2(IN.texcoord.x, IN.texcoord.y + _BlurDistance)) * IN.color;
color += tex2D(_MainTex, half2(IN.texcoord.x - _BlurDistance, IN.texcoord.y - _BlurDistance)) * IN.color;
color += tex2D(_MainTex, half2(IN.texcoord.x + _BlurDistance, IN.texcoord.y - _BlurDistance)) * IN.color;
color += tex2D(_MainTex, half2(IN.texcoord.x - _BlurDistance, IN.texcoord.y + _BlurDistance)) * IN.color;
color += tex2D(_MainTex, half2(IN.texcoord.x - _BlurDistance, IN.texcoord.y)) * IN.color;
color += tex2D(_MainTex, half2(IN.texcoord.x, IN.texcoord.y - _BlurDistance)) * IN.color;
color = color / 9;
#endif
#if defined(UIEFFECT_OVERLAY) || defined(UIEFFECT_OVERLAY_ANIMATION)
half2 uv = IN.texcoord.zw;
# ifdef UIEFFECT_OVERLAY_ANIMATION
uv.x += _Time.y * _OverlaySpeed;
# endif
half4 overlay = tex2D(_OverlayTex, uv);
if (_OverlayColorMode == 0)
{
color.rgb = color.rgb * (1 - overlay.a) + overlay.rgb * overlay.a;
}
else if (_OverlayColorMode == 1)
{
color.rgb += overlay.rgb;
}
else if (_OverlayColorMode == 2)
{
color.rgb = half3(1, 1, 1) - (half3(1, 1, 1) - color.rgb) * (half3(1, 1, 1) - overlay.rgb);
}
#endif
#if defined(UIEFFECT_INNER_BEVEL)
float factor = min(IN.texcoord.z, 1);
half2 highlightOffset = _HighlightOffset.x * half2(IN.tangent.xy) - _HighlightOffset.y * half2(IN.tangent.zw);
fixed shadowColAlpha = (1 - tex2D(_MainTex, IN.texcoord + highlightOffset).a) * _ShadowColor.a * factor;
if (_ShadowColorMode == 0)
{
color.rgb = color.rgb * (1 - shadowColAlpha) + _ShadowColor.rgb * shadowColAlpha;
}
else if (_ShadowColorMode == 1)
{
color.rgb = color.rgb + _ShadowColor.rgb * shadowColAlpha;
}
else
{
color.rgb = color.rgb * (1 - shadowColAlpha) + color.rgb * _ShadowColor.rgb * shadowColAlpha;
}
fixed highlightColAlpha = (1 - tex2D(_MainTex, IN.texcoord - highlightOffset).a) * _HighlightColor.a * factor;
if (_HighlightColorMode == 0)
{
color.rgb = color.rgb * (1 - highlightColAlpha) + _HighlightColor.rgb * highlightColAlpha;
}
else if (_HighlightColorMode == 1)
{
color.rgb = color.rgb + _HighlightColor.rgb * highlightColAlpha;
}
else
{
color.rgb = color.rgb * (1 - highlightColAlpha) + color.rgb * _HighlightColor.rgb * highlightColAlpha;
}
#endif
color.rgb = LinearToGammaSpace(color.rgb) * _LightOffset;
#ifdef UIEFFECT_GRAYSCALE
color.rgb = Luminance(color.rgb) * 1; //全灰状态下设置X倍亮度
#elif UIEFFECT_GRAYSCALE_LERP
color.rgb = lerp(Luminance(color.rgb), color.rgb, _GrayLerp);
#endif
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#ifdef UNITY_UI_ALPHACLIP
clip(color.a - 0.001);
#endif
#ifdef UIEFFECT_WHITEALL
color = (1, 1, 1, color.a);
#endif
return color;
}
ENDCG
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: ede8a18f8efc110419beef4572e9109b
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,181 @@
using System;
using UnityEngine;
namespace YIUIFramework
{
internal struct UIEffectMaterialKey : IEquatable<UIEffectMaterialKey>
{
internal float BlurDistance;
internal Texture2D OverlayTexture;
internal ColorModeEnum OverlayColorMode;
internal float OverlaySpeed;
internal bool EnableInnerBevel;
internal Color HighlightColor;
internal ColorModeEnum HighlightColorMode;
internal Color ShadowColor;
internal ColorModeEnum ShadowColorMode;
internal Vector2 HighlightOffset;
internal byte GrayScale;
public bool Equals(UIEffectMaterialKey o)
{
if (this.BlurDistance != o.BlurDistance)
{
return false;
}
if (this.OverlayTexture != o.OverlayTexture)
{
return false;
}
if (this.OverlayColorMode != o.OverlayColorMode)
{
return false;
}
if (this.OverlaySpeed != o.OverlaySpeed)
{
return false;
}
if (this.EnableInnerBevel != o.EnableInnerBevel)
{
return false;
}
if (this.HighlightColor != o.HighlightColor)
{
return false;
}
if (this.HighlightColorMode != o.HighlightColorMode)
{
return false;
}
if (this.ShadowColor != o.ShadowColor)
{
return false;
}
if (this.ShadowColorMode != o.ShadowColorMode)
{
return false;
}
if (this.HighlightOffset != o.HighlightOffset)
{
return false;
}
if (this.GrayScale != o.GrayScale)
{
return false;
}
return true;
}
public override int GetHashCode()
{
int hash = this.BlurDistance.GetHashCode();
if (this.OverlayTexture != null)
{
hash = (397 * hash) ^ this.OverlayTexture.GetHashCode();
}
hash = (397 * hash) ^ this.OverlayColorMode.GetHashCode();
hash = (397 * hash) ^ this.OverlaySpeed.GetHashCode();
hash = (397 * hash) ^ this.EnableInnerBevel.GetHashCode();
hash = (397 * hash) ^ this.HighlightColor.GetHashCode();
hash = (397 * hash) ^ this.HighlightColorMode.GetHashCode();
hash = (397 * hash) ^ this.ShadowColor.GetHashCode();
hash = (397 * hash) ^ this.ShadowColorMode.GetHashCode();
hash = (397 * hash) ^ this.HighlightOffset.GetHashCode();
hash = (397 * hash) ^ this.GrayScale.GetHashCode();
return hash;
}
internal Material CreateMaterial()
{
if (this.BlurDistance == 0 &&
this.OverlayTexture == null &&
!this.EnableInnerBevel &&
this.GrayScale == 0)
{
return null;
}
var shader = Shader.Find("YIUI/UIEffect");
if (shader == null)
{
Debug.LogError("Can not found shader: 'YIUI/UIEffect'");
return null;
}
var material = new Material(shader);
if (this.BlurDistance > 0)
{
material.EnableKeyword("UIEFFECT_BLUR");
material.SetFloat(
"_BlurDistance", this.BlurDistance);
}
if (this.OverlayTexture != null)
{
if (this.OverlaySpeed > 0)
{
material.EnableKeyword("UIEFFECT_OVERLAY_ANIMATION");
material.SetFloat(
"_OverlaySpeed", this.OverlaySpeed);
}
else
{
material.EnableKeyword("UIEFFECT_OVERLAY");
}
material.SetTexture(
"_OverlayTex", this.OverlayTexture);
material.SetInt(
"_OverlayColorMode", (int)this.OverlayColorMode);
}
if (this.EnableInnerBevel)
{
material.EnableKeyword("UIEFFECT_INNER_BEVEL");
material.SetColor(
"_HighlightColor", this.HighlightColor);
material.SetInt(
"_HighlightColorMode", (int)this.HighlightColorMode);
material.SetColor(
"_ShadowColor", this.ShadowColor);
material.SetInt(
"_ShadowColorMode", (int)this.ShadowColorMode);
material.SetVector(
"_HighlightOffset", this.HighlightOffset);
}
if (this.GrayScale > 0)
{
if (this.GrayScale == 255)
{
material.EnableKeyword("UIEFFECT_GRAYSCALE");
}
else
{
material.EnableKeyword("UIEFFECT_GRAYSCALE_LERP");
material.SetFloat(
"_GrayLerp",
1.0f - (this.GrayScale / 255.0f));
}
}
return material;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fed5620bfa944b1fad6e01825dc407f3
timeCreated: 1681377403

View File

@@ -0,0 +1,107 @@
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace YIUIFramework
{
internal static class UIEffectMaterials
{
private static Dictionary<UIEffectMaterialKey, MaterialRef> materials =
new Dictionary<UIEffectMaterialKey, MaterialRef>();
private static Dictionary<Material, UIEffectMaterialKey> lookup =
new Dictionary<Material, UIEffectMaterialKey>();
internal static Material Get(UIEffectMaterialKey key)
{
MaterialRef matref;
if (materials.TryGetValue(key, out matref))
{
++matref.RefCount;
return matref.Material;
}
var material = key.CreateMaterial();
if (material == null)
{
return null;
}
materials.Add(key, new MaterialRef(material));
lookup.Add(material, key);
return material;
}
internal static void Free(Material material)
{
UIEffectMaterialKey key;
if (!lookup.TryGetValue(material, out key))
{
Debug.LogError("Can not find the material key.");
return;
}
MaterialRef matref;
if (!materials.TryGetValue(key, out matref))
{
Debug.LogError("Can not find the material reference.");
return;
}
if (--matref.RefCount <= 0)
{
matref.Material.SafeDestroySelf();
materials.Remove(key);
lookup.Remove(material);
}
}
#if UNITY_EDITOR
private static void ClearCache()
{
materials.Clear();
lookup.Clear();
SceneView.RepaintAll();
}
#endif
private class MaterialKeyComparer : IEqualityComparer<UIEffectMaterialKey>
{
public bool Equals(UIEffectMaterialKey x, UIEffectMaterialKey y)
{
return x.Equals(y);
}
public int GetHashCode(UIEffectMaterialKey obj)
{
return obj.GetHashCode();
}
}
private class MaterialRef
{
private Material material;
private int refcount;
public MaterialRef(Material material)
{
this.material = material;
this.refcount = 1;
}
public Material Material
{
get { return this.material; }
}
public int RefCount
{
get { return this.refcount; }
set { this.refcount = value; }
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6c308540ddff41bc953ee01138bba22e
timeCreated: 1681377592

View File

@@ -0,0 +1,78 @@
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
namespace YIUIFramework
{
[ExecuteInEditMode]
[DisallowMultipleComponent]
[RequireComponent(typeof(UIMaterialEffect))]
public sealed class UIGrayscale : MonoBehaviour
{
[SerializeField]
[Range(0, 255)]
private int grayscale = 0;
private UIMaterialEffect materialEffect;
public int GrayScale
{
get { return this.grayscale; }
set
{
if (this.grayscale != value)
{
this.grayscale = value;
this.Refresh();
}
}
}
private void Awake()
{
this.Refresh();
}
private void OnDestroy()
{
if (this.materialEffect != null)
{
var key = this.materialEffect.MaterialKey;
key.GrayScale = 0;
this.materialEffect.MaterialKey = key;
this.materialEffect.MarkDirty();
}
}
#if UNITY_EDITOR
private void OnValidate()
{
this.Refresh();
}
#endif
private void Refresh()
{
#if UNITY_EDITOR
var prefabType = PrefabUtility.GetPrefabType(this.gameObject);
if (prefabType == PrefabType.Prefab)
{
return;
}
#endif
if (this.materialEffect == null)
{
this.materialEffect =
this.GetOrAddComponent<UIMaterialEffect>();
}
var key = this.materialEffect.MaterialKey;
key.GrayScale = (byte)this.grayscale;
this.materialEffect.MaterialKey = key;
this.materialEffect.MarkDirty();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3499dbcc4b3d4088a5a6557cc38479d9
timeCreated: 1681377624

View File

@@ -0,0 +1,87 @@
using UnityEngine;
using UnityEngine.UI;
namespace YIUIFramework
{
[ExecuteInEditMode]
[DisallowMultipleComponent]
[RequireComponent(typeof(Graphic))]
public sealed class UIMaterialEffect : MonoBehaviour, IMaterialModifier
{
private Graphic graphic;
private UIEffectMaterialKey materialKey;
private Material material;
internal UIEffectMaterialKey MaterialKey
{
get { return this.materialKey; }
set
{
if (!this.materialKey.Equals(value))
{
this.materialKey = value;
if (this.material != null)
{
UIEffectMaterials.Free(this.material);
this.material = null;
}
}
}
}
public Material GetModifiedMaterial(Material baseMaterial)
{
Material usedMaterial = baseMaterial;
if (this.enabled)
{
if (this.material == null)
{
this.material = UIEffectMaterials.Get(this.materialKey);
}
if (this.material)
{
usedMaterial = this.material;
}
}
var maskable = this.graphic as MaskableGraphic;
if (maskable != null)
{
return maskable.GetModifiedMaterial(usedMaterial);
}
return usedMaterial;
}
internal void MarkDirty()
{
if (this.graphic != null)
{
this.graphic.SetMaterialDirty();
}
}
private void Awake()
{
this.graphic = this.GetComponent<Graphic>();
}
private void OnEnable()
{
if (this.graphic != null)
{
this.graphic.SetMaterialDirty();
}
}
private void OnDisable()
{
if (this.graphic != null)
{
this.graphic.SetMaterialDirty();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 09fb950d90f2446d896c58e2ae60c109
timeCreated: 1681377379