228 lines
8.2 KiB
C#
228 lines
8.2 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.UI;
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Text.RegularExpressions;
|
|
|
|
using TMPro;
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Author: Colby-O
|
|
// File: VolumeComponentUICreator.cs
|
|
//-----------------------------------------------------------------------
|
|
namespace ColbyO.VNTG.Example
|
|
{
|
|
public class VolumeComponentUICreator : MonoBehaviour
|
|
{
|
|
[Header("References")]
|
|
[SerializeField] private TMP_Text _title;
|
|
[SerializeField] private Transform _container;
|
|
|
|
[Header("Effect")]
|
|
[SerializeField] private string _targetEffectName = "CRTSettings";
|
|
|
|
[Header("Prefabs")]
|
|
[SerializeField] private GameObject _sliderRowPrefab;
|
|
[SerializeField] private GameObject _toggleRowPrefab;
|
|
[SerializeField] private GameObject _headerPrefab;
|
|
[SerializeField] private GameObject _dropdownRowPrefab;
|
|
[SerializeField] private GameObject _vector2RowPrefab;
|
|
[SerializeField] private GameObject _colorRowPrefab;
|
|
|
|
private VolumeComponent _settings;
|
|
|
|
private void OnEnable()
|
|
{
|
|
RefreshUI(_targetEffectName);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
_settings = null;
|
|
}
|
|
|
|
private void GenerateUI()
|
|
{
|
|
_settings = GetSettings();
|
|
if (_settings == null) return;
|
|
|
|
FieldInfo[] fields = _settings.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
|
|
|
|
foreach (var field in fields)
|
|
{
|
|
HeaderAttribute header = field.GetCustomAttribute<HeaderAttribute>();
|
|
if (header != null) CreateHeader(header.header);
|
|
|
|
if (typeof(VolumeParameter).IsAssignableFrom(field.FieldType))
|
|
{
|
|
if (field.Name == "ShowInSceneView") continue;
|
|
CreateControl(field);
|
|
}
|
|
}
|
|
}
|
|
|
|
private VolumeComponent GetSettings()
|
|
{
|
|
#if UNITY_6000_4_OR_NEWER
|
|
Volume volume = FindAnyObjectByType<Volume>();
|
|
#else
|
|
Volume volume = FindFirstObjectByType<Volume>();
|
|
#endif
|
|
|
|
if (volume != null)
|
|
{
|
|
volume.profile = Instantiate(volume.profile);
|
|
}
|
|
|
|
if (volume == null || volume.profile == null) return null;
|
|
|
|
foreach (var component in volume.profile.components)
|
|
{
|
|
if (component.GetType().Name == _targetEffectName)
|
|
return component;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void RefreshUI(string effectName)
|
|
{
|
|
foreach (Transform child in _container)
|
|
{
|
|
if (child.gameObject) Destroy(child.gameObject);
|
|
}
|
|
|
|
_targetEffectName = effectName;
|
|
|
|
_title.text = (_targetEffectName == "CRTSettings") ? "CRT Post-Processing Settings" : "PSX Post-Processing Settings";
|
|
|
|
GenerateUI();
|
|
}
|
|
|
|
private void CreateControl(FieldInfo field)
|
|
{
|
|
string displayName = GetNameWithSpaces(field.Name);
|
|
object paramValue = field.GetValue(_settings);
|
|
|
|
if (paramValue is BoolParameter boolParam)
|
|
{
|
|
GameObject row = Instantiate(_toggleRowPrefab, _container);
|
|
row.GetComponentInChildren<TMP_Text>().text = displayName;
|
|
Toggle t = row.GetComponentInChildren<Toggle>();
|
|
t.isOn = boolParam.value;
|
|
t.onValueChanged.AddListener((val) => boolParam.value = val);
|
|
}
|
|
else if (paramValue is ClampedFloatParameter floatParam)
|
|
{
|
|
CreateSlider(displayName, floatParam.min, floatParam.max, floatParam.value, (val) => floatParam.value = val);
|
|
}
|
|
else if (paramValue is ClampedIntParameter intParam)
|
|
{
|
|
CreateSlider(displayName, intParam.min, intParam.max, intParam.value, (val) => intParam.value = (int)val);
|
|
}
|
|
else if (paramValue is Vector2Parameter vec2Param)
|
|
{
|
|
CreateVector2UI(displayName, vec2Param);
|
|
}
|
|
else if (paramValue is ColorParameter colorParam)
|
|
{
|
|
CreateColorUI(displayName, colorParam);
|
|
}
|
|
else if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(EnumParameter<>))
|
|
{
|
|
CreateEnumDropdown(displayName, paramValue);
|
|
}
|
|
}
|
|
|
|
private void CreateColorUI(string label, ColorParameter param)
|
|
{
|
|
GameObject row = Instantiate(_colorRowPrefab, _container);
|
|
row.GetComponentInChildren<TMP_Text>().text = label;
|
|
|
|
Image preview = row.transform.Find("Preview")?.GetComponent<Image>();
|
|
if (preview != null) preview.color = param.value;
|
|
|
|
Slider[] sliders = row.GetComponentsInChildren<Slider>();
|
|
if (sliders.Length >= 3)
|
|
{
|
|
sliders[0].value = param.value.r;
|
|
sliders[1].value = param.value.g;
|
|
sliders[2].value = param.value.b;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
sliders[i].onValueChanged.AddListener((val) => {
|
|
param.value = new Color(sliders[0].value, sliders[1].value, sliders[2].value, 1);
|
|
if (preview != null) preview.color = param.value;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CreateVector2UI(string label, Vector2Parameter param)
|
|
{
|
|
GameObject row = Instantiate(_vector2RowPrefab, _container);
|
|
row.GetComponentInChildren<TMP_Text>().text = label;
|
|
|
|
TMP_InputField[] inputs = row.GetComponentsInChildren<TMP_InputField>();
|
|
if (inputs.Length >= 2)
|
|
{
|
|
inputs[0].text = param.value.x.ToString();
|
|
inputs[1].text = param.value.y.ToString();
|
|
|
|
inputs[0].onEndEdit.AddListener((val) => { if (float.TryParse(val, out float res)) param.value = new Vector2(res, param.value.y); });
|
|
inputs[1].onEndEdit.AddListener((val) => { if (float.TryParse(val, out float res)) param.value = new Vector2(param.value.x, res); });
|
|
}
|
|
}
|
|
|
|
private void CreateEnumDropdown(string label, object paramValue)
|
|
{
|
|
GameObject row = Instantiate(_dropdownRowPrefab, _container);
|
|
row.GetComponentInChildren<TMP_Text>().text = label;
|
|
TMP_Dropdown dropdown = row.GetComponentInChildren<TMP_Dropdown>();
|
|
|
|
PropertyInfo valueProp = paramValue.GetType().GetProperty("value");
|
|
Enum currentEnum = (Enum)valueProp.GetValue(paramValue);
|
|
|
|
string[] names = Enum.GetNames(currentEnum.GetType());
|
|
List<string> options = new List<string>(names);
|
|
|
|
dropdown.ClearOptions();
|
|
dropdown.AddOptions(options);
|
|
dropdown.value = Array.IndexOf(names, currentEnum.ToString());
|
|
|
|
dropdown.onValueChanged.AddListener((index) =>
|
|
{
|
|
object enumVal = Enum.Parse(currentEnum.GetType(), names[index]);
|
|
valueProp.SetValue(paramValue, enumVal);
|
|
});
|
|
}
|
|
|
|
private void CreateHeader(string label)
|
|
{
|
|
GameObject headerObj = Instantiate(_headerPrefab, _container);
|
|
headerObj.GetComponentInChildren<TMP_Text>().text = label.ToUpper();
|
|
}
|
|
|
|
private string GetNameWithSpaces(string name)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(name)) return name;
|
|
|
|
return Regex.Replace(name, "([a-z0-9])([A-Z])", "$1 $2");
|
|
}
|
|
|
|
private void CreateSlider(string label, float min, float max, float startVal, UnityEngine.Events.UnityAction<float> callback)
|
|
{
|
|
GameObject row = Instantiate(_sliderRowPrefab, _container);
|
|
row.GetComponentInChildren<TMP_Text>().text = label;
|
|
Slider s = row.GetComponentInChildren<Slider>();
|
|
s.minValue = min;
|
|
s.maxValue = max;
|
|
s.value = startVal;
|
|
s.onValueChanged.AddListener(callback);
|
|
}
|
|
}
|
|
} |