Files
ichni_Official/Packages/NB_FX/XuanXuanRenderUtility/Runtime/AnimationSheetHelper.cs
SoulliesOfficial 40fa80cd70 NB_FX
2026-07-17 17:46:16 -04:00

371 lines
9.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using UnityEngine;
// using Sirenix.OdinInspector;
// using Unity.Mathematics;
using UnityEngine.UI;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
[ExecuteInEditMode]
public class AnimationSheetHelper : MonoBehaviour,IMaterialModifier
{
public bool isParticleBaseShader = true;
public string propertyName = "_BaseMap_ST";
private int _propertyID;
private int _particleBaseAniBlendStPropertyID = Shader.PropertyToID("_BaseMap_AnimationSheetBlend_ST");
private int _particleBaseAniBlendIntensityPropertyID = Shader.PropertyToID("_AnimationSheetHelperBlendIntensity");
private static readonly int ParticleShaderFlagsId = Shader.PropertyToID("_W9ParticleShaderFlags");
private static readonly int ParticleShaderFlags1Id = Shader.PropertyToID("_W9ParticleShaderFlags1");
private static readonly int NBShaderFlagsId = Shader.PropertyToID("_NBShaderFlags");
private static readonly int NBShaderFlags1Id = Shader.PropertyToID("_NBShaderFlags1");
private const int FlagBitUIEffectOn = 1 << 14;
private const int FlagBitAnimationSheetHelper = 1 << 15;
private const int FlagBitUIEffectBaseMapMode = 1 << 22;
// [LabelText("序列帧图横向帧数量")]
// [OnValueChanged("Init")]
public int xSize = 4;
// [LabelText("序列帧图纵向帧数量")]
// [OnValueChanged("Init")]
public int ySize = 4;
// [LabelText("手动控制播放")]
public bool manualPlay = false;
// [ShowIf("manualPlay")]
// [LabelText("手动播放位置")] [Range(0, 1)]
public float manualPlayePos = 0;
// [LabelText("播放速度fps")]
// [HideIf("manualPlay")]
public float speed = 16;
// [ReadOnly]
// [LabelText("TillingOffset")]
public Vector4 scaleOffset;
// [ReadOnly]
public Material mat;
// [ReadOnly]
public int frameIndex;
// [ReadOnly]
public int frameCount;
private float _time;
private float _xScale;
private float _yScale;
private static List<Material> usedMaterialList = new List<Material>();
// // Start is called before the first frame update
// void Start()
// {
// Debug.Log( "ASUpadate_Start");
// Init();
// }
private void OnEnable()
{
// Debug.Log( "ASUpadate_OnEnable");
Init();
#if UNITY_EDITOR
EditorApplication.update += EditorUpdate;
#endif
}
private void OnDisable()
{
Init();
//清掉,避免参数保留。
if (isParticleBaseShader)
{
if (mat)
{
GetShaderFlagIds(mat, out _, out int flags1Id);
ClearFlagBits(mat, flags1Id, FlagBitAnimationSheetHelper);
}
}
if (usedMaterialList.Contains(mat))
{
usedMaterialList.Remove(mat);
}
#if UNITY_EDITOR
EditorApplication.update -= EditorUpdate;
#endif
}
// [Button("初始化")]
public void Init()
{
_time = 0;
if (xSize <= 0)
{
xSize = 1;
}
if (ySize <= 0)
{
ySize = 1;
}
frameCount = xSize * ySize;
_xScale = 1 / (float)xSize;
_yScale = 1 / (float)ySize;
// if (frameCount <= 0)
// {
// frameCount = 1;
// }
// scaleOffset = new Vector4(1f/(float)xSize,1f/ (float)ySize, 0, 0);
if (gameObject.TryGetComponent(out Graphic g))
{
if (Application.isPlaying)
{
mat = g.materialForRendering;
}
else
{
mat = g.material;
}
}
else if (gameObject.TryGetComponent(out Renderer r))
{
if (Application.isPlaying)
{
mat = r.material;
}
else
{
mat = r.sharedMaterial;
}
// Debug.Log("AS_GetRenderer:Mat--"+mat.name);
}
else
{
mat = null;
}
InitParticleBaseShaderToggle();
// InitPostProcessToggle();
_propertyID = Shader.PropertyToID(propertyName);
if (mat != null)
{
mat.SetVector(_propertyID,CalSt(0));
}
}
public void InitParticleBaseShaderToggle()
{
if (isParticleBaseShader)
{
GetShaderFlagIds(mat, out int flagsId, out int flags1Id);
// Debug.Log(CheckFlagBits(mat, ParticleShaderFlags1Id, FlagBitUIEffectBaseMapMode));
if(CheckFlagBits(mat, flagsId, FlagBitUIEffectOn) && !CheckFlagBits(mat, flags1Id, FlagBitUIEffectBaseMapMode))
{
propertyName = "_UI_MainTex_ST";
}
else
{
propertyName = "_BaseMap_ST";
}
if (mat)
{
SetFlagBits(mat, flags1Id, FlagBitAnimationSheetHelper);
}
}
// else
// {
// if (mat)
// {
// if (mat.shader.name == "Mh2/Effects/Particle_NiuBi")
// {
// _flags.SetMaterial(mat);
// _flags.ClearFlagBits(W9ParticleShaderFlags.FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER,index:1);
// }
// }
// }
}
// public void InitPostProcessToggle()
// {
// if (isPostProcessShader)
// {
// TryGetComponent<PostProcessingController>(out postProcessingController);
// }
// else
// {
// postProcessingController = null;
// }
// }
// Update is called once per frame
private int _lastIndex;
private int _nextIndex = 1;
private float _blendLerp;
private void Update()
{
// if (!isPostProcessShader)//后处理控制不通过才知。
// {
// if(!mat || _propertyID==0) return;
// }
float frameIndexFloat;
if (manualPlay)
{
float playPos = Mathf.Repeat(manualPlayePos, 1f);
frameIndexFloat = playPos * frameCount;
}
else
{
if (!Application.isPlaying)
{
#if UNITY_EDITOR
_time += (float)editorDeltaTime * speed;
#endif
}
else
{
_time += Time.deltaTime * speed;
}
frameIndexFloat = _time % frameCount;
}
frameIndex = (int) frameIndexFloat;
if (frameIndex == frameCount)
{
frameIndex = frameCount - 1;
}
if (_lastIndex != frameIndex)
{
// if (isPostProcessShader)
// {
// postProcessingController.distortSpeedTexSt = CalSt(frameIndex);
// }
// else
// {
mat.SetVector(_propertyID,CalSt(frameIndex));
// }
_lastIndex = frameIndex;
_nextIndex = frameIndex + 1;
if (isParticleBaseShader)
{
mat.SetVector(_particleBaseAniBlendStPropertyID,CalSt(_nextIndex));
}
}
if (isParticleBaseShader)
{
_blendLerp = Mathf.Repeat(frameIndexFloat,1f);
mat.SetFloat(_particleBaseAniBlendIntensityPropertyID,_blendLerp);
}
}
public Material GetModifiedMaterial(Material baseMaterial)
{
if (usedMaterialList.Contains(baseMaterial))
{
//有可能打断UI合批烦请客户端判断
Material newMat = Instantiate(baseMaterial);
mat = newMat;
usedMaterialList.Add(newMat);
}
else
{
mat = baseMaterial;
usedMaterialList.Add(baseMaterial);
}
return mat;
}
private Vector4 CalSt(int index)
{
float xOffset = (index % xSize)*_xScale;
float yOffset = (ySize - index / xSize -1)*_yScale;
return new Vector4(_xScale, _yScale, xOffset, yOffset);
}
private static void SetFlagBits(Material material, int propertyId, int bits)
{
if (!material)
{
return;
}
material.SetInteger(propertyId, material.GetInteger(propertyId) | bits);
}
private static void ClearFlagBits(Material material, int propertyId, int bits)
{
if (!material)
{
return;
}
material.SetInteger(propertyId, material.GetInteger(propertyId) & ~bits);
}
private static bool CheckFlagBits(Material material, int propertyId, int bits)
{
return material && (material.GetInteger(propertyId) & bits) != 0;
}
private static void GetShaderFlagIds(Material material, out int flagsId, out int flags1Id)
{
if (material && (material.HasProperty(NBShaderFlagsId) || material.HasProperty(NBShaderFlags1Id)))
{
flagsId = NBShaderFlagsId;
flags1Id = NBShaderFlags1Id;
return;
}
flagsId = ParticleShaderFlagsId;
flags1Id = ParticleShaderFlags1Id;
}
#if UNITY_EDITOR
private double editorDeltaTime = 0;
private double lastEditorTime = 0;
void EditorUpdate()
{
if (lastEditorTime == 0)
{
lastEditorTime = EditorApplication.timeSinceStartup;
}
editorDeltaTime = EditorApplication.timeSinceStartup - lastEditorTime;
lastEditorTime = EditorApplication.timeSinceStartup;
if (!Application.isPlaying)
{
Update();
}
}
#endif
}