using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using System;
namespace Coffee.UIEffects
{
public interface IParameterTexture
{
int parameterIndex { get; set; }
ParameterTexture paramTex { get; }
}
///
/// Parameter texture.
///
[Serializable]
public class ParameterTexture
{
//################################
// Public Members.
//################################
///
/// Initializes a new instance of the class.
///
/// Channels.
/// Instance limit.
/// Property name.
public ParameterTexture(int channels, int instanceLimit, string propertyName)
{
this._propertyName = propertyName;
this._channels = ((channels - 1) / 4 + 1) * 4;
this._instanceLimit = ((instanceLimit - 1) / 2 + 1) * 2;
this._data = new byte[this._channels * this._instanceLimit];
this._stack = new Stack(this._instanceLimit);
for (int i = 1; i < this._instanceLimit + 1; i++)
{
this._stack.Push(i);
}
}
///
/// Register the specified target.
///
/// Target.
public void Register(IParameterTexture target)
{
Initialize();
if (target.parameterIndex <= 0 && 0 < this._stack.Count)
{
target.parameterIndex = this._stack.Pop();
// Debug.LogFormat("@@@ Register {0} : {1}", target, target.parameterIndex);
}
}
///
/// Unregister the specified target.
///
/// Target.
public void Unregister(IParameterTexture target)
{
if (0 < target.parameterIndex)
{
// Debug.LogFormat("@@@ Unregister {0} : {1}", target, target.parameterIndex);
this._stack.Push(target.parameterIndex);
target.parameterIndex = 0;
}
}
///
/// Sets the data.
///
/// Target.
/// Channel identifier.
/// Value.
public void SetData(IParameterTexture target, int channelId, byte value)
{
int index = (target.parameterIndex - 1) * this._channels + channelId;
if (0 < target.parameterIndex && this._data[index] != value)
{
this._data[index] = value;
this._needUpload = true;
}
}
///
/// Sets the data.
///
/// Target.
/// Channel identifier.
/// Value.
public void SetData(IParameterTexture target, int channelId, float value)
{
SetData(target, channelId, (byte) (Mathf.Clamp01(value) * 255));
}
///
/// Registers the material.
///
/// Mat.
public void RegisterMaterial(Material mat)
{
if (this._propertyId == 0)
{
this._propertyId = Shader.PropertyToID(this._propertyName);
}
if (mat)
{
mat.SetTexture(this._propertyId, this._texture);
}
}
///
/// Gets the index of the normalized.
///
/// The normalized index.
/// Target.
public float GetNormalizedIndex(IParameterTexture target)
{
return ((float) target.parameterIndex - 0.5f) / this._instanceLimit;
}
//################################
// Private Members.
//################################
Texture2D _texture;
bool _needUpload;
int _propertyId;
readonly string _propertyName;
readonly int _channels;
readonly int _instanceLimit;
readonly byte[] _data;
readonly Stack _stack;
static List updates;
///
/// Initialize this instance.
///
void Initialize()
{
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying && UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
{
return;
}
#endif
if (updates == null)
{
updates = new List();
Canvas.willRenderCanvases += () =>
{
var count = updates.Count;
for (int i = 0; i < count; i++)
{
updates[i].Invoke();
}
};
}
if (!this._texture)
{
bool isLinear = QualitySettings.activeColorSpace == ColorSpace.Linear;
this._texture = new Texture2D(this._channels / 4, this._instanceLimit, TextureFormat.RGBA32, false, isLinear);
this._texture.filterMode = FilterMode.Point;
this._texture.wrapMode = TextureWrapMode.Clamp;
updates.Add(UpdateParameterTexture);
this._needUpload = true;
}
}
void UpdateParameterTexture()
{
if (this._needUpload && this._texture)
{
this._needUpload = false;
this._texture.LoadRawTextureData(this._data);
this._texture.Apply(false, false);
}
}
}
}