Files
Continentis/Assets/OtherPlugins/Feel/NiceVibrations/Scripts/Editor/NVHapticDataDrawer.cs
SoulliesOfficial 9b1b5ca93f initial
2025-10-03 00:02:43 -04:00

165 lines
5.3 KiB
C#

using Lofelt.NiceVibrations;
using UnityEngine;
using UnityEditor;
namespace MoreMountains.FeedbacksForThirdParty
{
/// <summary>
/// A custom drawer for haptic data used by the NV Clip feedback
/// </summary>
[CustomPropertyDrawer(typeof(NVHapticData))]
public class NVHapticDataDrawer : PropertyDrawer
{
/// <summary>
/// Property height computation
/// </summary>
/// <param name="property"></param>
/// <param name="label"></param>
/// <returns></returns>
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
NVHapticData data = property.boxedValue as NVHapticData;
if (data.Clip == null)
{
return EditorGUIUtility.singleLineHeight;
}
else
{
return EditorGUIUtility.singleLineHeight * 14;
}
}
/// <summary>
/// Drawer
/// </summary>
/// <param name="position"></param>
/// <param name="property"></param>
/// <param name="label"></param>
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty rumbleData = property.FindPropertyRelative("RumbleData");
SerializedProperty totalDurationProp = rumbleData.FindPropertyRelative("totalDurationMs");
NVHapticData data = property.boxedValue as NVHapticData;
if (data.Clip == null)
{
return;
}
EditorGUI.LabelField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight),
label);
float lineHeight = EditorGUIUtility.singleLineHeight;
float y = position.y + lineHeight;
EditorGUI.PropertyField(new Rect(position.x, y, position.width, lineHeight), totalDurationProp);
y += lineHeight + 2;
// Generate curves
int[] amplitudeDurations = new int[data.AmplitudePoints.Count];
float[] amplitudeValues = new float[data.AmplitudePoints.Count];
float[] frequencyValues = new float[data.AmplitudePoints.Count];
for (int i = 0; i < data.AmplitudePoints.Count; i++)
{
var point = data.AmplitudePoints[i];
amplitudeDurations[i] = (int)(data.AmplitudePoints[i].time * 1000f);
amplitudeValues[i] = data.AmplitudePoints[i].emphasis.amplitude;
frequencyValues[i] = data.FrequencyPoints[i].frequency;
}
AnimationCurve amplitudeCurve = GenerateCurve(amplitudeDurations, amplitudeValues);
AnimationCurve emphasisCurve = GenerateCurve(amplitudeDurations, frequencyValues);
// Create rect for combined curve
Rect amplitudeCurveRect = new Rect(position.x, y, position.width, lineHeight * 5);
// Draw background
EditorGUI.DrawRect(amplitudeCurveRect, new Color(0.15f, 0.15f, 0.15f));
// Draw both curves manually
Handles.BeginGUI();
DrawCurveInRect(amplitudeCurve, amplitudeCurveRect, Color.yellow, data.SampleCount);
DrawCurveInRect(emphasisCurve, amplitudeCurveRect, Color.red, data.SampleCount);
Handles.EndGUI();
EditorGUI.LabelField(new Rect(position.x, y + amplitudeCurveRect.height, position.width, lineHeight),
"Yellow = Amplitude | Red = Frequency");
y += lineHeight * 6;
// Generate curves
AnimationCurve lowCurve = GenerateCurve(amplitudeDurations, data.RumbleData.lowFrequencyMotorSpeeds);
AnimationCurve highCurve = GenerateCurve(amplitudeDurations, data.RumbleData.highFrequencyMotorSpeeds);
// Create rect for combined curve
Rect curveRect = new Rect(position.x, y, position.width, lineHeight * 5);
// Draw background
EditorGUI.DrawRect(curveRect, new Color(0.15f, 0.15f, 0.15f));
// Draw both curves manually
Handles.BeginGUI();
DrawCurveInRect(lowCurve, curveRect, Color.green, data.SampleCount);
DrawCurveInRect(highCurve, curveRect, Color.cyan, data.SampleCount);
Handles.EndGUI();
EditorGUI.LabelField(new Rect(position.x, y + curveRect.height, position.width, lineHeight),
"Cyan = Amplitude | Green = Frequency");
}
/// <summary>
/// Curve drawing
/// </summary>
/// <param name="curve"></param>
/// <param name="rect"></param>
/// <param name="color"></param>
/// <param name="sampleCount"></param>
private void DrawCurveInRect(AnimationCurve curve, Rect rect, Color color, int sampleCount)
{
if (curve.length < 2)
return;
Handles.color = color;
Vector3[] points = new Vector3[sampleCount];
float startTime = curve.keys[0].time;
float endTime = curve.keys[curve.length - 1].time;
float timeRange = endTime - startTime;
for (int i = 0; i < points.Length; i++)
{
float t = Mathf.Lerp(startTime, endTime, i / (float)(points.Length - 1));
float val = curve.Evaluate(t);
float x = Mathf.Lerp(rect.x, rect.xMax, (t - startTime) / timeRange);
float y = Mathf.Lerp(rect.yMax, rect.y, val);
points[i] = new Vector3(x, y, 0);
}
Handles.DrawAAPolyLine(2f, points);
}
/// <summary>
/// Curve generation
/// </summary>
/// <param name="durationsProperty"></param>
/// <param name="valueProperty"></param>
/// <returns></returns>
private AnimationCurve GenerateCurve(int[] durationsProperty, float[] valueProperty)
{
AnimationCurve curve = new AnimationCurve();
if (durationsProperty == null || valueProperty == null || durationsProperty.Length != valueProperty.Length)
return curve;
float time = 0f;
for (int i = 0; i < valueProperty.Length; i++)
{
int duration = durationsProperty[i];
float speed = valueProperty[i];
curve.AddKey(time, speed);
time += duration / 1000f;
}
return curve;
}
}
}